Skip to content
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
2 changes: 1 addition & 1 deletion src/frontend/apps/drive/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
},
"dependencies": {
"@gouvfr-lasuite/cunningham-react": "4.3.0",
"@gouvfr-lasuite/ui-kit": "0.20.1",
"@gouvfr-lasuite/ui-kit": "0.20.2",
"@tanstack/react-query": "5.90.10",
"@tanstack/react-table": "8.21.3",
"@viselect/react": "3.9.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ $tablet: map.get($themes, "default", "globals", "breakpoints", "tablet");
}

.explorer__container {
width: 992px;
max-width: 992px;
width: 100%;
}

.explorer__content {
Expand Down Expand Up @@ -125,6 +126,7 @@ $tablet: map.get($themes, "default", "globals", "breakpoints", "tablet");
display: flex;
align-items: center;
gap: var(--c--globals--spacings--2xs);
flex-shrink: 0;
}

&--mobile {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ export const AppExplorerBreadcrumbs = () => {
(onDefaultRoute && defaultRouteId === DefaultRoute.MY_FILES) ||
(!onDefaultRoute && item?.abilities?.children_create);

if (!item && !onDefaultRoute) {
return null;
}

return (
<>
<div className="explorer__content__breadcrumbs">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
import { NavigationItem } from "../GlobalExplorerContext";
import { ItemActionDropdown } from "../item-actions/ItemActionDropdown";
import clsx from "clsx";
import { useBreadcrumbQuery } from "../../hooks/useBreadcrumb";
import { useItem } from "../../hooks/useQueries";
import { useItemWithBreadcrumb } from "../../hooks/useBreadcrumb";
import { useRouter } from "next/router";
import { Button, useModal } from "@gouvfr-lasuite/cunningham-react";
import { ItemShareModal } from "../modals/share/ItemShareModal";
Expand Down Expand Up @@ -67,13 +66,12 @@
const { user } = useAuth();

const defaultRouteData = getDefaultRoute(router.pathname);
const { data: breadcrumb } = useBreadcrumbQuery(currentItemId);

const { data: fetchedItem } = useItem(currentItemId!, {
enabled: !!currentItemId && !itemFromProps,
});

const item = itemFromProps ?? fetchedItem;
const { data } = useItemWithBreadcrumb(currentItemId);
// Prefer itemFromProps when provided: it comes from the surrounding
// explorer context which may have applied an optimistic mutation (rename,
// share toggle…) that the cached query data hasn't reflected yet.
const item = itemFromProps ?? data?.item;
const breadcrumb = data?.breadcrumb;

const handleGoBack = (item: Item | ItemBreadcrumb) => {
onGoBack?.(item);
Expand All @@ -92,7 +90,9 @@
>
{defaultRouteData.icon({ size: IconSize.MEDIUM })}

{t(defaultRouteData.label)}
<span className="c__breadcrumbs__button__label">
{t(defaultRouteData.label)}
</span>
</div>
);
};
Expand Down Expand Up @@ -179,33 +179,54 @@
return null;
};

const breadcrumbsItems = useMemo(() => {

Check failure on line 182 in src/frontend/apps/drive/src/features/explorer/components/embedded-explorer/EmbeddedExplorerGridBreadcrumbs.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 16 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=suitenumerique_drive&issues=AZ3ZUAo7fDERzwLpksIt&open=AZ3ZUAo7fDERzwLpksIt&pullRequest=695
const markLastActive = (entries: BreadcrumbItem[]): BreadcrumbItem[] => {
if (entries.length === 0) return entries;
const lastIdx = entries.length - 1;
return entries.map((entry, idx) =>
idx === lastIdx ? { ...entry, isActive: true } : entry,
);
};

if (forcedBreadcrumbsItems) {
return forcedBreadcrumbsItems.map((item) => ({
content: (
<BreadcrumbItemButton
item={item}
onClick={() => handleGoBack(item)}
/>
),
}));
return markLastActive(
forcedBreadcrumbsItems.map((item) => ({
content: (
<BreadcrumbItemButton
item={item}
onClick={() => handleGoBack(item)}
/>
),
label: item.title,
onClick: () => handleGoBack(item),
})),
);
}
const breadcrumbsItems: BreadcrumbItem[] = [];

if (defaultRouteData && !showAllFolderItem) {
breadcrumbsItems.push({
content: getDefaultRouteButton(defaultRouteData),
label: t(defaultRouteData.label),
onClick: () => router.push(defaultRouteData.route),
});
}

const fromRouteButton = getFromRouteButton();
if (fromRouteButton && !showAllFolderItem) {
const fromRouteData =
getFromRouteManualDefaultRouteData() ?? getGuessedDefaultRouteData();
breadcrumbsItems.push({
content: fromRouteButton,
label: fromRouteData ? t(fromRouteData.label) : "",
onClick: fromRouteData
? () => router.push(fromRouteData.route)
: undefined,
});
}

if (showAllFolderItem) {
const allFoldersLabel = t("explorer.breadcrumbs.all_folders");
breadcrumbsItems.push({
content: (
<div
Expand All @@ -214,38 +235,41 @@
goToSpaces?.();
}}
>
{t("explorer.breadcrumbs.all_folders")}
<span className="c__breadcrumbs__button__label">
{allFoldersLabel}
</span>
</div>
),
label: allFoldersLabel,
onClick: () => goToSpaces?.(),
});
}

const breadcrumbsData = showMenuLastItem
? (breadcrumb ?? []).slice(0, -1)
: (breadcrumb ?? []);

const lastItem = item;

breadcrumbsData.forEach((item) => {
const isActive = item.id === lastItem?.id;
breadcrumbsData.forEach((crumb) => {
breadcrumbsItems.push({
content: (
<BreadcrumbItemButton
item={item}
onClick={() => handleGoBack(item)}
isActive={isActive}
item={crumb}
onClick={() => handleGoBack(crumb)}
/>
),
label: crumb.title,
onClick: () => handleGoBack(crumb),
});
});

if (showMenuLastItem && lastItem) {
if (showMenuLastItem && item) {
breadcrumbsItems.push({
content: <LastItemBreadcrumb item={lastItem} />,
content: <LastItemBreadcrumb item={item} />,
label: item.title,
});
}

return breadcrumbsItems;
return markLastActive(breadcrumbsItems);
}, [
showAllFolderItem,
currentItemId,
Expand Down Expand Up @@ -278,7 +302,7 @@
data-testid="breadcrumb-button"
onClick={onClick}
>
{item.title}
<span className="c__breadcrumbs__button__label">{item.title}</span>
{rightIcon}
</button>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,28 @@ export const useBreadcrumbQuery = (id?: string | null) => {
queryKey: ["breadcrumb", id],
queryFn: () => driver.getItemBreadcrumb(id!),
enabled: !!id,
placeholderData: (previousData) => previousData,
});
};

/**
* Fetches the item and its breadcrumb in a single atomic query, so the two
* pieces never go out of sync during navigation. Combined with
* `placeholderData: previousData`, the previous chain remains visible until
* the new pair has resolved together — preventing the empty-middle flicker.
*/
export const useItemWithBreadcrumb = (id?: string | null) => {
const driver = getDriver();
return useQuery({
queryKey: ["itemWithBreadcrumb", id],
queryFn: async () => {
const [item, breadcrumb] = await Promise.all([
driver.getItem(id!),
driver.getItemBreadcrumb(id!),
]);
return { item, breadcrumb };
},
enabled: !!id,
placeholderData: (previousData) => previousData,
});
};
9 changes: 6 additions & 3 deletions src/frontend/apps/drive/src/features/i18n/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@
"explorer": {
"breadcrumbs": {
"spaces": "Spaces",
"all_folders": "All folders"
"all_folders": "All folders",
"show_hidden_folders": "Show hidden folders"
},
"modal": {
"move": {
Expand Down Expand Up @@ -772,7 +773,8 @@
"explorer": {
"breadcrumbs": {
"spaces": "Espaces",
"all_folders": "Tous les dossiers"
"all_folders": "Tous les dossiers",
"show_hidden_folders": "Afficher les dossiers masqués"
},
"modal": {
"move": {
Expand Down Expand Up @@ -1382,7 +1384,8 @@
"explorer": {
"breadcrumbs": {
"spaces": "Werkruimten",
"all_folders": "Alle mappen"
"all_folders": "Alle mappen",
"show_hidden_folders": "Toon verborgen mappen"
},
"modal": {
"move": {
Expand Down
Loading
Loading