Improvement: High Performance MobX Integration for Pages ✈︎ (#3397)
* fix: removed parameters `workspace`, `project` & `id` from the patch calls * feat: modified components to work with new pages hooks * feat: modified stores * feat: modified initial component * feat: component implementation changes * feat: store implementation * refactor pages store * feat: updated page store to perform async operations faster * fix: added types for archive and restore pages * feat: implemented archive and restore pages * fix: page creating twice when form submit * feat: updated create-page-modal * feat: updated page form and delete page modal * fix: create page modal not updating isSubmitted prop * feat: list items and list view refactored for pages * feat: refactored project-page-store for inserting computed pagesids * chore: renamed project pages hook * feat: added favourite pages implementation * fix: implemented store for archived pages * fix: project page store for recent pages * fix: issue suggestions breaking pages * fix: issue embeds and suggestions breaking * feat: implemented page store and project page store in page editor * chore: lock file changes * fix: modified page details header to catch mobx updates instead of swr calls * fix: modified usePage hook to fetch page details when reloaded directly on page * fix: fixed deleting pages * fix: removed render on props changed * feat: implemented page store inside page details * fix: role change in pages archives * fix: rerending of pages on tab change * fix: reimplementation of peek overview inside pages * chore: typo fixes * fix: issue suggestion widget selecting wrong issues on click * feat: added labels in pages * fix: deepsource errors fixed * fix: build errors * fix: review comments * fix: removed swr hooks from the `usePage` store hook and refactored `issueEmbed` hook * fix: resolved reviewed comments --------- Co-authored-by: Rahul R <rahulr@Rahuls-MacBook-Pro.local>
This commit is contained in:
parent
d3dedc8e51
commit
06a7bdffd7
32 changed files with 960 additions and 1100 deletions
|
|
@ -18,7 +18,7 @@ import {
|
|||
|
||||
type IPageRenderer = {
|
||||
documentDetails: DocumentDetails;
|
||||
updatePageTitle: (title: string) => Promise<void>;
|
||||
updatePageTitle: (title: string) => void;
|
||||
editor: Editor;
|
||||
onActionCompleteHandler: (action: {
|
||||
title: string;
|
||||
|
|
@ -30,18 +30,6 @@ type IPageRenderer = {
|
|||
readonly: boolean;
|
||||
};
|
||||
|
||||
const debounce = (func: (...args: any[]) => void, wait: number) => {
|
||||
let timeout: NodeJS.Timeout | null = null;
|
||||
return function executedFunction(...args: any[]) {
|
||||
const later = () => {
|
||||
if (timeout) clearTimeout(timeout);
|
||||
func(...args);
|
||||
};
|
||||
if (timeout) clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
};
|
||||
};
|
||||
|
||||
export const PageRenderer = (props: IPageRenderer) => {
|
||||
const { documentDetails, editor, editorClassNames, editorContentCustomClassNames, updatePageTitle, readonly } = props;
|
||||
|
||||
|
|
@ -64,11 +52,9 @@ export const PageRenderer = (props: IPageRenderer) => {
|
|||
|
||||
const { getFloatingProps } = useInteractions([dismiss]);
|
||||
|
||||
const debouncedUpdatePageTitle = debounce(updatePageTitle, 300);
|
||||
|
||||
const handlePageTitleChange = (title: string) => {
|
||||
setPagetitle(title);
|
||||
debouncedUpdatePageTitle(title);
|
||||
updatePageTitle(title);
|
||||
};
|
||||
|
||||
const [cleanup, setcleanup] = useState(() => () => {});
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ export const DocumentEditorExtensions = (
|
|||
.focus()
|
||||
.insertContentAt(
|
||||
range,
|
||||
"<p class='text-sm bg-gray-300 w-fit pl-3 pr-3 pt-1 pb-1 rounded shadow-sm'>#issue_</p>"
|
||||
"<p class='text-sm bg-gray-300 w-fit pl-3 pr-3 pt-1 pb-1 rounded shadow-sm'>#issue_</p>\n"
|
||||
)
|
||||
.run();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ export const IssueSuggestions = (suggestions: any[]) => {
|
|||
title: suggestion.name,
|
||||
priority: suggestion.priority.toString(),
|
||||
identifier: `${suggestion.project_detail.identifier}-${suggestion.sequence_id}`,
|
||||
state: suggestion.state_detail.name,
|
||||
state: suggestion.state_detail && suggestion.state_detail.name ? suggestion.state_detail.name : "Todo",
|
||||
command: ({ editor, range }) => {
|
||||
editor
|
||||
.chain()
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ export const IssueEmbedSuggestions = Extension.create({
|
|||
addOptions() {
|
||||
return {
|
||||
suggestion: {
|
||||
char: "#issue_",
|
||||
allowSpaces: true,
|
||||
command: ({ editor, range, props }: { editor: Editor; range: Range; props: any }) => {
|
||||
props.command({ editor, range });
|
||||
},
|
||||
|
|
@ -18,11 +20,8 @@ export const IssueEmbedSuggestions = Extension.create({
|
|||
addProseMirrorPlugins() {
|
||||
return [
|
||||
Suggestion({
|
||||
char: "#issue_",
|
||||
pluginKey: new PluginKey("issue-embed-suggestions"),
|
||||
editor: this.editor,
|
||||
allowSpaces: true,
|
||||
|
||||
...this.options.suggestion,
|
||||
}),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ const IssueSuggestionList = ({
|
|||
const commandListContainer = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
let newDisplayedItems: { [key: string]: IssueSuggestionProps[] } = {};
|
||||
const newDisplayedItems: { [key: string]: IssueSuggestionProps[] } = {};
|
||||
let totalLength = 0;
|
||||
sections.forEach((section) => {
|
||||
newDisplayedItems[section] = items.filter((item) => item.state === section).slice(0, 5);
|
||||
|
|
@ -65,8 +65,8 @@ const IssueSuggestionList = ({
|
|||
}, [items]);
|
||||
|
||||
const selectItem = useCallback(
|
||||
(index: number) => {
|
||||
const item = displayedItems[currentSection][index];
|
||||
(section: string, index: number) => {
|
||||
const item = displayedItems[section][index];
|
||||
if (item) {
|
||||
command(item);
|
||||
}
|
||||
|
|
@ -87,6 +87,7 @@ const IssueSuggestionList = ({
|
|||
setSelectedIndex(
|
||||
(selectedIndex + displayedItems[currentSection].length - 1) % displayedItems[currentSection].length
|
||||
);
|
||||
e.stopPropagation();
|
||||
return true;
|
||||
}
|
||||
if (e.key === "ArrowDown") {
|
||||
|
|
@ -101,10 +102,12 @@ const IssueSuggestionList = ({
|
|||
[currentSection]: [...prevItems[currentSection], ...nextItems],
|
||||
}));
|
||||
}
|
||||
e.stopPropagation();
|
||||
return true;
|
||||
}
|
||||
if (e.key === "Enter") {
|
||||
selectItem(selectedIndex);
|
||||
selectItem(currentSection, selectedIndex);
|
||||
e.stopPropagation();
|
||||
return true;
|
||||
}
|
||||
if (e.key === "Tab") {
|
||||
|
|
@ -112,6 +115,7 @@ const IssueSuggestionList = ({
|
|||
const nextSectionIndex = (currentSectionIndex + 1) % sections.length;
|
||||
setCurrentSection(sections[nextSectionIndex]);
|
||||
setSelectedIndex(0);
|
||||
e.stopPropagation();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -172,7 +176,7 @@ const IssueSuggestionList = ({
|
|||
}
|
||||
)}
|
||||
key={item.identifier}
|
||||
onClick={() => selectItem(index)}
|
||||
onClick={() => selectItem(section, index)}
|
||||
>
|
||||
<h5 className="whitespace-nowrap text-xs text-custom-text-300">{item.identifier}</h5>
|
||||
<PriorityIcon priority={item.priority} />
|
||||
|
|
@ -195,7 +199,7 @@ export const IssueListRenderer = () => {
|
|||
let popup: any | null = null;
|
||||
|
||||
return {
|
||||
onStart: (props: { editor: Editor; clientRect: DOMRect }) => {
|
||||
onStart: (props: { editor: Editor; clientRect?: (() => DOMRect | null) | null }) => {
|
||||
component = new ReactRenderer(IssueSuggestionList, {
|
||||
props,
|
||||
// @ts-ignore
|
||||
|
|
@ -210,10 +214,10 @@ export const IssueListRenderer = () => {
|
|||
showOnCreate: true,
|
||||
interactive: true,
|
||||
trigger: "manual",
|
||||
placement: "right",
|
||||
placement: "bottom-start",
|
||||
});
|
||||
},
|
||||
onUpdate: (props: { editor: Editor; clientRect: DOMRect }) => {
|
||||
onUpdate: (props: { editor: Editor; clientRect?: (() => DOMRect | null) | null }) => {
|
||||
component?.updateProps(props);
|
||||
|
||||
popup &&
|
||||
|
|
|
|||
|
|
@ -15,8 +15,7 @@ export const IssueWidgetCard = (props) => {
|
|||
setIssueDetails(issue);
|
||||
setLoading(0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
.catch(() => {
|
||||
setLoading(-1);
|
||||
});
|
||||
}, []);
|
||||
|
|
@ -30,7 +29,9 @@ export const IssueWidgetCard = (props) => {
|
|||
{loading == 0 ? (
|
||||
<div
|
||||
onClick={completeIssueEmbedAction}
|
||||
className="w-full cursor-pointer space-y-2 rounded-md border-[0.5px] border-custom-border-200 p-3 shadow-custom-shadow-2xs"
|
||||
className={`${
|
||||
props.selected ? "border-custom-primary-200 border-[2px]" : ""
|
||||
} w-full cursor-pointer space-y-2 rounded-md border-[0.5px] border-custom-border-200 p-3 shadow-custom-shadow-2xs`}
|
||||
>
|
||||
<h5 className="text-xs text-custom-text-300">
|
||||
{issueDetails.project_detail.identifier}-{issueDetails.sequence_id}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ interface IDocumentEditor {
|
|||
// document info
|
||||
documentDetails: DocumentDetails;
|
||||
value: string;
|
||||
rerenderOnPropsChange: {
|
||||
rerenderOnPropsChange?: {
|
||||
id: string;
|
||||
description_html: string;
|
||||
};
|
||||
|
|
@ -39,7 +39,7 @@ interface IDocumentEditor {
|
|||
setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void;
|
||||
setShouldShowAlert?: (showAlert: boolean) => void;
|
||||
forwardedRef?: any;
|
||||
updatePageTitle: (title: string) => Promise<void>;
|
||||
updatePageTitle: (title: string) => void;
|
||||
debouncedUpdatesEnabled?: boolean;
|
||||
isSubmitting: "submitting" | "submitted" | "saved";
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue