Skip to content

⚡️(frontend) improve tree stability #1207

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to

- ♻️(frontend) redirect to doc after duplicate #1175
- 🔧(project) change env.d system by using local files #1200
- ⚡️(frontend) improve tree stability #1207

### Fixed

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable jsx-a11y/click-events-have-key-events */
/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
import { useTreeContext } from '@gouvfr-lasuite/ui-kit';
import { Tooltip } from '@openfun/cunningham-react';
import { useQueryClient } from '@tanstack/react-query';
import React, { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { css } from 'styled-components';
Expand All @@ -12,7 +12,6 @@ import {
Doc,
KEY_DOC,
KEY_LIST_DOC,
KEY_SUB_PAGE,
useDocStore,
useTrans,
useUpdateDoc,
Expand Down Expand Up @@ -50,10 +49,10 @@ export const DocTitleText = () => {

const DocTitleInput = ({ doc }: DocTitleProps) => {
const { isDesktop } = useResponsiveStore();
const queryClient = useQueryClient();
const { t } = useTranslation();
const { colorsTokens } = useCunninghamTheme();
const [titleDisplay, setTitleDisplay] = useState(doc.title);
const treeContext = useTreeContext<Doc>();

const { untitledDocument } = useTrans();

Expand All @@ -64,10 +63,16 @@ const DocTitleInput = ({ doc }: DocTitleProps) => {
onSuccess(updatedDoc) {
// Broadcast to every user connected to the document
broadcast(`${KEY_DOC}-${updatedDoc.id}`);
queryClient.setQueryData(
[KEY_SUB_PAGE, { id: updatedDoc.id }],
updatedDoc,
);

if (!treeContext) {
return;
}

if (treeContext.root?.id === updatedDoc.id) {
treeContext?.setRoot(updatedDoc);
} else {
treeContext?.treeData.updateNode(updatedDoc.id, updatedDoc);
}
},
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export const getDoc = async ({ id }: DocParams): Promise<Doc> => {
};

export const KEY_DOC = 'doc';
export const KEY_SUB_PAGE = 'sub-page';
export const KEY_DOC_VISIBILITY = 'doc-visibility';

export function useDoc(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
import { VariantType, useToastProvider } from '@openfun/cunningham-react';
import { useQueryClient } from '@tanstack/react-query';
import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { css } from 'styled-components';

import { DropdownMenu, DropdownMenuOption, Text } from '@/components';
import {
Access,
Doc,
KEY_SUB_PAGE,
Role,
useTrans,
} from '@/docs/doc-management/';
import { Access, Doc, Role, useTrans } from '@/docs/doc-management/';

import { useDeleteDocAccess, useDeleteDocInvitation } from '../api';
import { Invitation, isInvitation } from '../types';
Expand Down Expand Up @@ -39,19 +32,9 @@ export const DocRoleDropdown = ({
}: DocRoleDropdownProps) => {
const { t } = useTranslation();
const { transRole, translatedRoles } = useTrans();
const queryClient = useQueryClient();
const { toast } = useToastProvider();

const { mutate: removeDocInvitation } = useDeleteDocInvitation({
onSuccess: () => {
if (!doc) {
return;
}

void queryClient.invalidateQueries({
queryKey: [KEY_SUB_PAGE, { id: doc.id }],
});
},
onError: (error) => {
toast(
error?.data?.role?.[0] ?? t('Error during delete invitation'),
Expand All @@ -64,14 +47,6 @@ export const DocRoleDropdown = ({
});

const { mutate: removeDocAccess } = useDeleteDocAccess({
onSuccess: () => {
if (!doc) {
return;
}
void queryClient.invalidateQueries({
queryKey: [KEY_SUB_PAGE, { id: doc.id }],
});
},
onError: () => {
toast(t('Error while deleting invitation'), VariantType.ERROR, {
duration: 4000,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ import {
VariantType,
useToastProvider,
} from '@openfun/cunningham-react';
import { useQueryClient } from '@tanstack/react-query';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { css } from 'styled-components';

import { APIError } from '@/api';
import { Box } from '@/components';
import { useCunninghamTheme } from '@/cunningham';
import { Doc, KEY_SUB_PAGE, Role } from '@/docs/doc-management';
import { Doc, Role } from '@/docs/doc-management';
import { User } from '@/features/auth';

import { useCreateDocAccess, useCreateDocInvitation } from '../api';
Expand Down Expand Up @@ -45,7 +44,6 @@ export const DocShareAddMemberList = ({
const { spacingsTokens, colorsTokens } = useCunninghamTheme();
const [invitationRole, setInvitationRole] = useState<Role>(Role.EDITOR);
const canShare = doc.abilities.accesses_manage;
const queryClient = useQueryClient();
const { mutateAsync: createInvitation } = useCreateDocInvitation();
const { mutateAsync: createDocAccess } = useCreateDocAccess();

Expand Down Expand Up @@ -91,32 +89,14 @@ export const DocShareAddMemberList = ({
};

return isInvitationMode
? createInvitation(
{
...payload,
email: user.email,
},
{
onSuccess: () => {
void queryClient.invalidateQueries({
queryKey: [KEY_SUB_PAGE, { id: doc.id }],
});
},
},
)
: createDocAccess(
{
...payload,
memberId: user.id,
},
{
onSuccess: () => {
void queryClient.invalidateQueries({
queryKey: [KEY_SUB_PAGE, { id: doc.id }],
});
},
},
);
? createInvitation({
...payload,
email: user.email,
})
: createDocAccess({
...payload,
memberId: user.id,
});
});

const settledPromises = await Promise.allSettled(promises);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { VariantType, useToastProvider } from '@openfun/cunningham-react';
import { useQueryClient } from '@tanstack/react-query';
import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { css } from 'styled-components';
Expand All @@ -15,7 +14,7 @@ import {
} from '@/components';
import { QuickSearchData, QuickSearchGroup } from '@/components/quick-search';
import { useCunninghamTheme } from '@/cunningham';
import { Doc, KEY_SUB_PAGE, Role } from '@/docs/doc-management';
import { Doc, Role } from '@/docs/doc-management';
import { User } from '@/features/auth';

import {
Expand All @@ -38,7 +37,6 @@ export const DocShareInvitationItem = ({
invitation,
}: DocShareInvitationItemProps) => {
const { t } = useTranslation();
const queryClient = useQueryClient();
const { spacingsTokens } = useCunninghamTheme();
const invitedUser: User = {
id: invitation.email,
Expand All @@ -52,11 +50,6 @@ export const DocShareInvitationItem = ({
const canUpdate = doc.abilities.accesses_manage;

const { mutate: updateDocInvitation } = useUpdateDocInvitation({
onSuccess: () => {
void queryClient.invalidateQueries({
queryKey: [KEY_SUB_PAGE, { id: doc.id }],
});
},
onError: (error) => {
toast(
error?.data?.role?.[0] ?? t('Error during update invitation'),
Expand All @@ -69,11 +62,6 @@ export const DocShareInvitationItem = ({
});

const { mutate: removeDocInvitation } = useDeleteDocInvitation({
onSuccess: () => {
void queryClient.invalidateQueries({
queryKey: [KEY_SUB_PAGE, { id: doc.id }],
});
},
onError: (error) => {
toast(
error?.data?.role?.[0] ?? t('Error during delete invitation'),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { VariantType, useToastProvider } from '@openfun/cunningham-react';
import { useQueryClient } from '@tanstack/react-query';
import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';

import { Box } from '@/components';
import { QuickSearchData } from '@/components/quick-search';
import { QuickSearchGroup } from '@/components/quick-search/QuickSearchGroup';
import { useCunninghamTheme } from '@/cunningham';
import { Access, Doc, KEY_SUB_PAGE, Role } from '@/docs/doc-management/';
import { Access, Doc, Role } from '@/docs/doc-management/';

import { useDocAccesses, useUpdateDocAccess } from '../api';
import { useWhoAmI } from '../hooks/';
Expand All @@ -26,7 +25,6 @@ export const DocShareMemberItem = ({
isInherited = false,
}: Props) => {
const { t } = useTranslation();
const queryClient = useQueryClient();
const { isLastOwner } = useWhoAmI(access);
const { toast } = useToastProvider();

Expand All @@ -39,14 +37,6 @@ export const DocShareMemberItem = ({
: undefined;

const { mutate: updateDocAccess } = useUpdateDocAccess({
onSuccess: () => {
if (!doc) {
return;
}
void queryClient.invalidateQueries({
queryKey: [KEY_SUB_PAGE, { id: doc.id }],
});
},
onError: () => {
toast(t('Error while updating the member role.'), VariantType.ERROR, {
duration: 4000,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@ export type DocsTreeParams = {
};

export const getDocTree = async ({ docId }: DocsTreeParams): Promise<Doc> => {
const searchParams = new URLSearchParams();

const response = await fetchAPI(
`documents/${docId}/tree/?${searchParams.toString()}`,
);
const response = await fetchAPI(`documents/${docId}/tree/`);

if (!response.ok) {
throw new APIError(
Expand All @@ -29,10 +25,7 @@ export const KEY_DOC_TREE = 'doc-tree';

export function useDocTree(
params: DocsTreeParams,
queryConfig?: Omit<
UseQueryOptions<Doc, APIError, Doc>,
'queryKey' | 'queryFn'
>,
queryConfig?: UseQueryOptions<Doc, APIError, Doc>,
) {
return useQuery<Doc, APIError, Doc>({
queryKey: [KEY_DOC_TREE, params],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,12 @@ import {
useTreeContext,
} from '@gouvfr-lasuite/ui-kit';
import { useRouter } from 'next/navigation';
import { useEffect, useRef, useState } from 'react';
import { useState } from 'react';
import { css } from 'styled-components';

import { Box, Icon, Text } from '@/components';
import { useCunninghamTheme } from '@/cunningham';
import {
Doc,
KEY_SUB_PAGE,
useDoc,
useTrans,
} from '@/features/docs/doc-management';
import { Doc, useTrans } from '@/features/docs/doc-management';
import { useLeftPanelStore } from '@/features/left-panel';
import { useResponsiveStore } from '@/stores';

Expand All @@ -31,8 +26,7 @@ const ItemTextCss = css`
-webkit-box-orient: vertical;
`;

type Props = TreeViewNodeProps<Doc>;
export const DocSubPageItem = (props: Props) => {
export const DocSubPageItem = (props: TreeViewNodeProps<Doc>) => {
const doc = props.node.data.value as Doc;
const treeContext = useTreeContext<Doc>();
const { untitledDocument } = useTrans();
Expand All @@ -44,28 +38,6 @@ export const DocSubPageItem = (props: Props) => {
const router = useRouter();
const { togglePanel } = useLeftPanelStore();

const isInitialLoad = useRef(false);
const { data: docQuery } = useDoc(
{ id: doc.id },
{
initialData: doc,
queryKey: [KEY_SUB_PAGE, { id: doc.id }],
refetchOnMount: false,
refetchOnWindowFocus: false,
},
);

useEffect(() => {
if (docQuery && isInitialLoad.current === true) {
treeContext?.treeData.updateNode(docQuery.id, docQuery);
}

if (docQuery) {
isInitialLoad.current = true;
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [docQuery]);

const afterCreate = (createdDoc: Doc) => {
const actualChildren = node.data.children ?? [];

Expand Down
Loading
Loading