forked from github/plane
fix: complete pages editor not clickable, recent pages calculation logic (#2820)
* fix: whole editor not clickable * fix: recent pages calculation * chore: update older pages calculation logic in recent pages list * fix: archived pages computed function * chore: add type for older pages
This commit is contained in:
parent
7aaf840fb1
commit
982eba0bd1
@ -1,33 +1,46 @@
|
|||||||
import { EditorContainer, EditorContentWrapper } from "@plane/editor-core"
|
import { EditorContainer, EditorContentWrapper } from "@plane/editor-core";
|
||||||
import { Editor } from "@tiptap/react"
|
import { Editor } from "@tiptap/react";
|
||||||
import { DocumentDetails } from "../types/editor-types"
|
import { DocumentDetails } from "../types/editor-types";
|
||||||
|
|
||||||
interface IPageRenderer {
|
interface IPageRenderer {
|
||||||
sidePeakVisible: boolean,
|
sidePeakVisible: boolean;
|
||||||
documentDetails: DocumentDetails ,
|
documentDetails: DocumentDetails;
|
||||||
editor: Editor,
|
editor: Editor;
|
||||||
editorClassNames: string,
|
editorClassNames: string;
|
||||||
editorContentCustomClassNames?: string
|
editorContentCustomClassNames?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PageRenderer = ({ sidePeakVisible, documentDetails, editor, editorClassNames, editorContentCustomClassNames }: IPageRenderer) => {
|
export const PageRenderer = ({
|
||||||
|
sidePeakVisible,
|
||||||
|
documentDetails,
|
||||||
|
editor,
|
||||||
|
editorClassNames,
|
||||||
|
editorContentCustomClassNames,
|
||||||
|
}: IPageRenderer) => {
|
||||||
return (
|
return (
|
||||||
<div className={`flex h-[88vh] flex-col w-full max-md:w-full max-md:ml-0 transition-all duration-200 ease-in-out ${sidePeakVisible ? 'ml-[3%] ' : 'ml-0'}`}>
|
<div
|
||||||
|
className={`flex h-[88vh] flex-col w-full max-md:w-full max-md:ml-0 transition-all duration-200 ease-in-out ${
|
||||||
|
sidePeakVisible ? "ml-[3%] " : "ml-0"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
<div className="items-start mt-4 h-full flex flex-col w-fit max-md:max-w-full overflow-auto">
|
<div className="items-start mt-4 h-full flex flex-col w-fit max-md:max-w-full overflow-auto">
|
||||||
<div className="flex flex-col py-2 max-md:max-w-full">
|
<div className="flex flex-col py-2 max-md:max-w-full">
|
||||||
<h1
|
<h1 className="border-none outline-none bg-transparent text-4xl font-bold leading-8 tracking-tight self-center w-[700px] max-w-full">
|
||||||
className="border-none outline-none bg-transparent text-4xl font-bold leading-8 tracking-tight self-center w-[700px] max-w-full"
|
{documentDetails.title}
|
||||||
>{documentDetails.title}</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="border-custom-border border-b border-solid self-stretch w-full h-0.5 mt-3" />
|
<div className="border-b border-custom-border-200 self-stretch w-full h-0.5 mt-3" />
|
||||||
<div className="flex flex-col max-md:max-w-full">
|
<div className="flex flex-col h-full w-full max-md:max-w-full">
|
||||||
<EditorContainer editor={editor} editorClassNames={editorClassNames}>
|
<EditorContainer editor={editor} editorClassNames={editorClassNames}>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col h-full w-full">
|
||||||
<EditorContentWrapper editor={editor} editorContentCustomClassNames={editorContentCustomClassNames} />
|
<EditorContentWrapper
|
||||||
|
editor={editor}
|
||||||
|
editorContentCustomClassNames={editorContentCustomClassNames}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</EditorContainer >
|
</EditorContainer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
@ -38,7 +38,7 @@ export const CreateUpdatePageModal: FC<Props> = (props) => {
|
|||||||
const createProjectPage = async (payload: IPage) => {
|
const createProjectPage = async (payload: IPage) => {
|
||||||
if (!workspaceSlug) return;
|
if (!workspaceSlug) return;
|
||||||
|
|
||||||
createPage(workspaceSlug.toString(), projectId, payload)
|
await createPage(workspaceSlug.toString(), projectId, payload)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
router.push(`/${workspaceSlug}/projects/${projectId}/pages/${res.id}`);
|
router.push(`/${workspaceSlug}/projects/${projectId}/pages/${res.id}`);
|
||||||
onClose();
|
onClose();
|
||||||
@ -67,7 +67,7 @@ export const CreateUpdatePageModal: FC<Props> = (props) => {
|
|||||||
const updateProjectPage = async (payload: IPage) => {
|
const updateProjectPage = async (payload: IPage) => {
|
||||||
if (!data || !workspaceSlug) return;
|
if (!data || !workspaceSlug) return;
|
||||||
|
|
||||||
return updatePage(workspaceSlug.toString(), projectId, data.id, payload)
|
await updatePage(workspaceSlug.toString(), projectId, data.id, payload)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
onClose();
|
onClose();
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { useEffect } from "react";
|
|
||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
// ui
|
// ui
|
||||||
import { Button, Input, Tooltip } from "@plane/ui";
|
import { Button, Input, Tooltip } from "@plane/ui";
|
||||||
// types
|
// types
|
||||||
import { IPage } from "types";
|
import { IPage } from "types";
|
||||||
|
// constants
|
||||||
import { PAGE_ACCESS_SPECIFIERS } from "constants/page";
|
import { PAGE_ACCESS_SPECIFIERS } from "constants/page";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -18,31 +18,21 @@ const defaultValues = {
|
|||||||
access: 0,
|
access: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PageForm: React.FC<Props> = ({ handleFormSubmit, handleClose, data }) => {
|
export const PageForm: React.FC<Props> = (props) => {
|
||||||
|
const { handleFormSubmit, handleClose, data } = props;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
formState: { errors, isSubmitting },
|
formState: { errors, isSubmitting },
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
control,
|
control,
|
||||||
reset,
|
|
||||||
} = useForm<IPage>({
|
} = useForm<IPage>({
|
||||||
defaultValues,
|
defaultValues: { ...defaultValues, ...data },
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleCreateUpdatePage = async (formData: IPage) => {
|
const handleCreateUpdatePage = async (formData: IPage) => {
|
||||||
await handleFormSubmit(formData);
|
await handleFormSubmit(formData);
|
||||||
|
|
||||||
reset({
|
|
||||||
...defaultValues,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
reset({
|
|
||||||
...defaultValues,
|
|
||||||
...data,
|
|
||||||
});
|
|
||||||
}, [data, reset]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit(handleCreateUpdatePage)}>
|
<form onSubmit={handleSubmit(handleCreateUpdatePage)}>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
|
@ -38,8 +38,9 @@ export const RecentPagesList: FC = observer(() => {
|
|||||||
<>
|
<>
|
||||||
{Object.keys(recentProjectPages).map((key) => {
|
{Object.keys(recentProjectPages).map((key) => {
|
||||||
if (recentProjectPages[key].length === 0) return null;
|
if (recentProjectPages[key].length === 0) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={key} className="h-full overflow-hidden pb-9">
|
<div key={key} className="overflow-hidden">
|
||||||
<h2 className="text-xl font-semibold capitalize mb-2">{replaceUnderscoreIfSnakeCase(key)}</h2>
|
<h2 className="text-xl font-semibold capitalize mb-2">{replaceUnderscoreIfSnakeCase(key)}</h2>
|
||||||
<PagesListView pages={recentProjectPages[key]} />
|
<PagesListView pages={recentProjectPages[key]} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -235,7 +235,7 @@ const PageDetailsPage: NextPageWithLayout = () => {
|
|||||||
debouncedUpdatesEnabled={false}
|
debouncedUpdatesEnabled={false}
|
||||||
setIsSubmitting={setIsSubmitting}
|
setIsSubmitting={setIsSubmitting}
|
||||||
value={!value || value === "" ? "<p></p>" : value}
|
value={!value || value === "" ? "<p></p>" : value}
|
||||||
customClassName="tracking-tight self-center w-full max-w-full px-0"
|
customClassName="tracking-tight self-center px-0 h-full w-full"
|
||||||
onChange={(_description_json: Object, description_html: string) => {
|
onChange={(_description_json: Object, description_html: string) => {
|
||||||
onChange(description_html);
|
onChange(description_html);
|
||||||
setIsSubmitting("submitting");
|
setIsSubmitting("submitting");
|
||||||
|
@ -90,7 +90,7 @@ const ProjectPagesPage: NextPageWithLayout = observer(() => {
|
|||||||
projectId={projectId.toString()}
|
projectId={projectId.toString()}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div className="space-y-5 p-8 h-full overflow-hidden flex flex-col">
|
<div className="space-y-5 p-6 h-full overflow-hidden flex flex-col">
|
||||||
<div className="flex gap-4 justify-between">
|
<div className="flex gap-4 justify-between">
|
||||||
<h3 className="text-2xl font-semibold text-custom-text-100">Pages</h3>
|
<h3 className="text-2xl font-semibold text-custom-text-100">Pages</h3>
|
||||||
</div>
|
</div>
|
||||||
|
@ -86,39 +86,67 @@ export class PageStore implements IPageStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get projectPages() {
|
get projectPages() {
|
||||||
if (!this.rootStore.project.projectId) return;
|
const projectId = this.rootStore.project.projectId;
|
||||||
return this.pages?.[this.rootStore.project.projectId] || [];
|
|
||||||
|
if (!projectId || !this.pages[projectId]) return undefined;
|
||||||
|
|
||||||
|
return this.pages?.[projectId] || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
get recentProjectPages() {
|
get recentProjectPages() {
|
||||||
if (!this.rootStore.project.projectId) return;
|
const projectId = this.rootStore.project.projectId;
|
||||||
const data: IRecentPages = { today: [], yesterday: [], this_week: [] };
|
|
||||||
data["today"] = this.pages[this.rootStore.project.projectId]?.filter((p) => isToday(new Date(p.created_at))) || [];
|
if (!projectId) return undefined;
|
||||||
data["yesterday"] =
|
|
||||||
this.pages[this.rootStore.project.projectId]?.filter((p) => isYesterday(new Date(p.created_at))) || [];
|
if (!this.pages[projectId]) return undefined;
|
||||||
|
|
||||||
|
const data: IRecentPages = { today: [], yesterday: [], this_week: [], older: [] };
|
||||||
|
|
||||||
|
data["today"] = this.pages[projectId]?.filter((p) => isToday(new Date(p.created_at))) || [];
|
||||||
|
data["yesterday"] = this.pages[projectId]?.filter((p) => isYesterday(new Date(p.created_at))) || [];
|
||||||
data["this_week"] =
|
data["this_week"] =
|
||||||
this.pages[this.rootStore.project.projectId]?.filter((p) => isThisWeek(new Date(p.created_at))) || [];
|
this.pages[projectId]?.filter(
|
||||||
|
(p) =>
|
||||||
|
isThisWeek(new Date(p.created_at)) && !isToday(new Date(p.created_at)) && !isYesterday(new Date(p.created_at))
|
||||||
|
) || [];
|
||||||
|
data["older"] =
|
||||||
|
this.pages[projectId]?.filter(
|
||||||
|
(p) => !isThisWeek(new Date(p.created_at)) && !isYesterday(new Date(p.created_at))
|
||||||
|
) || [];
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
get favoriteProjectPages() {
|
get favoriteProjectPages() {
|
||||||
if (!this.rootStore.project.projectId) return;
|
const projectId = this.rootStore.project.projectId;
|
||||||
return this.pages[this.rootStore.project.projectId]?.filter((p) => p.is_favorite);
|
|
||||||
|
if (!projectId || !this.pages[projectId]) return undefined;
|
||||||
|
|
||||||
|
return this.pages[projectId]?.filter((p) => p.is_favorite);
|
||||||
}
|
}
|
||||||
|
|
||||||
get privateProjectPages() {
|
get privateProjectPages() {
|
||||||
if (!this.rootStore.project.projectId) return;
|
const projectId = this.rootStore.project.projectId;
|
||||||
return this.pages[this.rootStore.project.projectId]?.filter((p) => p.access === 1);
|
|
||||||
|
if (!projectId || !this.pages[projectId]) return undefined;
|
||||||
|
|
||||||
|
return this.pages[projectId]?.filter((p) => p.access === 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
get sharedProjectPages() {
|
get sharedProjectPages() {
|
||||||
if (!this.rootStore.project.projectId) return;
|
const projectId = this.rootStore.project.projectId;
|
||||||
return this.pages[this.rootStore.project.projectId]?.filter((p) => p.access === 0);
|
|
||||||
|
if (!projectId || !this.pages[projectId]) return undefined;
|
||||||
|
|
||||||
|
return this.pages[projectId]?.filter((p) => p.access === 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
get archivedProjectPages() {
|
get archivedProjectPages() {
|
||||||
if (!this.rootStore.project.projectId) return;
|
const projectId = this.rootStore.project.projectId;
|
||||||
return this.archivedPages[this.rootStore.project.projectId];
|
|
||||||
|
if (!projectId || !this.archivedPages[projectId]) return undefined;
|
||||||
|
|
||||||
|
return this.archivedPages[projectId];
|
||||||
}
|
}
|
||||||
|
|
||||||
addToFavorites = async (workspaceSlug: string, projectId: string, pageId: string) => {
|
addToFavorites = async (workspaceSlug: string, projectId: string, pageId: string) => {
|
||||||
|
1
web/types/pages.d.ts
vendored
1
web/types/pages.d.ts
vendored
@ -30,6 +30,7 @@ export interface IRecentPages {
|
|||||||
today: IPage[];
|
today: IPage[];
|
||||||
yesterday: IPage[];
|
yesterday: IPage[];
|
||||||
this_week: IPage[];
|
this_week: IPage[];
|
||||||
|
older: IPage[];
|
||||||
[key: string]: IPage[];
|
[key: string]: IPage[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user