think/packages/client/src/data/document.ts

220 lines
5.4 KiB
TypeScript

import type { IUser, IDocument } from '@think/domains';
import useSWR from 'swr';
import { useState, useCallback, useEffect } from 'react';
import { useAsyncLoading } from 'hooks/useAsyncLoading';
import { HttpClient } from 'services/HttpClient';
import { getPublicDocumentDetail } from 'services/document';
interface IAuthority {
id: string;
documentId: string;
userId: string;
readable: boolean;
editable: boolean;
}
type ICreateDocument = Partial<Pick<IDocument, 'wikiId' | 'parentDocumentId'>>;
type IDocumentWithAuth = { document: IDocument; authority: IAuthority };
type IUpdateDocument = Partial<Pick<IDocument, 'title' | 'content'>>;
/**
* 创建文档
* @returns
*/
export const useCreateDocument = () => {
const [create, loading] = useAsyncLoading((data: ICreateDocument): Promise<IDocument> => {
return HttpClient.post('/document/create', data);
});
return { create, loading };
};
/**
* 更新文档阅读量
* @param id
* @returns
*/
export const updateDocumentViews = (id: string) => {
return HttpClient.get('/document/views/' + id);
};
/**
* 删除文档
* @param id
* @returns
*/
export const useDeleteDocument = (id) => {
const [deleteDocument, loading] = useAsyncLoading((): Promise<IDocument> => {
return HttpClient.delete('/document/delete/' + id);
});
return { deleteDocument, loading };
};
/**
* 获取文档详情
* @param documentId
* @returns
*/
export const useDocumentDetail = (documentId, options = null) => {
const { data, error, mutate } = useSWR<IDocumentWithAuth>(
`/document/detail/${documentId}`,
(url) => HttpClient.get(url),
options
);
const loading = !data && !error;
const update = async (data: IUpdateDocument) => {
const res = await HttpClient.post('/document/update/' + documentId, data);
mutate();
return res;
};
const toggleStatus = async (data: Partial<Pick<IDocument, 'sharePassword'>>) => {
const ret = await HttpClient.post('/document/share/' + documentId, data);
mutate();
return ret;
};
return { data, loading, error, update, toggleStatus };
};
/**
* 获取知识库最近更新的10条文档
* @returns
*/
export const useRecentDocuments = () => {
const { data, error, mutate } = useSWR<IDocument[]>('/document/recent', (url) => HttpClient.get(url));
const loading = !data && !error;
return { data, error, loading, refresh: mutate };
};
/**
* 收藏文档
* @param documentId
* @returns
*/
export const useDocumentStar = (documentId) => {
const { data, error, mutate } = useSWR<boolean>(`/collector/check/${documentId}`, () =>
HttpClient.post(`/collector/check`, {
type: 'document',
targetId: documentId,
})
);
const toggleStar = async () => {
await HttpClient.post('/collector/toggle/', {
type: 'document',
targetId: documentId,
});
mutate();
};
return { data, error, toggleStar };
};
/**
* 获取用户收藏的文档
* @returns
*/
export const useStaredDocuments = () => {
const { data, error, mutate } = useSWR<IDocument[]>('/collector/documents', (url) => HttpClient.post(url));
const loading = !data && !error;
return { data, error, loading, refresh: mutate };
};
/**
* 获取公开文档
* @param documentId
* @returns
*/
export const usePublicDocument = (documentId: string) => {
const [fetch] = useAsyncLoading(getPublicDocumentDetail);
const [document, setDocument] = useState<IDocument | null>(null);
const [error, setError] = useState<(Error & { statusCode?: number }) | null>(null);
const loading = !document && !error;
const queryData = useCallback(
(sharePassword = '') => {
fetch(documentId, { sharePassword })
.then((doc) => {
setDocument(doc);
setError(null);
})
.catch(setError);
},
[documentId, error]
);
useEffect(() => {
queryData();
}, [documentId]);
return {
data: document,
loading,
error,
query: queryData,
};
};
/**
* 协作文档
* @param documentId
* @returns
*/
export const useCollaborationDocument = (documentId) => {
const { data, error, mutate } = useSWR<Array<IAuthority & IUser>>(
`/document/user/${documentId}`,
(url) => HttpClient.get(url),
{ shouldRetryOnError: false }
);
const loading = !data && !error;
const addUser = async (userName) => {
const ret = await HttpClient.post(`/document/user/${documentId}/add`, {
documentId,
userName,
readable: true,
editable: false,
});
mutate();
return ret;
};
const updateUser = async (docAuth) => {
const ret = await HttpClient.post(`/document/user/${documentId}/update`, {
documentId,
...docAuth,
});
mutate();
return ret;
};
const deleteUser = async (docAuth) => {
const ret = await HttpClient.post(`/document/user/${documentId}/delete`, {
documentId,
...docAuth,
});
mutate();
return ret;
};
return { users: data, loading, error, addUser, updateUser, deleteUser };
};
/**
* 获取子文档
* @param documentId
* @param isShare 访问路径
* @returns
*/
export const useChildrenDocument = ({ wikiId, documentId, isShare = false }) => {
const { data, error, mutate } = useSWR<Array<IDocument>>(
isShare ? '/document/public/children' : `/document/children`,
wikiId || documentId ? (url) => HttpClient.post(url, { wikiId, documentId, isShare }) : null,
{ shouldRetryOnError: false }
);
const loading = !data && !error;
return { data, loading, error, refresh: mutate };
};