From eb0877a3c8244a2b2b22dfac0dbb93e856fe1d26 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Wed, 1 May 2024 18:10:39 +0530 Subject: [PATCH] [WEB-1135] chore: store page full width information in local storage (#4327) * chore: store page full width information in local storage * chore: update page types --- packages/types/src/pages.d.ts | 5 --- web/components/pages/editor/editor-body.tsx | 4 +- .../pages/editor/header/mobile-root.tsx | 7 +++- .../pages/editor/header/options-dropdown.tsx | 31 +++----------- web/components/pages/editor/header/root.tsx | 7 +++- web/hooks/use-page-filters.ts | 12 ++++++ web/store/pages/page.store.ts | 40 +------------------ 7 files changed, 32 insertions(+), 74 deletions(-) create mode 100644 web/hooks/use-page-filters.ts diff --git a/packages/types/src/pages.d.ts b/packages/types/src/pages.d.ts index a1df4527e..4871ddc06 100644 --- a/packages/types/src/pages.d.ts +++ b/packages/types/src/pages.d.ts @@ -16,14 +16,9 @@ export type TPage = { project: string | undefined; updated_at: Date | undefined; updated_by: string | undefined; - view_props: TPageViewProps | undefined; workspace: string | undefined; }; -export type TPageViewProps = { - full_width?: boolean; -}; - // page filters export type TPageNavigationTabs = "public" | "private" | "archived"; diff --git a/web/components/pages/editor/editor-body.tsx b/web/components/pages/editor/editor-body.tsx index 3f3877b5c..f1e38348b 100644 --- a/web/components/pages/editor/editor-body.tsx +++ b/web/components/pages/editor/editor-body.tsx @@ -18,6 +18,7 @@ import { PageContentBrowser, PageEditorTitle } from "@/components/pages"; import { cn } from "@/helpers/common.helper"; // hooks import { useMember, useMention, useUser, useWorkspace } from "@/hooks/store"; +import { usePageFilters } from "@/hooks/use-page-filters"; import useReloadConfirmations from "@/hooks/use-reload-confirmation"; // services import { FileService } from "@/services/file.service"; @@ -68,7 +69,6 @@ export const PageEditorBody: React.FC = observer((props) => { const workspaceId = workspaceSlug ? getWorkspaceBySlug(workspaceSlug.toString())?.id ?? "" : ""; const pageTitle = pageStore?.name ?? ""; const pageDescription = pageStore?.description_html ?? "

"; - const isFullWidth = !!pageStore?.view_props?.full_width; const { description_html, isContentEditable, updateTitle, isSubmitting, setIsSubmitting } = pageStore; const projectMemberIds = projectId ? getProjectMemberIds(projectId.toString()) : []; const projectMemberDetails = projectMemberIds?.map((id) => getUserDetails(id) as IUserLite); @@ -79,6 +79,8 @@ export const PageEditorBody: React.FC = observer((props) => { members: projectMemberDetails, user: currentUser ?? undefined, }); + // page filters + const { isFullWidth } = usePageFilters(); const { setShowAlert } = useReloadConfirmations(isSubmitting === "submitting"); diff --git a/web/components/pages/editor/header/mobile-root.tsx b/web/components/pages/editor/header/mobile-root.tsx index 59b33c335..de0425879 100644 --- a/web/components/pages/editor/header/mobile-root.tsx +++ b/web/components/pages/editor/header/mobile-root.tsx @@ -2,6 +2,8 @@ import { observer } from "mobx-react"; import { EditorReadOnlyRefApi, EditorRefApi, IMarking } from "@plane/document-editor"; // components import { PageExtraOptions, PageSummaryPopover, PageToolbar } from "@/components/pages"; +// hooks +import { usePageFilters } from "@/hooks/use-page-filters"; // store import { IPageStore } from "@/store/pages/page.store"; @@ -34,8 +36,9 @@ export const PageEditorMobileHeaderRoot: React.FC = observer((props) => { setSidePeekVisible, } = props; // derived values - const { isContentEditable, view_props } = pageStore; - const isFullWidth = !!view_props?.full_width; + const { isContentEditable } = pageStore; + // page filters + const { isFullWidth } = usePageFilters(); if (!editorRef.current && !readOnlyEditorRef.current) return null; diff --git a/web/components/pages/editor/header/options-dropdown.tsx b/web/components/pages/editor/header/options-dropdown.tsx index 11be54740..dedf94a3b 100644 --- a/web/components/pages/editor/header/options-dropdown.tsx +++ b/web/components/pages/editor/header/options-dropdown.tsx @@ -4,13 +4,11 @@ import { ArchiveRestoreIcon, Clipboard, Copy, Link, Lock, LockOpen } from "lucid import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/document-editor"; // ui import { ArchiveIcon, CustomMenu, TOAST_TYPE, ToggleSwitch, setToast } from "@plane/ui"; -// constants -import { EUserProjectRoles } from "@/constants/project"; // helpers -import { cn } from "@/helpers/common.helper"; import { copyTextToClipboard, copyUrlToClipboard } from "@/helpers/string.helper"; // hooks -import { useApplication, useUser } from "@/hooks/store"; +import { useApplication } from "@/hooks/store"; +import { usePageFilters } from "@/hooks/use-page-filters"; // store import { IPageStore } from "@/store/pages/page.store"; @@ -34,18 +32,13 @@ export const PageOptionsDropdown: React.FC = observer((props) => { canCurrentUserDuplicatePage, canCurrentUserLockPage, restore, - view_props, - updateViewProps, } = pageStore; // store hooks const { router: { workspaceSlug, projectId }, } = useApplication(); - const { - membership: { currentProjectRole }, - } = useUser(); - // auth - const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER; + // page filters + const { isFullWidth, handleFullWidth } = usePageFilters(); const handleArchivePage = async () => await archive().catch(() => @@ -149,22 +142,10 @@ export const PageOptionsDropdown: React.FC = observer((props) => { - updateViewProps({ - full_width: !view_props?.full_width, - }) - } - disabled={!isEditingAllowed} + onClick={() => handleFullWidth(!isFullWidth)} > Full width - {}} - className={cn({ - "opacity-40": !isEditingAllowed, - })} - disabled={!isEditingAllowed} - /> + {}} /> {MENU_ITEMS.map((item) => { if (!item.shouldRender) return null; diff --git a/web/components/pages/editor/header/root.tsx b/web/components/pages/editor/header/root.tsx index 9588eb84e..7234f3ad4 100644 --- a/web/components/pages/editor/header/root.tsx +++ b/web/components/pages/editor/header/root.tsx @@ -4,6 +4,8 @@ import { EditorReadOnlyRefApi, EditorRefApi, IMarking } from "@plane/document-ed import { PageEditorMobileHeaderRoot, PageExtraOptions, PageSummaryPopover, PageToolbar } from "@/components/pages"; // helpers import { cn } from "@/helpers/common.helper"; +// hooks +import { usePageFilters } from "@/hooks/use-page-filters"; // store import { IPageStore } from "@/store/pages/page.store"; @@ -36,8 +38,9 @@ export const PageEditorHeaderRoot: React.FC = observer((props) => { setSidePeekVisible, } = props; // derived values - const { isContentEditable, view_props } = pageStore; - const isFullWidth = !!view_props?.full_width; + const { isContentEditable } = pageStore; + // page filters + const { isFullWidth } = usePageFilters(); if (!editorRef.current && !readOnlyEditorRef.current) return null; diff --git a/web/hooks/use-page-filters.ts b/web/hooks/use-page-filters.ts new file mode 100644 index 000000000..4c8e5128c --- /dev/null +++ b/web/hooks/use-page-filters.ts @@ -0,0 +1,12 @@ +// hooks +import useLocalStorage from "@/hooks/use-local-storage"; + +export const usePageFilters = () => { + const { storedValue: isFullWidth, setValue: setFullWidth } = useLocalStorage("page_full_width", true); + const handleFullWidth = (value: boolean) => setFullWidth(value); + + return { + isFullWidth: !!isFullWidth, + handleFullWidth, + }; +}; diff --git a/web/store/pages/page.store.ts b/web/store/pages/page.store.ts index c901e4e87..d3f0877c6 100644 --- a/web/store/pages/page.store.ts +++ b/web/store/pages/page.store.ts @@ -1,7 +1,7 @@ import set from "lodash/set"; import { action, computed, makeObservable, observable, reaction, runInAction } from "mobx"; // types -import { TPage, TPageViewProps } from "@plane/types"; +import { TPage } from "@plane/types"; // constants import { EPageAccess } from "@/constants/page"; import { EUserProjectRoles } from "@/constants/project"; @@ -33,7 +33,6 @@ export interface IPageStore extends TPage { cleanup: () => void; // actions update: (pageData: Partial) => Promise; - updateViewProps: (viewProps: Partial) => void; makePublic: () => Promise; makePrivate: () => Promise; lock: () => Promise; @@ -65,7 +64,6 @@ export class PageStore implements IPageStore { updated_by: string | undefined; created_at: Date | undefined; updated_at: Date | undefined; - view_props: TPageViewProps | undefined; // helpers oldName: string = ""; // reactions @@ -93,7 +91,6 @@ export class PageStore implements IPageStore { this.updated_by = page?.updated_by || undefined; this.created_at = page?.created_at || undefined; this.updated_at = page?.updated_at || undefined; - this.view_props = page?.view_props || undefined; this.oldName = page?.name || ""; makeObservable(this, { @@ -117,7 +114,6 @@ export class PageStore implements IPageStore { updated_by: observable.ref, created_at: observable.ref, updated_at: observable.ref, - view_props: observable, // helpers oldName: observable, // computed @@ -137,7 +133,6 @@ export class PageStore implements IPageStore { cleanup: action, // actions update: action, - updateViewProps: action, makePublic: action, makePrivate: action, lock: action, @@ -216,7 +211,6 @@ export class PageStore implements IPageStore { updated_by: this.updated_by, created_at: this.created_at, updated_at: this.updated_at, - view_props: this.view_props, }; } @@ -338,38 +332,6 @@ export class PageStore implements IPageStore { } }; - /** - * @description update the page view props - * @param {Partial} updatedProps - */ - updateViewProps = async (updatedProps: Partial) => { - const { workspaceSlug, projectId } = this.store.app.router; - if (!workspaceSlug || !projectId || !this.id) return undefined; - - const currentViewProps = { ...this.view_props }; - - runInAction(() => { - Object.keys(updatedProps).forEach((key) => { - const currentPageKey = key as keyof TPageViewProps; - if (this.view_props) set(this.view_props, key, updatedProps[currentPageKey]); - }); - }); - - try { - await this.pageService.update(workspaceSlug, projectId, this.id, { - view_props: { - ...this.view_props, - ...updatedProps, - }, - }); - } catch (error) { - runInAction(() => { - this.view_props = currentViewProps; - }); - throw error; - } - }; - /** * @description make the page public */