mirror of
https://github.com/Shadowfita/docmost.git
synced 2025-11-10 04:22:00 +10:00
working page tree
This commit is contained in:
@ -22,6 +22,7 @@ import { SearchSpotlight } from "@/features/search/search-spotlight";
|
||||
import { treeApiAtom } from "@/features/page/tree/atoms/tree-api-atom";
|
||||
import PageTree from "@/features/page/tree/page-tree";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import SpaceContent from "@/features/page/component/space-content.tsx";
|
||||
|
||||
interface PrimaryMenuItem {
|
||||
icon: React.ElementType;
|
||||
@ -103,7 +104,8 @@ export function Navbar() {
|
||||
</Group>
|
||||
|
||||
<div className={classes.pages}>
|
||||
<PageTree />
|
||||
<SpaceContent />
|
||||
{/* <PageTree /> */}
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@ -1,19 +1,18 @@
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import React from 'react';
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import React from "react";
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
refetchOnMount: false,
|
||||
refetchOnWindowFocus: false,
|
||||
retry: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export function TanstackProvider({ children }: React.PropsWithChildren) {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
{children}
|
||||
</QueryClientProvider>
|
||||
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,17 +1,20 @@
|
||||
import '@/features/editor/styles/index.css';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { EditorContent, useEditor } from '@tiptap/react';
|
||||
import { Document } from '@tiptap/extension-document';
|
||||
import { Heading } from '@tiptap/extension-heading';
|
||||
import { Text } from '@tiptap/extension-text';
|
||||
import { Placeholder } from '@tiptap/extension-placeholder';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { pageEditorAtom, titleEditorAtom } from '@/features/editor/atoms/editor-atoms';
|
||||
import { useUpdatePageMutation } from '@/features/page/queries/page-query';
|
||||
import { useDebouncedValue } from '@mantine/hooks';
|
||||
import { useAtom } from 'jotai';
|
||||
import { treeDataAtom } from '@/features/page/tree/atoms/tree-data-atom';
|
||||
import { updateTreeNodeName } from '@/features/page/tree/utils';
|
||||
import "@/features/editor/styles/index.css";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { EditorContent, useEditor } from "@tiptap/react";
|
||||
import { Document } from "@tiptap/extension-document";
|
||||
import { Heading } from "@tiptap/extension-heading";
|
||||
import { Text } from "@tiptap/extension-text";
|
||||
import { Placeholder } from "@tiptap/extension-placeholder";
|
||||
import { useAtomValue } from "jotai";
|
||||
import {
|
||||
pageEditorAtom,
|
||||
titleEditorAtom,
|
||||
} from "@/features/editor/atoms/editor-atoms";
|
||||
import { useUpdatePageMutation } from "@/features/page/queries/page-query";
|
||||
import { useDebouncedValue } from "@mantine/hooks";
|
||||
import { useAtom } from "jotai";
|
||||
import { treeDataAtom } from "@/features/page/tree/atoms/tree-data-atom";
|
||||
import { updateTreeNodeName } from "@/features/page/tree/utils";
|
||||
|
||||
export interface TitleEditorProps {
|
||||
pageId: string;
|
||||
@ -19,7 +22,7 @@ export interface TitleEditorProps {
|
||||
}
|
||||
|
||||
export function TitleEditor({ pageId, title }: TitleEditorProps) {
|
||||
const [debouncedTitleState, setDebouncedTitleState] = useState('');
|
||||
const [debouncedTitleState, setDebouncedTitleState] = useState("");
|
||||
const [debouncedTitle] = useDebouncedValue(debouncedTitleState, 1000);
|
||||
const updatePageMutation = useUpdatePageMutation();
|
||||
const pageEditor = useAtomValue(pageEditorAtom);
|
||||
@ -29,14 +32,14 @@ export function TitleEditor({ pageId, title }: TitleEditorProps) {
|
||||
const titleEditor = useEditor({
|
||||
extensions: [
|
||||
Document.extend({
|
||||
content: 'heading',
|
||||
content: "heading",
|
||||
}),
|
||||
Heading.configure({
|
||||
levels: [1],
|
||||
}),
|
||||
Text,
|
||||
Placeholder.configure({
|
||||
placeholder: 'Untitled',
|
||||
placeholder: "Untitled",
|
||||
}),
|
||||
],
|
||||
onCreate({ editor }) {
|
||||
@ -53,8 +56,8 @@ export function TitleEditor({ pageId, title }: TitleEditorProps) {
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (debouncedTitle !== '') {
|
||||
updatePageMutation.mutate({ id: pageId, title: debouncedTitle });
|
||||
if (debouncedTitle !== "") {
|
||||
updatePageMutation.mutate({ pageId, title: debouncedTitle });
|
||||
|
||||
const newTreeData = updateTreeNodeName(treeData, pageId, debouncedTitle);
|
||||
setTreeData(newTreeData);
|
||||
@ -69,7 +72,7 @@ export function TitleEditor({ pageId, title }: TitleEditorProps) {
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
titleEditor?.commands.focus('end');
|
||||
titleEditor?.commands.focus("end");
|
||||
}, 500);
|
||||
}, [titleEditor]);
|
||||
|
||||
@ -79,15 +82,15 @@ export function TitleEditor({ pageId, title }: TitleEditorProps) {
|
||||
const { key } = event;
|
||||
const { $head } = titleEditor.state.selection;
|
||||
|
||||
const shouldFocusEditor = (key === 'Enter' || key === 'ArrowDown') ||
|
||||
(key === 'ArrowRight' && !$head.nodeAfter);
|
||||
const shouldFocusEditor =
|
||||
key === "Enter" ||
|
||||
key === "ArrowDown" ||
|
||||
(key === "ArrowRight" && !$head.nodeAfter);
|
||||
|
||||
if (shouldFocusEditor) {
|
||||
pageEditor.commands.focus('start');
|
||||
pageEditor.commands.focus("start");
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<EditorContent editor={titleEditor} onKeyDown={handleTitleKeyDown} />
|
||||
);
|
||||
return <EditorContent editor={titleEditor} onKeyDown={handleTitleKeyDown} />;
|
||||
}
|
||||
|
||||
64
apps/client/src/features/page/component/space-content.tsx
Normal file
64
apps/client/src/features/page/component/space-content.tsx
Normal file
@ -0,0 +1,64 @@
|
||||
import { useSpaceQuery } from "@/features/space/queries/space-query.ts";
|
||||
import { useAtom } from "jotai/index";
|
||||
import { currentUserAtom } from "@/features/user/atoms/current-user-atom.ts";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionControlProps,
|
||||
ActionIcon,
|
||||
Center,
|
||||
rem,
|
||||
Tooltip,
|
||||
} from "@mantine/core";
|
||||
import { IconPlus } from "@tabler/icons-react";
|
||||
import React from "react";
|
||||
import { treeApiAtom } from "@/features/page/tree/atoms/tree-api-atom.ts";
|
||||
import PageTree from "@/features/page/tree/page-tree.tsx";
|
||||
|
||||
export default function SpaceContent() {
|
||||
const [currentUser] = useAtom(currentUserAtom);
|
||||
const { data: space } = useSpaceQuery(currentUser?.workspace.defaultSpaceId);
|
||||
|
||||
if (!space) {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Accordion
|
||||
chevronPosition="left"
|
||||
maw={400}
|
||||
mx="auto"
|
||||
defaultValue={space.id}
|
||||
>
|
||||
<Accordion.Item key={space.id} value={space.id}>
|
||||
<AccordionControl>{space.name}</AccordionControl>
|
||||
<Accordion.Panel>
|
||||
<PageTree spaceId={space.id} />
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
</Accordion>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function AccordionControl(props: AccordionControlProps) {
|
||||
const [tree] = useAtom(treeApiAtom);
|
||||
|
||||
function handleCreatePage() {
|
||||
tree?.create({ parentId: null, type: "internal", index: 0 });
|
||||
}
|
||||
|
||||
return (
|
||||
<Center>
|
||||
<Accordion.Control {...props} />
|
||||
{/* <ActionIcon size="lg" variant="subtle" color="gray">
|
||||
<IconDots size="1rem" />
|
||||
</ActionIcon> */}
|
||||
<Tooltip label="Create page" withArrow position="right">
|
||||
<ActionIcon variant="default" size={18} onClick={handleCreatePage}>
|
||||
<IconPlus style={{ width: rem(12), height: rem(12) }} stroke={1.5} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
</Center>
|
||||
);
|
||||
}
|
||||
@ -1,17 +1,14 @@
|
||||
import {
|
||||
useMutation,
|
||||
useQuery,
|
||||
UseQueryResult,
|
||||
} from "@tanstack/react-query";
|
||||
import { useMutation, useQuery, UseQueryResult } from "@tanstack/react-query";
|
||||
import {
|
||||
createPage,
|
||||
deletePage,
|
||||
getPageById,
|
||||
getPages,
|
||||
getRecentChanges,
|
||||
getSpacePageOrder,
|
||||
updatePage,
|
||||
} from "@/features/page/services/page-service";
|
||||
import { IPage } from "@/features/page/types/page.types";
|
||||
import { IPage, IWorkspacePageOrder } from "@/features/page/types/page.types";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
|
||||
const RECENT_CHANGES_KEY = ["recentChanges"];
|
||||
@ -25,10 +22,12 @@ export function usePageQuery(pageId: string): UseQueryResult<IPage, Error> {
|
||||
});
|
||||
}
|
||||
|
||||
export function useGetPagesQuery(): UseQueryResult<IPage[], Error> {
|
||||
export function useGetPagesQuery(
|
||||
spaceId: string,
|
||||
): UseQueryResult<IPage[], Error> {
|
||||
return useQuery({
|
||||
queryKey: ["pages"],
|
||||
queryFn: () => getPages(),
|
||||
queryKey: ["pages", spaceId],
|
||||
queryFn: () => getPages(spaceId),
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
@ -63,3 +62,14 @@ export function useDeletePageMutation() {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export default function useSpacePageOrder(
|
||||
spaceId: string,
|
||||
): UseQueryResult<IWorkspacePageOrder> {
|
||||
return useQuery({
|
||||
queryKey: ["page-order", spaceId],
|
||||
queryFn: async () => {
|
||||
return await getSpacePageOrder(spaceId);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,28 +1,36 @@
|
||||
import api from '@/lib/api-client';
|
||||
import { IMovePage, IPage, IWorkspacePageOrder } from '@/features/page/types/page.types';
|
||||
import api from "@/lib/api-client";
|
||||
import {
|
||||
IMovePage,
|
||||
IPage,
|
||||
IWorkspacePageOrder,
|
||||
} from "@/features/page/types/page.types";
|
||||
|
||||
export async function createPage(data: Partial<IPage>): Promise<IPage> {
|
||||
const req = await api.post<IPage>('/pages/create', data);
|
||||
const req = await api.post<IPage>("/pages/create", data);
|
||||
return req.data as IPage;
|
||||
}
|
||||
|
||||
export async function getPageById(id: string): Promise<IPage> {
|
||||
const req = await api.post<IPage>('/pages/info', { id });
|
||||
export async function getPageById(pageId: string): Promise<IPage> {
|
||||
const req = await api.post<IPage>("/pages/info", { pageId });
|
||||
return req.data as IPage;
|
||||
}
|
||||
|
||||
export async function getRecentChanges(): Promise<IPage[]> {
|
||||
const req = await api.post<IPage[]>('/pages/recent');
|
||||
const req = await api.post<IPage[]>("/pages/recent");
|
||||
return req.data as IPage[];
|
||||
}
|
||||
|
||||
export async function getPages(): Promise<IPage[]> {
|
||||
const req = await api.post<IPage[]>('/pages');
|
||||
export async function getPages(spaceId: string): Promise<IPage[]> {
|
||||
const req = await api.post<IPage[]>("/pages", { spaceId });
|
||||
return req.data as IPage[];
|
||||
}
|
||||
|
||||
export async function getWorkspacePageOrder(): Promise<IWorkspacePageOrder[]> {
|
||||
const req = await api.post<IWorkspacePageOrder[]>('/pages/ordering');
|
||||
export async function getSpacePageOrder(
|
||||
spaceId: string,
|
||||
): Promise<IWorkspacePageOrder[]> {
|
||||
const req = await api.post<IWorkspacePageOrder[]>("/pages/ordering", {
|
||||
spaceId,
|
||||
});
|
||||
return req.data as IWorkspacePageOrder[];
|
||||
}
|
||||
|
||||
@ -32,9 +40,9 @@ export async function updatePage(data: Partial<IPage>): Promise<IPage> {
|
||||
}
|
||||
|
||||
export async function movePage(data: IMovePage): Promise<void> {
|
||||
await api.post<IMovePage>('/pages/move', data);
|
||||
await api.post<IMovePage>("/pages/move", data);
|
||||
}
|
||||
|
||||
export async function deletePage(id: string): Promise<void> {
|
||||
await api.post('/pages/delete', { id });
|
||||
await api.post("/pages/delete", { id });
|
||||
}
|
||||
|
||||
@ -1,21 +1,28 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useMemo } from "react";
|
||||
import {
|
||||
CreateHandler,
|
||||
DeleteHandler,
|
||||
MoveHandler,
|
||||
RenameHandler,
|
||||
SimpleTree,
|
||||
} from 'react-arborist';
|
||||
import { useAtom } from 'jotai';
|
||||
import { treeDataAtom } from '@/features/page/tree/atoms/tree-data-atom';
|
||||
import { movePage } from '@/features/page/services/page-service';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { IMovePage } from '@/features/page/types/page.types';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { TreeNode } from '@/features/page/tree/types';
|
||||
import { useCreatePageMutation, useDeletePageMutation, useUpdatePageMutation } from '@/features/page/queries/page-query';
|
||||
} from "react-arborist";
|
||||
import { useAtom } from "jotai";
|
||||
import { treeDataAtom } from "@/features/page/tree/atoms/tree-data-atom";
|
||||
import { movePage } from "@/features/page/services/page-service";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { IMovePage } from "@/features/page/types/page.types";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { TreeNode } from "@/features/page/tree/types";
|
||||
import {
|
||||
useCreatePageMutation,
|
||||
useDeletePageMutation,
|
||||
useUpdatePageMutation,
|
||||
} from "@/features/page/queries/page-query";
|
||||
|
||||
export function usePersistence<T>() {
|
||||
interface Props {
|
||||
spaceId: string;
|
||||
}
|
||||
export function usePersistence<T>(spaceId: string) {
|
||||
const [data, setData] = useAtom(treeDataAtom);
|
||||
const createPageMutation = useCreatePageMutation();
|
||||
const updatePageMutation = useUpdatePageMutation();
|
||||
@ -25,7 +32,13 @@ export function usePersistence<T>() {
|
||||
|
||||
const tree = useMemo(() => new SimpleTree<TreeNode>(data), [data]);
|
||||
|
||||
const onMove: MoveHandler<T> = (args: { parentId, index, parentNode, dragNodes, dragIds }) => {
|
||||
const onMove: MoveHandler<T> = (args: {
|
||||
parentId;
|
||||
index;
|
||||
parentNode;
|
||||
dragNodes;
|
||||
dragIds;
|
||||
}) => {
|
||||
for (const id of args.dragIds) {
|
||||
tree.move({ id, parentId: args.parentId, index: args.index });
|
||||
}
|
||||
@ -33,25 +46,30 @@ export function usePersistence<T>() {
|
||||
|
||||
const newDragIndex = tree.find(args.dragIds[0])?.childIndex;
|
||||
|
||||
const currentTreeData = args.parentId ? tree.find(args.parentId).children : tree.data;
|
||||
const currentTreeData = args.parentId
|
||||
? tree.find(args.parentId).children
|
||||
: tree.data;
|
||||
const afterId = currentTreeData[newDragIndex - 1]?.id || null;
|
||||
const beforeId = !afterId && currentTreeData[newDragIndex + 1]?.id || null;
|
||||
const beforeId =
|
||||
(!afterId && currentTreeData[newDragIndex + 1]?.id) || null;
|
||||
|
||||
const params: IMovePage = {
|
||||
id: args.dragIds[0],
|
||||
pageId: args.dragIds[0],
|
||||
after: afterId,
|
||||
before: beforeId,
|
||||
parentId: args.parentId || null,
|
||||
};
|
||||
|
||||
const payload = Object.fromEntries(
|
||||
Object.entries(params).filter(([key, value]) => value !== null && value !== undefined),
|
||||
Object.entries(params).filter(
|
||||
([key, value]) => value !== null && value !== undefined,
|
||||
),
|
||||
);
|
||||
|
||||
try {
|
||||
movePage(payload as IMovePage);
|
||||
} catch (error) {
|
||||
console.error('Error moving page:', error);
|
||||
console.error("Error moving page:", error);
|
||||
}
|
||||
};
|
||||
|
||||
@ -60,28 +78,32 @@ export function usePersistence<T>() {
|
||||
setData(tree.data);
|
||||
|
||||
try {
|
||||
updatePageMutation.mutateAsync({ id, title: name });
|
||||
updatePageMutation.mutateAsync({ pageId: id, title: name });
|
||||
} catch (error) {
|
||||
console.error('Error updating page title:', error);
|
||||
console.error("Error updating page title:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const onCreate: CreateHandler<T> = async ({ parentId, index, type }) => {
|
||||
const data = { id: uuidv4(), name: '' } as any;
|
||||
const data = { id: uuidv4(), name: "" } as any;
|
||||
data.children = [];
|
||||
tree.create({ parentId, index, data });
|
||||
setData(tree.data);
|
||||
|
||||
const payload: { id: string; parentPageId?: string } = { id: data.id };
|
||||
const payload: { pageId: string; parentPageId?: string; spaceId: string } =
|
||||
{
|
||||
pageId: data.id,
|
||||
spaceId: spaceId,
|
||||
};
|
||||
if (parentId) {
|
||||
payload.parentPageId = parentId;
|
||||
}
|
||||
|
||||
try {
|
||||
await createPageMutation.mutateAsync(payload);
|
||||
navigate(`/p/${payload.id}`);
|
||||
navigate(`/p/${payload.pageId}`);
|
||||
} catch (error) {
|
||||
console.error('Error creating the page:', error);
|
||||
console.error("Error creating the page:", error);
|
||||
}
|
||||
|
||||
return data;
|
||||
@ -93,9 +115,9 @@ export function usePersistence<T>() {
|
||||
|
||||
try {
|
||||
await deletePageMutation.mutateAsync(args.ids[0]);
|
||||
navigate('/home');
|
||||
navigate("/home");
|
||||
} catch (error) {
|
||||
console.error('Error deleting page:', error);
|
||||
console.error("Error deleting page:", error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
import { useQuery, UseQueryResult } from "@tanstack/react-query";
|
||||
import { IWorkspacePageOrder } from '@/features/page/types/page.types';
|
||||
import { getWorkspacePageOrder } from '@/features/page/services/page-service';
|
||||
|
||||
export default function useWorkspacePageOrder(): UseQueryResult<IWorkspacePageOrder> {
|
||||
return useQuery({
|
||||
queryKey: ["workspace-page-order"],
|
||||
queryFn: async () => {
|
||||
return await getWorkspacePageOrder();
|
||||
},
|
||||
});
|
||||
}
|
||||
@ -23,21 +23,25 @@ import { FillFlexParent } from "./components/fill-flex-parent";
|
||||
import { TreeNode } from "./types";
|
||||
import { treeApiAtom } from "./atoms/tree-api-atom";
|
||||
import { usePersistence } from "@/features/page/tree/hooks/use-persistence";
|
||||
import useWorkspacePageOrder from "@/features/page/tree/hooks/use-workspace-page-order";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { convertToTree, updateTreeNodeIcon } from "@/features/page/tree/utils";
|
||||
import {
|
||||
import useSpacePageOrder, {
|
||||
useGetPagesQuery,
|
||||
useUpdatePageMutation,
|
||||
} from "@/features/page/queries/page-query";
|
||||
import EmojiPicker from "@/components/ui/emoji-picker.tsx";
|
||||
import { treeDataAtom } from "@/features/page/tree/atoms/tree-data-atom";
|
||||
|
||||
export default function PageTree() {
|
||||
const { data, setData, controllers } = usePersistence<TreeApi<TreeNode>>();
|
||||
interface PageTreeProps {
|
||||
spaceId: string;
|
||||
}
|
||||
|
||||
export default function PageTree({ spaceId }: PageTreeProps) {
|
||||
const { data, setData, controllers } =
|
||||
usePersistence<TreeApi<TreeNode>>(spaceId);
|
||||
const [tree, setTree] = useAtom<TreeApi<TreeNode>>(treeApiAtom);
|
||||
const { data: pageOrderData } = useWorkspacePageOrder();
|
||||
const { data: pagesData, isLoading } = useGetPagesQuery();
|
||||
const { data: pageOrderData } = useSpacePageOrder(spaceId);
|
||||
const { data: pagesData, isLoading } = useGetPagesQuery(spaceId);
|
||||
const rootElement = useRef<HTMLDivElement>();
|
||||
const { pageId } = useParams();
|
||||
|
||||
@ -113,12 +117,12 @@ function Node({ node, style, dragHandle }: NodeRendererProps<any>) {
|
||||
|
||||
const handleEmojiSelect = (emoji) => {
|
||||
handleUpdateNodeIcon(node.id, emoji.native);
|
||||
updatePageMutation.mutateAsync({ id: node.id, icon: emoji.native });
|
||||
updatePageMutation.mutateAsync({ pageId: node.id, icon: emoji.native });
|
||||
};
|
||||
|
||||
const handleRemoveEmoji = () => {
|
||||
handleUpdateNodeIcon(node.id, null);
|
||||
updatePageMutation.mutateAsync({ id: node.id, icon: null });
|
||||
updatePageMutation.mutateAsync({ pageId: node.id, icon: null });
|
||||
};
|
||||
|
||||
if (node.willReceiveDrop && node.isClosed) {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
export type TreeNode = {
|
||||
id: string
|
||||
name: string
|
||||
icon?: string
|
||||
slug?: string
|
||||
children: TreeNode[]
|
||||
}
|
||||
id: string;
|
||||
name: string;
|
||||
icon?: string;
|
||||
slug?: string;
|
||||
children: TreeNode[];
|
||||
};
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
export interface IPage {
|
||||
pageId: string;
|
||||
id: string;
|
||||
title: string;
|
||||
content: string;
|
||||
@ -10,9 +11,10 @@ export interface IPage {
|
||||
shareId: string;
|
||||
parentPageId: string;
|
||||
creatorId: string;
|
||||
spaceId: string;
|
||||
workspaceId: string;
|
||||
children:[]
|
||||
childrenIds:[]
|
||||
children: [];
|
||||
childrenIds: [];
|
||||
isLocked: boolean;
|
||||
status: string;
|
||||
publishedAt: Date;
|
||||
@ -22,7 +24,7 @@ export interface IPage {
|
||||
}
|
||||
|
||||
export interface IMovePage {
|
||||
id: string;
|
||||
pageId: string;
|
||||
after?: string;
|
||||
before?: string;
|
||||
parentId?: string;
|
||||
|
||||
@ -1,10 +1,24 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import {
|
||||
useMutation,
|
||||
useQuery,
|
||||
useQueryClient,
|
||||
UseQueryResult,
|
||||
} from "@tanstack/react-query";
|
||||
import {
|
||||
changeMemberRole,
|
||||
getWorkspace,
|
||||
getWorkspaceMembers,
|
||||
} from "@/features/workspace/services/workspace-service";
|
||||
import { QueryParams } from "@/lib/types.ts";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
import { IWorkspace } from "@/features/workspace/types/workspace.types.ts";
|
||||
|
||||
export function useWorkspace(): UseQueryResult<IWorkspace, Error> {
|
||||
return useQuery({
|
||||
queryKey: ["workspace"],
|
||||
queryFn: () => getWorkspace(),
|
||||
});
|
||||
}
|
||||
|
||||
export function useWorkspaceMembersQuery(params?: QueryParams) {
|
||||
return useQuery({
|
||||
|
||||
@ -4,6 +4,7 @@ export interface IWorkspace {
|
||||
description: string;
|
||||
logo: string;
|
||||
hostname: string;
|
||||
defaultSpaceId: string;
|
||||
customDomain: string;
|
||||
enableInvite: boolean;
|
||||
inviteCode: string;
|
||||
|
||||
Reference in New Issue
Block a user