forked from github/plane
chore: peek overview for issue view and my issue view (#2172)
* chore: peak overview for issue view and my issue view * fix: profile issue peak overview mutation fix * chore: code refactor * fix: image prefix url fix
This commit is contained in:
parent
1b1ed37405
commit
32d08570e7
@ -13,7 +13,7 @@ import useToast from "hooks/use-toast";
|
|||||||
// components
|
// components
|
||||||
import { EmailPasswordForm, GithubLoginButton, GoogleLoginButton, EmailCodeForm } from "components/accounts";
|
import { EmailPasswordForm, GithubLoginButton, GoogleLoginButton, EmailCodeForm } from "components/accounts";
|
||||||
// images
|
// images
|
||||||
const imagePrefix = process.env.NEXT_PUBLIC_DEPLOY_WITH_NGINX ? "/spaces/" : "";
|
const imagePrefix = process.env.NEXT_PUBLIC_DEPLOY_WITH_NGINX ? "/spaces" : "";
|
||||||
|
|
||||||
export const SignInView = observer(() => {
|
export const SignInView = observer(() => {
|
||||||
const { user: userStore } = useMobxStore();
|
const { user: userStore } = useMobxStore();
|
||||||
|
@ -5,7 +5,7 @@ import { useMobxStore } from "lib/mobx/store-provider";
|
|||||||
// components
|
// components
|
||||||
import { OnBoardingForm } from "components/accounts/onboarding-form";
|
import { OnBoardingForm } from "components/accounts/onboarding-form";
|
||||||
|
|
||||||
const imagePrefix = process.env.NEXT_PUBLIC_DEPLOY_WITH_NGINX ? "/spaces/" : "";
|
const imagePrefix = process.env.NEXT_PUBLIC_DEPLOY_WITH_NGINX ? "/spaces" : "";
|
||||||
|
|
||||||
const OnBoardingPage = () => {
|
const OnBoardingPage = () => {
|
||||||
const { user: userStore } = useMobxStore();
|
const { user: userStore } = useMobxStore();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useCallback } from "react";
|
import React, { useCallback, useState } from "react";
|
||||||
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
@ -77,6 +77,8 @@ export const AllViews: React.FC<Props> = ({
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
|
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
|
||||||
|
|
||||||
|
const [myIssueProjectId, setMyIssueProjectId] = useState<string | null>(null);
|
||||||
|
|
||||||
const { user } = useUser();
|
const { user } = useUser();
|
||||||
const { memberRole } = useProjectMyMembership();
|
const { memberRole } = useProjectMyMembership();
|
||||||
|
|
||||||
@ -90,6 +92,10 @@ export const AllViews: React.FC<Props> = ({
|
|||||||
);
|
);
|
||||||
const states = getStatesList(stateGroups);
|
const states = getStatesList(stateGroups);
|
||||||
|
|
||||||
|
const handleMyIssueOpen = (issue: IIssue) => {
|
||||||
|
setMyIssueProjectId(issue.project);
|
||||||
|
};
|
||||||
|
|
||||||
const handleTrashBox = useCallback(
|
const handleTrashBox = useCallback(
|
||||||
(isDragging: boolean) => {
|
(isDragging: boolean) => {
|
||||||
if (isDragging && !trashBox) setTrashBox(true);
|
if (isDragging && !trashBox) setTrashBox(true);
|
||||||
@ -128,6 +134,8 @@ export const AllViews: React.FC<Props> = ({
|
|||||||
handleIssueAction={handleIssueAction}
|
handleIssueAction={handleIssueAction}
|
||||||
openIssuesListModal={cycleId || moduleId ? openIssuesListModal : null}
|
openIssuesListModal={cycleId || moduleId ? openIssuesListModal : null}
|
||||||
removeIssue={removeIssue}
|
removeIssue={removeIssue}
|
||||||
|
myIssueProjectId={myIssueProjectId}
|
||||||
|
handleMyIssueOpen={handleMyIssueOpen}
|
||||||
disableUserActions={disableUserActions}
|
disableUserActions={disableUserActions}
|
||||||
disableAddIssueOption={disableAddIssueOption}
|
disableAddIssueOption={disableAddIssueOption}
|
||||||
user={user}
|
user={user}
|
||||||
@ -143,6 +151,8 @@ export const AllViews: React.FC<Props> = ({
|
|||||||
handleIssueAction={handleIssueAction}
|
handleIssueAction={handleIssueAction}
|
||||||
handleTrashBox={handleTrashBox}
|
handleTrashBox={handleTrashBox}
|
||||||
openIssuesListModal={cycleId || moduleId ? openIssuesListModal : null}
|
openIssuesListModal={cycleId || moduleId ? openIssuesListModal : null}
|
||||||
|
myIssueProjectId={myIssueProjectId}
|
||||||
|
handleMyIssueOpen={handleMyIssueOpen}
|
||||||
removeIssue={removeIssue}
|
removeIssue={removeIssue}
|
||||||
states={states}
|
states={states}
|
||||||
user={user}
|
user={user}
|
||||||
@ -166,7 +176,9 @@ export const AllViews: React.FC<Props> = ({
|
|||||||
userAuth={memberRole}
|
userAuth={memberRole}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
displayFilters?.layout === "gantt_chart" && <GanttChartView />
|
displayFilters?.layout === "gantt_chart" && (
|
||||||
|
<GanttChartView disableUserActions={disableUserActions} />
|
||||||
|
)
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
) : router.pathname.includes("archived-issues") ? (
|
) : router.pathname.includes("archived-issues") ? (
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
|
//hook
|
||||||
|
import useMyIssues from "hooks/my-issues/use-my-issues";
|
||||||
|
import useIssuesView from "hooks/use-issues-view";
|
||||||
|
import useProfileIssues from "hooks/use-profile-issues";
|
||||||
// components
|
// components
|
||||||
import { SingleBoard } from "components/core/views/board-view/single-board";
|
import { SingleBoard } from "components/core/views/board-view/single-board";
|
||||||
|
import { IssuePeekOverview } from "components/issues";
|
||||||
// icons
|
// icons
|
||||||
import { StateGroupIcon } from "components/icons";
|
import { StateGroupIcon } from "components/icons";
|
||||||
// helpers
|
// helpers
|
||||||
@ -16,6 +23,8 @@ type Props = {
|
|||||||
handleTrashBox: (isDragging: boolean) => void;
|
handleTrashBox: (isDragging: boolean) => void;
|
||||||
openIssuesListModal?: (() => void) | null;
|
openIssuesListModal?: (() => void) | null;
|
||||||
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
||||||
|
myIssueProjectId?: string | null;
|
||||||
|
handleMyIssueOpen?: (issue: IIssue) => void;
|
||||||
states: IState[] | undefined;
|
states: IState[] | undefined;
|
||||||
user: ICurrentUserResponse | undefined;
|
user: ICurrentUserResponse | undefined;
|
||||||
userAuth: UserAuth;
|
userAuth: UserAuth;
|
||||||
@ -30,16 +39,40 @@ export const AllBoards: React.FC<Props> = ({
|
|||||||
handleIssueAction,
|
handleIssueAction,
|
||||||
handleTrashBox,
|
handleTrashBox,
|
||||||
openIssuesListModal,
|
openIssuesListModal,
|
||||||
|
myIssueProjectId,
|
||||||
|
handleMyIssueOpen,
|
||||||
removeIssue,
|
removeIssue,
|
||||||
states,
|
states,
|
||||||
user,
|
user,
|
||||||
userAuth,
|
userAuth,
|
||||||
viewProps,
|
viewProps,
|
||||||
}) => {
|
}) => {
|
||||||
|
const router = useRouter();
|
||||||
|
const { workspaceSlug, projectId, userId } = router.query;
|
||||||
|
|
||||||
|
const isProfileIssue =
|
||||||
|
router.pathname.includes("assigned") ||
|
||||||
|
router.pathname.includes("created") ||
|
||||||
|
router.pathname.includes("subscribed");
|
||||||
|
|
||||||
|
const isMyIssue = router.pathname.includes("my-issues");
|
||||||
|
|
||||||
|
const { mutateIssues } = useIssuesView();
|
||||||
|
const { mutateMyIssues } = useMyIssues(workspaceSlug?.toString());
|
||||||
|
const { mutateProfileIssues } = useProfileIssues(workspaceSlug?.toString(), userId?.toString());
|
||||||
|
|
||||||
const { displayFilters, groupedIssues } = viewProps;
|
const { displayFilters, groupedIssues } = viewProps;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<IssuePeekOverview
|
||||||
|
handleMutation={() =>
|
||||||
|
isMyIssue ? mutateMyIssues() : isProfileIssue ? mutateProfileIssues() : mutateIssues()
|
||||||
|
}
|
||||||
|
projectId={myIssueProjectId ? myIssueProjectId : projectId?.toString() ?? ""}
|
||||||
|
workspaceSlug={workspaceSlug?.toString() ?? ""}
|
||||||
|
readOnly={disableUserActions}
|
||||||
|
/>
|
||||||
{groupedIssues ? (
|
{groupedIssues ? (
|
||||||
<div className="horizontal-scroll-enable flex h-full gap-x-4 p-8">
|
<div className="horizontal-scroll-enable flex h-full gap-x-4 p-8">
|
||||||
{Object.keys(groupedIssues).map((singleGroup, index) => {
|
{Object.keys(groupedIssues).map((singleGroup, index) => {
|
||||||
@ -63,6 +96,7 @@ export const AllBoards: React.FC<Props> = ({
|
|||||||
handleIssueAction={handleIssueAction}
|
handleIssueAction={handleIssueAction}
|
||||||
handleTrashBox={handleTrashBox}
|
handleTrashBox={handleTrashBox}
|
||||||
openIssuesListModal={openIssuesListModal ?? null}
|
openIssuesListModal={openIssuesListModal ?? null}
|
||||||
|
handleMyIssueOpen={handleMyIssueOpen}
|
||||||
removeIssue={removeIssue}
|
removeIssue={removeIssue}
|
||||||
user={user}
|
user={user}
|
||||||
userAuth={userAuth}
|
userAuth={userAuth}
|
||||||
|
@ -26,6 +26,7 @@ type Props = {
|
|||||||
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
|
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
|
||||||
handleTrashBox: (isDragging: boolean) => void;
|
handleTrashBox: (isDragging: boolean) => void;
|
||||||
openIssuesListModal?: (() => void) | null;
|
openIssuesListModal?: (() => void) | null;
|
||||||
|
handleMyIssueOpen?: (issue: IIssue) => void;
|
||||||
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
||||||
user: ICurrentUserResponse | undefined;
|
user: ICurrentUserResponse | undefined;
|
||||||
userAuth: UserAuth;
|
userAuth: UserAuth;
|
||||||
@ -42,6 +43,7 @@ export const SingleBoard: React.FC<Props> = ({
|
|||||||
handleIssueAction,
|
handleIssueAction,
|
||||||
handleTrashBox,
|
handleTrashBox,
|
||||||
openIssuesListModal,
|
openIssuesListModal,
|
||||||
|
handleMyIssueOpen,
|
||||||
removeIssue,
|
removeIssue,
|
||||||
user,
|
user,
|
||||||
userAuth,
|
userAuth,
|
||||||
@ -50,7 +52,7 @@ export const SingleBoard: React.FC<Props> = ({
|
|||||||
// collapse/expand
|
// collapse/expand
|
||||||
const [isCollapsed, setIsCollapsed] = useState(true);
|
const [isCollapsed, setIsCollapsed] = useState(true);
|
||||||
|
|
||||||
const { displayFilters, groupedIssues, properties } = viewProps;
|
const { displayFilters, groupedIssues } = viewProps;
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { cycleId, moduleId } = router.query;
|
const { cycleId, moduleId } = router.query;
|
||||||
@ -135,6 +137,7 @@ export const SingleBoard: React.FC<Props> = ({
|
|||||||
makeIssueCopy={() => handleIssueAction(issue, "copy")}
|
makeIssueCopy={() => handleIssueAction(issue, "copy")}
|
||||||
handleDeleteIssue={() => handleIssueAction(issue, "delete")}
|
handleDeleteIssue={() => handleIssueAction(issue, "delete")}
|
||||||
handleTrashBox={handleTrashBox}
|
handleTrashBox={handleTrashBox}
|
||||||
|
handleMyIssueOpen={handleMyIssueOpen}
|
||||||
removeIssue={() => {
|
removeIssue={() => {
|
||||||
if (removeIssue && issue.bridge_id)
|
if (removeIssue && issue.bridge_id)
|
||||||
removeIssue(issue.bridge_id, issue.id);
|
removeIssue(issue.bridge_id, issue.id);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
import Link from "next/link";
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import { mutate } from "swr";
|
import { mutate } from "swr";
|
||||||
@ -58,6 +57,7 @@ type Props = {
|
|||||||
index: number;
|
index: number;
|
||||||
editIssue: () => void;
|
editIssue: () => void;
|
||||||
makeIssueCopy: () => void;
|
makeIssueCopy: () => void;
|
||||||
|
handleMyIssueOpen?: (issue: IIssue) => void;
|
||||||
removeIssue?: (() => void) | null;
|
removeIssue?: (() => void) | null;
|
||||||
handleDeleteIssue: (issue: IIssue) => void;
|
handleDeleteIssue: (issue: IIssue) => void;
|
||||||
handleTrashBox: (isDragging: boolean) => void;
|
handleTrashBox: (isDragging: boolean) => void;
|
||||||
@ -75,6 +75,7 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
|||||||
index,
|
index,
|
||||||
editIssue,
|
editIssue,
|
||||||
makeIssueCopy,
|
makeIssueCopy,
|
||||||
|
handleMyIssueOpen,
|
||||||
removeIssue,
|
removeIssue,
|
||||||
groupTitle,
|
groupTitle,
|
||||||
handleDeleteIssue,
|
handleDeleteIssue,
|
||||||
@ -187,6 +188,17 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
|||||||
|
|
||||||
useOutsideClickDetector(actionSectionRef, () => setIsMenuActive(false));
|
useOutsideClickDetector(actionSectionRef, () => setIsMenuActive(false));
|
||||||
|
|
||||||
|
const openPeekOverview = () => {
|
||||||
|
const { query } = router;
|
||||||
|
|
||||||
|
if (handleMyIssueOpen) handleMyIssueOpen(issue);
|
||||||
|
|
||||||
|
router.push({
|
||||||
|
pathname: router.pathname,
|
||||||
|
query: { ...query, peekIssue: issue.id },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const isNotAllowed = userAuth.isGuest || userAuth.isViewer || disableUserActions;
|
const isNotAllowed = userAuth.isGuest || userAuth.isViewer || disableUserActions;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -286,16 +298,22 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<Link href={`/${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`}>
|
|
||||||
<a className="flex flex-col gap-1.5">
|
<div className="flex flex-col gap-1.5">
|
||||||
{properties.key && (
|
{properties.key && (
|
||||||
<div className="text-xs font-medium text-custom-text-200">
|
<div className="text-xs font-medium text-custom-text-200">
|
||||||
{issue.project_detail.identifier}-{issue.sequence_id}
|
{issue.project_detail.identifier}-{issue.sequence_id}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<h5 className="text-sm break-words line-clamp-2">{issue.name}</h5>
|
<button
|
||||||
</a>
|
type="button"
|
||||||
</Link>
|
className="text-sm text-left break-words line-clamp-2"
|
||||||
|
onClick={openPeekOverview}
|
||||||
|
>
|
||||||
|
{issue.name}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className={`flex items-center gap-2 text-xs ${
|
className={`flex items-center gap-2 text-xs ${
|
||||||
isDropdownActive ? "" : "overflow-x-scroll"
|
isDropdownActive ? "" : "overflow-x-scroll"
|
||||||
|
@ -12,6 +12,7 @@ import issuesService from "services/issues.service";
|
|||||||
import useCalendarIssuesView from "hooks/use-calendar-issues-view";
|
import useCalendarIssuesView from "hooks/use-calendar-issues-view";
|
||||||
// components
|
// components
|
||||||
import { SingleCalendarDate, CalendarHeader } from "components/core";
|
import { SingleCalendarDate, CalendarHeader } from "components/core";
|
||||||
|
import { IssuePeekOverview } from "components/issues";
|
||||||
// ui
|
// ui
|
||||||
import { Spinner } from "components/ui";
|
import { Spinner } from "components/ui";
|
||||||
// helpers
|
// helpers
|
||||||
@ -60,7 +61,8 @@ export const CalendarView: React.FC<Props> = ({
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query;
|
const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query;
|
||||||
|
|
||||||
const { calendarIssues, params, displayFilters, setDisplayFilters } = useCalendarIssuesView();
|
const { calendarIssues, mutateIssues, params, displayFilters, setDisplayFilters } =
|
||||||
|
useCalendarIssuesView();
|
||||||
|
|
||||||
const totalDate = eachDayOfInterval({
|
const totalDate = eachDayOfInterval({
|
||||||
start: calendarDates.startDate,
|
start: calendarDates.startDate,
|
||||||
@ -170,7 +172,15 @@ export const CalendarView: React.FC<Props> = ({
|
|||||||
|
|
||||||
const isNotAllowed = userAuth.isGuest || userAuth.isViewer || disableUserActions;
|
const isNotAllowed = userAuth.isGuest || userAuth.isViewer || disableUserActions;
|
||||||
|
|
||||||
return calendarIssues ? (
|
return (
|
||||||
|
<>
|
||||||
|
<IssuePeekOverview
|
||||||
|
handleMutation={() => mutateIssues()}
|
||||||
|
projectId={projectId?.toString() ?? ""}
|
||||||
|
workspaceSlug={workspaceSlug?.toString() ?? ""}
|
||||||
|
readOnly={disableUserActions}
|
||||||
|
/>
|
||||||
|
{calendarIssues ? (
|
||||||
<div className="h-full overflow-y-auto">
|
<div className="h-full overflow-y-auto">
|
||||||
<DragDropContext onDragEnd={onDragEnd}>
|
<DragDropContext onDragEnd={onDragEnd}>
|
||||||
<div className="h-full rounded-lg p-8 text-custom-text-200">
|
<div className="h-full rounded-lg p-8 text-custom-text-200">
|
||||||
@ -240,5 +250,7 @@ export const CalendarView: React.FC<Props> = ({
|
|||||||
<div className="flex h-full w-full items-center justify-center">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<Spinner />
|
<Spinner />
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import React, { useCallback } from "react";
|
import React, { useCallback } from "react";
|
||||||
|
|
||||||
import Link from "next/link";
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import { mutate } from "swr";
|
import { mutate } from "swr";
|
||||||
@ -158,6 +157,15 @@ export const SingleCalendarIssue: React.FC<Props> = ({
|
|||||||
? Object.values(properties).some((value) => value === true)
|
? Object.values(properties).some((value) => value === true)
|
||||||
: false;
|
: false;
|
||||||
|
|
||||||
|
const openPeekOverview = () => {
|
||||||
|
const { query } = router;
|
||||||
|
|
||||||
|
router.push({
|
||||||
|
pathname: router.pathname,
|
||||||
|
query: { ...query, peekIssue: issue.id },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
@ -193,8 +201,12 @@ export const SingleCalendarIssue: React.FC<Props> = ({
|
|||||||
</CustomMenu>
|
</CustomMenu>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<Link href={`/${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`}>
|
|
||||||
<a className="flex w-full cursor-pointer flex-col items-start justify-center gap-1.5">
|
<button
|
||||||
|
type="button"
|
||||||
|
className="flex w-full cursor-pointer flex-col items-start justify-center gap-1.5"
|
||||||
|
onClick={openPeekOverview}
|
||||||
|
>
|
||||||
{properties.key && (
|
{properties.key && (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
tooltipHeading="Issue ID"
|
tooltipHeading="Issue ID"
|
||||||
@ -208,8 +220,8 @@ export const SingleCalendarIssue: React.FC<Props> = ({
|
|||||||
<Tooltip position="top-left" tooltipHeading="Title" tooltipContent={issue.name}>
|
<Tooltip position="top-left" tooltipHeading="Title" tooltipContent={issue.name}>
|
||||||
<span className="text-xs text-custom-text-100">{truncateText(issue.name, 25)}</span>
|
<span className="text-xs text-custom-text-100">{truncateText(issue.name, 25)}</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</a>
|
</button>
|
||||||
</Link>
|
|
||||||
{displayProperties && (
|
{displayProperties && (
|
||||||
<div className="relative mt-1.5 w-full flex flex-wrap items-center gap-2 text-xs">
|
<div className="relative mt-1.5 w-full flex flex-wrap items-center gap-2 text-xs">
|
||||||
{properties.priority && (
|
{properties.priority && (
|
||||||
|
@ -6,20 +6,24 @@ import { IssueGanttChartView } from "components/issues";
|
|||||||
import { ModuleIssuesGanttChartView } from "components/modules";
|
import { ModuleIssuesGanttChartView } from "components/modules";
|
||||||
import { ViewIssuesGanttChartView } from "components/views";
|
import { ViewIssuesGanttChartView } from "components/views";
|
||||||
|
|
||||||
export const GanttChartView = () => {
|
type Props = {
|
||||||
|
disableUserActions: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const GanttChartView: React.FC<Props> = ({ disableUserActions }) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { cycleId, moduleId, viewId } = router.query;
|
const { cycleId, moduleId, viewId } = router.query;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{cycleId ? (
|
{cycleId ? (
|
||||||
<CycleIssuesGanttChartView />
|
<CycleIssuesGanttChartView disableUserActions={disableUserActions} />
|
||||||
) : moduleId ? (
|
) : moduleId ? (
|
||||||
<ModuleIssuesGanttChartView />
|
<ModuleIssuesGanttChartView disableUserActions={disableUserActions} />
|
||||||
) : viewId ? (
|
) : viewId ? (
|
||||||
<ViewIssuesGanttChartView />
|
<ViewIssuesGanttChartView disableUserActions={disableUserActions} />
|
||||||
) : (
|
) : (
|
||||||
<IssueGanttChartView />
|
<IssueGanttChartView disableUserActions={disableUserActions} />
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -19,7 +19,7 @@ import useIssuesProperties from "hooks/use-issue-properties";
|
|||||||
import useProjectMembers from "hooks/use-project-members";
|
import useProjectMembers from "hooks/use-project-members";
|
||||||
// components
|
// components
|
||||||
import { FiltersList, AllViews } from "components/core";
|
import { FiltersList, AllViews } from "components/core";
|
||||||
import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues";
|
import { CreateUpdateIssueModal, DeleteIssueModal, IssuePeekOverview } from "components/issues";
|
||||||
import { CreateUpdateViewModal } from "components/views";
|
import { CreateUpdateViewModal } from "components/views";
|
||||||
// ui
|
// ui
|
||||||
import { PrimaryButton, SecondaryButton } from "components/ui";
|
import { PrimaryButton, SecondaryButton } from "components/ui";
|
||||||
@ -462,6 +462,7 @@ export const IssuesView: React.FC<Props> = ({
|
|||||||
data={issueToDelete}
|
data={issueToDelete}
|
||||||
user={user}
|
user={user}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{areFiltersApplied && (
|
{areFiltersApplied && (
|
||||||
<>
|
<>
|
||||||
<div className="flex items-center justify-between gap-2 px-5 pt-3 pb-0">
|
<div className="flex items-center justify-between gap-2 px-5 pt-3 pb-0">
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
|
// hooks
|
||||||
|
import useMyIssues from "hooks/my-issues/use-my-issues";
|
||||||
|
import useIssuesView from "hooks/use-issues-view";
|
||||||
|
import useProfileIssues from "hooks/use-profile-issues";
|
||||||
// components
|
// components
|
||||||
import { SingleList } from "components/core/views/list-view/single-list";
|
import { SingleList } from "components/core/views/list-view/single-list";
|
||||||
|
import { IssuePeekOverview } from "components/issues";
|
||||||
// types
|
// types
|
||||||
import { ICurrentUserResponse, IIssue, IIssueViewProps, IState, UserAuth } from "types";
|
import { ICurrentUserResponse, IIssue, IIssueViewProps, IState, UserAuth } from "types";
|
||||||
|
|
||||||
@ -9,6 +16,8 @@ type Props = {
|
|||||||
addIssueToGroup: (groupTitle: string) => void;
|
addIssueToGroup: (groupTitle: string) => void;
|
||||||
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
|
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
|
||||||
openIssuesListModal?: (() => void) | null;
|
openIssuesListModal?: (() => void) | null;
|
||||||
|
myIssueProjectId?: string | null;
|
||||||
|
handleMyIssueOpen?: (issue: IIssue) => void;
|
||||||
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
||||||
disableUserActions: boolean;
|
disableUserActions: boolean;
|
||||||
disableAddIssueOption?: boolean;
|
disableAddIssueOption?: boolean;
|
||||||
@ -23,16 +32,39 @@ export const AllLists: React.FC<Props> = ({
|
|||||||
disableUserActions,
|
disableUserActions,
|
||||||
disableAddIssueOption = false,
|
disableAddIssueOption = false,
|
||||||
openIssuesListModal,
|
openIssuesListModal,
|
||||||
|
handleMyIssueOpen,
|
||||||
|
myIssueProjectId,
|
||||||
removeIssue,
|
removeIssue,
|
||||||
states,
|
states,
|
||||||
user,
|
user,
|
||||||
userAuth,
|
userAuth,
|
||||||
viewProps,
|
viewProps,
|
||||||
}) => {
|
}) => {
|
||||||
|
const router = useRouter();
|
||||||
|
const { workspaceSlug, projectId, userId } = router.query;
|
||||||
|
|
||||||
|
const isProfileIssue =
|
||||||
|
router.pathname.includes("assigned") ||
|
||||||
|
router.pathname.includes("created") ||
|
||||||
|
router.pathname.includes("subscribed");
|
||||||
|
|
||||||
|
const isMyIssue = router.pathname.includes("my-issues");
|
||||||
|
const { mutateIssues } = useIssuesView();
|
||||||
|
const { mutateMyIssues } = useMyIssues(workspaceSlug?.toString());
|
||||||
|
const { mutateProfileIssues } = useProfileIssues(workspaceSlug?.toString(), userId?.toString());
|
||||||
|
|
||||||
const { displayFilters, groupedIssues } = viewProps;
|
const { displayFilters, groupedIssues } = viewProps;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<IssuePeekOverview
|
||||||
|
handleMutation={() =>
|
||||||
|
isMyIssue ? mutateMyIssues() : isProfileIssue ? mutateProfileIssues() : mutateIssues()
|
||||||
|
}
|
||||||
|
projectId={myIssueProjectId ? myIssueProjectId : projectId?.toString() ?? ""}
|
||||||
|
workspaceSlug={workspaceSlug?.toString() ?? ""}
|
||||||
|
readOnly={disableUserActions}
|
||||||
|
/>
|
||||||
{groupedIssues && (
|
{groupedIssues && (
|
||||||
<div className="h-full overflow-y-auto">
|
<div className="h-full overflow-y-auto">
|
||||||
{Object.keys(groupedIssues).map((singleGroup) => {
|
{Object.keys(groupedIssues).map((singleGroup) => {
|
||||||
@ -51,6 +83,7 @@ export const AllLists: React.FC<Props> = ({
|
|||||||
currentState={currentState}
|
currentState={currentState}
|
||||||
addIssueToGroup={() => addIssueToGroup(singleGroup)}
|
addIssueToGroup={() => addIssueToGroup(singleGroup)}
|
||||||
handleIssueAction={handleIssueAction}
|
handleIssueAction={handleIssueAction}
|
||||||
|
handleMyIssueOpen={handleMyIssueOpen}
|
||||||
openIssuesListModal={openIssuesListModal}
|
openIssuesListModal={openIssuesListModal}
|
||||||
removeIssue={removeIssue}
|
removeIssue={removeIssue}
|
||||||
disableUserActions={disableUserActions}
|
disableUserActions={disableUserActions}
|
||||||
|
@ -61,6 +61,7 @@ type Props = {
|
|||||||
makeIssueCopy: () => void;
|
makeIssueCopy: () => void;
|
||||||
removeIssue?: (() => void) | null;
|
removeIssue?: (() => void) | null;
|
||||||
handleDeleteIssue: (issue: IIssue) => void;
|
handleDeleteIssue: (issue: IIssue) => void;
|
||||||
|
handleMyIssueOpen?: (issue: IIssue) => void;
|
||||||
disableUserActions: boolean;
|
disableUserActions: boolean;
|
||||||
user: ICurrentUserResponse | undefined;
|
user: ICurrentUserResponse | undefined;
|
||||||
userAuth: UserAuth;
|
userAuth: UserAuth;
|
||||||
@ -76,6 +77,7 @@ export const SingleListIssue: React.FC<Props> = ({
|
|||||||
removeIssue,
|
removeIssue,
|
||||||
groupTitle,
|
groupTitle,
|
||||||
handleDeleteIssue,
|
handleDeleteIssue,
|
||||||
|
handleMyIssueOpen,
|
||||||
disableUserActions,
|
disableUserActions,
|
||||||
user,
|
user,
|
||||||
userAuth,
|
userAuth,
|
||||||
@ -178,6 +180,16 @@ export const SingleListIssue: React.FC<Props> = ({
|
|||||||
? `/${workspaceSlug}/projects/${issue.project}/archived-issues/${issue.id}`
|
? `/${workspaceSlug}/projects/${issue.project}/archived-issues/${issue.id}`
|
||||||
: `/${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`;
|
: `/${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`;
|
||||||
|
|
||||||
|
const openPeekOverview = (issue: IIssue) => {
|
||||||
|
const { query } = router;
|
||||||
|
|
||||||
|
if (handleMyIssueOpen) handleMyIssueOpen(issue);
|
||||||
|
router.push({
|
||||||
|
pathname: router.pathname,
|
||||||
|
query: { ...query, peekIssue: issue.id },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const isNotAllowed =
|
const isNotAllowed =
|
||||||
userAuth.isGuest || userAuth.isViewer || disableUserActions || isArchivedIssues;
|
userAuth.isGuest || userAuth.isViewer || disableUserActions || isArchivedIssues;
|
||||||
|
|
||||||
@ -220,8 +232,7 @@ export const SingleListIssue: React.FC<Props> = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex-grow cursor-pointer min-w-[200px] whitespace-nowrap overflow-hidden overflow-ellipsis">
|
<div className="flex-grow cursor-pointer min-w-[200px] whitespace-nowrap overflow-hidden overflow-ellipsis">
|
||||||
<Link href={issuePath}>
|
<div className="group relative flex items-center gap-2">
|
||||||
<a className="group relative flex items-center gap-2">
|
|
||||||
{properties.key && (
|
{properties.key && (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
tooltipHeading="Issue ID"
|
tooltipHeading="Issue ID"
|
||||||
@ -233,10 +244,15 @@ export const SingleListIssue: React.FC<Props> = ({
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
<Tooltip position="top-left" tooltipHeading="Title" tooltipContent={issue.name}>
|
<Tooltip position="top-left" tooltipHeading="Title" tooltipContent={issue.name}>
|
||||||
<span className="truncate text-[0.825rem] text-custom-text-100">{issue.name}</span>
|
<button
|
||||||
|
type="button"
|
||||||
|
className="truncate text-[0.825rem] text-custom-text-100"
|
||||||
|
onClick={() => openPeekOverview(issue)}
|
||||||
|
>
|
||||||
|
{issue.name}
|
||||||
|
</button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</a>
|
</div>
|
||||||
</Link>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
@ -41,6 +41,7 @@ type Props = {
|
|||||||
addIssueToGroup: () => void;
|
addIssueToGroup: () => void;
|
||||||
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
|
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
|
||||||
openIssuesListModal?: (() => void) | null;
|
openIssuesListModal?: (() => void) | null;
|
||||||
|
handleMyIssueOpen?: (issue: IIssue) => void;
|
||||||
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
||||||
disableUserActions: boolean;
|
disableUserActions: boolean;
|
||||||
disableAddIssueOption?: boolean;
|
disableAddIssueOption?: boolean;
|
||||||
@ -55,6 +56,7 @@ export const SingleList: React.FC<Props> = ({
|
|||||||
addIssueToGroup,
|
addIssueToGroup,
|
||||||
handleIssueAction,
|
handleIssueAction,
|
||||||
openIssuesListModal,
|
openIssuesListModal,
|
||||||
|
handleMyIssueOpen,
|
||||||
removeIssue,
|
removeIssue,
|
||||||
disableUserActions,
|
disableUserActions,
|
||||||
disableAddIssueOption = false,
|
disableAddIssueOption = false,
|
||||||
@ -251,6 +253,7 @@ export const SingleList: React.FC<Props> = ({
|
|||||||
editIssue={() => handleIssueAction(issue, "edit")}
|
editIssue={() => handleIssueAction(issue, "edit")}
|
||||||
makeIssueCopy={() => handleIssueAction(issue, "copy")}
|
makeIssueCopy={() => handleIssueAction(issue, "copy")}
|
||||||
handleDeleteIssue={() => handleIssueAction(issue, "delete")}
|
handleDeleteIssue={() => handleIssueAction(issue, "delete")}
|
||||||
|
handleMyIssueOpen={handleMyIssueOpen}
|
||||||
removeIssue={() => {
|
removeIssue={() => {
|
||||||
if (removeIssue !== null && issue.bridge_id)
|
if (removeIssue !== null && issue.bridge_id)
|
||||||
removeIssue(issue.bridge_id, issue.id);
|
removeIssue(issue.bridge_id, issue.id);
|
||||||
|
@ -8,11 +8,15 @@ import { updateGanttIssue } from "components/gantt-chart/hooks/block-update";
|
|||||||
import useProjectDetails from "hooks/use-project-details";
|
import useProjectDetails from "hooks/use-project-details";
|
||||||
// components
|
// components
|
||||||
import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
|
import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
|
||||||
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
import { IssueGanttBlock, IssueGanttSidebarBlock, IssuePeekOverview } from "components/issues";
|
||||||
// types
|
// types
|
||||||
import { IIssue } from "types";
|
import { IIssue } from "types";
|
||||||
|
|
||||||
export const CycleIssuesGanttChartView = () => {
|
type Props = {
|
||||||
|
disableUserActions: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CycleIssuesGanttChartView: React.FC<Props> = ({ disableUserActions }) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, cycleId } = router.query;
|
const { workspaceSlug, projectId, cycleId } = router.query;
|
||||||
|
|
||||||
@ -30,6 +34,13 @@ export const CycleIssuesGanttChartView = () => {
|
|||||||
const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
|
const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
<IssuePeekOverview
|
||||||
|
handleMutation={() => mutateGanttIssues()}
|
||||||
|
projectId={projectId?.toString() ?? ""}
|
||||||
|
workspaceSlug={workspaceSlug?.toString() ?? ""}
|
||||||
|
readOnly={disableUserActions}
|
||||||
|
/>
|
||||||
<div className="w-full h-full">
|
<div className="w-full h-full">
|
||||||
<GanttChartRoot
|
<GanttChartRoot
|
||||||
border={false}
|
border={false}
|
||||||
@ -48,5 +59,6 @@ export const CycleIssuesGanttChartView = () => {
|
|||||||
bottomSpacing
|
bottomSpacing
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -23,14 +23,7 @@ import {
|
|||||||
import { CreateStateModal } from "components/states";
|
import { CreateStateModal } from "components/states";
|
||||||
import { CreateLabelModal } from "components/labels";
|
import { CreateLabelModal } from "components/labels";
|
||||||
// ui
|
// ui
|
||||||
import {
|
import { CustomMenu, Input, PrimaryButton, SecondaryButton, ToggleSwitch } from "components/ui";
|
||||||
CustomMenu,
|
|
||||||
Input,
|
|
||||||
Loader,
|
|
||||||
PrimaryButton,
|
|
||||||
SecondaryButton,
|
|
||||||
ToggleSwitch,
|
|
||||||
} from "components/ui";
|
|
||||||
import { TipTapEditor } from "components/tiptap";
|
import { TipTapEditor } from "components/tiptap";
|
||||||
// icons
|
// icons
|
||||||
import { SparklesIcon, XMarkIcon } from "@heroicons/react/24/outline";
|
import { SparklesIcon, XMarkIcon } from "@heroicons/react/24/outline";
|
||||||
|
@ -11,13 +11,21 @@ import { IIssue } from "types";
|
|||||||
|
|
||||||
export const IssueGanttBlock = ({ data }: { data: IIssue }) => {
|
export const IssueGanttBlock = ({ data }: { data: IIssue }) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug } = router.query;
|
|
||||||
|
const openPeekOverview = () => {
|
||||||
|
const { query } = router;
|
||||||
|
|
||||||
|
router.push({
|
||||||
|
pathname: router.pathname,
|
||||||
|
query: { ...query, peekIssue: data.id },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="flex items-center relative h-full w-full rounded cursor-pointer"
|
className="flex items-center relative h-full w-full rounded cursor-pointer"
|
||||||
style={{ backgroundColor: data?.state_detail?.color }}
|
style={{ backgroundColor: data?.state_detail?.color }}
|
||||||
onClick={() => router.push(`/${workspaceSlug}/projects/${data?.project}/issues/${data?.id}`)}
|
onClick={openPeekOverview}
|
||||||
>
|
>
|
||||||
<div className="absolute top-0 left-0 h-full w-full bg-custom-background-100/50" />
|
<div className="absolute top-0 left-0 h-full w-full bg-custom-background-100/50" />
|
||||||
<Tooltip
|
<Tooltip
|
||||||
@ -43,14 +51,22 @@ export const IssueGanttBlock = ({ data }: { data: IIssue }) => {
|
|||||||
// rendering issues on gantt sidebar
|
// rendering issues on gantt sidebar
|
||||||
export const IssueGanttSidebarBlock = ({ data }: { data: IIssue }) => {
|
export const IssueGanttSidebarBlock = ({ data }: { data: IIssue }) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug } = router.query;
|
|
||||||
|
|
||||||
const duration = findTotalDaysInRange(data?.start_date ?? "", data?.target_date ?? "", true);
|
const duration = findTotalDaysInRange(data?.start_date ?? "", data?.target_date ?? "", true);
|
||||||
|
|
||||||
|
const openPeekOverview = () => {
|
||||||
|
const { query } = router;
|
||||||
|
|
||||||
|
router.push({
|
||||||
|
pathname: router.pathname,
|
||||||
|
query: { ...query, peekIssue: data.id },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="relative w-full flex items-center gap-2 h-full cursor-pointer"
|
className="relative w-full flex items-center gap-2 h-full cursor-pointer"
|
||||||
onClick={() => router.push(`/${workspaceSlug}/projects/${data?.project}/issues/${data?.id}`)}
|
onClick={openPeekOverview}
|
||||||
>
|
>
|
||||||
<StateGroupIcon stateGroup={data?.state_detail?.group} color={data?.state_detail?.color} />
|
<StateGroupIcon stateGroup={data?.state_detail?.group} color={data?.state_detail?.color} />
|
||||||
<div className="text-xs text-custom-text-300 flex-shrink-0">
|
<div className="text-xs text-custom-text-300 flex-shrink-0">
|
||||||
|
@ -8,11 +8,15 @@ import { updateGanttIssue } from "components/gantt-chart/hooks/block-update";
|
|||||||
import useProjectDetails from "hooks/use-project-details";
|
import useProjectDetails from "hooks/use-project-details";
|
||||||
// components
|
// components
|
||||||
import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
|
import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
|
||||||
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
import { IssueGanttBlock, IssueGanttSidebarBlock, IssuePeekOverview } from "components/issues";
|
||||||
// types
|
// types
|
||||||
import { IIssue } from "types";
|
import { IIssue } from "types";
|
||||||
|
|
||||||
export const IssueGanttChartView = () => {
|
type Props = {
|
||||||
|
disableUserActions: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const IssueGanttChartView: React.FC<Props> = ({ disableUserActions }) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId } = router.query;
|
const { workspaceSlug, projectId } = router.query;
|
||||||
|
|
||||||
@ -29,6 +33,13 @@ export const IssueGanttChartView = () => {
|
|||||||
const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
|
const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
<IssuePeekOverview
|
||||||
|
handleMutation={() => mutateGanttIssues()}
|
||||||
|
projectId={projectId?.toString() ?? ""}
|
||||||
|
workspaceSlug={workspaceSlug?.toString() ?? ""}
|
||||||
|
readOnly={disableUserActions}
|
||||||
|
/>
|
||||||
<div className="w-full h-full">
|
<div className="w-full h-full">
|
||||||
<GanttChartRoot
|
<GanttChartRoot
|
||||||
border={false}
|
border={false}
|
||||||
@ -47,5 +58,6 @@ export const IssueGanttChartView = () => {
|
|||||||
bottomSpacing
|
bottomSpacing
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -57,7 +57,7 @@ export const MyIssuesView: React.FC<Props> = ({
|
|||||||
const { user } = useUserAuth();
|
const { user } = useUserAuth();
|
||||||
|
|
||||||
const { groupedIssues, mutateMyIssues, isEmpty, params } = useMyIssues(workspaceSlug?.toString());
|
const { groupedIssues, mutateMyIssues, isEmpty, params } = useMyIssues(workspaceSlug?.toString());
|
||||||
const { filters, setFilters, displayFilters, setDisplayFilters, properties } = useMyIssuesFilters(
|
const { filters, setFilters, displayFilters, properties } = useMyIssuesFilters(
|
||||||
workspaceSlug?.toString()
|
workspaceSlug?.toString()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import { FC } from "react";
|
|
||||||
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
@ -10,13 +8,13 @@ import { updateGanttIssue } from "components/gantt-chart/hooks/block-update";
|
|||||||
import useProjectDetails from "hooks/use-project-details";
|
import useProjectDetails from "hooks/use-project-details";
|
||||||
// components
|
// components
|
||||||
import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
|
import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
|
||||||
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
import { IssueGanttBlock, IssueGanttSidebarBlock, IssuePeekOverview } from "components/issues";
|
||||||
// types
|
// types
|
||||||
import { IIssue } from "types";
|
import { IIssue } from "types";
|
||||||
|
|
||||||
type Props = {};
|
type Props = { disableUserActions: boolean };
|
||||||
|
|
||||||
export const ModuleIssuesGanttChartView: FC<Props> = ({}) => {
|
export const ModuleIssuesGanttChartView: React.FC<Props> = ({ disableUserActions }) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, moduleId } = router.query;
|
const { workspaceSlug, projectId, moduleId } = router.query;
|
||||||
|
|
||||||
@ -34,6 +32,13 @@ export const ModuleIssuesGanttChartView: FC<Props> = ({}) => {
|
|||||||
const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
|
const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
<IssuePeekOverview
|
||||||
|
handleMutation={() => mutateGanttIssues()}
|
||||||
|
projectId={projectId?.toString() ?? ""}
|
||||||
|
workspaceSlug={workspaceSlug?.toString() ?? ""}
|
||||||
|
readOnly={disableUserActions}
|
||||||
|
/>
|
||||||
<div className="w-full h-full">
|
<div className="w-full h-full">
|
||||||
<GanttChartRoot
|
<GanttChartRoot
|
||||||
border={false}
|
border={false}
|
||||||
@ -52,5 +57,6 @@ export const ModuleIssuesGanttChartView: FC<Props> = ({}) => {
|
|||||||
bottomSpacing
|
bottomSpacing
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import { FC } from "react";
|
|
||||||
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
@ -9,13 +7,13 @@ import { updateGanttIssue } from "components/gantt-chart/hooks/block-update";
|
|||||||
import useProjectDetails from "hooks/use-project-details";
|
import useProjectDetails from "hooks/use-project-details";
|
||||||
// components
|
// components
|
||||||
import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
|
import { GanttChartRoot, renderIssueBlocksStructure } from "components/gantt-chart";
|
||||||
import { IssueGanttBlock, IssueGanttSidebarBlock } from "components/issues";
|
import { IssueGanttBlock, IssueGanttSidebarBlock, IssuePeekOverview } from "components/issues";
|
||||||
// types
|
// types
|
||||||
import { IIssue } from "types";
|
import { IIssue } from "types";
|
||||||
|
|
||||||
type Props = {};
|
type Props = { disableUserActions: boolean };
|
||||||
|
|
||||||
export const ViewIssuesGanttChartView: FC<Props> = ({}) => {
|
export const ViewIssuesGanttChartView: React.FC<Props> = ({ disableUserActions }) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, viewId } = router.query;
|
const { workspaceSlug, projectId, viewId } = router.query;
|
||||||
|
|
||||||
@ -31,6 +29,13 @@ export const ViewIssuesGanttChartView: FC<Props> = ({}) => {
|
|||||||
const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
|
const isAllowed = projectDetails?.member_role === 20 || projectDetails?.member_role === 15;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
<IssuePeekOverview
|
||||||
|
handleMutation={() => mutateGanttIssues()}
|
||||||
|
projectId={projectId?.toString() ?? ""}
|
||||||
|
workspaceSlug={workspaceSlug?.toString() ?? ""}
|
||||||
|
readOnly={disableUserActions}
|
||||||
|
/>
|
||||||
<div className="w-full h-full">
|
<div className="w-full h-full">
|
||||||
<GanttChartRoot
|
<GanttChartRoot
|
||||||
border={false}
|
border={false}
|
||||||
@ -48,5 +53,6 @@ export const ViewIssuesGanttChartView: FC<Props> = ({}) => {
|
|||||||
enableReorder={isAllowed}
|
enableReorder={isAllowed}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -44,7 +44,7 @@ const useCalendarIssuesView = () => {
|
|||||||
target_date: displayFilters?.calendar_date_range,
|
target_date: displayFilters?.calendar_date_range,
|
||||||
};
|
};
|
||||||
|
|
||||||
const { data: projectCalendarIssues } = useSWR(
|
const { data: projectCalendarIssues, mutate: mutateProjectCalendarIssues } = useSWR(
|
||||||
workspaceSlug && projectId
|
workspaceSlug && projectId
|
||||||
? PROJECT_ISSUES_LIST_WITH_PARAMS(projectId.toString(), params)
|
? PROJECT_ISSUES_LIST_WITH_PARAMS(projectId.toString(), params)
|
||||||
: null,
|
: null,
|
||||||
@ -54,7 +54,7 @@ const useCalendarIssuesView = () => {
|
|||||||
: null
|
: null
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data: cycleCalendarIssues } = useSWR(
|
const { data: cycleCalendarIssues, mutate: mutateCycleCalendarIssues } = useSWR(
|
||||||
workspaceSlug && projectId && cycleId
|
workspaceSlug && projectId && cycleId
|
||||||
? CYCLE_ISSUES_WITH_PARAMS(cycleId.toString(), params)
|
? CYCLE_ISSUES_WITH_PARAMS(cycleId.toString(), params)
|
||||||
: null,
|
: null,
|
||||||
@ -69,7 +69,7 @@ const useCalendarIssuesView = () => {
|
|||||||
: null
|
: null
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data: moduleCalendarIssues } = useSWR(
|
const { data: moduleCalendarIssues, mutate: mutateModuleCalendarIssues } = useSWR(
|
||||||
workspaceSlug && projectId && moduleId
|
workspaceSlug && projectId && moduleId
|
||||||
? MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), params)
|
? MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), params)
|
||||||
: null,
|
: null,
|
||||||
@ -84,7 +84,7 @@ const useCalendarIssuesView = () => {
|
|||||||
: null
|
: null
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data: viewCalendarIssues } = useSWR(
|
const { data: viewCalendarIssues, mutate: mutateViewCalendarIssues } = useSWR(
|
||||||
workspaceSlug && projectId && viewId && params ? VIEW_ISSUES(viewId.toString(), params) : null,
|
workspaceSlug && projectId && viewId && params ? VIEW_ISSUES(viewId.toString(), params) : null,
|
||||||
workspaceSlug && projectId && viewId && params
|
workspaceSlug && projectId && viewId && params
|
||||||
? () =>
|
? () =>
|
||||||
@ -104,6 +104,13 @@ const useCalendarIssuesView = () => {
|
|||||||
displayFilters,
|
displayFilters,
|
||||||
setDisplayFilters,
|
setDisplayFilters,
|
||||||
calendarIssues: calendarIssues ?? [],
|
calendarIssues: calendarIssues ?? [],
|
||||||
|
mutateIssues: cycleId
|
||||||
|
? mutateCycleCalendarIssues
|
||||||
|
: moduleId
|
||||||
|
? mutateModuleCalendarIssues
|
||||||
|
: viewId
|
||||||
|
? mutateViewCalendarIssues
|
||||||
|
: mutateProjectCalendarIssues,
|
||||||
filters,
|
filters,
|
||||||
setFilters,
|
setFilters,
|
||||||
params,
|
params,
|
||||||
|
Loading…
Reference in New Issue
Block a user