Skip to content
This repository was archived by the owner on Jul 21, 2025. It is now read-only.

Commit 633c2d8

Browse files
prateekshourya29nishantPFM
authored andcommitted
refactor: enhance command palette modularity (makeplane#6139)
* refactor: enhance command palette modularity * chore: minor updates to command palette store
1 parent 5e55bb1 commit 633c2d8

File tree

16 files changed

+342
-212
lines changed

16 files changed

+342
-212
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export type TCommandPaletteActionList = Record<
2+
string,
3+
{ title: string; description: string; action: () => void }
4+
>;
5+
6+
export type TCommandPaletteShortcutList = {
7+
key: string;
8+
title: string;
9+
shortcuts: TCommandPaletteShortcut[];
10+
};
11+
12+
export type TCommandPaletteShortcut = {
13+
keys: string; // comma separated keys
14+
description: string;
15+
};

packages/types/src/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@ export * from "./workspace-notifications";
3232
export * from "./favorite";
3333
export * from "./file";
3434
export * from "./workspace-draft-issues/base";
35+
export * from "./command-palette";
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from "./workspace-level";
2+
export * from "./project-level";
3+
export * from "./issue-level";
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { observer } from "mobx-react";
2+
import { useParams, usePathname } from "next/navigation";
3+
import useSWR from "swr";
4+
// components
5+
import { BulkDeleteIssuesModal } from "@/components/core";
6+
import { CreateUpdateIssueModal, DeleteIssueModal } from "@/components/issues";
7+
// constants
8+
import { ISSUE_DETAILS } from "@/constants/fetch-keys";
9+
// hooks
10+
import { useCommandPalette, useUser } from "@/hooks/store";
11+
import { useAppRouter } from "@/hooks/use-app-router";
12+
import { useIssuesStore } from "@/hooks/use-issue-layout-store";
13+
// services
14+
import { IssueService } from "@/services/issue";
15+
16+
// services
17+
const issueService = new IssueService();
18+
19+
export const IssueLevelModals = observer(() => {
20+
// router
21+
const pathname = usePathname();
22+
const { workspaceSlug, projectId, issueId, cycleId, moduleId } = useParams();
23+
const router = useAppRouter();
24+
// store hooks
25+
const { data: currentUser } = useUser();
26+
const {
27+
issues: { removeIssue },
28+
} = useIssuesStore();
29+
const {
30+
isCreateIssueModalOpen,
31+
toggleCreateIssueModal,
32+
isDeleteIssueModalOpen,
33+
toggleDeleteIssueModal,
34+
isBulkDeleteIssueModalOpen,
35+
toggleBulkDeleteIssueModal,
36+
} = useCommandPalette();
37+
// derived values
38+
const isDraftIssue = pathname?.includes("draft-issues") || false;
39+
40+
const { data: issueDetails } = useSWR(
41+
workspaceSlug && projectId && issueId ? ISSUE_DETAILS(issueId as string) : null,
42+
workspaceSlug && projectId && issueId
43+
? () => issueService.retrieve(workspaceSlug as string, projectId as string, issueId as string)
44+
: null
45+
);
46+
47+
return (
48+
<>
49+
<CreateUpdateIssueModal
50+
isOpen={isCreateIssueModalOpen}
51+
onClose={() => toggleCreateIssueModal(false)}
52+
data={cycleId ? { cycle_id: cycleId.toString() } : moduleId ? { module_ids: [moduleId.toString()] } : undefined}
53+
isDraft={isDraftIssue}
54+
/>
55+
{workspaceSlug && projectId && issueId && issueDetails && (
56+
<DeleteIssueModal
57+
handleClose={() => toggleDeleteIssueModal(false)}
58+
isOpen={isDeleteIssueModalOpen}
59+
data={issueDetails}
60+
onSubmit={async () => {
61+
await removeIssue(workspaceSlug.toString(), projectId.toString(), issueId.toString());
62+
router.push(`/${workspaceSlug}/projects/${projectId}/issues`);
63+
}}
64+
/>
65+
)}
66+
<BulkDeleteIssuesModal
67+
isOpen={isBulkDeleteIssueModalOpen}
68+
onClose={() => toggleBulkDeleteIssueModal(false)}
69+
user={currentUser}
70+
/>
71+
</>
72+
);
73+
});
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { observer } from "mobx-react";
2+
// components
3+
import { CycleCreateUpdateModal } from "@/components/cycles";
4+
import { CreateUpdateModuleModal } from "@/components/modules";
5+
import { CreatePageModal } from "@/components/pages";
6+
import { CreateUpdateProjectViewModal } from "@/components/views";
7+
// hooks
8+
import { useCommandPalette } from "@/hooks/store";
9+
10+
export type TProjectLevelModalsProps = {
11+
workspaceSlug: string;
12+
projectId: string;
13+
};
14+
15+
export const ProjectLevelModals = observer((props: TProjectLevelModalsProps) => {
16+
const { workspaceSlug, projectId } = props;
17+
// store hooks
18+
const {
19+
isCreateCycleModalOpen,
20+
toggleCreateCycleModal,
21+
isCreateModuleModalOpen,
22+
toggleCreateModuleModal,
23+
isCreateViewModalOpen,
24+
toggleCreateViewModal,
25+
createPageModal,
26+
toggleCreatePageModal,
27+
} = useCommandPalette();
28+
29+
return (
30+
<>
31+
<CycleCreateUpdateModal
32+
isOpen={isCreateCycleModalOpen}
33+
handleClose={() => toggleCreateCycleModal(false)}
34+
workspaceSlug={workspaceSlug.toString()}
35+
projectId={projectId.toString()}
36+
/>
37+
<CreateUpdateModuleModal
38+
isOpen={isCreateModuleModalOpen}
39+
onClose={() => toggleCreateModuleModal(false)}
40+
workspaceSlug={workspaceSlug.toString()}
41+
projectId={projectId.toString()}
42+
/>
43+
<CreateUpdateProjectViewModal
44+
isOpen={isCreateViewModalOpen}
45+
onClose={() => toggleCreateViewModal(false)}
46+
workspaceSlug={workspaceSlug.toString()}
47+
projectId={projectId.toString()}
48+
/>
49+
<CreatePageModal
50+
workspaceSlug={workspaceSlug.toString()}
51+
projectId={projectId.toString()}
52+
isModalOpen={createPageModal.isOpen}
53+
pageAccess={createPageModal.pageAccess}
54+
handleModalClose={() => toggleCreatePageModal({ isOpen: false })}
55+
redirectionEnabled
56+
/>
57+
</>
58+
);
59+
});
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { observer } from "mobx-react";
2+
// components
3+
import { CreateProjectModal } from "@/components/project";
4+
// hooks
5+
import { useCommandPalette } from "@/hooks/store";
6+
7+
export type TWorkspaceLevelModalsProps = {
8+
workspaceSlug: string;
9+
};
10+
11+
export const WorkspaceLevelModals = observer((props: TWorkspaceLevelModalsProps) => {
12+
const { workspaceSlug } = props;
13+
// store hooks
14+
const { isCreateProjectModalOpen, toggleCreateProjectModal } = useCommandPalette();
15+
16+
return (
17+
<>
18+
<CreateProjectModal
19+
isOpen={isCreateProjectModalOpen}
20+
onClose={() => toggleCreateProjectModal(false)}
21+
workspaceSlug={workspaceSlug.toString()}
22+
/>
23+
</>
24+
);
25+
});

web/ce/helpers/command-palette.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// types
2+
import { TCommandPaletteActionList, TCommandPaletteShortcut, TCommandPaletteShortcutList } from "@plane/types";
3+
// store
4+
import { store } from "@/lib/store-context";
5+
6+
export const getGlobalShortcutsList: () => TCommandPaletteActionList = () => {
7+
const { toggleCreateIssueModal } = store.commandPalette;
8+
9+
return {
10+
c: {
11+
title: "Create a new issue",
12+
description: "Create a new issue in the current project",
13+
action: () => toggleCreateIssueModal(true),
14+
},
15+
};
16+
};
17+
18+
export const getWorkspaceShortcutsList: () => TCommandPaletteActionList = () => {
19+
const { toggleCreateProjectModal } = store.commandPalette;
20+
21+
return {
22+
p: {
23+
title: "Create a new project",
24+
description: "Create a new project in the current workspace",
25+
action: () => toggleCreateProjectModal(true),
26+
},
27+
};
28+
};
29+
30+
export const getProjectShortcutsList: () => TCommandPaletteActionList = () => {
31+
const {
32+
toggleCreatePageModal,
33+
toggleCreateModuleModal,
34+
toggleCreateCycleModal,
35+
toggleCreateViewModal,
36+
toggleBulkDeleteIssueModal,
37+
} = store.commandPalette;
38+
39+
return {
40+
d: {
41+
title: "Create a new page",
42+
description: "Create a new page in the current project",
43+
action: () => toggleCreatePageModal({ isOpen: true }),
44+
},
45+
m: {
46+
title: "Create a new module",
47+
description: "Create a new module in the current project",
48+
action: () => toggleCreateModuleModal(true),
49+
},
50+
q: {
51+
title: "Create a new cycle",
52+
description: "Create a new cycle in the current project",
53+
action: () => toggleCreateCycleModal(true),
54+
},
55+
v: {
56+
title: "Create a new view",
57+
description: "Create a new view in the current project",
58+
action: () => toggleCreateViewModal(true),
59+
},
60+
backspace: {
61+
title: "Bulk delete issues",
62+
description: "Bulk delete issues in the current project",
63+
action: () => toggleBulkDeleteIssueModal(true),
64+
},
65+
delete: {
66+
title: "Bulk delete issues",
67+
description: "Bulk delete issues in the current project",
68+
action: () => toggleBulkDeleteIssueModal(true),
69+
},
70+
};
71+
};
72+
73+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
74+
export const handleAdditionalKeyDownEvents = (e: KeyboardEvent) => null;
75+
76+
export const getNavigationShortcutsList = (): TCommandPaletteShortcut[] => [
77+
{ keys: "Ctrl,K", description: "Open command menu" },
78+
];
79+
80+
export const getCommonShortcutsList = (platform: string): TCommandPaletteShortcut[] => [
81+
{ keys: "P", description: "Create project" },
82+
{ keys: "C", description: "Create issue" },
83+
{ keys: "Q", description: "Create cycle" },
84+
{ keys: "M", description: "Create module" },
85+
{ keys: "V", description: "Create view" },
86+
{ keys: "D", description: "Create page" },
87+
{ keys: "Delete", description: "Bulk delete issues" },
88+
{ keys: "Shift,/", description: "Open shortcuts guide" },
89+
{
90+
keys: platform === "MacOS" ? "Ctrl,control,C" : "Ctrl,Alt,C",
91+
description: "Copy issue URL from the issue details page",
92+
},
93+
];
94+
95+
export const getAdditionalShortcutsList = (): TCommandPaletteShortcutList[] => [];
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { makeObservable } from "mobx";
2+
// types / constants
3+
import { BaseCommandPaletteStore, IBaseCommandPaletteStore } from "@/store/base-command-palette.store";
4+
5+
export type ICommandPaletteStore = IBaseCommandPaletteStore;
6+
7+
export class CommandPaletteStore extends BaseCommandPaletteStore implements ICommandPaletteStore {
8+
constructor() {
9+
super();
10+
makeObservable(this, {});
11+
}
12+
}

0 commit comments

Comments
 (0)