forked from github/plane
chore: issue action added and code refactor
This commit is contained in:
parent
3b8a8cdfa4
commit
06722408b8
@ -20,6 +20,7 @@ import {
|
||||
// hooks
|
||||
import useSpreadsheetIssuesView from "hooks/use-spreadsheet-issues-view";
|
||||
import useToast from "hooks/use-toast";
|
||||
import useWorkspaceIssuesFilters from "hooks/use-worskpace-issue-filter";
|
||||
// services
|
||||
import issuesService from "services/issues.service";
|
||||
import trackEventServices from "services/track-event.service";
|
||||
@ -32,6 +33,7 @@ import {
|
||||
PROJECT_ISSUES_LIST_WITH_PARAMS,
|
||||
SUB_ISSUES,
|
||||
VIEW_ISSUES,
|
||||
WORKSPACE_VIEW_ISSUES,
|
||||
} from "constants/fetch-keys";
|
||||
// types
|
||||
import {
|
||||
@ -82,12 +84,51 @@ export const SingleSpreadsheetIssue: React.FC<Props> = ({
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const { workspaceSlug, cycleId, moduleId, viewId } = router.query;
|
||||
const { workspaceSlug, cycleId, moduleId, viewId, workspaceViewId } = router.query;
|
||||
|
||||
const { params } = useSpreadsheetIssuesView();
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const workspaceIssuesPath = [
|
||||
{
|
||||
params: {
|
||||
sub_issue: false,
|
||||
},
|
||||
path: "workspace-views/all-issues",
|
||||
},
|
||||
{
|
||||
params: {
|
||||
assignees: user?.id ?? undefined,
|
||||
sub_issue: false,
|
||||
},
|
||||
path: "workspace-views/assigned",
|
||||
},
|
||||
{
|
||||
params: {
|
||||
created_by: user?.id ?? undefined,
|
||||
sub_issue: false,
|
||||
},
|
||||
path: "workspace-views/created",
|
||||
},
|
||||
{
|
||||
params: {
|
||||
subscriber: user?.id ?? undefined,
|
||||
sub_issue: false,
|
||||
},
|
||||
path: "workspace-views/subscribed",
|
||||
},
|
||||
];
|
||||
|
||||
const currentWorkspaceIssuePath = workspaceIssuesPath.find((path) =>
|
||||
router.pathname.includes(path.path)
|
||||
);
|
||||
|
||||
const { params: workspaceViewParams } = useWorkspaceIssuesFilters(
|
||||
workspaceSlug?.toString(),
|
||||
workspaceViewId?.toString()
|
||||
);
|
||||
|
||||
const partialUpdateIssue = useCallback(
|
||||
(formData: Partial<IIssue>, issue: IIssue) => {
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
@ -98,6 +139,10 @@ export const SingleSpreadsheetIssue: React.FC<Props> = ({
|
||||
? MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), params)
|
||||
: viewId
|
||||
? VIEW_ISSUES(viewId.toString(), params)
|
||||
: workspaceViewId
|
||||
? WORKSPACE_VIEW_ISSUES(workspaceSlug.toString(), workspaceViewParams)
|
||||
: currentWorkspaceIssuePath
|
||||
? WORKSPACE_VIEW_ISSUES(workspaceSlug.toString(), currentWorkspaceIssuePath?.params)
|
||||
: PROJECT_ISSUES_LIST_WITH_PARAMS(projectId, params);
|
||||
|
||||
if (issue.parent)
|
||||
@ -153,7 +198,18 @@ export const SingleSpreadsheetIssue: React.FC<Props> = ({
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
[workspaceSlug, projectId, cycleId, moduleId, viewId, params, user]
|
||||
[
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
cycleId,
|
||||
moduleId,
|
||||
viewId,
|
||||
workspaceViewId,
|
||||
currentWorkspaceIssuePath,
|
||||
workspaceViewParams,
|
||||
params,
|
||||
user,
|
||||
]
|
||||
);
|
||||
|
||||
const openPeekOverview = () => {
|
||||
|
@ -9,6 +9,7 @@ import { ICurrentUserResponse, IIssue, Properties, UserAuth } from "types";
|
||||
|
||||
type Props = {
|
||||
issue: IIssue;
|
||||
projectId: string;
|
||||
index: number;
|
||||
expandedIssues: string[];
|
||||
setExpandedIssues: React.Dispatch<React.SetStateAction<string[]>>;
|
||||
@ -24,6 +25,7 @@ type Props = {
|
||||
export const SpreadsheetIssues: React.FC<Props> = ({
|
||||
index,
|
||||
issue,
|
||||
projectId,
|
||||
expandedIssues,
|
||||
setExpandedIssues,
|
||||
gridTemplateColumns,
|
||||
@ -55,7 +57,7 @@ export const SpreadsheetIssues: React.FC<Props> = ({
|
||||
<div>
|
||||
<SingleSpreadsheetIssue
|
||||
issue={issue}
|
||||
projectId={issue.project_detail.id}
|
||||
projectId={projectId}
|
||||
index={index}
|
||||
expanded={isExpanded}
|
||||
handleToggleExpand={handleToggleExpand}
|
||||
@ -77,6 +79,7 @@ export const SpreadsheetIssues: React.FC<Props> = ({
|
||||
<SpreadsheetIssues
|
||||
key={subIssue.id}
|
||||
issue={subIssue}
|
||||
projectId={subIssue.project_detail.id}
|
||||
index={index}
|
||||
expandedIssues={expandedIssues}
|
||||
setExpandedIssues={setExpandedIssues}
|
||||
|
@ -86,6 +86,7 @@ export const SpreadsheetView: React.FC<Props> = ({
|
||||
key={`${issue.id}_${index}`}
|
||||
index={index}
|
||||
issue={issue}
|
||||
projectId={issue.project_detail.id}
|
||||
expandedIssues={expandedIssues}
|
||||
setExpandedIssues={setExpandedIssues}
|
||||
gridTemplateColumns={gridTemplateColumns}
|
||||
|
@ -161,6 +161,7 @@ export const IssueProperty: React.FC<IIssueProperty> = ({
|
||||
<div className="flex-shrink-0">
|
||||
<StateSelect
|
||||
value={issue.state_detail}
|
||||
projectId={issue.project_detail.id}
|
||||
onChange={handleStateChange}
|
||||
hideDropdownArrow
|
||||
disabled={!editable}
|
||||
@ -194,6 +195,7 @@ export const IssueProperty: React.FC<IIssueProperty> = ({
|
||||
<div className="flex-shrink-0">
|
||||
<MembersSelect
|
||||
value={issue.assignees}
|
||||
projectId={issue.project_detail.id}
|
||||
onChange={handleAssigneeChange}
|
||||
membersDetails={issue.assignee_details}
|
||||
hideDropdownArrow
|
||||
|
@ -17,7 +17,6 @@ import { DangerButton, SecondaryButton } from "components/ui";
|
||||
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
|
||||
// types
|
||||
import type { ICurrentUserResponse, IView } from "types";
|
||||
import { IWorkspaceView } from "types/workspace-view";
|
||||
// fetch-keys
|
||||
import { VIEWS_LIST, WORKSPACE_VIEWS_LIST } from "constants/fetch-keys";
|
||||
|
||||
@ -25,7 +24,7 @@ type Props = {
|
||||
isOpen: boolean;
|
||||
viewType: "project" | "workspace";
|
||||
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
data: IView | IWorkspaceView | null;
|
||||
data: IView | null;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
};
|
||||
|
||||
|
@ -12,7 +12,6 @@ import { CustomMenu } from "components/ui";
|
||||
import viewsService from "services/views.service";
|
||||
// types
|
||||
import { IView } from "types";
|
||||
import { IWorkspaceView } from "types/workspace-view";
|
||||
// fetch keys
|
||||
import { VIEWS_LIST } from "constants/fetch-keys";
|
||||
// hooks
|
||||
@ -21,7 +20,7 @@ import useToast from "hooks/use-toast";
|
||||
import { truncateText } from "helpers/string.helper";
|
||||
|
||||
type Props = {
|
||||
view: IView | IWorkspaceView;
|
||||
view: IView;
|
||||
viewType: "project" | "workspace";
|
||||
handleEditView: () => void;
|
||||
handleDeleteView: () => void;
|
||||
|
@ -159,7 +159,7 @@ export const WORKSPACE_VIEWS_LIST = (workspaceSlug: string) =>
|
||||
`WORKSPACE_VIEWS_LIST_${workspaceSlug.toUpperCase()}`;
|
||||
export const WORKSPACE_VIEW_DETAILS = (workspaceViewId: string) =>
|
||||
`WORKSPACE_VIEW_DETAILS_${workspaceViewId.toUpperCase()}`;
|
||||
export const WORKSPACE_VIEW_ISSUES = (workspaceViewId: string, params: any) => {
|
||||
export const WORKSPACE_VIEW_ISSUES = (workspaceViewId: string, params?: any) => {
|
||||
if (!params) return `WORKSPACE_VIEW_ISSUES_${workspaceViewId.toUpperCase()}`;
|
||||
|
||||
const paramsKey = paramsToKey(params);
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { useCallback, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
import useSWR from "swr";
|
||||
@ -9,12 +10,12 @@ import useMyIssuesFilters from "hooks/my-issues/use-my-issues-filter";
|
||||
import workspaceService from "services/workspace.service";
|
||||
// layouts
|
||||
import { WorkspaceAuthorizationLayout } from "layouts/auth-layout";
|
||||
// contexts
|
||||
import { IssueViewContextProvider } from "contexts/issue-view.context";
|
||||
// components
|
||||
import { SpreadsheetView } from "components/core";
|
||||
import { WorkspaceViewsNavigation } from "components/workspace/views/workpace-view-navigation";
|
||||
import { WorkspaceIssuesViewOptions } from "components/issues/workspace-views/workspace-issue-view-option";
|
||||
import { CreateUpdateViewModal } from "components/views";
|
||||
import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues";
|
||||
// ui
|
||||
import { EmptyState, PrimaryButton } from "components/ui";
|
||||
// icons
|
||||
@ -24,8 +25,28 @@ import { CheckCircle } from "lucide-react";
|
||||
import emptyView from "public/empty-state/view.svg";
|
||||
// fetch-keys
|
||||
import { WORKSPACE_VIEW_DETAILS, WORKSPACE_VIEW_ISSUES } from "constants/fetch-keys";
|
||||
// types
|
||||
import { IIssue } from "types";
|
||||
|
||||
const WorkspaceViewAllIssue: React.FC = () => {
|
||||
const [createViewModal, setCreateViewModal] = useState<any>(null);
|
||||
|
||||
// create issue modal
|
||||
const [createIssueModal, setCreateIssueModal] = useState(false);
|
||||
const [preloadedData, setPreloadedData] = useState<
|
||||
(Partial<IIssue> & { actionType: "createIssue" | "edit" | "delete" }) | undefined
|
||||
>(undefined);
|
||||
|
||||
// update issue modal
|
||||
const [editIssueModal, setEditIssueModal] = useState(false);
|
||||
const [issueToEdit, setIssueToEdit] = useState<
|
||||
(IIssue & { actionType: "edit" | "delete" }) | undefined
|
||||
>(undefined);
|
||||
|
||||
// delete issue modal
|
||||
const [deleteIssueModal, setDeleteIssueModal] = useState(false);
|
||||
const [issueToDelete, setIssueToDelete] = useState<IIssue | null>(null);
|
||||
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, workspaceViewId } = router.query;
|
||||
|
||||
@ -58,67 +79,138 @@ const WorkspaceViewAllIssue: React.FC = () => {
|
||||
workspaceSlug ? () => workspaceService.getViewIssues(workspaceSlug.toString(), params) : null
|
||||
);
|
||||
|
||||
const makeIssueCopy = useCallback(
|
||||
(issue: IIssue) => {
|
||||
setCreateIssueModal(true);
|
||||
|
||||
setPreloadedData({ ...issue, name: `${issue.name} (Copy)`, actionType: "createIssue" });
|
||||
},
|
||||
[setCreateIssueModal, setPreloadedData]
|
||||
);
|
||||
|
||||
const handleEditIssue = useCallback(
|
||||
(issue: IIssue) => {
|
||||
setEditIssueModal(true);
|
||||
setIssueToEdit({
|
||||
...issue,
|
||||
actionType: "edit",
|
||||
cycle: issue.issue_cycle ? issue.issue_cycle.cycle : null,
|
||||
module: issue.issue_module ? issue.issue_module.module : null,
|
||||
});
|
||||
},
|
||||
[setEditIssueModal, setIssueToEdit]
|
||||
);
|
||||
|
||||
const handleDeleteIssue = useCallback(
|
||||
(issue: IIssue) => {
|
||||
setDeleteIssueModal(true);
|
||||
setIssueToDelete(issue);
|
||||
},
|
||||
[setDeleteIssueModal, setIssueToDelete]
|
||||
);
|
||||
|
||||
const handleIssueAction = useCallback(
|
||||
(issue: IIssue, action: "copy" | "edit" | "delete" | "updateDraft") => {
|
||||
if (action === "copy") makeIssueCopy(issue);
|
||||
else if (action === "edit") handleEditIssue(issue);
|
||||
else if (action === "delete") handleDeleteIssue(issue);
|
||||
},
|
||||
[makeIssueCopy, handleEditIssue, handleDeleteIssue]
|
||||
);
|
||||
|
||||
return (
|
||||
<IssueViewContextProvider>
|
||||
<WorkspaceAuthorizationLayout
|
||||
breadcrumbs={
|
||||
<div className="flex gap-2 items-center">
|
||||
<CheckCircle className="h-[18px] w-[18px] stroke-[1.5]" />
|
||||
<span className="text-sm font-medium">
|
||||
{viewDetails ? `${viewDetails.name} Issues` : "Workspace Issues"}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
right={
|
||||
<div className="flex items-center gap-2">
|
||||
<WorkspaceIssuesViewOptions />
|
||||
<PrimaryButton
|
||||
className="flex items-center gap-2"
|
||||
onClick={() => {
|
||||
const e = new KeyboardEvent("keydown", { key: "c" });
|
||||
document.dispatchEvent(e);
|
||||
<WorkspaceAuthorizationLayout
|
||||
breadcrumbs={
|
||||
<div className="flex gap-2 items-center">
|
||||
<CheckCircle className="h-[18px] w-[18px] stroke-[1.5]" />
|
||||
<span className="text-sm font-medium">
|
||||
{viewDetails ? `${viewDetails.name} Issues` : "Workspace Issues"}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
right={
|
||||
<div className="flex items-center gap-2">
|
||||
<WorkspaceIssuesViewOptions />
|
||||
<PrimaryButton
|
||||
className="flex items-center gap-2"
|
||||
onClick={() => {
|
||||
const e = new KeyboardEvent("keydown", { key: "c" });
|
||||
document.dispatchEvent(e);
|
||||
}}
|
||||
>
|
||||
<PlusIcon className="h-4 w-4" />
|
||||
Add Issue
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<CreateUpdateIssueModal
|
||||
isOpen={createIssueModal && preloadedData?.actionType === "createIssue"}
|
||||
handleClose={() => setCreateIssueModal(false)}
|
||||
prePopulateData={{
|
||||
...preloadedData,
|
||||
}}
|
||||
onSubmit={async () => {
|
||||
mutateIssues();
|
||||
}}
|
||||
/>
|
||||
<CreateUpdateIssueModal
|
||||
isOpen={editIssueModal && issueToEdit?.actionType !== "delete"}
|
||||
handleClose={() => setEditIssueModal(false)}
|
||||
data={issueToEdit}
|
||||
onSubmit={async () => {
|
||||
mutateIssues();
|
||||
}}
|
||||
/>
|
||||
<DeleteIssueModal
|
||||
handleClose={() => setDeleteIssueModal(false)}
|
||||
isOpen={deleteIssueModal}
|
||||
data={issueToDelete}
|
||||
user={user}
|
||||
onSubmit={async () => {
|
||||
mutateIssues();
|
||||
}}
|
||||
/>
|
||||
<CreateUpdateViewModal
|
||||
isOpen={createViewModal !== null}
|
||||
handleClose={() => setCreateViewModal(null)}
|
||||
viewType="workspace"
|
||||
preLoadedData={createViewModal}
|
||||
user={user}
|
||||
/>
|
||||
<div className="h-full flex flex-col overflow-hidden bg-custom-background-100">
|
||||
<div className="h-full w-full border-b border-custom-border-300">
|
||||
<WorkspaceViewsNavigation handleAddView={() => setCreateViewModal(true)} />
|
||||
{error ? (
|
||||
<EmptyState
|
||||
image={emptyView}
|
||||
title="View does not exist"
|
||||
description="The view you are looking for does not exist or has been deleted."
|
||||
primaryButton={{
|
||||
text: "View other views",
|
||||
onClick: () => router.push(`/${workspaceSlug}/workspace-views`),
|
||||
}}
|
||||
>
|
||||
<PlusIcon className="h-4 w-4" />
|
||||
Add Issue
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className="h-full flex flex-col overflow-hidden bg-custom-background-100">
|
||||
<div className="h-full w-full border-b border-custom-border-300">
|
||||
<WorkspaceViewsNavigation user={user} />
|
||||
{error ? (
|
||||
<EmptyState
|
||||
image={emptyView}
|
||||
title="View does not exist"
|
||||
description="The view you are looking for does not exist or has been deleted."
|
||||
primaryButton={{
|
||||
text: "View other views",
|
||||
onClick: () => router.push(`/${workspaceSlug}/workspace-views`),
|
||||
/>
|
||||
) : (
|
||||
<div className="h-full w-full flex flex-col">
|
||||
<SpreadsheetView
|
||||
spreadsheetIssues={viewIssues}
|
||||
mutateIssues={mutateIssues}
|
||||
handleIssueAction={handleIssueAction}
|
||||
disableUserActions={false}
|
||||
user={user}
|
||||
userAuth={{
|
||||
isGuest: false,
|
||||
isMember: false,
|
||||
isOwner: false,
|
||||
isViewer: false,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div className="h-full w-full flex flex-col">
|
||||
<SpreadsheetView
|
||||
spreadsheetIssues={viewIssues}
|
||||
mutateIssues={mutateIssues}
|
||||
handleIssueAction={(...args) => {}}
|
||||
disableUserActions={false}
|
||||
user={user}
|
||||
userAuth={{
|
||||
isGuest: false,
|
||||
isMember: false,
|
||||
isOwner: false,
|
||||
isViewer: false,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</WorkspaceAuthorizationLayout>
|
||||
</IssueViewContextProvider>
|
||||
</div>
|
||||
</WorkspaceAuthorizationLayout>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { useCallback, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
import useSWR from "swr";
|
||||
@ -9,12 +10,12 @@ import useMyIssuesFilters from "hooks/my-issues/use-my-issues-filter";
|
||||
import workspaceService from "services/workspace.service";
|
||||
// layouts
|
||||
import { WorkspaceAuthorizationLayout } from "layouts/auth-layout";
|
||||
// contexts
|
||||
import { IssueViewContextProvider } from "contexts/issue-view.context";
|
||||
// components
|
||||
import { SpreadsheetView } from "components/core";
|
||||
import { WorkspaceViewsNavigation } from "components/workspace/views/workpace-view-navigation";
|
||||
import { WorkspaceIssuesViewOptions } from "components/issues/workspace-views/workspace-issue-view-option";
|
||||
import { CreateUpdateViewModal } from "components/views";
|
||||
import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues";
|
||||
// ui
|
||||
import { EmptyState, PrimaryButton } from "components/ui";
|
||||
// icons
|
||||
@ -24,8 +25,28 @@ import { CheckCircle } from "lucide-react";
|
||||
import emptyView from "public/empty-state/view.svg";
|
||||
// fetch-keys
|
||||
import { WORKSPACE_VIEW_DETAILS, WORKSPACE_VIEW_ISSUES } from "constants/fetch-keys";
|
||||
// types
|
||||
import { IIssue } from "types";
|
||||
|
||||
const WorkspaceViewAssignedIssue: React.FC = () => {
|
||||
const [createViewModal, setCreateViewModal] = useState<any>(null);
|
||||
|
||||
// create issue modal
|
||||
const [createIssueModal, setCreateIssueModal] = useState(false);
|
||||
const [preloadedData, setPreloadedData] = useState<
|
||||
(Partial<IIssue> & { actionType: "createIssue" | "edit" | "delete" }) | undefined
|
||||
>(undefined);
|
||||
|
||||
// update issue modal
|
||||
const [editIssueModal, setEditIssueModal] = useState(false);
|
||||
const [issueToEdit, setIssueToEdit] = useState<
|
||||
(IIssue & { actionType: "edit" | "delete" }) | undefined
|
||||
>(undefined);
|
||||
|
||||
// delete issue modal
|
||||
const [deleteIssueModal, setDeleteIssueModal] = useState(false);
|
||||
const [issueToDelete, setIssueToDelete] = useState<IIssue | null>(null);
|
||||
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, workspaceViewId } = router.query;
|
||||
|
||||
@ -58,67 +79,138 @@ const WorkspaceViewAssignedIssue: React.FC = () => {
|
||||
workspaceSlug ? () => workspaceService.getViewIssues(workspaceSlug.toString(), params) : null
|
||||
);
|
||||
|
||||
const makeIssueCopy = useCallback(
|
||||
(issue: IIssue) => {
|
||||
setCreateIssueModal(true);
|
||||
|
||||
setPreloadedData({ ...issue, name: `${issue.name} (Copy)`, actionType: "createIssue" });
|
||||
},
|
||||
[setCreateIssueModal, setPreloadedData]
|
||||
);
|
||||
|
||||
const handleEditIssue = useCallback(
|
||||
(issue: IIssue) => {
|
||||
setEditIssueModal(true);
|
||||
setIssueToEdit({
|
||||
...issue,
|
||||
actionType: "edit",
|
||||
cycle: issue.issue_cycle ? issue.issue_cycle.cycle : null,
|
||||
module: issue.issue_module ? issue.issue_module.module : null,
|
||||
});
|
||||
},
|
||||
[setEditIssueModal, setIssueToEdit]
|
||||
);
|
||||
|
||||
const handleDeleteIssue = useCallback(
|
||||
(issue: IIssue) => {
|
||||
setDeleteIssueModal(true);
|
||||
setIssueToDelete(issue);
|
||||
},
|
||||
[setDeleteIssueModal, setIssueToDelete]
|
||||
);
|
||||
|
||||
const handleIssueAction = useCallback(
|
||||
(issue: IIssue, action: "copy" | "edit" | "delete" | "updateDraft") => {
|
||||
if (action === "copy") makeIssueCopy(issue);
|
||||
else if (action === "edit") handleEditIssue(issue);
|
||||
else if (action === "delete") handleDeleteIssue(issue);
|
||||
},
|
||||
[makeIssueCopy, handleEditIssue, handleDeleteIssue]
|
||||
);
|
||||
|
||||
return (
|
||||
<IssueViewContextProvider>
|
||||
<WorkspaceAuthorizationLayout
|
||||
breadcrumbs={
|
||||
<div className="flex gap-2 items-center">
|
||||
<CheckCircle className="h-[18px] w-[18px] stroke-[1.5]" />
|
||||
<span className="text-sm font-medium">
|
||||
{viewDetails ? `${viewDetails.name} Issues` : "Workspace Issues"}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
right={
|
||||
<div className="flex items-center gap-2">
|
||||
<WorkspaceIssuesViewOptions />
|
||||
<PrimaryButton
|
||||
className="flex items-center gap-2"
|
||||
onClick={() => {
|
||||
const e = new KeyboardEvent("keydown", { key: "c" });
|
||||
document.dispatchEvent(e);
|
||||
<WorkspaceAuthorizationLayout
|
||||
breadcrumbs={
|
||||
<div className="flex gap-2 items-center">
|
||||
<CheckCircle className="h-[18px] w-[18px] stroke-[1.5]" />
|
||||
<span className="text-sm font-medium">
|
||||
{viewDetails ? `${viewDetails.name} Issues` : "Workspace Issues"}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
right={
|
||||
<div className="flex items-center gap-2">
|
||||
<WorkspaceIssuesViewOptions />
|
||||
<PrimaryButton
|
||||
className="flex items-center gap-2"
|
||||
onClick={() => {
|
||||
const e = new KeyboardEvent("keydown", { key: "c" });
|
||||
document.dispatchEvent(e);
|
||||
}}
|
||||
>
|
||||
<PlusIcon className="h-4 w-4" />
|
||||
Add Issue
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<CreateUpdateIssueModal
|
||||
isOpen={createIssueModal && preloadedData?.actionType === "createIssue"}
|
||||
handleClose={() => setCreateIssueModal(false)}
|
||||
prePopulateData={{
|
||||
...preloadedData,
|
||||
}}
|
||||
onSubmit={async () => {
|
||||
mutateIssues();
|
||||
}}
|
||||
/>
|
||||
<CreateUpdateIssueModal
|
||||
isOpen={editIssueModal && issueToEdit?.actionType !== "delete"}
|
||||
handleClose={() => setEditIssueModal(false)}
|
||||
data={issueToEdit}
|
||||
onSubmit={async () => {
|
||||
mutateIssues();
|
||||
}}
|
||||
/>
|
||||
<DeleteIssueModal
|
||||
handleClose={() => setDeleteIssueModal(false)}
|
||||
isOpen={deleteIssueModal}
|
||||
data={issueToDelete}
|
||||
user={user}
|
||||
onSubmit={async () => {
|
||||
mutateIssues();
|
||||
}}
|
||||
/>
|
||||
<CreateUpdateViewModal
|
||||
isOpen={createViewModal !== null}
|
||||
handleClose={() => setCreateViewModal(null)}
|
||||
viewType="workspace"
|
||||
preLoadedData={createViewModal}
|
||||
user={user}
|
||||
/>
|
||||
<div className="h-full flex flex-col overflow-hidden bg-custom-background-100">
|
||||
<div className="h-full w-full border-b border-custom-border-300">
|
||||
<WorkspaceViewsNavigation handleAddView={() => setCreateViewModal(true)} />
|
||||
{error ? (
|
||||
<EmptyState
|
||||
image={emptyView}
|
||||
title="View does not exist"
|
||||
description="The view you are looking for does not exist or has been deleted."
|
||||
primaryButton={{
|
||||
text: "View other views",
|
||||
onClick: () => router.push(`/${workspaceSlug}/workspace-views`),
|
||||
}}
|
||||
>
|
||||
<PlusIcon className="h-4 w-4" />
|
||||
Add Issue
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className="h-full flex flex-col overflow-hidden bg-custom-background-100">
|
||||
<div className="h-full w-full border-b border-custom-border-300">
|
||||
<WorkspaceViewsNavigation user={user} />
|
||||
{error ? (
|
||||
<EmptyState
|
||||
image={emptyView}
|
||||
title="View does not exist"
|
||||
description="The view you are looking for does not exist or has been deleted."
|
||||
primaryButton={{
|
||||
text: "View other views",
|
||||
onClick: () => router.push(`/${workspaceSlug}/workspace-views`),
|
||||
/>
|
||||
) : (
|
||||
<div className="h-full w-full flex flex-col">
|
||||
<SpreadsheetView
|
||||
spreadsheetIssues={viewIssues}
|
||||
mutateIssues={mutateIssues}
|
||||
handleIssueAction={handleIssueAction}
|
||||
disableUserActions={false}
|
||||
user={user}
|
||||
userAuth={{
|
||||
isGuest: false,
|
||||
isMember: false,
|
||||
isOwner: false,
|
||||
isViewer: false,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div className="h-full w-full flex flex-col">
|
||||
<SpreadsheetView
|
||||
spreadsheetIssues={viewIssues}
|
||||
mutateIssues={mutateIssues}
|
||||
handleIssueAction={(...args) => {}}
|
||||
disableUserActions={false}
|
||||
user={user}
|
||||
userAuth={{
|
||||
isGuest: false,
|
||||
isMember: false,
|
||||
isOwner: false,
|
||||
isViewer: false,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</WorkspaceAuthorizationLayout>
|
||||
</IssueViewContextProvider>
|
||||
</div>
|
||||
</WorkspaceAuthorizationLayout>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { useCallback, useState } from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
import useSWR from "swr";
|
||||
@ -9,12 +11,12 @@ import useMyIssuesFilters from "hooks/my-issues/use-my-issues-filter";
|
||||
import workspaceService from "services/workspace.service";
|
||||
// layouts
|
||||
import { WorkspaceAuthorizationLayout } from "layouts/auth-layout";
|
||||
// contexts
|
||||
import { IssueViewContextProvider } from "contexts/issue-view.context";
|
||||
// components
|
||||
import { SpreadsheetView } from "components/core";
|
||||
import { WorkspaceViewsNavigation } from "components/workspace/views/workpace-view-navigation";
|
||||
import { WorkspaceIssuesViewOptions } from "components/issues/workspace-views/workspace-issue-view-option";
|
||||
import { CreateUpdateViewModal } from "components/views";
|
||||
import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues";
|
||||
// ui
|
||||
import { EmptyState, PrimaryButton } from "components/ui";
|
||||
// icons
|
||||
@ -24,8 +26,28 @@ import { CheckCircle } from "lucide-react";
|
||||
import emptyView from "public/empty-state/view.svg";
|
||||
// fetch-keys
|
||||
import { WORKSPACE_VIEW_DETAILS, WORKSPACE_VIEW_ISSUES } from "constants/fetch-keys";
|
||||
// types
|
||||
import { IIssue } from "types";
|
||||
|
||||
const WorkspaceViewCreatedIssue: React.FC = () => {
|
||||
const [createViewModal, setCreateViewModal] = useState<any>(null);
|
||||
|
||||
// create issue modal
|
||||
const [createIssueModal, setCreateIssueModal] = useState(false);
|
||||
const [preloadedData, setPreloadedData] = useState<
|
||||
(Partial<IIssue> & { actionType: "createIssue" | "edit" | "delete" }) | undefined
|
||||
>(undefined);
|
||||
|
||||
// update issue modal
|
||||
const [editIssueModal, setEditIssueModal] = useState(false);
|
||||
const [issueToEdit, setIssueToEdit] = useState<
|
||||
(IIssue & { actionType: "edit" | "delete" }) | undefined
|
||||
>(undefined);
|
||||
|
||||
// delete issue modal
|
||||
const [deleteIssueModal, setDeleteIssueModal] = useState(false);
|
||||
const [issueToDelete, setIssueToDelete] = useState<IIssue | null>(null);
|
||||
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, workspaceViewId } = router.query;
|
||||
|
||||
@ -58,67 +80,138 @@ const WorkspaceViewCreatedIssue: React.FC = () => {
|
||||
workspaceSlug ? () => workspaceService.getViewIssues(workspaceSlug.toString(), params) : null
|
||||
);
|
||||
|
||||
const makeIssueCopy = useCallback(
|
||||
(issue: IIssue) => {
|
||||
setCreateIssueModal(true);
|
||||
|
||||
setPreloadedData({ ...issue, name: `${issue.name} (Copy)`, actionType: "createIssue" });
|
||||
},
|
||||
[setCreateIssueModal, setPreloadedData]
|
||||
);
|
||||
|
||||
const handleEditIssue = useCallback(
|
||||
(issue: IIssue) => {
|
||||
setEditIssueModal(true);
|
||||
setIssueToEdit({
|
||||
...issue,
|
||||
actionType: "edit",
|
||||
cycle: issue.issue_cycle ? issue.issue_cycle.cycle : null,
|
||||
module: issue.issue_module ? issue.issue_module.module : null,
|
||||
});
|
||||
},
|
||||
[setEditIssueModal, setIssueToEdit]
|
||||
);
|
||||
|
||||
const handleDeleteIssue = useCallback(
|
||||
(issue: IIssue) => {
|
||||
setDeleteIssueModal(true);
|
||||
setIssueToDelete(issue);
|
||||
},
|
||||
[setDeleteIssueModal, setIssueToDelete]
|
||||
);
|
||||
|
||||
const handleIssueAction = useCallback(
|
||||
(issue: IIssue, action: "copy" | "edit" | "delete" | "updateDraft") => {
|
||||
if (action === "copy") makeIssueCopy(issue);
|
||||
else if (action === "edit") handleEditIssue(issue);
|
||||
else if (action === "delete") handleDeleteIssue(issue);
|
||||
},
|
||||
[makeIssueCopy, handleEditIssue, handleDeleteIssue]
|
||||
);
|
||||
|
||||
return (
|
||||
<IssueViewContextProvider>
|
||||
<WorkspaceAuthorizationLayout
|
||||
breadcrumbs={
|
||||
<div className="flex gap-2 items-center">
|
||||
<CheckCircle className="h-[18px] w-[18px] stroke-[1.5]" />
|
||||
<span className="text-sm font-medium">
|
||||
{viewDetails ? `${viewDetails.name} Issues` : "Workspace Issues"}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
right={
|
||||
<div className="flex items-center gap-2">
|
||||
<WorkspaceIssuesViewOptions />
|
||||
<PrimaryButton
|
||||
className="flex items-center gap-2"
|
||||
onClick={() => {
|
||||
const e = new KeyboardEvent("keydown", { key: "c" });
|
||||
document.dispatchEvent(e);
|
||||
<WorkspaceAuthorizationLayout
|
||||
breadcrumbs={
|
||||
<div className="flex gap-2 items-center">
|
||||
<CheckCircle className="h-[18px] w-[18px] stroke-[1.5]" />
|
||||
<span className="text-sm font-medium">
|
||||
{viewDetails ? `${viewDetails.name} Issues` : "Workspace Issues"}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
right={
|
||||
<div className="flex items-center gap-2">
|
||||
<WorkspaceIssuesViewOptions />
|
||||
<PrimaryButton
|
||||
className="flex items-center gap-2"
|
||||
onClick={() => {
|
||||
const e = new KeyboardEvent("keydown", { key: "c" });
|
||||
document.dispatchEvent(e);
|
||||
}}
|
||||
>
|
||||
<PlusIcon className="h-4 w-4" />
|
||||
Add Issue
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<CreateUpdateIssueModal
|
||||
isOpen={createIssueModal && preloadedData?.actionType === "createIssue"}
|
||||
handleClose={() => setCreateIssueModal(false)}
|
||||
prePopulateData={{
|
||||
...preloadedData,
|
||||
}}
|
||||
onSubmit={async () => {
|
||||
mutateIssues();
|
||||
}}
|
||||
/>
|
||||
<CreateUpdateIssueModal
|
||||
isOpen={editIssueModal && issueToEdit?.actionType !== "delete"}
|
||||
handleClose={() => setEditIssueModal(false)}
|
||||
data={issueToEdit}
|
||||
onSubmit={async () => {
|
||||
mutateIssues();
|
||||
}}
|
||||
/>
|
||||
<DeleteIssueModal
|
||||
handleClose={() => setDeleteIssueModal(false)}
|
||||
isOpen={deleteIssueModal}
|
||||
data={issueToDelete}
|
||||
user={user}
|
||||
onSubmit={async () => {
|
||||
mutateIssues();
|
||||
}}
|
||||
/>
|
||||
<CreateUpdateViewModal
|
||||
isOpen={createViewModal !== null}
|
||||
handleClose={() => setCreateViewModal(null)}
|
||||
viewType="workspace"
|
||||
preLoadedData={createViewModal}
|
||||
user={user}
|
||||
/>
|
||||
<div className="h-full flex flex-col overflow-hidden bg-custom-background-100">
|
||||
<div className="h-full w-full border-b border-custom-border-300">
|
||||
<WorkspaceViewsNavigation handleAddView={() => setCreateViewModal(true)} />
|
||||
{error ? (
|
||||
<EmptyState
|
||||
image={emptyView}
|
||||
title="View does not exist"
|
||||
description="The view you are looking for does not exist or has been deleted."
|
||||
primaryButton={{
|
||||
text: "View other views",
|
||||
onClick: () => router.push(`/${workspaceSlug}/workspace-views`),
|
||||
}}
|
||||
>
|
||||
<PlusIcon className="h-4 w-4" />
|
||||
Add Issue
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className="h-full flex flex-col overflow-hidden bg-custom-background-100">
|
||||
<div className="h-full w-full border-b border-custom-border-300">
|
||||
<WorkspaceViewsNavigation user={user} />
|
||||
{error ? (
|
||||
<EmptyState
|
||||
image={emptyView}
|
||||
title="View does not exist"
|
||||
description="The view you are looking for does not exist or has been deleted."
|
||||
primaryButton={{
|
||||
text: "View other views",
|
||||
onClick: () => router.push(`/${workspaceSlug}/workspace-views`),
|
||||
/>
|
||||
) : (
|
||||
<div className="h-full w-full flex flex-col">
|
||||
<SpreadsheetView
|
||||
spreadsheetIssues={viewIssues}
|
||||
mutateIssues={mutateIssues}
|
||||
handleIssueAction={handleIssueAction}
|
||||
disableUserActions={false}
|
||||
user={user}
|
||||
userAuth={{
|
||||
isGuest: false,
|
||||
isMember: false,
|
||||
isOwner: false,
|
||||
isViewer: false,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div className="h-full w-full flex flex-col">
|
||||
<SpreadsheetView
|
||||
spreadsheetIssues={viewIssues}
|
||||
mutateIssues={mutateIssues}
|
||||
handleIssueAction={(...args) => {}}
|
||||
disableUserActions={false}
|
||||
user={user}
|
||||
userAuth={{
|
||||
isGuest: false,
|
||||
isMember: false,
|
||||
isOwner: false,
|
||||
isViewer: false,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</WorkspaceAuthorizationLayout>
|
||||
</IssueViewContextProvider>
|
||||
</div>
|
||||
</WorkspaceAuthorizationLayout>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -25,7 +25,7 @@ import { PhotoFilterOutlined } from "@mui/icons-material";
|
||||
import emptyView from "public/empty-state/view.svg";
|
||||
// types
|
||||
import type { NextPage } from "next";
|
||||
import { IWorkspaceView } from "types/workspace-view";
|
||||
import { IView } from "types";
|
||||
// constants
|
||||
import { WORKSPACE_VIEWS_LIST } from "constants/fetch-keys";
|
||||
// helper
|
||||
@ -33,17 +33,17 @@ import { truncateText } from "helpers/string.helper";
|
||||
|
||||
const WorkspaceViews: NextPage = () => {
|
||||
const [createUpdateViewModal, setCreateUpdateViewModal] = useState(false);
|
||||
const [selectedViewToUpdate, setSelectedViewToUpdate] = useState<IWorkspaceView | null>(null);
|
||||
const [selectedViewToUpdate, setSelectedViewToUpdate] = useState<IView | null>(null);
|
||||
|
||||
const [deleteViewModal, setDeleteViewModal] = useState(false);
|
||||
const [selectedViewToDelete, setSelectedViewToDelete] = useState<IWorkspaceView | null>(null);
|
||||
const [selectedViewToDelete, setSelectedViewToDelete] = useState<IView | null>(null);
|
||||
|
||||
const handleEditView = (view: IWorkspaceView) => {
|
||||
const handleEditView = (view: IView) => {
|
||||
setSelectedViewToUpdate(view);
|
||||
setCreateUpdateViewModal(true);
|
||||
};
|
||||
|
||||
const handleDeleteView = (view: IWorkspaceView) => {
|
||||
const handleDeleteView = (view: IView) => {
|
||||
setSelectedViewToDelete(view);
|
||||
setDeleteViewModal(true);
|
||||
};
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { useCallback, useState } from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
import useSWR from "swr";
|
||||
@ -9,12 +11,12 @@ import useMyIssuesFilters from "hooks/my-issues/use-my-issues-filter";
|
||||
import workspaceService from "services/workspace.service";
|
||||
// layouts
|
||||
import { WorkspaceAuthorizationLayout } from "layouts/auth-layout";
|
||||
// contexts
|
||||
import { IssueViewContextProvider } from "contexts/issue-view.context";
|
||||
// components
|
||||
import { SpreadsheetView } from "components/core";
|
||||
import { WorkspaceViewsNavigation } from "components/workspace/views/workpace-view-navigation";
|
||||
import { WorkspaceIssuesViewOptions } from "components/issues/workspace-views/workspace-issue-view-option";
|
||||
import { CreateUpdateViewModal } from "components/views";
|
||||
import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues";
|
||||
// ui
|
||||
import { EmptyState, PrimaryButton } from "components/ui";
|
||||
// icons
|
||||
@ -24,8 +26,28 @@ import { CheckCircle } from "lucide-react";
|
||||
import emptyView from "public/empty-state/view.svg";
|
||||
// fetch-keys
|
||||
import { WORKSPACE_VIEW_DETAILS, WORKSPACE_VIEW_ISSUES } from "constants/fetch-keys";
|
||||
// types
|
||||
import { IIssue } from "types";
|
||||
|
||||
const WorkspaceViewSubscribedIssue: React.FC = () => {
|
||||
const [createViewModal, setCreateViewModal] = useState<any>(null);
|
||||
|
||||
// create issue modal
|
||||
const [createIssueModal, setCreateIssueModal] = useState(false);
|
||||
const [preloadedData, setPreloadedData] = useState<
|
||||
(Partial<IIssue> & { actionType: "createIssue" | "edit" | "delete" }) | undefined
|
||||
>(undefined);
|
||||
|
||||
// update issue modal
|
||||
const [editIssueModal, setEditIssueModal] = useState(false);
|
||||
const [issueToEdit, setIssueToEdit] = useState<
|
||||
(IIssue & { actionType: "edit" | "delete" }) | undefined
|
||||
>(undefined);
|
||||
|
||||
// delete issue modal
|
||||
const [deleteIssueModal, setDeleteIssueModal] = useState(false);
|
||||
const [issueToDelete, setIssueToDelete] = useState<IIssue | null>(null);
|
||||
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, workspaceViewId } = router.query;
|
||||
|
||||
@ -58,67 +80,138 @@ const WorkspaceViewSubscribedIssue: React.FC = () => {
|
||||
workspaceSlug ? () => workspaceService.getViewIssues(workspaceSlug.toString(), params) : null
|
||||
);
|
||||
|
||||
const makeIssueCopy = useCallback(
|
||||
(issue: IIssue) => {
|
||||
setCreateIssueModal(true);
|
||||
|
||||
setPreloadedData({ ...issue, name: `${issue.name} (Copy)`, actionType: "createIssue" });
|
||||
},
|
||||
[setCreateIssueModal, setPreloadedData]
|
||||
);
|
||||
|
||||
const handleEditIssue = useCallback(
|
||||
(issue: IIssue) => {
|
||||
setEditIssueModal(true);
|
||||
setIssueToEdit({
|
||||
...issue,
|
||||
actionType: "edit",
|
||||
cycle: issue.issue_cycle ? issue.issue_cycle.cycle : null,
|
||||
module: issue.issue_module ? issue.issue_module.module : null,
|
||||
});
|
||||
},
|
||||
[setEditIssueModal, setIssueToEdit]
|
||||
);
|
||||
|
||||
const handleDeleteIssue = useCallback(
|
||||
(issue: IIssue) => {
|
||||
setDeleteIssueModal(true);
|
||||
setIssueToDelete(issue);
|
||||
},
|
||||
[setDeleteIssueModal, setIssueToDelete]
|
||||
);
|
||||
|
||||
const handleIssueAction = useCallback(
|
||||
(issue: IIssue, action: "copy" | "edit" | "delete" | "updateDraft") => {
|
||||
if (action === "copy") makeIssueCopy(issue);
|
||||
else if (action === "edit") handleEditIssue(issue);
|
||||
else if (action === "delete") handleDeleteIssue(issue);
|
||||
},
|
||||
[makeIssueCopy, handleEditIssue, handleDeleteIssue]
|
||||
);
|
||||
|
||||
return (
|
||||
<IssueViewContextProvider>
|
||||
<WorkspaceAuthorizationLayout
|
||||
breadcrumbs={
|
||||
<div className="flex gap-2 items-center">
|
||||
<CheckCircle className="h-[18px] w-[18px] stroke-[1.5]" />
|
||||
<span className="text-sm font-medium">
|
||||
{viewDetails ? `${viewDetails.name} Issues` : "Workspace Issues"}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
right={
|
||||
<div className="flex items-center gap-2">
|
||||
<WorkspaceIssuesViewOptions />
|
||||
<PrimaryButton
|
||||
className="flex items-center gap-2"
|
||||
onClick={() => {
|
||||
const e = new KeyboardEvent("keydown", { key: "c" });
|
||||
document.dispatchEvent(e);
|
||||
<WorkspaceAuthorizationLayout
|
||||
breadcrumbs={
|
||||
<div className="flex gap-2 items-center">
|
||||
<CheckCircle className="h-[18px] w-[18px] stroke-[1.5]" />
|
||||
<span className="text-sm font-medium">
|
||||
{viewDetails ? `${viewDetails.name} Issues` : "Workspace Issues"}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
right={
|
||||
<div className="flex items-center gap-2">
|
||||
<WorkspaceIssuesViewOptions />
|
||||
<PrimaryButton
|
||||
className="flex items-center gap-2"
|
||||
onClick={() => {
|
||||
const e = new KeyboardEvent("keydown", { key: "c" });
|
||||
document.dispatchEvent(e);
|
||||
}}
|
||||
>
|
||||
<PlusIcon className="h-4 w-4" />
|
||||
Add Issue
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<CreateUpdateIssueModal
|
||||
isOpen={createIssueModal && preloadedData?.actionType === "createIssue"}
|
||||
handleClose={() => setCreateIssueModal(false)}
|
||||
prePopulateData={{
|
||||
...preloadedData,
|
||||
}}
|
||||
onSubmit={async () => {
|
||||
mutateIssues();
|
||||
}}
|
||||
/>
|
||||
<CreateUpdateIssueModal
|
||||
isOpen={editIssueModal && issueToEdit?.actionType !== "delete"}
|
||||
handleClose={() => setEditIssueModal(false)}
|
||||
data={issueToEdit}
|
||||
onSubmit={async () => {
|
||||
mutateIssues();
|
||||
}}
|
||||
/>
|
||||
<DeleteIssueModal
|
||||
handleClose={() => setDeleteIssueModal(false)}
|
||||
isOpen={deleteIssueModal}
|
||||
data={issueToDelete}
|
||||
user={user}
|
||||
onSubmit={async () => {
|
||||
mutateIssues();
|
||||
}}
|
||||
/>
|
||||
<CreateUpdateViewModal
|
||||
isOpen={createViewModal !== null}
|
||||
handleClose={() => setCreateViewModal(null)}
|
||||
viewType="workspace"
|
||||
preLoadedData={createViewModal}
|
||||
user={user}
|
||||
/>
|
||||
<div className="h-full flex flex-col overflow-hidden bg-custom-background-100">
|
||||
<div className="h-full w-full border-b border-custom-border-300">
|
||||
<WorkspaceViewsNavigation handleAddView={() => setCreateViewModal(true)} />
|
||||
{error ? (
|
||||
<EmptyState
|
||||
image={emptyView}
|
||||
title="View does not exist"
|
||||
description="The view you are looking for does not exist or has been deleted."
|
||||
primaryButton={{
|
||||
text: "View other views",
|
||||
onClick: () => router.push(`/${workspaceSlug}/workspace-views`),
|
||||
}}
|
||||
>
|
||||
<PlusIcon className="h-4 w-4" />
|
||||
Add Issue
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className="h-full flex flex-col overflow-hidden bg-custom-background-100">
|
||||
<div className="h-full w-full border-b border-custom-border-300">
|
||||
<WorkspaceViewsNavigation user={user} />
|
||||
{error ? (
|
||||
<EmptyState
|
||||
image={emptyView}
|
||||
title="View does not exist"
|
||||
description="The view you are looking for does not exist or has been deleted."
|
||||
primaryButton={{
|
||||
text: "View other views",
|
||||
onClick: () => router.push(`/${workspaceSlug}/workspace-views`),
|
||||
/>
|
||||
) : (
|
||||
<div className="h-full w-full flex flex-col">
|
||||
<SpreadsheetView
|
||||
spreadsheetIssues={viewIssues}
|
||||
mutateIssues={mutateIssues}
|
||||
handleIssueAction={handleIssueAction}
|
||||
disableUserActions={false}
|
||||
user={user}
|
||||
userAuth={{
|
||||
isGuest: false,
|
||||
isMember: false,
|
||||
isOwner: false,
|
||||
isViewer: false,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div className="h-full w-full flex flex-col">
|
||||
<SpreadsheetView
|
||||
spreadsheetIssues={viewIssues}
|
||||
mutateIssues={mutateIssues}
|
||||
handleIssueAction={(...args) => {}}
|
||||
disableUserActions={false}
|
||||
user={user}
|
||||
userAuth={{
|
||||
isGuest: false,
|
||||
isMember: false,
|
||||
isOwner: false,
|
||||
isViewer: false,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</WorkspaceAuthorizationLayout>
|
||||
</IssueViewContextProvider>
|
||||
</div>
|
||||
</WorkspaceAuthorizationLayout>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -14,9 +14,9 @@ import {
|
||||
ICurrentUserResponse,
|
||||
IWorkspaceBulkInviteFormData,
|
||||
IWorkspaceViewProps,
|
||||
IView,
|
||||
IIssueFilterOptions,
|
||||
} from "types";
|
||||
import { IWorkspaceView } from "types/workspace-view";
|
||||
|
||||
class WorkspaceService extends APIService {
|
||||
constructor() {
|
||||
@ -264,7 +264,7 @@ class WorkspaceService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async createView(workspaceSlug: string, data: IWorkspaceView): Promise<any> {
|
||||
async createView(workspaceSlug: string, data: IView): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/views/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
@ -272,11 +272,7 @@ class WorkspaceService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async updateView(
|
||||
workspaceSlug: string,
|
||||
viewId: string,
|
||||
data: Partial<IWorkspaceView>
|
||||
): Promise<any> {
|
||||
async updateView(workspaceSlug: string, viewId: string, data: Partial<IView>): Promise<any> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/views/${viewId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
@ -292,7 +288,7 @@ class WorkspaceService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async getAllViews(workspaceSlug: string): Promise<IWorkspaceView[]> {
|
||||
async getAllViews(workspaceSlug: string): Promise<IView[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/views/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
@ -300,7 +296,7 @@ class WorkspaceService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async getViewDetails(workspaceSlug: string, viewId: string): Promise<IWorkspaceView> {
|
||||
async getViewDetails(workspaceSlug: string, viewId: string): Promise<IView> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/views/${viewId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
|
6
web/types/views.d.ts
vendored
6
web/types/views.d.ts
vendored
@ -14,6 +14,11 @@ export interface IView {
|
||||
query_data: IIssueFilterOptions;
|
||||
project: string;
|
||||
workspace: string;
|
||||
workspace_detail: {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IQuery {
|
||||
@ -25,4 +30,5 @@ export interface IQuery {
|
||||
start_date: string[] | null;
|
||||
target_date: string[] | null;
|
||||
type: "active" | "backlog" | null;
|
||||
projects: string[] | null;
|
||||
}
|
||||
|
21
web/types/workspace-view.d.ts
vendored
21
web/types/workspace-view.d.ts
vendored
@ -1,21 +0,0 @@
|
||||
import { IIssueFilterOptions } from "./view-props";
|
||||
|
||||
export interface IWorkspaceView {
|
||||
access: string;
|
||||
created_at: Date;
|
||||
created_by: string;
|
||||
description: string;
|
||||
id: string;
|
||||
name: string;
|
||||
query: IIssueFilterOptions;
|
||||
query_data: IIssueFilterOptions;
|
||||
updated_at: Date;
|
||||
updated_by: string;
|
||||
is_favorite: boolean;
|
||||
workspace: string;
|
||||
workspace_detail: {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user