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: 2 additions & 0 deletions admin/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './useAPI';
export * from './useSettingsPermissions';
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { getFetchClient } from '@strapi/strapi/admin';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useCallback } from 'react';

import { getApiClient } from '../../../api';
import { NavigationSchema } from '../../../api/validators';
import { Effect } from '../../../types';
import { getApiClient } from '../api';
import { NavigationSchema } from '../api/validators';
import { Effect } from '../types';
import { appendViewId } from '../utils/appendViewId';

export const useLocale = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useMemo } from 'react';

import { useRBAC } from '@strapi/strapi/admin';

import pluginPermissions from '../../../utils/permissions';
import pluginPermissions from '../utils/permissions';

export const useSettingsPermissions = () => {
const viewPermissions = useMemo(
Expand Down
21 changes: 14 additions & 7 deletions admin/src/pages/App.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import { Page } from '@strapi/strapi/admin';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { Route, Routes } from 'react-router-dom';

import { HomePage } from './HomePage';
import { DetailPage } from './DetailPage';
import { OverviewPage } from './OverviewPage';

const queryClient = new QueryClient();

const App = () => {
return (
<DndProvider backend={HTML5Backend}>
<Routes>
<Route path={`/`} index Component={HomePage} />
<Route path={`/*`} Component={Page.Error} />
</Routes>
</DndProvider>
<QueryClientProvider client={queryClient}>
<DndProvider backend={HTML5Backend}>
<Routes>
<Route path={`/`} index Component={OverviewPage} />
<Route path={`/:documentId`} Component={DetailPage} />
<Route path={`/*`} Component={Page.Error} />
</Routes>
</DndProvider>
</QueryClientProvider>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
useResetNavigations,
} from '../../hooks';
import { NavigationSchema } from '../../../../api/validators';
import { appendViewId } from '../../utils/appendViewId';
import { appendViewId } from '../../../../utils/appendViewId';

type NavigationEmptyStateProps = {
canUpdate: boolean;
Expand Down
120 changes: 120 additions & 0 deletions admin/src/pages/DetailPage/components/NavigationHeader/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { Button, Flex, Link, SingleSelect, SingleSelectOption, Tag } from '@strapi/design-system';
import { ArrowLeft, Check, Feather, Information } from '@strapi/icons';
import { Layouts } from '@strapi/strapi/admin';
import React from 'react';
import { useIntl } from 'react-intl';
import { NavLink } from 'react-router-dom';
import { NavigationSchema } from '../../../../api/validators';
import { PLUGIN_ID } from '../../../../pluginId';
import { getTrad } from '../../../../translations';
import { Effect } from '../../../../types';
import { useConfig, usePluginMediaQuery } from '../../hooks';

const submitIcon = <Check />;

interface Props {
activeNavigation?: NavigationSchema;
structureHasErrors?: boolean;
structureHasChanged?: boolean;
isSaving?: boolean;
handleLocalizationSelection: Effect<string>;
handleSave: Effect<void>;
handleCachePurge: Effect<void>;
permissions: { canUpdate?: boolean };
locale: {
defaultLocale: string;
restLocale: string[];
};
currentLocale?: string;
}

export const NavigationHeader: React.FC<Props> = ({
activeNavigation,
structureHasErrors,
structureHasChanged,
isSaving,
handleLocalizationSelection,
handleSave,
handleCachePurge,
permissions = {},
locale,
currentLocale,
}) => {
const { formatMessage } = useIntl();

const configQuery = useConfig();

const hasLocalizations = !!locale.restLocale?.length;
const hasCache = !!configQuery.data?.isCacheEnabled;

const { canUpdate } = permissions;

const { isMobile } = usePluginMediaQuery();

return (
<Layouts.Header
navigationAction={
<Link tag={NavLink} startIcon={<ArrowLeft />} to={`/plugins/${PLUGIN_ID}`}>
{formatMessage(getTrad('popup.navigation.manage.button.goBack'))}
</Link>
}
title={activeNavigation?.name ?? formatMessage(getTrad('header.title', 'UI Navigation'))}
subtitle={formatMessage(getTrad('header.description'))}
primaryAction={
<Flex direction="row" gap={2}>
{hasLocalizations && (
<SingleSelect
type="select"
placeholder={formatMessage(
getTrad('pages.main.header.localization.select.placeholder')
)}
name="navigationLocalizationSelect"
onChange={handleLocalizationSelection}
value={currentLocale}
size="S"
>
{[locale.defaultLocale, ...locale.restLocale].map((code) => (
<SingleSelectOption key={code} value={code}>
{code}
</SingleSelectOption>
))}
</SingleSelect>
)}
{canUpdate && hasCache && (
<Button
onClick={handleCachePurge}
startIcon={<Feather />}
variant="danger-light"
type="button"
size="S"
>
{formatMessage(getTrad('submit.cta.cache.purge'))}
</Button>
)}
{canUpdate && (
<Button
onClick={handleSave}
startIcon={submitIcon}
disabled={structureHasErrors || !structureHasChanged || isSaving}
type="submit"
size="S"
>
{formatMessage(getTrad('submit.cta.save'))}
</Button>
)}
</Flex>
}
secondaryAction={
!isMobile &&
activeNavigation && (
<Tag icon={<Information aria-hidden={true} />}>
{formatMessage(getTrad('header.meta'), {
id: activeNavigation.documentId,
key: activeNavigation.slug,
})}
</Tag>
)
}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
NavigationItemTypeSchema,
StrapiContentTypeItemSchema,
} from '../../../../../api/validators';
import { extractRelatedItemLabel } from '../../../../HomePage/utils';
import { extractRelatedItemLabel } from '../../../utils';
import { type NavigationItemFormSchema } from './form';

interface GenerateUiRouterKeyInput {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
export * from './useAPI';
export * from '../../../hooks';
export * from './useI18nCopyNavigationItemsModal';
export * from './useInvalidateQueries';
export * from './useLocales';
export * from './useNavigationItemPopup';
export * from './useSearch';
export * from './useSettingsPermissions';
export * from './usePluginMediaQuery';
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Data } from '@strapi/strapi';
import { Layouts, Page, useNotification } from '@strapi/strapi/admin';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { first } from 'lodash';
import { SyntheticEvent, useEffect, useState } from 'react';
import { useIntl } from 'react-intl';
import { useNavigate, useParams } from 'react-router-dom';

import { NavigationSchema } from '../../api/validators';
import { PLUGIN_ID } from '../../pluginId';
import { getTrad } from '../../translations';
import { appendViewId } from '../../utils/appendViewId';
import { NavigationHeader } from './components';
import { ChangeLanguageDialog } from './components/ChangeLanguageDialog';
import { NavigationContentHeader } from './components/NavigationContentHeader';
Expand All @@ -27,21 +27,19 @@ import {
import { getPendingAction, transformItemToViewPayload } from './utils';
import { ManageNavigationItems } from './components/NavigationContentHeader/ManageNavigationItems';
import { NavigationEmptyState } from './components/NavigationEmptyState';
import { appendViewId } from './utils/appendViewId';
import { type NavigationItemFormSchema } from './components/NavigationItemForm';

const queryClient = new QueryClient();

const Inner = () => {
const DetailPage = () => {
const { formatMessage } = useIntl();
const { documentId } = useParams<{ documentId: string }>();
const navigate = useNavigate();

const navigationsQuery = useNavigations();
const configQuery = useConfig();
const purgeMutation = usePurgeNavigation();

const { toggleNotification } = useNotification();

const [recentNavigation, setRecentNavigation] = useState<{ documentId?: string; id?: Data.ID }>();
const [currentNavigation, setCurrentNavigation] = useState<NavigationSchema>();
const [structureChanged, setStructureChanged] = useState(false);

Expand Down Expand Up @@ -85,11 +83,6 @@ const Inner = () => {
items: next.items.map(appendViewId),
});

setRecentNavigation({
documentId: next.documentId,
id: next.id,
});

setStructureChanged(false);
},
});
Expand Down Expand Up @@ -136,23 +129,29 @@ const Inner = () => {
const listItems = isSearchEmpty ? (currentNavigation?.items ?? []) : filteredList;

useEffect(() => {
if (!currentNavigation && navigationsQuery.data?.[0]) {
let navigation;
if (recentNavigation?.documentId) {
navigation = navigationsQuery.data.find(
(nav) => nav.documentId === recentNavigation.documentId && nav.id === recentNavigation.id
);
}
if (!navigationsQuery.data) {
return;
}

const localeVersions = navigationsQuery.data.filter(
(navigation) => navigation.documentId === documentId
);

setRecentNavigation(undefined);
setCurrentNavigation(navigation ? navigation : first(navigationsQuery.data));
if (!localeVersions.length) {
navigate(`/plugins/${PLUGIN_ID}`);
return;
}
}, [navigationsQuery.data, currentNavigation]);

if (!currentNavigation || currentNavigation.documentId !== documentId) {
setCurrentNavigation(
localeVersions.find((navigation) => navigation.locale === currentLocale) ??
localeVersions[0]
);
}
}, [navigationsQuery.data, currentNavigation, documentId, currentLocale, navigate]);

useEffect(() => {
if (currentNavigation && currentLocale !== currentNavigation.locale) {
setRecentNavigation(undefined);

const nextNavigation = navigationsQuery.data?.find(
(navigation) =>
navigation.documentId === currentNavigation.documentId &&
Expand Down Expand Up @@ -180,10 +179,8 @@ const Inner = () => {
<Page.Title children={formatMessage(getTrad('header.title', 'UI Navigation'))} />
<Page.Main>
<NavigationHeader
availableNavigations={navigationsQuery.data}
activeNavigation={currentNavigation}
handleCachePurge={() => purgeMutation.mutate(undefined)}
handleChangeSelection={setCurrentNavigation}
handleCachePurge={() => purgeMutation.mutate(documentId ? [documentId] : undefined)}
handleLocalizationSelection={
structureChanged ? changeCurrentLocaleAction.trigger : changeCurrentLocaleAction.perform
}
Expand Down Expand Up @@ -256,12 +253,4 @@ const Inner = () => {
);
};

export default function HomePage() {
return (
<QueryClientProvider client={queryClient}>
<Inner />
</QueryClientProvider>
);
}

export { HomePage };
export { DetailPage };
25 changes: 0 additions & 25 deletions admin/src/pages/HomePage/components/NavigationHeader/hooks.tsx

This file was deleted.

Loading