👔(frontend) create versions api endpoints
Create versions api endpoints: - Add useDocVersion hook - to retrieve a version - Add useDocVersions hook - to list versions with pagination We add an helper to type more easily the react-query hooks.
This commit is contained in:
46
src/frontend/apps/impress/src/api/helpers.tsx
Normal file
46
src/frontend/apps/impress/src/api/helpers.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import {
|
||||
DefinedInitialDataInfiniteOptions,
|
||||
InfiniteData,
|
||||
QueryKey,
|
||||
UseQueryOptions,
|
||||
useInfiniteQuery,
|
||||
} from '@tanstack/react-query';
|
||||
|
||||
import { APIError } from './APIError';
|
||||
import { APIList } from './types';
|
||||
|
||||
export type UseQueryOptionsAPI<Q> = UseQueryOptions<Q, APIError, Q>;
|
||||
export type DefinedInitialDataInfiniteOptionsAPI<Q> =
|
||||
DefinedInitialDataInfiniteOptions<
|
||||
Q,
|
||||
APIError,
|
||||
InfiniteData<Q>,
|
||||
QueryKey,
|
||||
number
|
||||
>;
|
||||
|
||||
/**
|
||||
* @param param Used for infinite scroll pagination
|
||||
* @param queryConfig
|
||||
* @returns
|
||||
*/
|
||||
export const useAPIInfiniteQuery = <T, Q extends { next?: APIList<Q>['next'] }>(
|
||||
key: string,
|
||||
api: (props: T & { page: number }) => Promise<Q>,
|
||||
param: T,
|
||||
queryConfig?: DefinedInitialDataInfiniteOptionsAPI<Q>,
|
||||
) => {
|
||||
return useInfiniteQuery<Q, APIError, InfiniteData<Q>, QueryKey, number>({
|
||||
initialPageParam: 1,
|
||||
queryKey: [key, param],
|
||||
queryFn: ({ pageParam }) =>
|
||||
api({
|
||||
...param,
|
||||
page: pageParam,
|
||||
}),
|
||||
getNextPageParam(lastPage, allPages) {
|
||||
return lastPage.next ? allPages.length + 1 : undefined;
|
||||
},
|
||||
...queryConfig,
|
||||
});
|
||||
};
|
||||
@@ -1,4 +1,5 @@
|
||||
export * from './APIError';
|
||||
export * from './fetchApi';
|
||||
export * from './helpers';
|
||||
export * from './types';
|
||||
export * from './utils';
|
||||
|
||||
@@ -4,7 +4,8 @@ import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import * as Y from 'yjs';
|
||||
|
||||
import { useUpdateDoc } from '@/features/docs/doc-management/';
|
||||
import { KEY_DOC, useUpdateDoc } from '@/features/docs/doc-management/';
|
||||
import { KEY_LIST_DOC_VERSIONS } from '@/features/docs/doc-versioning';
|
||||
|
||||
import { toBase64 } from '../utils';
|
||||
|
||||
@@ -21,6 +22,7 @@ const useSaveDoc = (docId: string, doc: Y.Doc, canSave: boolean) => {
|
||||
VariantType.SUCCESS,
|
||||
);
|
||||
},
|
||||
listInvalideQueries: [KEY_LIST_DOC_VERSIONS, KEY_DOC],
|
||||
});
|
||||
const [initialDoc, setInitialDoc] = useState<string>(
|
||||
toBase64(Y.encodeStateAsUpdate(doc)),
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from './useDocVersions';
|
||||
@@ -0,0 +1,41 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { APIError, UseQueryOptionsAPI, errorCauses, fetchAPI } from '@/api';
|
||||
|
||||
import { Version } from '../types';
|
||||
|
||||
export type DocVersionParam = {
|
||||
docId: string;
|
||||
versionId: string;
|
||||
};
|
||||
|
||||
const getDocVersion = async ({
|
||||
versionId,
|
||||
docId,
|
||||
}: DocVersionParam): Promise<Version> => {
|
||||
const url = `documents/${docId}/versions/${versionId}/`;
|
||||
|
||||
const response = await fetchAPI(url);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new APIError(
|
||||
'Failed to get the doc version',
|
||||
await errorCauses(response),
|
||||
);
|
||||
}
|
||||
|
||||
return response.json() as Promise<Version>;
|
||||
};
|
||||
|
||||
export const KEY_DOC_VERSION = 'doc-version';
|
||||
|
||||
export function useDocVersion(
|
||||
params: DocVersionParam,
|
||||
queryConfig?: UseQueryOptionsAPI<Version>,
|
||||
) {
|
||||
return useQuery<Version, APIError, Version>({
|
||||
queryKey: [KEY_DOC_VERSION, params],
|
||||
queryFn: () => getDocVersion(params),
|
||||
...queryConfig,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import {
|
||||
APIError,
|
||||
APIList,
|
||||
DefinedInitialDataInfiniteOptionsAPI,
|
||||
UseQueryOptionsAPI,
|
||||
errorCauses,
|
||||
fetchAPI,
|
||||
useAPIInfiniteQuery,
|
||||
} from '@/api';
|
||||
|
||||
import { Versions } from '../types';
|
||||
|
||||
export type DocVersionsParam = {
|
||||
docId: string;
|
||||
};
|
||||
|
||||
export type DocVersionsAPIParams = DocVersionsParam & {
|
||||
page: number;
|
||||
};
|
||||
|
||||
type VersionsResponse = APIList<Versions>;
|
||||
|
||||
const getDocVersions = async ({
|
||||
page,
|
||||
docId,
|
||||
}: DocVersionsAPIParams): Promise<VersionsResponse> => {
|
||||
const url = `documents/${docId}/versions/?page=${page}`;
|
||||
|
||||
const response = await fetchAPI(url);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new APIError(
|
||||
'Failed to get the doc versions',
|
||||
await errorCauses(response),
|
||||
);
|
||||
}
|
||||
|
||||
return response.json() as Promise<VersionsResponse>;
|
||||
};
|
||||
|
||||
export const KEY_LIST_DOC_VERSIONS = 'doc-versions';
|
||||
|
||||
export function useDocVersions(
|
||||
params: DocVersionsAPIParams,
|
||||
queryConfig?: UseQueryOptionsAPI<VersionsResponse>,
|
||||
) {
|
||||
return useQuery<VersionsResponse, APIError, VersionsResponse>({
|
||||
queryKey: [KEY_LIST_DOC_VERSIONS, params],
|
||||
queryFn: () => getDocVersions(params),
|
||||
...queryConfig,
|
||||
});
|
||||
}
|
||||
|
||||
export function useDocVersionsInfiniteQuery(
|
||||
param: DocVersionsParam,
|
||||
queryConfig?: DefinedInitialDataInfiniteOptionsAPI<VersionsResponse>,
|
||||
) {
|
||||
return useAPIInfiniteQuery<DocVersionsParam, VersionsResponse>(
|
||||
KEY_LIST_DOC_VERSIONS,
|
||||
getDocVersions,
|
||||
param,
|
||||
queryConfig,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Doc } from '../doc-management';
|
||||
|
||||
export interface Versions {
|
||||
etag: string;
|
||||
is_latest: boolean;
|
||||
last_modified: string;
|
||||
version_id: string;
|
||||
}
|
||||
|
||||
export interface Version {
|
||||
content: Doc['content'];
|
||||
last_modified: string;
|
||||
}
|
||||
@@ -5,7 +5,12 @@ import {
|
||||
} from '@tanstack/react-query';
|
||||
|
||||
import { APIError, errorCauses, fetchAPI } from '@/api';
|
||||
import { Access, KEY_DOC, Role } from '@/features/docs/doc-management';
|
||||
import {
|
||||
Access,
|
||||
KEY_DOC,
|
||||
KEY_LIST_DOC,
|
||||
Role,
|
||||
} from '@/features/docs/doc-management';
|
||||
|
||||
import { KEY_LIST_DOC_ACCESSES } from './useDocAccesses';
|
||||
|
||||
@@ -54,6 +59,9 @@ export const useUpdateDocAccess = (options?: UseUpdateDocAccessOptions) => {
|
||||
void queryClient.invalidateQueries({
|
||||
queryKey: [KEY_DOC],
|
||||
});
|
||||
void queryClient.invalidateQueries({
|
||||
queryKey: [KEY_LIST_DOC],
|
||||
});
|
||||
if (options?.onSuccess) {
|
||||
options.onSuccess(data, variables, context);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user