diff --git a/admin/src/hooks/index.ts b/admin/src/hooks/index.ts new file mode 100644 index 00000000..b01e8b8e --- /dev/null +++ b/admin/src/hooks/index.ts @@ -0,0 +1,2 @@ +export * from './useAPI'; +export * from './useSettingsPermissions'; diff --git a/admin/src/pages/HomePage/hooks/useAPI.ts b/admin/src/hooks/useAPI.ts similarity index 97% rename from admin/src/pages/HomePage/hooks/useAPI.ts rename to admin/src/hooks/useAPI.ts index 8ef07de8..d64afdd5 100644 --- a/admin/src/pages/HomePage/hooks/useAPI.ts +++ b/admin/src/hooks/useAPI.ts @@ -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 = () => { diff --git a/admin/src/pages/HomePage/hooks/useSettingsPermissions.ts b/admin/src/hooks/useSettingsPermissions.ts similarity index 89% rename from admin/src/pages/HomePage/hooks/useSettingsPermissions.ts rename to admin/src/hooks/useSettingsPermissions.ts index 38ec20ff..214bbba4 100644 --- a/admin/src/pages/HomePage/hooks/useSettingsPermissions.ts +++ b/admin/src/hooks/useSettingsPermissions.ts @@ -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( diff --git a/admin/src/pages/App.tsx b/admin/src/pages/App.tsx index 79994162..002a900e 100644 --- a/admin/src/pages/App.tsx +++ b/admin/src/pages/App.tsx @@ -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 ( - - - - - - + + + + + + + + + ); }; diff --git a/admin/src/pages/HomePage/components/ChangeLanguageDialog/index.tsx b/admin/src/pages/DetailPage/components/ChangeLanguageDialog/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/ChangeLanguageDialog/index.tsx rename to admin/src/pages/DetailPage/components/ChangeLanguageDialog/index.tsx diff --git a/admin/src/pages/HomePage/components/CollapseButton/index.tsx b/admin/src/pages/DetailPage/components/CollapseButton/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/CollapseButton/index.tsx rename to admin/src/pages/DetailPage/components/CollapseButton/index.tsx diff --git a/admin/src/pages/HomePage/components/ControllableCombobox/index.tsx b/admin/src/pages/DetailPage/components/ControllableCombobox/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/ControllableCombobox/index.tsx rename to admin/src/pages/DetailPage/components/ControllableCombobox/index.tsx diff --git a/admin/src/pages/HomePage/components/DragButton/index.tsx b/admin/src/pages/DetailPage/components/DragButton/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/DragButton/index.tsx rename to admin/src/pages/DetailPage/components/DragButton/index.tsx diff --git a/admin/src/pages/HomePage/components/I18nCopyNavigationItems/index.tsx b/admin/src/pages/DetailPage/components/I18nCopyNavigationItems/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/I18nCopyNavigationItems/index.tsx rename to admin/src/pages/DetailPage/components/I18nCopyNavigationItems/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationContentHeader/ManageNavigationItems/index.tsx b/admin/src/pages/DetailPage/components/NavigationContentHeader/ManageNavigationItems/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationContentHeader/ManageNavigationItems/index.tsx rename to admin/src/pages/DetailPage/components/NavigationContentHeader/ManageNavigationItems/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationContentHeader/Search/index.tsx b/admin/src/pages/DetailPage/components/NavigationContentHeader/Search/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationContentHeader/Search/index.tsx rename to admin/src/pages/DetailPage/components/NavigationContentHeader/Search/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationContentHeader/index.tsx b/admin/src/pages/DetailPage/components/NavigationContentHeader/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationContentHeader/index.tsx rename to admin/src/pages/DetailPage/components/NavigationContentHeader/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationEmptyState/index.tsx b/admin/src/pages/DetailPage/components/NavigationEmptyState/index.tsx similarity index 98% rename from admin/src/pages/HomePage/components/NavigationEmptyState/index.tsx rename to admin/src/pages/DetailPage/components/NavigationEmptyState/index.tsx index f5de2ae9..9cd90423 100644 --- a/admin/src/pages/HomePage/components/NavigationEmptyState/index.tsx +++ b/admin/src/pages/DetailPage/components/NavigationEmptyState/index.tsx @@ -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; diff --git a/admin/src/pages/DetailPage/components/NavigationHeader/index.tsx b/admin/src/pages/DetailPage/components/NavigationHeader/index.tsx new file mode 100644 index 00000000..b60791d7 --- /dev/null +++ b/admin/src/pages/DetailPage/components/NavigationHeader/index.tsx @@ -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 = ; + +interface Props { + activeNavigation?: NavigationSchema; + structureHasErrors?: boolean; + structureHasChanged?: boolean; + isSaving?: boolean; + handleLocalizationSelection: Effect; + handleSave: Effect; + handleCachePurge: Effect; + permissions: { canUpdate?: boolean }; + locale: { + defaultLocale: string; + restLocale: string[]; + }; + currentLocale?: string; +} + +export const NavigationHeader: React.FC = ({ + 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 ( + } to={`/plugins/${PLUGIN_ID}`}> + {formatMessage(getTrad('popup.navigation.manage.button.goBack'))} + + } + title={activeNavigation?.name ?? formatMessage(getTrad('header.title', 'UI Navigation'))} + subtitle={formatMessage(getTrad('header.description'))} + primaryAction={ + + {hasLocalizations && ( + + {[locale.defaultLocale, ...locale.restLocale].map((code) => ( + + {code} + + ))} + + )} + {canUpdate && hasCache && ( + + )} + {canUpdate && ( + + )} + + } + secondaryAction={ + !isMobile && + activeNavigation && ( + }> + {formatMessage(getTrad('header.meta'), { + id: activeNavigation.documentId, + key: activeNavigation.slug, + })} + + ) + } + /> + ); +}; diff --git a/admin/src/pages/HomePage/components/NavigationHeader/styles.ts b/admin/src/pages/DetailPage/components/NavigationHeader/styles.ts similarity index 100% rename from admin/src/pages/HomePage/components/NavigationHeader/styles.ts rename to admin/src/pages/DetailPage/components/NavigationHeader/styles.ts diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/components/AdditionalFields/AdditionalFieldInput/index.tsx b/admin/src/pages/DetailPage/components/NavigationItemForm/components/AdditionalFields/AdditionalFieldInput/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemForm/components/AdditionalFields/AdditionalFieldInput/index.tsx rename to admin/src/pages/DetailPage/components/NavigationItemForm/components/AdditionalFields/AdditionalFieldInput/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/components/AdditionalFields/AudienceField/index.tsx b/admin/src/pages/DetailPage/components/NavigationItemForm/components/AdditionalFields/AudienceField/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemForm/components/AdditionalFields/AudienceField/index.tsx rename to admin/src/pages/DetailPage/components/NavigationItemForm/components/AdditionalFields/AudienceField/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/components/AdditionalFields/CustomFieldsField/index.tsx b/admin/src/pages/DetailPage/components/NavigationItemForm/components/AdditionalFields/CustomFieldsField/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemForm/components/AdditionalFields/CustomFieldsField/index.tsx rename to admin/src/pages/DetailPage/components/NavigationItemForm/components/AdditionalFields/CustomFieldsField/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/components/AdditionalFields/index.tsx b/admin/src/pages/DetailPage/components/NavigationItemForm/components/AdditionalFields/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemForm/components/AdditionalFields/index.tsx rename to admin/src/pages/DetailPage/components/NavigationItemForm/components/AdditionalFields/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/components/AttachToMenuField/index.tsx b/admin/src/pages/DetailPage/components/NavigationItemForm/components/AttachToMenuField/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemForm/components/AttachToMenuField/index.tsx rename to admin/src/pages/DetailPage/components/NavigationItemForm/components/AttachToMenuField/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/components/CopyFromLocales/index.tsx b/admin/src/pages/DetailPage/components/NavigationItemForm/components/CopyFromLocales/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemForm/components/CopyFromLocales/index.tsx rename to admin/src/pages/DetailPage/components/NavigationItemForm/components/CopyFromLocales/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/components/ManualPathField/index.tsx b/admin/src/pages/DetailPage/components/NavigationItemForm/components/ManualPathField/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemForm/components/ManualPathField/index.tsx rename to admin/src/pages/DetailPage/components/NavigationItemForm/components/ManualPathField/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/components/NavigationItemTypeField/index.tsx b/admin/src/pages/DetailPage/components/NavigationItemForm/components/NavigationItemTypeField/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemForm/components/NavigationItemTypeField/index.tsx rename to admin/src/pages/DetailPage/components/NavigationItemForm/components/NavigationItemTypeField/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/components/PathField/index.tsx b/admin/src/pages/DetailPage/components/NavigationItemForm/components/PathField/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemForm/components/PathField/index.tsx rename to admin/src/pages/DetailPage/components/NavigationItemForm/components/PathField/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/components/ReadFieldsFromRelatedField/index.tsx b/admin/src/pages/DetailPage/components/NavigationItemForm/components/ReadFieldsFromRelatedField/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemForm/components/ReadFieldsFromRelatedField/index.tsx rename to admin/src/pages/DetailPage/components/NavigationItemForm/components/ReadFieldsFromRelatedField/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/components/RelatedEntityField/hooks.ts b/admin/src/pages/DetailPage/components/NavigationItemForm/components/RelatedEntityField/hooks.ts similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemForm/components/RelatedEntityField/hooks.ts rename to admin/src/pages/DetailPage/components/NavigationItemForm/components/RelatedEntityField/hooks.ts diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/components/RelatedEntityField/index.tsx b/admin/src/pages/DetailPage/components/NavigationItemForm/components/RelatedEntityField/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemForm/components/RelatedEntityField/index.tsx rename to admin/src/pages/DetailPage/components/NavigationItemForm/components/RelatedEntityField/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/components/RelatedTypeField/index.tsx b/admin/src/pages/DetailPage/components/NavigationItemForm/components/RelatedTypeField/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemForm/components/RelatedTypeField/index.tsx rename to admin/src/pages/DetailPage/components/NavigationItemForm/components/RelatedTypeField/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/components/TitleField/index.tsx b/admin/src/pages/DetailPage/components/NavigationItemForm/components/TitleField/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemForm/components/TitleField/index.tsx rename to admin/src/pages/DetailPage/components/NavigationItemForm/components/TitleField/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/context/NavigationItemFormContext.ts b/admin/src/pages/DetailPage/components/NavigationItemForm/context/NavigationItemFormContext.ts similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemForm/context/NavigationItemFormContext.ts rename to admin/src/pages/DetailPage/components/NavigationItemForm/context/NavigationItemFormContext.ts diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/index.tsx b/admin/src/pages/DetailPage/components/NavigationItemForm/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemForm/index.tsx rename to admin/src/pages/DetailPage/components/NavigationItemForm/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/types.ts b/admin/src/pages/DetailPage/components/NavigationItemForm/types.ts similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemForm/types.ts rename to admin/src/pages/DetailPage/components/NavigationItemForm/types.ts diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/utils/form.ts b/admin/src/pages/DetailPage/components/NavigationItemForm/utils/form.ts similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemForm/utils/form.ts rename to admin/src/pages/DetailPage/components/NavigationItemForm/utils/form.ts diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/utils/hooks.ts b/admin/src/pages/DetailPage/components/NavigationItemForm/utils/hooks.ts similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemForm/utils/hooks.ts rename to admin/src/pages/DetailPage/components/NavigationItemForm/utils/hooks.ts diff --git a/admin/src/pages/HomePage/components/NavigationItemForm/utils/properties.ts b/admin/src/pages/DetailPage/components/NavigationItemForm/utils/properties.ts similarity index 97% rename from admin/src/pages/HomePage/components/NavigationItemForm/utils/properties.ts rename to admin/src/pages/DetailPage/components/NavigationItemForm/utils/properties.ts index 2d1cc52e..97f9805f 100644 --- a/admin/src/pages/HomePage/components/NavigationItemForm/utils/properties.ts +++ b/admin/src/pages/DetailPage/components/NavigationItemForm/utils/properties.ts @@ -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 { diff --git a/admin/src/pages/HomePage/components/NavigationItemList/Wrapper.ts b/admin/src/pages/DetailPage/components/NavigationItemList/Wrapper.ts similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemList/Wrapper.ts rename to admin/src/pages/DetailPage/components/NavigationItemList/Wrapper.ts diff --git a/admin/src/pages/HomePage/components/NavigationItemList/index.tsx b/admin/src/pages/DetailPage/components/NavigationItemList/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemList/index.tsx rename to admin/src/pages/DetailPage/components/NavigationItemList/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemListItem/ItemCardBadge/index.ts b/admin/src/pages/DetailPage/components/NavigationItemListItem/ItemCardBadge/index.ts similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemListItem/ItemCardBadge/index.ts rename to admin/src/pages/DetailPage/components/NavigationItemListItem/ItemCardBadge/index.ts diff --git a/admin/src/pages/HomePage/components/NavigationItemListItem/ItemCardHeader/Wrapper.tsx b/admin/src/pages/DetailPage/components/NavigationItemListItem/ItemCardHeader/Wrapper.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemListItem/ItemCardHeader/Wrapper.tsx rename to admin/src/pages/DetailPage/components/NavigationItemListItem/ItemCardHeader/Wrapper.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemListItem/ItemCardHeader/icons.tsx b/admin/src/pages/DetailPage/components/NavigationItemListItem/ItemCardHeader/icons.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemListItem/ItemCardHeader/icons.tsx rename to admin/src/pages/DetailPage/components/NavigationItemListItem/ItemCardHeader/icons.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemListItem/ItemCardHeader/index.tsx b/admin/src/pages/DetailPage/components/NavigationItemListItem/ItemCardHeader/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemListItem/ItemCardHeader/index.tsx rename to admin/src/pages/DetailPage/components/NavigationItemListItem/ItemCardHeader/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemListItem/ItemCardRemovedOverlay/index.ts b/admin/src/pages/DetailPage/components/NavigationItemListItem/ItemCardRemovedOverlay/index.ts similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemListItem/ItemCardRemovedOverlay/index.ts rename to admin/src/pages/DetailPage/components/NavigationItemListItem/ItemCardRemovedOverlay/index.ts diff --git a/admin/src/pages/HomePage/components/NavigationItemListItem/Wrapper.ts b/admin/src/pages/DetailPage/components/NavigationItemListItem/Wrapper.ts similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemListItem/Wrapper.ts rename to admin/src/pages/DetailPage/components/NavigationItemListItem/Wrapper.ts diff --git a/admin/src/pages/HomePage/components/NavigationItemListItem/index.tsx b/admin/src/pages/DetailPage/components/NavigationItemListItem/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemListItem/index.tsx rename to admin/src/pages/DetailPage/components/NavigationItemListItem/index.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemPopup/NavigationItemPopupFooter.tsx b/admin/src/pages/DetailPage/components/NavigationItemPopup/NavigationItemPopupFooter.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemPopup/NavigationItemPopupFooter.tsx rename to admin/src/pages/DetailPage/components/NavigationItemPopup/NavigationItemPopupFooter.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemPopup/NavigationItemPopupHeader.tsx b/admin/src/pages/DetailPage/components/NavigationItemPopup/NavigationItemPopupHeader.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemPopup/NavigationItemPopupHeader.tsx rename to admin/src/pages/DetailPage/components/NavigationItemPopup/NavigationItemPopupHeader.tsx diff --git a/admin/src/pages/HomePage/components/NavigationItemPopup/index.tsx b/admin/src/pages/DetailPage/components/NavigationItemPopup/index.tsx similarity index 100% rename from admin/src/pages/HomePage/components/NavigationItemPopup/index.tsx rename to admin/src/pages/DetailPage/components/NavigationItemPopup/index.tsx diff --git a/admin/src/pages/HomePage/components/index.ts b/admin/src/pages/DetailPage/components/index.ts similarity index 100% rename from admin/src/pages/HomePage/components/index.ts rename to admin/src/pages/DetailPage/components/index.ts diff --git a/admin/src/pages/HomePage/hooks/index.tsx b/admin/src/pages/DetailPage/hooks/index.tsx similarity index 77% rename from admin/src/pages/HomePage/hooks/index.tsx rename to admin/src/pages/DetailPage/hooks/index.tsx index 89e9b419..7c054dce 100644 --- a/admin/src/pages/HomePage/hooks/index.tsx +++ b/admin/src/pages/DetailPage/hooks/index.tsx @@ -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'; diff --git a/admin/src/pages/HomePage/hooks/useI18nCopyNavigationItemsModal.tsx b/admin/src/pages/DetailPage/hooks/useI18nCopyNavigationItemsModal.tsx similarity index 100% rename from admin/src/pages/HomePage/hooks/useI18nCopyNavigationItemsModal.tsx rename to admin/src/pages/DetailPage/hooks/useI18nCopyNavigationItemsModal.tsx diff --git a/admin/src/pages/HomePage/hooks/useInvalidateQueries.ts b/admin/src/pages/DetailPage/hooks/useInvalidateQueries.ts similarity index 100% rename from admin/src/pages/HomePage/hooks/useInvalidateQueries.ts rename to admin/src/pages/DetailPage/hooks/useInvalidateQueries.ts diff --git a/admin/src/pages/HomePage/hooks/useLocales.ts b/admin/src/pages/DetailPage/hooks/useLocales.ts similarity index 100% rename from admin/src/pages/HomePage/hooks/useLocales.ts rename to admin/src/pages/DetailPage/hooks/useLocales.ts diff --git a/admin/src/pages/HomePage/hooks/useNavigationItemPopup.ts b/admin/src/pages/DetailPage/hooks/useNavigationItemPopup.ts similarity index 100% rename from admin/src/pages/HomePage/hooks/useNavigationItemPopup.ts rename to admin/src/pages/DetailPage/hooks/useNavigationItemPopup.ts diff --git a/admin/src/pages/HomePage/hooks/usePluginMediaQuery.tsx b/admin/src/pages/DetailPage/hooks/usePluginMediaQuery.tsx similarity index 100% rename from admin/src/pages/HomePage/hooks/usePluginMediaQuery.tsx rename to admin/src/pages/DetailPage/hooks/usePluginMediaQuery.tsx diff --git a/admin/src/pages/HomePage/hooks/useSearch.ts b/admin/src/pages/DetailPage/hooks/useSearch.ts similarity index 100% rename from admin/src/pages/HomePage/hooks/useSearch.ts rename to admin/src/pages/DetailPage/hooks/useSearch.ts diff --git a/admin/src/pages/HomePage/index.tsx b/admin/src/pages/DetailPage/index.tsx similarity index 85% rename from admin/src/pages/HomePage/index.tsx rename to admin/src/pages/DetailPage/index.tsx index 6df2148f..ba5b9c77 100644 --- a/admin/src/pages/HomePage/index.tsx +++ b/admin/src/pages/DetailPage/index.tsx @@ -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'; @@ -27,13 +27,12 @@ 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(); @@ -41,7 +40,6 @@ const Inner = () => { const { toggleNotification } = useNotification(); - const [recentNavigation, setRecentNavigation] = useState<{ documentId?: string; id?: Data.ID }>(); const [currentNavigation, setCurrentNavigation] = useState(); const [structureChanged, setStructureChanged] = useState(false); @@ -85,11 +83,6 @@ const Inner = () => { items: next.items.map(appendViewId), }); - setRecentNavigation({ - documentId: next.documentId, - id: next.id, - }); - setStructureChanged(false); }, }); @@ -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 && @@ -180,10 +179,8 @@ const Inner = () => { purgeMutation.mutate(undefined)} - handleChangeSelection={setCurrentNavigation} + handleCachePurge={() => purgeMutation.mutate(documentId ? [documentId] : undefined)} handleLocalizationSelection={ structureChanged ? changeCurrentLocaleAction.trigger : changeCurrentLocaleAction.perform } @@ -256,12 +253,4 @@ const Inner = () => { ); }; -export default function HomePage() { - return ( - - - - ); -} - -export { HomePage }; +export { DetailPage }; diff --git a/admin/src/pages/HomePage/utils/index.ts b/admin/src/pages/DetailPage/utils/index.ts similarity index 100% rename from admin/src/pages/HomePage/utils/index.ts rename to admin/src/pages/DetailPage/utils/index.ts diff --git a/admin/src/pages/HomePage/utils/parsers.ts b/admin/src/pages/DetailPage/utils/parsers.ts similarity index 100% rename from admin/src/pages/HomePage/utils/parsers.ts rename to admin/src/pages/DetailPage/utils/parsers.ts diff --git a/admin/src/pages/HomePage/components/NavigationHeader/hooks.tsx b/admin/src/pages/HomePage/components/NavigationHeader/hooks.tsx deleted file mode 100644 index 8ed5ee11..00000000 --- a/admin/src/pages/HomePage/components/NavigationHeader/hooks.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { useCallback, useMemo, useState } from 'react'; -import { NavigationManager } from '../NavigationManager'; - -export const useNavigationManager = () => { - const [isOpened, setIsOpened] = useState(false); - const open = useCallback(() => setIsOpened(true), [setIsOpened]); - const close = useCallback(() => setIsOpened(false), [setIsOpened]); - - const modal = useMemo( - () => - isOpened ? ( - - ) : null, - [isOpened, close] - ); - - return useMemo( - () => ({ - navigationManagerModal: modal, - openNavigationManagerModal: open, - closeNavigationManagerModal: close, - }), - [modal, open, close] - ); -}; diff --git a/admin/src/pages/HomePage/components/NavigationHeader/index.tsx b/admin/src/pages/HomePage/components/NavigationHeader/index.tsx deleted file mode 100644 index 0623aaf0..00000000 --- a/admin/src/pages/HomePage/components/NavigationHeader/index.tsx +++ /dev/null @@ -1,238 +0,0 @@ -import { - Box, - Button, - Field, - Flex, - Grid, - SingleSelect, - SingleSelectOption, - Tag, -} from '@strapi/design-system'; -import { Check, Information } from '@strapi/icons'; -import { Layouts } from '@strapi/strapi/admin'; -import React from 'react'; -import { useIntl } from 'react-intl'; -import styled from 'styled-components'; -import { NavigationSchema } from '../../../../api/validators'; -import { getTrad } from '../../../../translations'; -import { Effect } from '../../../../types'; -import { useConfig, usePluginMediaQuery } from '../../hooks'; -import { useNavigationManager } from './hooks'; - -const StyledGridItem = styled(Grid.Item)<{ - orderInitial?: number; - orderSmall?: number; - orderMedium?: number; -}>` - order: ${({ orderInitial }) => orderInitial ?? 'unset'}; - - @media (min-width: 520px) { - order: ${({ orderSmall }) => orderSmall ?? 'unset'}; - } - - @media (min-width: 768px) { - order: ${({ orderMedium }) => orderMedium ?? 'unset'}; - } -`; - -const submitIcon = ; - -interface Props { - activeNavigation?: NavigationSchema; - availableNavigations: NavigationSchema[]; - structureHasErrors?: boolean; - structureHasChanged?: boolean; - isSaving?: boolean; - handleChangeSelection: Effect; - handleLocalizationSelection: Effect; - handleSave: Effect; - handleCachePurge: Effect; - permissions: { canUpdate?: boolean }; - locale: { - defaultLocale: string; - restLocale: string[]; - }; - currentLocale?: string; -} - -export const NavigationHeader: React.FC = ({ - activeNavigation, - availableNavigations, - structureHasErrors, - structureHasChanged, - isSaving, - handleChangeSelection, - handleLocalizationSelection, - handleSave, - handleCachePurge, - permissions = {}, - locale, - currentLocale, -}) => { - const { formatMessage } = useIntl(); - const { openNavigationManagerModal, navigationManagerModal } = useNavigationManager(); - - const configQuery = useConfig(); - - const hasLocalizations = !!locale.restLocale?.length; - const hasCache = configQuery.data?.isCacheEnabled; - - const { canUpdate } = permissions; - - const { isDesktop, isMobile, isLargeDesktop } = usePluginMediaQuery(); - - return ( - <> - - - - {!hasLocalizations && isLargeDesktop ? : null} - {canUpdate && ( - - - - )} - - - { - const nextNavigation = availableNavigations.find( - ({ documentId }) => nextDocumentId === documentId - ); - - if (nextNavigation) { - handleChangeSelection(nextNavigation); - } - }} - value={activeNavigation?.documentId} - size="S" - style={null} - > - {availableNavigations - .filter(({ locale }) => locale === currentLocale) - .map(({ documentId, name }) => ( - - {name} - - ))} - - - - {hasLocalizations ? ( - - - - {[locale.defaultLocale, ...locale.restLocale].map((code) => ( - - {code} - - ))} - - - - ) : null} - {canUpdate && ( - - - - )} - {hasCache && ( - <> - {isDesktop && ( - - )} - - - - - )} - - - {canUpdate && navigationManagerModal} - - } - secondaryAction={ - !isMobile && ( - }> - {activeNavigation - ? formatMessage(getTrad('header.meta'), { - id: activeNavigation?.documentId, - key: activeNavigation?.slug, - }) - : null} - - ) - } - /> - - ); -}; diff --git a/admin/src/pages/HomePage/components/NavigationManager/AllNavigations/icons.tsx b/admin/src/pages/HomePage/components/NavigationManager/AllNavigations/icons.tsx deleted file mode 100644 index 9d650ddb..00000000 --- a/admin/src/pages/HomePage/components/NavigationManager/AllNavigations/icons.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import React from 'react'; -import { Pencil, Trash, Feather } from '@strapi/icons'; - -export const edit = ; -export const deleteIcon = ; -export const featherIcon = ; diff --git a/admin/src/pages/HomePage/components/NavigationManager/AllNavigations/index.tsx b/admin/src/pages/HomePage/components/NavigationManager/AllNavigations/index.tsx deleted file mode 100644 index b2d717a9..00000000 --- a/admin/src/pages/HomePage/components/NavigationManager/AllNavigations/index.tsx +++ /dev/null @@ -1,263 +0,0 @@ -import { - Box, - Button, - Checkbox, - Flex, - Grid, - IconButton, - Table, - Tbody, - Td, - Th, - Thead, - Tr, - Typography, -} from '@strapi/design-system'; -import { prop } from 'lodash/fp'; -import { useCallback, useMemo } from 'react'; -import { useIntl } from 'react-intl'; - -import { getTrad } from '../../../../../translations'; -import { useConfig, useLocale } from '../../../hooks'; -import { Footer, FooterBase } from '../Footer'; -import { INITIAL_NAVIGATION } from '../NewNavigation'; -import { CommonProps, ListState, Navigation } from '../types'; -import * as icons from './icons'; - -interface Props extends ListState, CommonProps {} - -export const AllNavigations = ({ navigations, selected, setState }: Props) => { - const configQuery = useConfig(); - - const hasAnySelected = !!selected.length; - - const { formatMessage } = useIntl(); - - const localeQuery = useLocale(); - - const toggleSelected = useCallback( - () => - setState({ - navigations, - selected: hasAnySelected ? [] : navigations.map((n) => n), - view: 'LIST', - }), - [setState, navigations, hasAnySelected] - ); - - const currentlySelectedSet = useMemo(() => new Set(selected.map(prop('documentId'))), [selected]); - - const handleSelect = (navigation: Navigation, isSelected: boolean) => () => { - setState({ - navigations, - selected: isSelected - ? selected.filter(({ documentId }) => documentId !== navigation.documentId) - : selected.concat([navigation]), - view: 'LIST', - }); - }; - - const edit = (navigation: Navigation) => () => { - setState({ - view: 'EDIT', - current: navigation, - navigation, - alreadyUsedNames: navigations.reduce( - (acc, { name }) => (name !== navigation.name ? acc.concat([name]) : acc), - [] - ), - }); - }; - - const _delete = (navigations: Array) => () => { - setState({ - view: 'DELETE', - navigations, - }); - }; - - const purgeCache = (navigations: Array) => () => { - setState({ - view: 'CACHE_PURGE', - navigations, - }); - }; - - const deleteSelected = useCallback(_delete(selected), [_delete]); - - const purgeSelected = useCallback(purgeCache(selected), [purgeCache]); - - const getLocalizations = (focused: Navigation) => - [focused].concat( - navigations.filter( - (navigation) => - navigation.documentId === focused.documentId && navigation.locale !== focused.locale - ) - ); - - return ( - <> - - - {hasAnySelected ? ( - - - {formatMessage(getTrad('popup.navigation.manage.table.hasSelected'), { - count: selected.length, - })} - - - {configQuery.data?.isCacheEnabled ? ( - - ) : null} - - ) : null} - - - - - - - - - - - - - - - {navigations - .filter(({ locale }) => locale === localeQuery.data?.defaultLocale) - .map((navigation) => ( - - - - - - - - - ))} - -
- - - - {formatMessage(getTrad('popup.navigation.manage.table.id'))} - - - - {formatMessage(getTrad('popup.navigation.manage.table.name'))} - - - - {formatMessage(getTrad('popup.navigation.manage.table.locale'))} - - - - {formatMessage(getTrad('popup.navigation.manage.table.visibility'))} - - - {configQuery.data?.isCacheEnabled ? ( - - - - - - ) : null} -
- - - {navigation.documentId} - - {navigation.name} - - - {getLocalizations(navigation).map(prop('locale')).join(', ')} - - - - {navigation.visible - ? formatMessage(getTrad('popup.navigation.manage.navigation.visible')) - : formatMessage(getTrad('popup.navigation.manage.navigation.hidden'))} - - - - - - - - - - {configQuery.data?.isCacheEnabled ? ( - - - - ) : null} - -
- - ); -}; - -export const AllNavigationsFooter: Footer = ({ - onClose, - state, - setState, - navigations, - isLoading, -}) => { - const { formatMessage } = useIntl(); - - return ( - - setState({ - view: 'CREATE', - alreadyUsedNames: navigations.map(({ name }) => name), - current: INITIAL_NAVIGATION, - }), - variant: 'default', - disabled: isLoading, - children: formatMessage(getTrad('popup.navigation.manage.button.create')), - }} - /> - ); -}; diff --git a/admin/src/pages/HomePage/components/NavigationManager/DeletionConfirm/index.tsx b/admin/src/pages/HomePage/components/NavigationManager/DeletionConfirm/index.tsx deleted file mode 100644 index ccac3278..00000000 --- a/admin/src/pages/HomePage/components/NavigationManager/DeletionConfirm/index.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { Flex, Grid, Typography } from '@strapi/design-system'; -import { prop } from 'lodash/fp'; -import { useIntl } from 'react-intl'; - -import { getTrad } from '../../../../../translations'; -import { Footer, FooterBase } from '../Footer'; -import { CommonProps, DeleteState, Navigation } from '../types'; - -interface Props extends DeleteState, CommonProps {} - -export const DeletionConfirm = ({ navigations }: Props) => { - const { formatMessage } = useIntl(); - - return ( - - - - - {formatMessage(getTrad('popup.navigation.manage.delete.header'))} - - - - - - {renderItems(navigations)} - - - - ); -}; - -export const DeleteConfirmFooter: Footer = ({ state, onSubmit, onReset, isLoading }) => { - const { formatMessage } = useIntl(); - - return ( - - ); -}; - -const renderItems = (navigations: Array) => navigations.map(prop('name')).join(', '); diff --git a/admin/src/pages/HomePage/components/NavigationManager/ErrorDetails/index.tsx b/admin/src/pages/HomePage/components/NavigationManager/ErrorDetails/index.tsx deleted file mode 100644 index 39ae9359..00000000 --- a/admin/src/pages/HomePage/components/NavigationManager/ErrorDetails/index.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { Grid } from '@strapi/design-system'; -import { useNotification } from '@strapi/strapi/admin'; -import { useEffect } from 'react'; -import { useIntl } from 'react-intl'; - -import { getTrad } from '../../../../../translations'; -import { Footer, FooterBase } from '../Footer'; -import { CommonProps, ErrorState } from '../types'; - -interface Props extends ErrorState, CommonProps {} - -export const ErrorDetails = ({ errors }: Props) => { - const { formatMessage } = useIntl(); - - const { toggleNotification } = useNotification(); - - useEffect(() => { - errors.map((error) => { - toggleNotification({ - type: 'warning', - message: formatMessage({ id: '', defaultMessage: error.message }), - }); - console.error(error); - }); - }, []); - - return ( - - - {formatMessage(getTrad('popup.navigation.manage.error.message'))} - - - ); -}; - -export const ErrorDetailsFooter: Footer = ({ onReset }) => { - const { formatMessage } = useIntl(); - - return ( - - ); -}; diff --git a/admin/src/pages/HomePage/components/NavigationManager/Footer/index.tsx b/admin/src/pages/HomePage/components/NavigationManager/Footer/index.tsx deleted file mode 100644 index e3b51085..00000000 --- a/admin/src/pages/HomePage/components/NavigationManager/Footer/index.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { Button, Modal } from '@strapi/design-system'; - -import { NavigationSchema } from '../../../../../api/validators'; -import { VoidEffect } from '../../../../../types'; -import { SetState, State } from '../types'; - -interface FooterBaseProps { - end?: ActionProps; - start?: ActionProps; -} - -export type Footer = React.FC<{ - navigations: Array; - onClose?: VoidEffect; - onReset: VoidEffect; - onSubmit: VoidEffect; - setState: SetState; - state: State; - disabled?: boolean; - isLoading: boolean; -}>; - -interface ActionProps { - children: React.ReactNode; - disabled?: boolean; - onClick?: VoidEffect; - variant: 'danger' | 'secondary' | 'tertiary' | 'default'; -} - -export const FooterBase: React.FC = ({ start, end }) => { - return ( - - {renderActions(start)} - {renderActions(end)} - - ); -}; - -const renderActions = (actions: ActionProps | undefined): React.ReactNode => - actions ? ( - - ) : null; diff --git a/admin/src/pages/HomePage/components/NavigationManager/NavigationUpdate/index.tsx b/admin/src/pages/HomePage/components/NavigationManager/NavigationUpdate/index.tsx deleted file mode 100644 index 732caf83..00000000 --- a/admin/src/pages/HomePage/components/NavigationManager/NavigationUpdate/index.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { useCallback, useMemo } from 'react'; -import { useIntl } from 'react-intl'; - -import { getTrad } from '../../../../../translations'; -import { Effect } from '../../../../../types'; -import { Footer, FooterBase } from '../Footer'; -import { Form } from '../Form'; -import { CommonProps, EditState, Navigation } from '../types'; - -interface Props extends EditState, CommonProps {} - -export const NavigationUpdate = ({ - alreadyUsedNames, - current, - isLoading, - navigation: initialValue, - setState, -}: Props) => { - const navigation: Navigation = useMemo(() => current ?? initialValue, [current]); - - const onChange: Effect = useCallback( - ({ disabled, ...updated }: Navigation & { disabled?: boolean }) => { - setState({ - view: 'EDIT', - alreadyUsedNames, - current: updated, - disabled, - navigation: initialValue, - }); - }, - [setState, initialValue, alreadyUsedNames] - ); - - return ( - - navigation={navigation} - onChange={onChange} - isLoading={isLoading} - alreadyUsedNames={alreadyUsedNames} - /> - ); -}; - -export const NavigationUpdateFooter: Footer = ({ onSubmit, onReset, disabled, isLoading }) => { - const { formatMessage } = useIntl(); - - return ( - - ); -}; diff --git a/admin/src/pages/HomePage/components/NavigationManager/NewNavigation/index.tsx b/admin/src/pages/HomePage/components/NavigationManager/NewNavigation/index.tsx deleted file mode 100644 index 2a139291..00000000 --- a/admin/src/pages/HomePage/components/NavigationManager/NewNavigation/index.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { useCallback } from 'react'; -import { useIntl } from 'react-intl'; - -import { getTrad } from '../../../../../translations'; -import { Footer, FooterBase } from '../Footer'; -import { Form } from '../Form'; -import { CommonProps, CreateState, Navigation, NewNavigation as NewNavigationType } from '../types'; - -interface Props extends CreateState, CommonProps {} - -export const INITIAL_NAVIGATION = { - name: '', - items: [], - visible: false, -} as unknown as Navigation; - -export const NewNavigation = ({ setState, current, isLoading, alreadyUsedNames }: Props) => { - const onSubmit = useCallback( - ({ disabled, ...updated }: NewNavigationType & { disabled?: boolean }) => { - setState({ - view: 'CREATE', - current: updated, - alreadyUsedNames, - disabled, - }); - }, - [setState] - ); - - return ( - - alreadyUsedNames={alreadyUsedNames} - navigation={current} - onChange={onSubmit} - isLoading={isLoading} - /> - ); -}; - -export const NewNavigationFooter: Footer = ({ onSubmit, onReset, disabled, isLoading }) => { - const { formatMessage } = useIntl(); - - return ( - - ); -}; diff --git a/admin/src/pages/HomePage/components/NavigationManager/PurgeCacheConfirm/index.tsx b/admin/src/pages/HomePage/components/NavigationManager/PurgeCacheConfirm/index.tsx deleted file mode 100644 index eaa03b8e..00000000 --- a/admin/src/pages/HomePage/components/NavigationManager/PurgeCacheConfirm/index.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { Flex, Grid, Typography } from '@strapi/design-system'; -import { prop } from 'lodash/fp'; -import { useIntl } from 'react-intl'; -import { getTrad } from '../../../../../translations'; - -import { Footer, FooterBase } from '../Footer'; -import { CommonProps, Navigation, PurgeCacheState } from '../types'; - -interface Props extends PurgeCacheState, CommonProps {} - -export const PurgeCacheConfirm = ({ navigations }: Props) => { - const { formatMessage } = useIntl(); - - return ( - - - - - {formatMessage(getTrad('popup.navigation.manage.purge.header'))} - - - - - - {renderItems(navigations)} - - - - ); -}; - -export const PurgeCacheConfirmFooter: Footer = ({ onSubmit, onReset, isLoading }) => { - const { formatMessage } = useIntl(); - - return ( - - ); -}; - -const renderItems = (navigations: Array) => navigations.map(prop('name')).join(', '); diff --git a/admin/src/pages/HomePage/components/NavigationManager/index.tsx b/admin/src/pages/HomePage/components/NavigationManager/index.tsx deleted file mode 100644 index c895c936..00000000 --- a/admin/src/pages/HomePage/components/NavigationManager/index.tsx +++ /dev/null @@ -1,319 +0,0 @@ -import { Flex, Loader, Modal } from '@strapi/design-system'; -import { useNotification } from '@strapi/strapi/admin'; -import { sortBy } from 'lodash'; -import { useCallback, useEffect, useMemo, useState } from 'react'; -import { useIntl } from 'react-intl'; -import { getTrad } from '../../../../translations'; -import { VoidEffect } from '../../../../types'; -import { - useCreateNavigation, - useDeleteNavigations, - useHardReset, - useLocale, - useNavigations, - usePurgeNavigation, - useUpdateNavigation, -} from '../../hooks'; -import { getPendingAction } from '../../utils'; -import { AllNavigations, AllNavigationsFooter } from './AllNavigations'; -import { DeleteConfirmFooter, DeletionConfirm } from './DeletionConfirm'; -import { ErrorDetails, ErrorDetailsFooter } from './ErrorDetails'; -import { Footer } from './Footer'; -import { NavigationUpdate, NavigationUpdateFooter } from './NavigationUpdate'; -import { NewNavigation, NewNavigationFooter } from './NewNavigation'; -import { PurgeCacheConfirm, PurgeCacheConfirmFooter } from './PurgeCacheConfirm'; -import { SetState, State } from './types'; -import { Typography } from '@strapi/design-system'; - -interface Props { - initialState: State; - isOpened?: boolean; - onClose?: VoidEffect; -} - -export const NavigationManager = ({ initialState, isOpened, onClose }: Props) => { - const { formatMessage } = useIntl(); - const [state, setState] = useState(initialState); - - const { toggleNotification } = useNotification(); - - const hardReset = useHardReset(); - - const deleteNavigationsMutation = useDeleteNavigations(); - - const createNavigationMutation = useCreateNavigation(); - - const updateNavigationMutation = useUpdateNavigation({}); - - const purgeNavigationsMutation = usePurgeNavigation(); - - const navigationsQuery = useNavigations(); - - const localeQuery = useLocale(); - - const navigations = useMemo( - () => sortBy(navigationsQuery.data ?? [], 'id'), - [navigationsQuery.data] - ); - - const pending = getPendingAction([ - deleteNavigationsMutation, - navigationsQuery, - createNavigationMutation, - updateNavigationMutation, - purgeNavigationsMutation, - localeQuery, - ]); - - const onReset = useCallback(() => setState({ view: 'INITIAL' }), [setState]); - - const onSubmit = useCallback(async () => { - const performAction = - state.view === 'DELETE' - ? () => { - deleteNavigationsMutation.mutate( - state.navigations.reduce((acc, navigation) => { - if (navigation.documentId) { - acc.push(navigation.documentId); - } - - return acc; - }, []), - { - onSuccess: hardReset, - } - ); - } - : state.view === 'EDIT' - ? () => { - updateNavigationMutation.mutate(state.current, { - onSuccess() { - hardReset(); - toggleNotification({ - type: 'success', - message: formatMessage(getTrad('notification.navigation.submit')), - }); - }, - onError(error) { - // TODO: handle errors - console.warn(error); - - toggleNotification({ - type: 'warning', - message: formatMessage(getTrad('notification.navigation.error'), { - errorTitles: '', - }), - }); - }, - }); - } - : state.view === 'CREATE' && state.current - ? () => { - createNavigationMutation.mutate(state.current, { - onSuccess() { - hardReset(); - toggleNotification({ - type: 'success', - message: formatMessage(getTrad('notification.navigation.submit')), - }); - }, - onError(error) { - // TODO: handle errors - console.warn(error); - - toggleNotification({ - type: 'warning', - message: formatMessage(getTrad('notification.navigation.error'), { - errorTitles: '', - }), - }); - }, - }); - } - : state.view === 'CACHE_PURGE' - ? () => { - purgeNavigationsMutation.mutate( - state.navigations.reduce((acc, navigation) => { - if (navigation.documentId) { - acc.push(navigation.documentId); - } - - return acc; - }, []), - { - onSuccess: hardReset, - } - ); - } - : () => {}; - - try { - performAction(); - setState({ view: 'INITIAL' }); - } catch (error) { - setState({ - view: 'ERROR', - errors: error instanceof Error ? [error] : [], - }); - } - }, [ - state, - setState, - hardReset, - createNavigationMutation, - purgeNavigationsMutation, - updateNavigationMutation, - deleteNavigationsMutation, - toggleNotification, - formatMessage, - getTrad, - ]); - - useEffect(() => { - if (state.view === 'INITIAL' || state.view === 'LIST') { - setState({ - view: 'LIST', - navigations, - selected: [], - }); - } - }, [state.view, navigations]); - - const header = renderHeader(state, formatMessage, !!pending); - const content = renderContent(state, setState, !!pending); - const footer = renderFooter({ - state, - setState, - onClose, - onSubmit, - onReset, - navigations, - isLoading: !!pending, - }); - - return ( - { - if (!isOpen) { - onClose?.(); - } - }} - open={isOpened} - > - - - - {header} - - - {content} - {footer} - - - ); -}; - -const renderHeader = ( - state: State, - formatMessage: ReturnType['formatMessage'], - isLoading: boolean -) => { - switch (state.view) { - case 'LIST': - case 'CREATE': - case 'ERROR': - case 'CACHE_PURGE': - case 'DELETE': { - return ( - - {isLoading ? : null} - {formatMessage(getTrad(`popup.navigation.manage.header.${state.view}`))} - - ); - } - case 'EDIT': { - return ( - - {isLoading ? : null} - - {formatMessage(getTrad('popup.navigation.manage.header.EDIT'), { - name: state.navigation.name, - })} - - ); - } - case 'INITIAL': { - return null; - } - default: - return handleUnknownState(state); - } -}; - -const renderContent = (state: State, setState: SetState, isLoading: boolean) => { - const commonProps = { - setState, - isLoading, - }; - - switch (state.view) { - case 'LIST': { - return ; - } - case 'EDIT': { - return ; - } - case 'CREATE': { - return ; - } - case 'DELETE': { - return ; - } - case 'CACHE_PURGE': { - return ; - } - case 'INITIAL': { - return ; - } - case 'ERROR': { - return ; - } - default: - return handleUnknownState(state); - } -}; - -const renderFooter: Footer = (props) => { - switch (props.state.view) { - case 'LIST': { - return ; - } - case 'CREATE': { - return ; - } - case 'EDIT': { - return ; - } - case 'DELETE': { - return ; - } - case 'CACHE_PURGE': { - return ; - } - case 'ERROR': { - return ; - } - case 'INITIAL': { - return null; - } - default: - return handleUnknownState(props.state); - } -}; - -const handleUnknownState = (state: undefined | { view: string }) => { - console.warn(`Unknown state "${state?.view}". (${JSON.stringify(state)})`); - - return null; -}; diff --git a/admin/src/pages/HomePage/components/NavigationManager/types.ts b/admin/src/pages/HomePage/components/NavigationManager/types.ts deleted file mode 100644 index 0a383cd0..00000000 --- a/admin/src/pages/HomePage/components/NavigationManager/types.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Dispatch, SetStateAction } from 'react'; - -import { NavigationSchema } from '../../../../api/validators'; - -export type Navigation = Pick< - NavigationSchema, - 'id' | 'items' | 'name' | 'locale' | 'visible' | 'documentId' | 'slug' ->; - -export type NewNavigation = Omit; - -export type State = - | InitialState - | ListState - | EditState - | CreateState - | DeleteState - | PurgeCacheState - | ErrorState; - -export type SetState = Dispatch>; - -interface CommonState {} - -export interface CommonProps { - setState: SetState; - isLoading: boolean; -} - -export interface InitialState extends CommonState { - view: 'INITIAL'; -} - -export interface ListState extends CommonState { - view: 'LIST'; - navigations: Array; - selected: Array; -} - -export interface EditState extends CommonState { - view: 'EDIT'; - navigation: Navigation; - current: Navigation; - disabled?: boolean; - alreadyUsedNames: Array; -} - -export interface CreateState extends CommonState { - view: 'CREATE'; - current: NewNavigation; - disabled?: boolean; - alreadyUsedNames: Array; -} - -export interface DeleteState extends CommonState { - view: 'DELETE'; - navigations: Array; -} - -export interface PurgeCacheState extends CommonState { - view: 'CACHE_PURGE'; - navigations: Array; -} - -export interface ErrorState extends CommonState { - view: 'ERROR'; - errors: Array; -} diff --git a/admin/src/pages/HomePage/components/NavigationManager/Form/hooks.ts b/admin/src/pages/OverviewPage/components/NavigationForm/hooks.ts similarity index 100% rename from admin/src/pages/HomePage/components/NavigationManager/Form/hooks.ts rename to admin/src/pages/OverviewPage/components/NavigationForm/hooks.ts diff --git a/admin/src/pages/HomePage/components/NavigationManager/Form/index.tsx b/admin/src/pages/OverviewPage/components/NavigationForm/index.tsx similarity index 96% rename from admin/src/pages/HomePage/components/NavigationManager/Form/index.tsx rename to admin/src/pages/OverviewPage/components/NavigationForm/index.tsx index 13ed4de8..69f70a3f 100644 --- a/admin/src/pages/HomePage/components/NavigationManager/Form/index.tsx +++ b/admin/src/pages/OverviewPage/components/NavigationForm/index.tsx @@ -5,9 +5,9 @@ import { useEffect, useState } from 'react'; import { useIntl } from 'react-intl'; import { Field } from '@sensinum/strapi-utils'; -import { getTrad } from '../../../../../translations'; -import { Effect, FormChangeEvent, FormItemErrorSchema } from '../../../../../types'; -import { Navigation } from '../types'; +import { getTrad } from '../../../../translations'; +import { Effect, FormChangeEvent, FormItemErrorSchema } from '../../../../types'; +import { Navigation } from '../../types'; import { formSchema } from './hooks'; interface Props> { @@ -95,6 +95,10 @@ export const Form = >({ }, []); useEffect(() => { + if (name === undefined && visible === undefined) { + return; + } + if (`${name}-${visible}` !== `${navigation.name}-${navigation.visible}`) { const { error } = formSchema({ alreadyUsedNames }).safeParse(formValue); diff --git a/admin/src/pages/OverviewPage/components/NavigationFormModal/index.tsx b/admin/src/pages/OverviewPage/components/NavigationFormModal/index.tsx new file mode 100644 index 00000000..395407db --- /dev/null +++ b/admin/src/pages/OverviewPage/components/NavigationFormModal/index.tsx @@ -0,0 +1,77 @@ +import { Button, Modal } from '@strapi/design-system'; +import { useState } from 'react'; +import { useIntl } from 'react-intl'; + +import { getTrad } from '../../../../translations'; +import { Effect, VoidEffect } from '../../../../types'; +import { Navigation } from '../../types'; +import { Form } from '../NavigationForm'; + +interface Props { + navigation: Partial; + alreadyUsedNames: Array; + isLoading?: boolean; + onClose: VoidEffect; + onSubmit: Effect>; +} + +export const NavigationFormModal = ({ + navigation, + alreadyUsedNames, + isLoading, + onClose, + onSubmit, +}: Props) => { + const { formatMessage } = useIntl(); + + const [current, setCurrent] = useState(navigation); + const [isDisabled, setIsDisabled] = useState(false); + + const isEdit = !!navigation.documentId; + + const handleChange = ({ disabled, ...updated }: Partial & { disabled?: boolean }) => { + setCurrent(updated); + setIsDisabled(!!disabled); + }; + + return ( + { + if (!isOpen) { + onClose(); + } + }} + > + + + + {isEdit + ? formatMessage(getTrad('popup.navigation.manage.header.EDIT'), { + name: navigation.name, + }) + : formatMessage(getTrad('popup.navigation.manage.header.CREATE'))} + + + +
+ + + + + + + + + + ); +}; diff --git a/admin/src/pages/OverviewPage/index.tsx b/admin/src/pages/OverviewPage/index.tsx new file mode 100644 index 00000000..94b90b12 --- /dev/null +++ b/admin/src/pages/OverviewPage/index.tsx @@ -0,0 +1,365 @@ +import { + Button, + EmptyStateLayout, + Flex, + IconButton, + Status, + Table, + Tbody, + Td, + Th, + Thead, + Tr, + Typography, + VisuallyHidden, +} from '@strapi/design-system'; +import { Feather, Pencil, Plus, Trash } from '@strapi/icons'; +import { EmptyDocuments } from '@strapi/icons/symbols'; +import { Layouts, Page, useNotification } from '@strapi/strapi/admin'; +import { sortBy } from 'lodash'; +import { useMemo, useState } from 'react'; +import { useIntl } from 'react-intl'; +import { useNavigate } from 'react-router-dom'; + +import { ConfirmationDialog } from '../../components/ConfirmationDialog'; +import { + useConfig, + useCreateNavigation, + useDeleteNavigations, + useHardReset, + useLocale, + useNavigations, + usePurgeNavigation, + useSettingsPermissions, + useUpdateNavigation, +} from '../../hooks'; +import { PLUGIN_ID } from '../../pluginId'; +import { getTrad } from '../../translations'; +import { NavigationFormModal } from './components/NavigationFormModal'; +import { Navigation } from './types'; + +const INITIAL_NAVIGATION: Partial = { + name: '', + items: [], + visible: false, +}; + +type OverlayState = + | { type: 'create' } + | { type: 'edit'; navigation: Navigation } + | { type: 'delete'; navigation: Navigation } + | { type: 'purge'; navigation?: Navigation } + | null; + +const OverviewPage = () => { + const { formatMessage } = useIntl(); + const navigate = useNavigate(); + const { toggleNotification } = useNotification(); + + const navigationsQuery = useNavigations(); + const localeQuery = useLocale(); + const configQuery = useConfig(); + const { canUpdate, isLoadingForPermissions } = useSettingsPermissions(); + + const createNavigationMutation = useCreateNavigation(); + const updateNavigationMutation = useUpdateNavigation({}); + const deleteNavigationsMutation = useDeleteNavigations(); + const purgeNavigationsMutation = usePurgeNavigation(); + const hardReset = useHardReset(); + + const [overlay, setOverlay] = useState(null); + + const navigations = useMemo( + () => sortBy(navigationsQuery.data ?? [], 'id'), + [navigationsQuery.data] + ); + + const defaultLocaleNavigations = useMemo( + () => navigations.filter(({ locale }) => locale === localeQuery.data?.defaultLocale), + [navigations, localeQuery.data?.defaultLocale] + ); + + const hasCache = !!configQuery.data?.isCacheEnabled; + + const isMutating = + createNavigationMutation.isPending || + updateNavigationMutation.isPending || + deleteNavigationsMutation.isPending || + purgeNavigationsMutation.isPending; + + const getLocaleVersions = (focused: Navigation) => + [focused].concat( + navigations.filter( + (navigation) => + navigation.documentId === focused.documentId && navigation.locale !== focused.locale + ) + ); + + const goToDetails = (navigation: Navigation) => { + navigate(`/plugins/${PLUGIN_ID}/${navigation.documentId}`); + }; + + const handleFormSubmit = (updated: Partial) => { + const options = { + onSuccess() { + hardReset(); + setOverlay(null); + toggleNotification({ + type: 'success', + message: formatMessage(getTrad('notification.navigation.submit')), + }); + }, + onError(error: unknown) { + console.warn(error); + toggleNotification({ + type: 'warning', + message: formatMessage(getTrad('notification.error.common')), + }); + }, + }; + + if (overlay?.type === 'edit') { + updateNavigationMutation.mutate(updated as Navigation, options); + } else { + createNavigationMutation.mutate(updated as Navigation, options); + } + }; + + const handleDelete = () => { + if (overlay?.type !== 'delete') { + return; + } + + deleteNavigationsMutation.mutate([overlay.navigation.documentId], { + onSuccess() { + hardReset(); + setOverlay(null); + }, + }); + }; + + const handlePurge = () => { + if (overlay?.type !== 'purge') { + return; + } + + purgeNavigationsMutation.mutate( + overlay.navigation ? [overlay.navigation.documentId] : undefined, + { + onSuccess() { + hardReset(); + setOverlay(null); + }, + } + ); + }; + + if ( + navigationsQuery.isPending || + localeQuery.isPending || + configQuery.isPending || + isLoadingForPermissions + ) { + return ; + } + + return ( + + + + + {hasCache && ( + + )} + + + ) + } + /> + + {defaultLocaleNavigations.length === 0 ? ( + } + content={formatMessage(getTrad('pages.overview.empty.description'))} + action={ + canUpdate && ( + + ) + } + /> + ) : ( + + + + + + + + + + + + {defaultLocaleNavigations.map((navigation) => ( + goToDetails(navigation)} + style={{ cursor: 'pointer' }} + > + + + + + + + ))} + +
+ + {formatMessage(getTrad('popup.navigation.manage.table.name'))} + + + + {formatMessage(getTrad('popup.navigation.manage.table.locale'))} + + + + {formatMessage(getTrad('popup.navigation.manage.table.visibility'))} + + + + {formatMessage(getTrad('pages.overview.table.items'))} + + + + {formatMessage(getTrad('pages.overview.table.actions'))} + +
+ + {navigation.name} + + + + {getLocaleVersions(navigation) + .map(({ locale }) => locale) + .join(', ')} + + + + + {navigation.visible + ? formatMessage(getTrad('popup.navigation.form.visible.toggle.visible')) + : formatMessage(getTrad('popup.navigation.form.visible.toggle.hidden'))} + + + + {navigation.items.length} + event.stopPropagation()}> + + {canUpdate && ( + setOverlay({ type: 'edit', navigation })} + label={formatMessage(getTrad('popup.navigation.manage.button.edit'))} + variant="ghost" + > + + + )} + {canUpdate && ( + setOverlay({ type: 'delete', navigation })} + label={formatMessage(getTrad('popup.navigation.manage.button.delete'))} + variant="ghost" + > + + + )} + {canUpdate && hasCache && ( + setOverlay({ type: 'purge', navigation })} + label={formatMessage(getTrad('popup.navigation.manage.button.purge'))} + variant="ghost" + > + + + )} + +
+ )} + + {(overlay?.type === 'create' || overlay?.type === 'edit') && ( + >( + (acc, { name }) => + overlay.type === 'edit' && name === overlay.navigation.name + ? acc + : acc.concat([name]), + [] + )} + isLoading={isMutating} + onClose={() => setOverlay(null)} + onSubmit={handleFormSubmit} + /> + )} + + {overlay?.type === 'delete' && ( + } + onConfirm={handleDelete} + onCancel={() => setOverlay(null)} + > + {`${formatMessage(getTrad('popup.navigation.manage.delete.header'))} "${overlay.navigation.name}"`} + + )} + + {overlay?.type === 'purge' && ( + } + onConfirm={handlePurge} + onCancel={() => setOverlay(null)} + > + {overlay.navigation + ? `${formatMessage(getTrad('popup.navigation.manage.purge.header'))} "${overlay.navigation.name}"` + : formatMessage(getTrad('popup.navigation.manage.purge.header'))} + + )} +
+
+
+ ); +}; + +export { OverviewPage }; diff --git a/admin/src/pages/OverviewPage/types.ts b/admin/src/pages/OverviewPage/types.ts new file mode 100644 index 00000000..d2d08c31 --- /dev/null +++ b/admin/src/pages/OverviewPage/types.ts @@ -0,0 +1,8 @@ +import { NavigationSchema } from '../../api/validators'; + +export type Navigation = Pick< + NavigationSchema, + 'id' | 'items' | 'name' | 'locale' | 'visible' | 'documentId' | 'slug' +>; + +export type NewNavigation = Omit; diff --git a/admin/src/translations/ca.ts b/admin/src/translations/ca.ts index 5947288f..496cd800 100644 --- a/admin/src/translations/ca.ts +++ b/admin/src/translations/ca.ts @@ -12,7 +12,6 @@ const ca = { meta: 'ID: { id }, slug: { key }', action: { newItem: 'Nouvel élément', - manage: 'Gérer', collapseAll: 'Tout réduire', expandAll: 'Tout développer', }, @@ -34,10 +33,8 @@ const ca = { navigation: { manage: { header: { - LIST: 'Toutes les navigations', CREATE: 'Nouvelle navigation', DELETE: 'Suppression', - ERROR: 'Erreur', EDIT: 'Édition de "{name}"', }, button: { @@ -45,16 +42,13 @@ const ca = { delete: 'Supprimer', save: 'Enregistrer', edit: 'Modifier', - create: 'Créer', goBack: 'Retourner', purge: 'Effacer le cache de lecture', }, table: { - id: 'Id', name: 'Nom', locale: 'Versions locales', visibility: 'Visibilité', - hasSelected: '{count} entrées sélectionnées', }, footer: { button: { @@ -68,14 +62,6 @@ const ca = { delete: { header: 'Les navigations suivantes seront supprimées :', }, - error: { - header: 'Une erreur est survenue :(', - message: 'Une erreur est survenue lors du traitement de la demande.', - }, - navigation: { - visible: 'visible', - hidden: 'caché', - }, }, form: { name: { @@ -94,6 +80,10 @@ const ca = { }, visible: { label: 'Visibilité', + toggle: { + visible: 'Visible', + hidden: 'Masqué', + }, }, }, }, @@ -229,6 +219,18 @@ const ca = { allowed: "Oups ! Il semble que vous n'ayez pas accès à cette page...", }, }, + overview: { + header: { + subtitle: '{count, plural, one {# navigation trouvée} other {# navigations trouvées}}', + }, + table: { + items: 'Éléments', + actions: 'Actions', + }, + empty: { + description: "Vous n'avez pas encore de navigation", + }, + }, main: { search: { placeholder: 'Tapez pour commencer à rechercher...', diff --git a/admin/src/translations/de.ts b/admin/src/translations/de.ts index 9f57ed18..26e54eb6 100644 --- a/admin/src/translations/de.ts +++ b/admin/src/translations/de.ts @@ -12,7 +12,6 @@ const de = { meta: 'ID: { id }, Slug: { key }', action: { newItem: 'Neuer Eintrag', - manage: 'Verwalten', collapseAll: 'Alle einklappen', expandAll: 'Alle ausklappen', }, @@ -34,10 +33,8 @@ const de = { navigation: { manage: { header: { - LIST: 'Alle Navigationen', CREATE: 'Neue Navigation', DELETE: 'Löschen', - ERROR: 'Fehler', EDIT: '"{name}" bearbeiten', }, button: { @@ -45,16 +42,13 @@ const de = { delete: 'Löschen', save: 'Speichern', edit: 'Bearbeiten', - create: 'Erstellen', goBack: 'Zurück', purge: 'Lese-Cache leeren', }, table: { - id: 'ID', name: 'Name', locale: 'Sprachversionen', visibility: 'Sichtbarkeit', - hasSelected: '{count} Einträge ausgewählt', }, footer: { button: { @@ -68,14 +62,6 @@ const de = { delete: { header: 'Die folgenden Navigationen werden entfernt:', }, - error: { - header: 'Ein Fehler ist aufgetreten :(', - message: 'Beim Verarbeiten der Anfrage ist ein Fehler aufgetreten.', - }, - navigation: { - visible: 'sichtbar', - hidden: 'ausgeblendet', - }, }, form: { name: { @@ -234,6 +220,18 @@ const de = { allowed: 'Sie haben offenbar keinen Zugriff auf diese Seite...', }, }, + overview: { + header: { + subtitle: '{count, plural, one {# Navigation gefunden} other {# Navigationen gefunden}}', + }, + table: { + items: 'Einträge', + actions: 'Aktionen', + }, + empty: { + description: 'Sie haben noch keine Navigationen', + }, + }, main: { search: { placeholder: 'Tippen, um die Suche zu starten...', diff --git a/admin/src/translations/en.ts b/admin/src/translations/en.ts index 17b00b5c..44fc8f8c 100644 --- a/admin/src/translations/en.ts +++ b/admin/src/translations/en.ts @@ -12,7 +12,6 @@ const en = { meta: 'ID: { id }, slug: { key }', action: { newItem: 'New Item', - manage: 'Manage', collapseAll: 'Collapse All', expandAll: 'Expand All', }, @@ -34,10 +33,8 @@ const en = { navigation: { manage: { header: { - LIST: 'All navigations', CREATE: 'New navigation', DELETE: 'Deleting', - ERROR: 'Error', EDIT: 'Editing "{name}"', }, button: { @@ -45,16 +42,13 @@ const en = { delete: 'Delete', save: 'Save', edit: 'Edit', - create: 'Create', goBack: 'Go back', purge: 'Clear read cache', }, table: { - id: 'Id', name: 'Name', locale: 'Locale versions', visibility: 'Visibility', - hasSelected: '{count} entries selected', }, footer: { button: { @@ -68,14 +62,6 @@ const en = { delete: { header: 'Following navigations will be removed:', }, - error: { - header: 'An error happened :(', - message: 'An error happened while processing request.', - }, - navigation: { - visible: 'visible', - hidden: 'hidden', - }, }, form: { name: { @@ -232,6 +218,18 @@ const en = { allowed: 'Oops! It seems like You do not have access to this page...', }, }, + overview: { + header: { + subtitle: '{count, plural, one {# navigation} other {# navigations}} found', + }, + table: { + items: 'Items', + actions: 'Actions', + }, + empty: { + description: 'You don’t have any navigations yet', + }, + }, main: { search: { placeholder: 'Type to start searching...', diff --git a/admin/src/translations/es.ts b/admin/src/translations/es.ts index 81157794..2f3b3f48 100644 --- a/admin/src/translations/es.ts +++ b/admin/src/translations/es.ts @@ -12,7 +12,6 @@ const en = { meta: 'ID: { id }, slug: { key }', action: { newItem: 'Nuevo ítem', - manage: 'Gestionar', collapseAll: 'Colapsar todo', expandAll: 'Expandir todo', }, @@ -34,10 +33,8 @@ const en = { navigation: { manage: { header: { - LIST: 'Todas las navegaciones', CREATE: 'Nueva navegación', DELETE: 'Eliminando', - ERROR: 'Error', EDIT: 'Editando "{name}"', }, button: { @@ -45,16 +42,13 @@ const en = { delete: 'Eliminar', save: 'Guardar', edit: 'Edit', - create: 'Create', goBack: 'Volver', purge: 'Borrar caché de lectura', }, table: { - id: 'Id', name: 'Nombre', locale: 'Versiones de idioma', visibility: 'Visibilidad', - hasSelected: '{count} entradas seleccionadas', }, footer: { button: { @@ -68,14 +62,6 @@ const en = { delete: { header: 'Las siguientes navegaciones serán eliminadas:', }, - error: { - header: 'Ocurrió un error :(', - message: 'Ocurrió un error al procesar la solicitud.', - }, - navigation: { - visible: 'visible', - hidden: 'oculto', - }, }, form: { name: { @@ -233,6 +219,19 @@ const en = { allowed: '¡Ups! Parece que no tienes acceso a esta página...', }, }, + overview: { + header: { + subtitle: + '{count, plural, one {# navegación encontrada} other {# navegaciones encontradas}}', + }, + table: { + items: 'Ítems', + actions: 'Acciones', + }, + empty: { + description: 'Todavía no tienes ninguna navegación', + }, + }, main: { search: { placeholder: 'Escribe para comenzar la búsqueda...', diff --git a/admin/src/translations/fr.ts b/admin/src/translations/fr.ts index 7513c38b..d602297c 100644 --- a/admin/src/translations/fr.ts +++ b/admin/src/translations/fr.ts @@ -12,7 +12,6 @@ const fr = { meta: 'ID : { id }, slug : { key }', action: { newItem: 'Nouvel élément', - manage: 'Gérer', collapseAll: 'Tout réduire', expandAll: 'Tout développer', }, @@ -34,10 +33,8 @@ const fr = { navigation: { manage: { header: { - LIST: 'Toutes les navigations', CREATE: 'Nouvelle navigation', DELETE: 'Suppression', - ERROR: 'Erreur', EDIT: 'Édition de « {name} »', }, button: { @@ -45,16 +42,13 @@ const fr = { delete: 'Supprimer', save: 'Enregistrer', edit: 'Modifier', - create: 'Créer', goBack: 'Retour', purge: 'Effacer le cache de lecture', }, table: { - id: 'Id', name: 'Nom', locale: 'Versions locales', visibility: 'Visibilité', - hasSelected: '{count} entrées sélectionnées', }, footer: { button: { @@ -68,14 +62,6 @@ const fr = { delete: { header: 'Les navigations suivantes seront supprimées :', }, - error: { - header: 'Une erreur est survenue :(', - message: 'Une erreur est survenue lors du traitement de la demande.', - }, - navigation: { - visible: 'visible', - hidden: 'masqué', - }, }, form: { name: { @@ -233,6 +219,18 @@ const fr = { allowed: "Oups ! Il semble que vous n'ayez pas accès à cette page…", }, }, + overview: { + header: { + subtitle: '{count, plural, one {# navigation trouvée} other {# navigations trouvées}}', + }, + table: { + items: 'Éléments', + actions: 'Actions', + }, + empty: { + description: "Vous n'avez pas encore de navigation", + }, + }, main: { search: { placeholder: 'Tapez pour commencer à rechercher…', diff --git a/admin/src/translations/tr.ts b/admin/src/translations/tr.ts index 2fdb2286..ed9024a3 100644 --- a/admin/src/translations/tr.ts +++ b/admin/src/translations/tr.ts @@ -12,7 +12,6 @@ const tr = { meta: 'ID: { id }, slug: { key }', action: { newItem: 'Yeni Öğe', - manage: 'Yönet', collapseAll: 'Tümünü Daralt', expandAll: 'Tümünü Genişlet', }, @@ -34,10 +33,8 @@ const tr = { navigation: { manage: { header: { - LIST: 'Tüm navigasyonlar', CREATE: 'Yeni navigasyon', DELETE: 'Silme işlemi', - ERROR: 'Hata', EDIT: '"{name}" düzenleniyor', }, button: { @@ -45,16 +42,13 @@ const tr = { delete: 'Sil', save: 'Kaydet', edit: 'Düzenle', - create: 'Oluştur', goBack: 'Geri dön', purge: 'Önbelleği temizle', }, table: { - id: 'Id', name: 'Ad', locale: 'Dil versiyonları', visibility: 'Görünürlük', - hasSelected: '{count} öğe seçildi', }, footer: { button: { @@ -68,14 +62,6 @@ const tr = { delete: { header: 'Aşağıdaki navigasyonlar kaldırılacaktır:', }, - error: { - header: 'Bir hata oluştu :(', - message: 'İstek işlenirken bir hata oluştu.', - }, - navigation: { - visible: 'görünür', - hidden: 'gizli', - }, }, form: { name: { @@ -232,6 +218,18 @@ const tr = { allowed: 'Üzgünüz! Bu sayfaya erişim yetkiniz yok gibi görünüyor...', }, }, + overview: { + header: { + subtitle: '{count, plural, one {# navigasyon bulundu} other {# navigasyon bulundu}}', + }, + table: { + items: 'Öğeler', + actions: 'İşlemler', + }, + empty: { + description: 'Henüz bir navigasyonunuz yok', + }, + }, main: { search: { placeholder: 'Arama yapmak için yazmaya başlayın...', diff --git a/admin/src/pages/HomePage/utils/appendViewId.ts b/admin/src/utils/appendViewId.ts similarity index 76% rename from admin/src/pages/HomePage/utils/appendViewId.ts rename to admin/src/utils/appendViewId.ts index 39dacad2..f351090a 100644 --- a/admin/src/pages/HomePage/utils/appendViewId.ts +++ b/admin/src/utils/appendViewId.ts @@ -1,4 +1,4 @@ -import { NavigationItemSchema } from '../../../api/validators'; +import { NavigationItemSchema } from '../api/validators'; export const appendViewId = (item: NavigationItemSchema): NavigationItemSchema => { return {