Skip to content

Commit eb95e17

Browse files
committed
✨(frontend) Can mask a document from the list view
We can be member of some documents, but sometimes we want to mask them from the list view because we don't want to interact with them anymore. This commit adds the ability to mask a document from the list view.
1 parent 67a195f commit eb95e17

File tree

6 files changed

+81
-12
lines changed

6 files changed

+81
-12
lines changed

src/frontend/apps/impress/src/features/docs/doc-management/api/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ export * from './useDeleteFavoriteDoc';
44
export * from './useDoc';
55
export * from './useDocOptions';
66
export * from './useDocs';
7-
export * from './useSubDocs';
87
export * from './useDuplicateDoc';
8+
export * from './useMaskDoc';
9+
export * from './useSubDocs';
910
export * from './useUpdateDoc';
1011
export * from './useUpdateDocLink';

src/frontend/apps/impress/src/features/docs/doc-management/api/useDocs.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export type DocsParams = {
1616
is_creator_me?: boolean;
1717
title?: string;
1818
is_favorite?: boolean;
19+
is_masked?: boolean;
1920
};
2021

2122
export const constructParams = (params: DocsParams): URLSearchParams => {
@@ -36,6 +37,9 @@ export const constructParams = (params: DocsParams): URLSearchParams => {
3637
if (params.is_favorite !== undefined) {
3738
searchParams.set('is_favorite', params.is_favorite.toString());
3839
}
40+
if (params.is_masked !== undefined) {
41+
searchParams.set('is_masked', params.is_masked.toString());
42+
}
3943

4044
return searchParams;
4145
};
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { useMutation, useQueryClient } from '@tanstack/react-query';
2+
3+
import { APIError, errorCauses, fetchAPI } from '@/api';
4+
import { Doc } from '@/docs/doc-management';
5+
6+
export type MaskDocParams = Pick<Doc, 'id'>;
7+
8+
export const maskDoc = async ({ id }: MaskDocParams) => {
9+
const response = await fetchAPI(`documents/${id}/mask/`, {
10+
method: 'POST',
11+
});
12+
13+
if (!response.ok) {
14+
throw new APIError(
15+
'Failed to make the doc as masked',
16+
await errorCauses(response),
17+
);
18+
}
19+
};
20+
21+
interface MaskDocProps {
22+
onSuccess?: () => void;
23+
listInvalideQueries?: string[];
24+
}
25+
26+
export function useMaskDoc({ onSuccess, listInvalideQueries }: MaskDocProps) {
27+
const queryClient = useQueryClient();
28+
return useMutation<void, APIError, MaskDocParams>({
29+
mutationFn: maskDoc,
30+
onSuccess: () => {
31+
listInvalideQueries?.forEach((queryKey) => {
32+
void queryClient.invalidateQueries({
33+
queryKey: [queryKey],
34+
});
35+
});
36+
onSuccess?.();
37+
},
38+
});
39+
}

src/frontend/apps/impress/src/features/docs/doc-management/types.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export interface Doc {
8484
favorite: boolean;
8585
invite_owner: boolean;
8686
link_configuration: boolean;
87+
mask: boolean;
8788
media_auth: boolean;
8889
move: boolean;
8990
partial_update: boolean;

src/frontend/apps/impress/src/features/docs/docs-grid/components/DocsGrid.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,13 @@ export const DocsGrid = ({
3232
hasNextPage,
3333
} = useInfiniteDocs({
3434
page: 1,
35-
...(target &&
36-
target !== DocDefaultFilter.ALL_DOCS && {
37-
is_creator_me: target === DocDefaultFilter.MY_DOCS,
38-
}),
35+
is_masked: target === DocDefaultFilter.ALL_DOCS ? false : undefined,
36+
is_creator_me:
37+
target === DocDefaultFilter.MY_DOCS
38+
? true
39+
: target === DocDefaultFilter.SHARED_WITH_ME
40+
? false
41+
: undefined,
3942
});
4043

4144
const docs = data?.pages.flatMap((page) => page.results) ?? [];

src/frontend/apps/impress/src/features/docs/docs-grid/components/DocsGridActions.tsx

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
useCreateFavoriteDoc,
1010
useDeleteFavoriteDoc,
1111
useDuplicateDoc,
12+
useMaskDoc,
1213
} from '@/docs/doc-management';
1314

1415
interface DocsGridActionsProps {
@@ -31,6 +32,9 @@ export const DocsGridActions = ({
3132
const makeFavoriteDoc = useCreateFavoriteDoc({
3233
listInvalideQueries: [KEY_LIST_DOC],
3334
});
35+
const maskDoc = useMaskDoc({
36+
listInvalideQueries: [KEY_LIST_DOC],
37+
});
3438

3539
const options: DropdownMenuOption[] = [
3640
{
@@ -44,6 +48,7 @@ export const DocsGridActions = ({
4448
}
4549
},
4650
testId: `docs-grid-actions-${doc.is_favorite ? 'unpin' : 'pin'}-${doc.id}`,
51+
showSeparator: true,
4752
},
4853
{
4954
label: t('Share'),
@@ -65,16 +70,32 @@ export const DocsGridActions = ({
6570
canSave: false,
6671
});
6772
},
68-
},
69-
{
70-
label: t('Remove'),
71-
icon: 'delete',
72-
callback: () => deleteModal.open(),
73-
disabled: !doc.abilities.destroy,
74-
testId: `docs-grid-actions-remove-${doc.id}`,
73+
showSeparator: true,
7574
},
7675
];
7776

77+
const leaveDocOption: DropdownMenuOption = doc.abilities.destroy
78+
? {
79+
label: t('Remove'),
80+
icon: 'delete',
81+
callback: () => deleteModal.open(),
82+
disabled: !doc.abilities.destroy,
83+
testId: `docs-grid-actions-remove-${doc.id}`,
84+
}
85+
: {
86+
label: t('Leave doc'),
87+
icon: 'logout',
88+
callback: () => {
89+
maskDoc.mutate({
90+
id: doc.id,
91+
});
92+
},
93+
disabled: !doc.abilities.mask,
94+
testId: `docs-grid-actions-leave-${doc.id}`,
95+
};
96+
97+
options.push(leaveDocOption);
98+
7899
return (
79100
<>
80101
<DropdownMenu options={options}>

0 commit comments

Comments
 (0)