Skip to content

Commit

Permalink
🔧 WOR-4 Refactor global states
Browse files Browse the repository at this point in the history
  • Loading branch information
steeeee0223 committed Nov 28, 2024
1 parent df9b1ae commit 29dadca
Show file tree
Hide file tree
Showing 34 changed files with 1,371 additions and 62 deletions.
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export * from "./base-layout";
export * from "./liveblocks-layout";
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useTree, type TreeItemData } from "@swy/ui/shared";

const fetcher = () => Promise.resolve(documents);

export const usePages = (workspaceId: string) => {
export const usePages = (workspaceId: string | null) => {
const tree = useTree();
const [pageId, setPageId] = useState("#");

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import React from "react";

import { createClient, createRoomContext, RoomProvider } from "@swy/liveblocks";
import { Navbar, PageHeader, PageProvider, Sidebar } from "@swy/notion";
import {
Navbar,
PageHeader,
PageProvider,
Sidebar2,
useBoundStore,
WorkspaceSwitcher2,
} from "@swy/notion";
import {
mockConnections,
mockLogs,
Expand Down Expand Up @@ -29,7 +36,13 @@ type LayoutProps = React.PropsWithChildren;
export const LayoutWithLiveblocks = ({ children }: LayoutProps) => {
const { minSize, ref, collapse, expand, isResizing, isMobile, isCollapsed } =
useSidebarLayout("group", "sidebar", 240);
const { pageId, isLoading, fetchPages, selectPage } = usePages("workspace-0");
/** Bound stores */
const activeWorkspace = useBoundStore((state) => state.activeWorkspace);
const workspaces = useBoundStore((state) => state.workspaces);
const user = useBoundStore((state) => state.user);
const setActiveWorkspace = useBoundStore((state) => state.setActiveWorkspace);
const { pageId, isLoading, fetchPages, selectPage } =
usePages(activeWorkspace);

return (
<ResizablePanelGroup
Expand All @@ -47,7 +60,7 @@ export const LayoutWithLiveblocks = ({ children }: LayoutProps) => {
collapsible
order={1}
>
<Sidebar
<Sidebar2
className="w-full"
isMobile={isMobile}
collapse={collapse}
Expand All @@ -57,11 +70,15 @@ export const LayoutWithLiveblocks = ({ children }: LayoutProps) => {
onFetchConnections: () => Promise.resolve(mockConnections),
onFetchMemberships: () => Promise.resolve(mockMemberships),
}}
pageHandlers={{
isLoading,
fetchPages,
}}
workspaceHandlers={{}}
pageHandlers={{ isLoading, fetchPages }}
WorkspaceSwitcher={
<WorkspaceSwitcher2
user={user!}
activeWorkspace={workspaces[activeWorkspace!]!}
workspaces={Object.values(workspaces)}
onSelect={setActiveWorkspace}
/>
}
/>
</ResizablePanel>
<ResizableHandle />
Expand Down
30 changes: 30 additions & 0 deletions apps/storybook/src/stories/playground/use-pages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import useSWR from "swr";

import { useBoundStore, type Page } from "@swy/notion";
import { mockPages } from "@swy/notion/mock";

import { delay } from "@/lib/utils";

const fetcher = async () => {
await delay(2000);
return await Promise.resolve(Object.values(mockPages));
};

export const usePages = (workspaceId: string | null) => {
const activePage = useBoundStore((state) => state.activePage);
const setActivePage = useBoundStore((state) => state.setActivePage);
const setPages = useBoundStore((state) => state.setPages);

const { isLoading } = useSWR<Page[], Error>(workspaceId, fetcher, {
onSuccess: (data) => setPages(data),
onError: (e) => console.log(`[swr:workspace]: ${e.message}`),
});
const fetchPages = () => Promise.resolve(Object.values(mockPages));
const selectPage = (path: string) => {
const [, , id] = path.split("/");
if (!id) return;
setActivePage(id);
};

return { pageId: activePage ?? "#", isLoading, fetchPages, selectPage };
};
46 changes: 28 additions & 18 deletions apps/storybook/src/stories/playground/worxpace.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { useEffect } from "react";
import type { Meta, StoryObj } from "@storybook/react";

import { CollaborativeEditor } from "@swy/liveblocks";
import { WorkspaceProvider } from "@swy/notion";
import { useBoundStore } from "@swy/notion";
import { user, workspaces } from "@swy/notion/mock";
import { ModalProvider } from "@swy/ui/shared";

import { liveblocksAuth } from "@/stories/notion/__mock__";
import { LayoutWithLiveblocks } from "@/stories/notion/workspace-provider/_components";
import { LayoutWithLiveblocks } from "./liveblocks-layout";

const meta = {
title: "Playground",
Expand All @@ -19,21 +20,30 @@ export default meta;

type Story = StoryObj<typeof meta>;

const Template: Story["render"] = () => {
const setWorkspaces = useBoundStore((state) => state.setWorkspaces);
const setUser = useBoundStore((state) => state.setUser);
const setActiveWorkspace = useBoundStore((state) => state.setActiveWorkspace);
const setActivePage = useBoundStore((state) => state.setActivePage);
useEffect(() => {
setWorkspaces(workspaces);
setUser(user);
setActiveWorkspace(workspaces[0]!.id);
setActivePage("#");
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return (
<ModalProvider>
<div className="flex h-screen bg-main">
<LayoutWithLiveblocks>
<CollaborativeEditor />
</LayoutWithLiveblocks>
</div>
</ModalProvider>
);
};

export const Playground: Story = {
render: () => (
<WorkspaceProvider
user={user}
workspaces={workspaces}
initial="workspace-0"
className="h-full"
>
<ModalProvider>
<div className="flex h-screen bg-main">
<LayoutWithLiveblocks>
<CollaborativeEditor />
</LayoutWithLiveblocks>
</div>
</ModalProvider>
</WorkspaceProvider>
),
render: Template,
};
13 changes: 4 additions & 9 deletions apps/worxpace/src/lib/data-transfer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { format } from "date-fns";

import type {
DocItemData,
Page,
Expand Down Expand Up @@ -40,10 +38,6 @@ export function toIcon(info: IconInfo): Icon | null {
}
}

export function toDateString(date: Date | string | number): string {
return format(new Date(date), "MMM d, yyyy 'at' h:mm a");
}

export function toDocItem(doc: DetailedDocument): DocItemData {
return {
id: doc.id,
Expand All @@ -52,14 +46,15 @@ export function toDocItem(doc: DetailedDocument): DocItemData {
icon: toIconInfo(doc.icon),
group: doc.isArchived ? `trash:${doc.type}` : doc.type,
lastEditedBy: doc.updatedBy.preferredName,
lastEditedAt: doc.updatedAt.getMilliseconds(),
lastEditedAt: doc.updatedAt.getUTCMilliseconds(),
};
}

export function toPage(doc?: DetailedDocument): Page | null {
return doc
? {
id: doc.id,
parentId: doc.parentId,
title: doc.title,
type: doc.type,
isArchived: doc.isArchived,
Expand All @@ -68,8 +63,8 @@ export function toPage(doc?: DetailedDocument): Page | null {
coverImage: doc.coverImage,
createdBy: doc.createdBy.preferredName,
lastEditedBy: doc.updatedBy.preferredName,
createdAt: toDateString(doc.createdAt),
lastEditedAt: toDateString(doc.updatedAt),
createdAt: doc.createdAt.getUTCMilliseconds(),
lastEditedAt: doc.updatedAt.getUTCMilliseconds(),
}
: null;
}
Expand Down
4 changes: 2 additions & 2 deletions packages/notion/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
Note: There are several components that require context dependencies.

1. Components requiring `ModalProvider`: `Sidebar`
2. Components requiring `WorpsaceProvider`: `Sidebar`, `WorkspaceSwitcher`
3. Components requiring `TreeProvider`: `Sidebar`
2. `Deprecated` Components requiring `WorpsaceProvider`: `Sidebar`, `WorkspaceSwitcher`
3. `Deprecated` Components requiring `TreeProvider`: `Sidebar`
4. Components requiring `PageProvider`: `Navbar`, `PageHeader`
40 changes: 22 additions & 18 deletions packages/notion/src/__mock__/workspaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { Plan, Role } from "@swy/validators";

import { mockUsers } from "./users";

const getRandomTs = () =>
randomInt(Date.UTC(2024, 1, 1), Date.UTC(2024, 10, 31));

export const documents: DocItemData[] = [
{
group: "document",
Expand All @@ -16,15 +19,15 @@ export const documents: DocItemData[] = [
url: "https://img.freepik.com/premium-vector/line-art-flag-language-korean-illustration-vector_490632-422.jpg",
},
lastEditedBy: "",
lastEditedAt: randomInt(1704067200000, 1730332800000),
lastEditedAt: getRandomTs(),
},
{
group: "document",
id: "page2",
title: "Pronunciation",
parentId: "page1",
lastEditedBy: "",
lastEditedAt: randomInt(1704067200000, 1730332800000),
lastEditedAt: getRandomTs(),
},
{
group: "document",
Expand All @@ -33,7 +36,7 @@ export const documents: DocItemData[] = [
parentId: null,
icon: { type: "lucide", name: "book", color: "#CB912F" },
lastEditedBy: "",
lastEditedAt: randomInt(1704067200000, 1730332800000),
lastEditedAt: getRandomTs(),
},
{
group: "document",
Expand All @@ -42,15 +45,15 @@ export const documents: DocItemData[] = [
icon: { type: "lucide", name: "book-check", color: "#CB912F" },
parentId: null,
lastEditedBy: "",
lastEditedAt: randomInt(1704067200000, 1730332800000),
lastEditedAt: getRandomTs(),
},
{
group: "document",
id: "page5",
title: "System flowchart",
parentId: null,
lastEditedBy: "",
lastEditedAt: randomInt(1704067200000, 1730332800000),
lastEditedAt: getRandomTs(),
},
{
group: "trash:document",
Expand All @@ -59,23 +62,23 @@ export const documents: DocItemData[] = [
parentId: null,
icon: { type: "lucide", name: "book", color: "#337EA9" },
lastEditedBy: "",
lastEditedAt: randomInt(1704067200000, 1730332800000),
lastEditedAt: getRandomTs(),
},
{
group: "kanban",
id: "page7",
title: "TODO List",
parentId: null,
lastEditedBy: "",
lastEditedAt: randomInt(1704067200000, 1730332800000),
lastEditedAt: getRandomTs(),
},
{
group: "whiteboard",
id: "page8",
title: "System flowchart",
parentId: null,
lastEditedBy: "",
lastEditedAt: randomInt(1704067200000, 1730332800000),
lastEditedAt: getRandomTs(),
},
{
group: "document",
Expand All @@ -87,7 +90,7 @@ export const documents: DocItemData[] = [
url: "https://cdn.iconscout.com/icon/premium/png-256-thumb/bar-table-1447763-1224177.png",
},
lastEditedBy: "",
lastEditedAt: randomInt(1704067200000, 1730332800000),
lastEditedAt: getRandomTs(),
},
{
group: "document",
Expand All @@ -96,7 +99,7 @@ export const documents: DocItemData[] = [
title: "The Continental",
icon: { type: "emoji", emoji: "🏠" },
lastEditedBy: "",
lastEditedAt: randomInt(1704067200000, 1730332800000),
lastEditedAt: getRandomTs(),
},
];

Expand Down Expand Up @@ -138,18 +141,19 @@ export const workspaces: Workspace[] = [

export const otherUsers = mockUsers.slice(2, 7);

const createPageData = (treeItem: DocItemData): Page => {
const res = treeItem.group!.split(":");
const createPageData = (item: DocItemData): Page => {
const res = item.group!.split(":");
return {
id: treeItem.id,
type: res.length > 1 ? res[1]! : treeItem.group!,
title: treeItem.title,
icon: treeItem.icon ?? null,
id: item.id,
parentId: item.parentId ?? null,
type: res.length > 1 ? res[1]! : item.group!,
title: item.title,
icon: item.icon ?? null,
isArchived: res.length > 1,
coverImage: null,
isPublished: false,
createdAt: Date.UTC(2023, 3, 5).toString(),
lastEditedAt: treeItem.lastEditedAt.toString(),
createdAt: Date.UTC(2023, 3, 5),
lastEditedAt: item.lastEditedAt,
createdBy: user.name,
lastEditedBy: user.name,
};
Expand Down
9 changes: 9 additions & 0 deletions packages/notion/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
export * from "./navbar";
export * from "./page-header";
export * from "./settings-panel";
/**
* @deprecated use `Sidebar2` instead
*/
export * from "./sidebar";
export * from "./sidebar-2";
export * from "./tables";
/**
* @deprecated use `WorkspaceSwitcher2` instead
*/
export * from "./workspace-switcher";
export * from "./workspace-switcher-2";
/** Providers */
export * from "./page-provider";
export * from "./workspace-provider";
/** Utils */
export * from "./common";
export * from "./scopes";
export * from "./slices";
/** Types */
export * from "./types";
3 changes: 2 additions & 1 deletion packages/notion/src/navbar/_components/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from "@swy/ui/shadcn";
import { Hint } from "@swy/ui/shared";

import { toDateString } from "../../common";
import type { PageContextInterface } from "../../page-provider";
import type { Page } from "../../types";

Expand Down Expand Up @@ -44,7 +45,7 @@ export const Menu = ({ page, onChangeState }: MenuProps) => {
<DropdownMenuSeparator />
<div className="flex flex-col items-center px-2 py-1 text-xs text-muted dark:text-muted-dark">
<div className="w-full">Last edited by: {page.lastEditedBy}</div>
<div className="w-full">{page.lastEditedAt}</div>
<div className="w-full">{toDateString(page.lastEditedAt)}</div>
</div>
</DropdownMenuContent>
</DropdownMenu>
Expand Down
Loading

0 comments on commit 29dadca

Please sign in to comment.