diff --git a/packages/plugin-import-export/src/components/SortBy/index.tsx b/packages/plugin-import-export/src/components/SortBy/index.tsx index 742f362f1..a44b3df0b 100644 --- a/packages/plugin-import-export/src/components/SortBy/index.tsx +++ b/packages/plugin-import-export/src/components/SortBy/index.tsx @@ -11,8 +11,9 @@ import { useField, useListQuery, } from '@payloadcms/ui' -import React, { useEffect, useState } from 'react' +import React, { useEffect, useMemo, useState } from 'react' +import { applySortOrder, stripSortDash } from '../../utilities/sortHelpers.js' import { reduceFields } from '../FieldsToExport/reduceFields.js' import { useImportExport } from '../ImportExportProvider/index.js' import './index.scss' @@ -21,12 +22,19 @@ const baseClass = 'sort-by-fields' export const SortBy: SelectFieldClientComponent = (props) => { const { id } = useDocumentInfo() - const { setValue, value } = useField() + + // The "sort" text field that stores 'title' or '-title' + const { setValue: setSort, value: sortRaw } = useField() + + // Sibling order field ('asc' | 'desc') used when writing sort on change + const { value: sortOrder = 'asc' } = useField({ path: 'sortOrder' }) + const { value: collectionSlug } = useField({ path: 'collectionSlug' }) const { query } = useListQuery() const { getEntityConfig } = useConfig() const { collection } = useImportExport() + // ReactSelect's displayed option const [displayedValue, setDisplayedValue] = useState<{ id: string label: ReactNode @@ -34,40 +42,52 @@ export const SortBy: SelectFieldClientComponent = (props) => { } | null>(null) const collectionConfig = getEntityConfig({ collectionSlug: collectionSlug ?? collection }) - const fieldOptions = reduceFields({ fields: collectionConfig?.fields }) + const fieldOptions = useMemo( + () => reduceFields({ fields: collectionConfig?.fields }), + [collectionConfig?.fields], + ) - // Sync displayedValue with value from useField + // Normalize the stored value for display (strip the '-') and pick the option useEffect(() => { - if (!value) { + const clean = stripSortDash(sortRaw) + if (!clean) { setDisplayedValue(null) return } - const option = fieldOptions.find((field) => field.value === value) - if (option && (!displayedValue || displayedValue.value !== value)) { + const option = fieldOptions.find((f) => f.value === clean) + if (option && (!displayedValue || displayedValue.value !== clean)) { setDisplayedValue(option) } - }, [displayedValue, fieldOptions, value]) + }, [sortRaw, fieldOptions, displayedValue]) + // Sync the visible select from list-view query sort, + // but no need to write to the "sort" field here — SortOrder owns initial combined value. useEffect(() => { - if (id || !query?.sort || value) { + if (id || !query?.sort || sortRaw) { return } - const option = fieldOptions.find((field) => field.value === query.sort) + if (!query.sort) { + return + } + + const clean = stripSortDash(query.sort as string) + const option = fieldOptions.find((f) => f.value === clean) if (option) { - setValue(option.value) setDisplayedValue(option) } - }, [fieldOptions, id, query?.sort, value, setValue]) + }, [id, query?.sort, sortRaw, fieldOptions]) + // When user selects a different field, store it with the current order applied const onChange = (option: { id: string; label: ReactNode; value: string } | null) => { if (!option) { - setValue('') + setSort('') setDisplayedValue(null) } else { - setValue(option.value) setDisplayedValue(option) + const next = applySortOrder(option.value, String(sortOrder) as 'asc' | 'desc') + setSort(next) } } diff --git a/packages/plugin-import-export/src/components/SortOrder/index.scss b/packages/plugin-import-export/src/components/SortOrder/index.scss new file mode 100644 index 000000000..eb5bad6ac --- /dev/null +++ b/packages/plugin-import-export/src/components/SortOrder/index.scss @@ -0,0 +1,3 @@ +.sort-order-field { + --field-width: 25%; +} diff --git a/packages/plugin-import-export/src/components/SortOrder/index.tsx b/packages/plugin-import-export/src/components/SortOrder/index.tsx new file mode 100644 index 000000000..008ba0587 --- /dev/null +++ b/packages/plugin-import-export/src/components/SortOrder/index.tsx @@ -0,0 +1,109 @@ +'use client' + +import type { SelectFieldClientComponent } from 'payload' + +import { FieldLabel, ReactSelect, useDocumentInfo, useField, useListQuery } from '@payloadcms/ui' +import React, { useEffect, useMemo, useState } from 'react' + +import { applySortOrder, stripSortDash } from '../../utilities/sortHelpers.js' +import './index.scss' + +const baseClass = 'sort-order-field' + +type Order = 'asc' | 'desc' +type OrderOption = { label: string; value: Order } + +const options = [ + { label: 'Ascending', value: 'asc' as const }, + { label: 'Descending', value: 'desc' as const }, +] as const + +const defaultOption: OrderOption = options[0] + +// Safely coerce query.sort to a string (ignore arrays) +const normalizeSortParam = (v: unknown): string | undefined => { + if (typeof v === 'string') { + return v + } + if (Array.isArray(v) && typeof v[0] === 'string') { + return v[0] + } + return undefined +} + +export const SortOrder: SelectFieldClientComponent = (props) => { + const { id } = useDocumentInfo() + const { query } = useListQuery() + + // 'sortOrder' select field: 'asc' | 'desc' + const { setValue: setOrder, value: orderValueRaw } = useField() + + // 'sort' text field: 'title' | '-title' + const { setValue: setSort, value: sortRaw } = useField({ path: 'sort' }) + + // The current order value, defaulting to 'asc' for UI + const orderValue: Order = orderValueRaw || 'asc' + + // Map 'asc' | 'desc' to the option object for ReactSelect + const currentOption = useMemo( + () => options.find((o) => o.value === orderValue) ?? defaultOption, + [orderValue], + ) + const [displayed, setDisplayed] = useState(currentOption) + + // Derive from list-view query.sort if present + useEffect(() => { + if (id) { + return + } + const qs = normalizeSortParam(query?.sort) + if (!qs) { + return + } + + const isDesc = qs.startsWith('-') + const base = stripSortDash(qs) + const order: Order = isDesc ? 'desc' : 'asc' + + setOrder(order) + setSort(applySortOrder(base, order)) + }, [id, query?.sort, setOrder, setSort]) + + // Keep the select's displayed option in sync with the stored order + useEffect(() => { + setDisplayed(currentOption ?? defaultOption) + }, [currentOption]) + + // Handle manual order changes via ReactSelect: + // - update the order field + // - rewrite the combined "sort" string to add/remove the leading '-' + const onChange = (option: null | OrderOption) => { + const next = option?.value ?? 'asc' + setOrder(next) + + const base = stripSortDash(sortRaw) + if (base) { + setSort(applySortOrder(base, next)) + } + + setDisplayed(option ?? defaultOption) + } + + return ( +
+ + +
+ ) +} diff --git a/packages/plugin-import-export/src/export/getFields.ts b/packages/plugin-import-export/src/export/getFields.ts index 9b744e88a..493dc0a03 100644 --- a/packages/plugin-import-export/src/export/getFields.ts +++ b/packages/plugin-import-export/src/export/getFields.ts @@ -118,6 +118,21 @@ export const getFields = (config: Config, pluginConfig?: ImportExportPluginConfi // @ts-expect-error - this is not correctly typed in plugins right now label: ({ t }) => t('plugin-import-export:field-sort-label'), }, + { + name: 'sortOrder', + type: 'select', + admin: { + components: { + Field: '@payloadcms/plugin-import-export/rsc#SortOrder', + }, + }, + // @ts-expect-error - this is not correctly typed in plugins right now + label: ({ t }) => t('plugin-import-export:field-sort-order-label'), + options: [ + { label: 'Ascending', value: 'asc' }, + { label: 'Descending', value: 'desc' }, + ], + }, ...(localeField ? [localeField] : []), { name: 'drafts', diff --git a/packages/plugin-import-export/src/exports/rsc.ts b/packages/plugin-import-export/src/exports/rsc.ts index 51a2d8802..37e1f49a8 100644 --- a/packages/plugin-import-export/src/exports/rsc.ts +++ b/packages/plugin-import-export/src/exports/rsc.ts @@ -7,3 +7,4 @@ export { Page } from '../components/Page/index.js' export { Preview } from '../components/Preview/index.js' export { SelectionToUseField } from '../components/SelectionToUseField/index.js' export { SortBy } from '../components/SortBy/index.js' +export { SortOrder } from '../components/SortOrder/index.js' diff --git a/packages/plugin-import-export/src/translations/languages/ar.ts b/packages/plugin-import-export/src/translations/languages/ar.ts index 7a06c9d47..cec015882 100644 --- a/packages/plugin-import-export/src/translations/languages/ar.ts +++ b/packages/plugin-import-export/src/translations/languages/ar.ts @@ -15,6 +15,7 @@ export const arTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'صفحة', 'field-selectionToUse-label': 'اختيار للاستخدام', 'field-sort-label': 'ترتيب حسب', + 'field-sort-order-label': 'ترتيب', 'selectionToUse-allDocuments': 'استخدم جميع الوثائق', 'selectionToUse-currentFilters': 'استخدم الفلاتر الحالية', 'selectionToUse-currentSelection': 'استخدم الاختيار الحالي', diff --git a/packages/plugin-import-export/src/translations/languages/az.ts b/packages/plugin-import-export/src/translations/languages/az.ts index 7fb36d71b..e48e31757 100644 --- a/packages/plugin-import-export/src/translations/languages/az.ts +++ b/packages/plugin-import-export/src/translations/languages/az.ts @@ -15,6 +15,7 @@ export const azTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Səhifə', 'field-selectionToUse-label': 'İstifadə etmək üçün seçim', 'field-sort-label': 'Sırala', + 'field-sort-order-label': 'Sıralama', 'selectionToUse-allDocuments': 'Bütün sənədlərdən istifadə edin', 'selectionToUse-currentFilters': 'Cari filtrlərdən istifadə edin', 'selectionToUse-currentSelection': 'Cari seçimi istifadə edin', diff --git a/packages/plugin-import-export/src/translations/languages/bg.ts b/packages/plugin-import-export/src/translations/languages/bg.ts index 91a636f09..39276c6ba 100644 --- a/packages/plugin-import-export/src/translations/languages/bg.ts +++ b/packages/plugin-import-export/src/translations/languages/bg.ts @@ -15,6 +15,7 @@ export const bgTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Страница', 'field-selectionToUse-label': 'Избор за използване', 'field-sort-label': 'Сортирай по', + 'field-sort-order-label': 'Ред на сортиране', 'selectionToUse-allDocuments': 'Използвайте всички документи', 'selectionToUse-currentFilters': 'Използвайте текущите филтри', 'selectionToUse-currentSelection': 'Използвайте текущия избор', diff --git a/packages/plugin-import-export/src/translations/languages/ca.ts b/packages/plugin-import-export/src/translations/languages/ca.ts index 63eed2481..24ce0d828 100644 --- a/packages/plugin-import-export/src/translations/languages/ca.ts +++ b/packages/plugin-import-export/src/translations/languages/ca.ts @@ -15,6 +15,7 @@ export const caTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Pàgina', 'field-selectionToUse-label': 'Selecció per utilitzar', 'field-sort-label': 'Ordena per', + 'field-sort-order-label': 'Ordre de classificació', 'selectionToUse-allDocuments': 'Utilitzeu tots els documents', 'selectionToUse-currentFilters': 'Utilitza els filtres actuals', 'selectionToUse-currentSelection': 'Utilitza la selecció actual', diff --git a/packages/plugin-import-export/src/translations/languages/cs.ts b/packages/plugin-import-export/src/translations/languages/cs.ts index 9a2ea349a..f1614c22a 100644 --- a/packages/plugin-import-export/src/translations/languages/cs.ts +++ b/packages/plugin-import-export/src/translations/languages/cs.ts @@ -15,6 +15,7 @@ export const csTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Stránka', 'field-selectionToUse-label': 'Výběr k použití', 'field-sort-label': 'Seřadit podle', + 'field-sort-order-label': 'Řazení', 'selectionToUse-allDocuments': 'Použijte všechny dokumenty', 'selectionToUse-currentFilters': 'Použijte aktuální filtry', 'selectionToUse-currentSelection': 'Použijte aktuální výběr', diff --git a/packages/plugin-import-export/src/translations/languages/da.ts b/packages/plugin-import-export/src/translations/languages/da.ts index 33f4b3a56..e16deb88a 100644 --- a/packages/plugin-import-export/src/translations/languages/da.ts +++ b/packages/plugin-import-export/src/translations/languages/da.ts @@ -15,6 +15,7 @@ export const daTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Side', 'field-selectionToUse-label': 'Valg til brug', 'field-sort-label': 'Sorter efter', + 'field-sort-order-label': 'Sorteringsrækkefølge', 'selectionToUse-allDocuments': 'Brug alle dokumenter', 'selectionToUse-currentFilters': 'Brug nuværende filtre', 'selectionToUse-currentSelection': 'Brug nuværende valg', diff --git a/packages/plugin-import-export/src/translations/languages/de.ts b/packages/plugin-import-export/src/translations/languages/de.ts index 5c844cb1e..9d12c6835 100644 --- a/packages/plugin-import-export/src/translations/languages/de.ts +++ b/packages/plugin-import-export/src/translations/languages/de.ts @@ -15,6 +15,7 @@ export const deTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Seite', 'field-selectionToUse-label': 'Auswahl zur Verwendung', 'field-sort-label': 'Sortieren nach', + 'field-sort-order-label': 'Sortierreihenfolge', 'selectionToUse-allDocuments': 'Verwenden Sie alle Dokumente.', 'selectionToUse-currentFilters': 'Verwenden Sie aktuelle Filter', 'selectionToUse-currentSelection': 'Verwenden Sie die aktuelle Auswahl', diff --git a/packages/plugin-import-export/src/translations/languages/en.ts b/packages/plugin-import-export/src/translations/languages/en.ts index e32d5c487..6181aa113 100644 --- a/packages/plugin-import-export/src/translations/languages/en.ts +++ b/packages/plugin-import-export/src/translations/languages/en.ts @@ -14,6 +14,7 @@ export const enTranslations = { 'field-page-label': 'Page', 'field-selectionToUse-label': 'Selection to use', 'field-sort-label': 'Sort by', + 'field-sort-order-label': 'Sort order', 'selectionToUse-allDocuments': 'Use all documents', 'selectionToUse-currentFilters': 'Use current filters', 'selectionToUse-currentSelection': 'Use current selection', diff --git a/packages/plugin-import-export/src/translations/languages/es.ts b/packages/plugin-import-export/src/translations/languages/es.ts index 6a2ab7af9..5cb9f3e3e 100644 --- a/packages/plugin-import-export/src/translations/languages/es.ts +++ b/packages/plugin-import-export/src/translations/languages/es.ts @@ -15,6 +15,7 @@ export const esTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Página', 'field-selectionToUse-label': 'Selección para usar', 'field-sort-label': 'Ordenar por', + 'field-sort-order-label': 'Orden de clasificación', 'selectionToUse-allDocuments': 'Utilice todos los documentos', 'selectionToUse-currentFilters': 'Utilice los filtros actuales', 'selectionToUse-currentSelection': 'Usar selección actual', diff --git a/packages/plugin-import-export/src/translations/languages/et.ts b/packages/plugin-import-export/src/translations/languages/et.ts index b69573bac..238b8b250 100644 --- a/packages/plugin-import-export/src/translations/languages/et.ts +++ b/packages/plugin-import-export/src/translations/languages/et.ts @@ -15,6 +15,7 @@ export const etTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Leht', 'field-selectionToUse-label': 'Valiku kasutamine', 'field-sort-label': 'Sorteeri järgi', + 'field-sort-order-label': 'Sorteerimise järjekord', 'selectionToUse-allDocuments': 'Kasutage kõiki dokumente', 'selectionToUse-currentFilters': 'Kasuta praeguseid filtreid', 'selectionToUse-currentSelection': 'Kasuta praegust valikut', diff --git a/packages/plugin-import-export/src/translations/languages/fa.ts b/packages/plugin-import-export/src/translations/languages/fa.ts index 29c886748..bf1e2c2b3 100644 --- a/packages/plugin-import-export/src/translations/languages/fa.ts +++ b/packages/plugin-import-export/src/translations/languages/fa.ts @@ -15,6 +15,7 @@ export const faTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'صفحه', 'field-selectionToUse-label': 'انتخاب برای استفاده', 'field-sort-label': 'مرتب سازی بر اساس', + 'field-sort-order-label': 'ترتیب', 'selectionToUse-allDocuments': 'از تمام مستندات استفاده کنید', 'selectionToUse-currentFilters': 'از فیلترهای فعلی استفاده کنید', 'selectionToUse-currentSelection': 'از انتخاب فعلی استفاده کنید', diff --git a/packages/plugin-import-export/src/translations/languages/fr.ts b/packages/plugin-import-export/src/translations/languages/fr.ts index 2e5f11950..d2e294efd 100644 --- a/packages/plugin-import-export/src/translations/languages/fr.ts +++ b/packages/plugin-import-export/src/translations/languages/fr.ts @@ -15,6 +15,7 @@ export const frTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Page', 'field-selectionToUse-label': 'Sélection à utiliser', 'field-sort-label': 'Trier par', + 'field-sort-order-label': 'Ordre de tri', 'selectionToUse-allDocuments': 'Utilisez tous les documents', 'selectionToUse-currentFilters': 'Utilisez les filtres actuels', 'selectionToUse-currentSelection': 'Utilisez la sélection actuelle', diff --git a/packages/plugin-import-export/src/translations/languages/he.ts b/packages/plugin-import-export/src/translations/languages/he.ts index fca29ad1d..37047f47a 100644 --- a/packages/plugin-import-export/src/translations/languages/he.ts +++ b/packages/plugin-import-export/src/translations/languages/he.ts @@ -15,6 +15,7 @@ export const heTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'עמוד', 'field-selectionToUse-label': 'בחירה לשימוש', 'field-sort-label': 'מיין לפי', + 'field-sort-order-label': 'סדר מיון', 'selectionToUse-allDocuments': 'השתמש בכל המסמכים', 'selectionToUse-currentFilters': 'השתמש במסננים הנוכחיים', 'selectionToUse-currentSelection': 'השתמש בבחירה הנוכחית', diff --git a/packages/plugin-import-export/src/translations/languages/hr.ts b/packages/plugin-import-export/src/translations/languages/hr.ts index 32e67b7e0..c4f6ea4b2 100644 --- a/packages/plugin-import-export/src/translations/languages/hr.ts +++ b/packages/plugin-import-export/src/translations/languages/hr.ts @@ -15,6 +15,7 @@ export const hrTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Stranica', 'field-selectionToUse-label': 'Odabir za upotrebu', 'field-sort-label': 'Sortiraj po', + 'field-sort-order-label': 'Redoslijed sortiranja', 'selectionToUse-allDocuments': 'Koristite sve dokumente', 'selectionToUse-currentFilters': 'Koristite trenutne filtre', 'selectionToUse-currentSelection': 'Koristite trenutni odabir', diff --git a/packages/plugin-import-export/src/translations/languages/hu.ts b/packages/plugin-import-export/src/translations/languages/hu.ts index 4749fe5e0..ea191db6b 100644 --- a/packages/plugin-import-export/src/translations/languages/hu.ts +++ b/packages/plugin-import-export/src/translations/languages/hu.ts @@ -15,6 +15,7 @@ export const huTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Oldal', 'field-selectionToUse-label': 'Használatra kiválasztva', 'field-sort-label': 'Rendezés szerint', + 'field-sort-order-label': 'Rendezési sorrend', 'selectionToUse-allDocuments': 'Használjon minden dokumentumot', 'selectionToUse-currentFilters': 'Használja az aktuális szűrőket', 'selectionToUse-currentSelection': 'Használja a jelenlegi kiválasztást', diff --git a/packages/plugin-import-export/src/translations/languages/hy.ts b/packages/plugin-import-export/src/translations/languages/hy.ts index 052fcee1a..bf95b6fd3 100644 --- a/packages/plugin-import-export/src/translations/languages/hy.ts +++ b/packages/plugin-import-export/src/translations/languages/hy.ts @@ -15,6 +15,7 @@ export const hyTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Էջ', 'field-selectionToUse-label': 'Օգտագործման ընտրություն', 'field-sort-label': 'Դասավորել ըստ', + 'field-sort-order-label': 'Դասավորության կարգ', 'selectionToUse-allDocuments': 'Օգտագործեք բոլոր փաստաթղթերը', 'selectionToUse-currentFilters': 'Օգտագործեք ընթացիկ ֆիլտրերը', 'selectionToUse-currentSelection': 'Օգտագործել ընթացիկ ընտրությունը', diff --git a/packages/plugin-import-export/src/translations/languages/it.ts b/packages/plugin-import-export/src/translations/languages/it.ts index 4f53b901e..96afb392a 100644 --- a/packages/plugin-import-export/src/translations/languages/it.ts +++ b/packages/plugin-import-export/src/translations/languages/it.ts @@ -15,6 +15,7 @@ export const itTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Pagina', 'field-selectionToUse-label': 'Selezione da utilizzare', 'field-sort-label': 'Ordina per', + 'field-sort-order-label': 'Ordine di sort', 'selectionToUse-allDocuments': 'Utilizza tutti i documenti', 'selectionToUse-currentFilters': 'Utilizza i filtri correnti', 'selectionToUse-currentSelection': 'Utilizza la selezione corrente', diff --git a/packages/plugin-import-export/src/translations/languages/ja.ts b/packages/plugin-import-export/src/translations/languages/ja.ts index 8c5bf2630..e56d0b9ee 100644 --- a/packages/plugin-import-export/src/translations/languages/ja.ts +++ b/packages/plugin-import-export/src/translations/languages/ja.ts @@ -15,6 +15,7 @@ export const jaTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'ページ', 'field-selectionToUse-label': '使用する選択', 'field-sort-label': '並び替える', + 'field-sort-order-label': '並び替えの順序', 'selectionToUse-allDocuments': 'すべての文書を使用してください。', 'selectionToUse-currentFilters': '現在のフィルターを使用してください', 'selectionToUse-currentSelection': '現在の選択を使用する', diff --git a/packages/plugin-import-export/src/translations/languages/ko.ts b/packages/plugin-import-export/src/translations/languages/ko.ts index b6dd57c7e..09a1adcc5 100644 --- a/packages/plugin-import-export/src/translations/languages/ko.ts +++ b/packages/plugin-import-export/src/translations/languages/ko.ts @@ -15,6 +15,7 @@ export const koTranslations: PluginDefaultTranslationsObject = { 'field-page-label': '페이지', 'field-selectionToUse-label': '사용할 선택', 'field-sort-label': '정렬 방식', + 'field-sort-order-label': '정렬 순서', 'selectionToUse-allDocuments': '모든 문서를 사용하십시오.', 'selectionToUse-currentFilters': '현재 필터를 사용하십시오.', 'selectionToUse-currentSelection': '현재 선택 항목을 사용하십시오.', diff --git a/packages/plugin-import-export/src/translations/languages/lt.ts b/packages/plugin-import-export/src/translations/languages/lt.ts index e6d872f68..b568976c7 100644 --- a/packages/plugin-import-export/src/translations/languages/lt.ts +++ b/packages/plugin-import-export/src/translations/languages/lt.ts @@ -15,6 +15,7 @@ export const ltTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Puslapis', 'field-selectionToUse-label': 'Naudojimo pasirinkimas', 'field-sort-label': 'Rūšiuoti pagal', + 'field-sort-order-label': 'Rūšiavimo tvarka', 'selectionToUse-allDocuments': 'Naudokite visus dokumentus.', 'selectionToUse-currentFilters': 'Naudoti esamus filtrus', 'selectionToUse-currentSelection': 'Naudoti dabartinį pasirinkimą', diff --git a/packages/plugin-import-export/src/translations/languages/lv.ts b/packages/plugin-import-export/src/translations/languages/lv.ts index 1ff5263c8..9838abf8a 100644 --- a/packages/plugin-import-export/src/translations/languages/lv.ts +++ b/packages/plugin-import-export/src/translations/languages/lv.ts @@ -15,6 +15,7 @@ export const lvTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Lapa', 'field-selectionToUse-label': 'Izvēles lietošana', 'field-sort-label': 'Kārtot pēc', + 'field-sort-order-label': 'Kārtot pēc secības', 'selectionToUse-allDocuments': 'Izmantojiet visus dokumentus', 'selectionToUse-currentFilters': 'Izmantot pašreizējos filtrus', 'selectionToUse-currentSelection': 'Izmantot pašreizējo izvēli', diff --git a/packages/plugin-import-export/src/translations/languages/my.ts b/packages/plugin-import-export/src/translations/languages/my.ts index b8a60878e..f481567bd 100644 --- a/packages/plugin-import-export/src/translations/languages/my.ts +++ b/packages/plugin-import-export/src/translations/languages/my.ts @@ -15,6 +15,7 @@ export const myTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'စာမျက်နှာ', 'field-selectionToUse-label': 'Pilihan untuk digunakan', 'field-sort-label': 'စီမံအလိုက်', + 'field-sort-order-label': 'Sorteringsrækkefølge', 'selectionToUse-allDocuments': 'Gunakan semua dokumen', 'selectionToUse-currentFilters': 'Gunakan penapis semasa', 'selectionToUse-currentSelection': 'Gunakan pilihan semasa', diff --git a/packages/plugin-import-export/src/translations/languages/nb.ts b/packages/plugin-import-export/src/translations/languages/nb.ts index 512e561ee..2adcaf3f0 100644 --- a/packages/plugin-import-export/src/translations/languages/nb.ts +++ b/packages/plugin-import-export/src/translations/languages/nb.ts @@ -15,6 +15,7 @@ export const nbTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Side', 'field-selectionToUse-label': 'Valg til bruk', 'field-sort-label': 'Sorter etter', + 'field-sort-order-label': 'Sorteringsrekkefølge', 'selectionToUse-allDocuments': 'Bruk alle dokumentene', 'selectionToUse-currentFilters': 'Bruk gjeldende filtre', 'selectionToUse-currentSelection': 'Bruk gjeldende utvalg', diff --git a/packages/plugin-import-export/src/translations/languages/nl.ts b/packages/plugin-import-export/src/translations/languages/nl.ts index b555e2bee..22a4125fc 100644 --- a/packages/plugin-import-export/src/translations/languages/nl.ts +++ b/packages/plugin-import-export/src/translations/languages/nl.ts @@ -15,6 +15,7 @@ export const nlTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Pagina', 'field-selectionToUse-label': 'Selectie om te gebruiken', 'field-sort-label': 'Sorteer op', + 'field-sort-order-label': 'Sorteer volgorde', 'selectionToUse-allDocuments': 'Gebruik alle documenten', 'selectionToUse-currentFilters': 'Gebruik huidige filters', 'selectionToUse-currentSelection': 'Gebruik huidige selectie', diff --git a/packages/plugin-import-export/src/translations/languages/pl.ts b/packages/plugin-import-export/src/translations/languages/pl.ts index 8d2ef5c55..4faf67bec 100644 --- a/packages/plugin-import-export/src/translations/languages/pl.ts +++ b/packages/plugin-import-export/src/translations/languages/pl.ts @@ -15,6 +15,7 @@ export const plTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Strona', 'field-selectionToUse-label': 'Wybór do użycia', 'field-sort-label': 'Sortuj według', + 'field-sort-order-label': 'Sortowanie według', 'selectionToUse-allDocuments': 'Użyj wszystkich dokumentów.', 'selectionToUse-currentFilters': 'Użyj aktualnych filtrów', 'selectionToUse-currentSelection': 'Użyj aktualnego wyboru', diff --git a/packages/plugin-import-export/src/translations/languages/pt.ts b/packages/plugin-import-export/src/translations/languages/pt.ts index efdb8046b..f0f1c6809 100644 --- a/packages/plugin-import-export/src/translations/languages/pt.ts +++ b/packages/plugin-import-export/src/translations/languages/pt.ts @@ -15,6 +15,7 @@ export const ptTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Página', 'field-selectionToUse-label': 'Seleção para usar', 'field-sort-label': 'Ordenar por', + 'field-sort-order-label': 'Ordem de classificação', 'selectionToUse-allDocuments': 'Use todos os documentos', 'selectionToUse-currentFilters': 'Use os filtros atuais', 'selectionToUse-currentSelection': 'Use a seleção atual', diff --git a/packages/plugin-import-export/src/translations/languages/ro.ts b/packages/plugin-import-export/src/translations/languages/ro.ts index 1a0f34ac2..41fa893ce 100644 --- a/packages/plugin-import-export/src/translations/languages/ro.ts +++ b/packages/plugin-import-export/src/translations/languages/ro.ts @@ -15,6 +15,7 @@ export const roTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Pagina', 'field-selectionToUse-label': 'Selectarea pentru utilizare', 'field-sort-label': 'Sortează după', + 'field-sort-order-label': 'Ordine de sortare', 'selectionToUse-allDocuments': 'Utilizați toate documentele.', 'selectionToUse-currentFilters': 'Utilizați filtrele curente', 'selectionToUse-currentSelection': 'Utilizați selecția curentă', diff --git a/packages/plugin-import-export/src/translations/languages/rs.ts b/packages/plugin-import-export/src/translations/languages/rs.ts index fba6205ba..1962f61f5 100644 --- a/packages/plugin-import-export/src/translations/languages/rs.ts +++ b/packages/plugin-import-export/src/translations/languages/rs.ts @@ -15,6 +15,7 @@ export const rsTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Strana', 'field-selectionToUse-label': 'Izbor za upotrebu', 'field-sort-label': 'Sortiraj po', + 'field-sort-order-label': 'Redoslijed sortiranja', 'selectionToUse-allDocuments': 'Koristite sve dokumente', 'selectionToUse-currentFilters': 'Koristite trenutne filtere', 'selectionToUse-currentSelection': 'Koristite trenutni izbor', diff --git a/packages/plugin-import-export/src/translations/languages/rsLatin.ts b/packages/plugin-import-export/src/translations/languages/rsLatin.ts index a1dff02b9..d61e9272c 100644 --- a/packages/plugin-import-export/src/translations/languages/rsLatin.ts +++ b/packages/plugin-import-export/src/translations/languages/rsLatin.ts @@ -15,6 +15,7 @@ export const rsLatinTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Strana', 'field-selectionToUse-label': 'Izbor za upotrebu', 'field-sort-label': 'Sortiraj po', + 'field-sort-order-label': 'Redoslijed sortiranja', 'selectionToUse-allDocuments': 'Koristite sve dokumente', 'selectionToUse-currentFilters': 'Koristite trenutne filtere', 'selectionToUse-currentSelection': 'Koristi trenutni izbor', diff --git a/packages/plugin-import-export/src/translations/languages/ru.ts b/packages/plugin-import-export/src/translations/languages/ru.ts index 82ea80915..d18ebe33e 100644 --- a/packages/plugin-import-export/src/translations/languages/ru.ts +++ b/packages/plugin-import-export/src/translations/languages/ru.ts @@ -15,6 +15,7 @@ export const ruTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Страница', 'field-selectionToUse-label': 'Выбор использования', 'field-sort-label': 'Сортировать по', + 'field-sort-order-label': 'Порядок сортировки', 'selectionToUse-allDocuments': 'Используйте все документы', 'selectionToUse-currentFilters': 'Использовать текущие фильтры', 'selectionToUse-currentSelection': 'Использовать текущий выбор', diff --git a/packages/plugin-import-export/src/translations/languages/sk.ts b/packages/plugin-import-export/src/translations/languages/sk.ts index 837ba8f22..7bd3a009e 100644 --- a/packages/plugin-import-export/src/translations/languages/sk.ts +++ b/packages/plugin-import-export/src/translations/languages/sk.ts @@ -15,6 +15,7 @@ export const skTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Stránka', 'field-selectionToUse-label': 'Výber na použitie', 'field-sort-label': 'Triediť podľa', + 'field-sort-order-label': 'Poradie triedenia', 'selectionToUse-allDocuments': 'Použite všetky dokumenty', 'selectionToUse-currentFilters': 'Použiť aktuálne filtre', 'selectionToUse-currentSelection': 'Použiť aktuálny výber', diff --git a/packages/plugin-import-export/src/translations/languages/sl.ts b/packages/plugin-import-export/src/translations/languages/sl.ts index 247c77041..7f862df89 100644 --- a/packages/plugin-import-export/src/translations/languages/sl.ts +++ b/packages/plugin-import-export/src/translations/languages/sl.ts @@ -15,6 +15,7 @@ export const slTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Stran', 'field-selectionToUse-label': 'Izbor za uporabo', 'field-sort-label': 'Razvrsti po', + 'field-sort-order-label': 'Razvrsti po vrstnem redu', 'selectionToUse-allDocuments': 'Uporabite vse dokumente', 'selectionToUse-currentFilters': 'Uporabite trenutne filtre.', 'selectionToUse-currentSelection': 'Uporabi trenutno izbiro', diff --git a/packages/plugin-import-export/src/translations/languages/sv.ts b/packages/plugin-import-export/src/translations/languages/sv.ts index 1cd37d1db..95d2d5c17 100644 --- a/packages/plugin-import-export/src/translations/languages/sv.ts +++ b/packages/plugin-import-export/src/translations/languages/sv.ts @@ -15,6 +15,7 @@ export const svTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Sida', 'field-selectionToUse-label': 'Val att använda', 'field-sort-label': 'Sortera efter', + 'field-sort-order-label': 'Sortera i ordning', 'selectionToUse-allDocuments': 'Använd alla dokument', 'selectionToUse-currentFilters': 'Använd aktuella filter', 'selectionToUse-currentSelection': 'Använd nuvarande urval', diff --git a/packages/plugin-import-export/src/translations/languages/th.ts b/packages/plugin-import-export/src/translations/languages/th.ts index 19bb2af59..7b5d9a41d 100644 --- a/packages/plugin-import-export/src/translations/languages/th.ts +++ b/packages/plugin-import-export/src/translations/languages/th.ts @@ -15,6 +15,7 @@ export const thTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'หน้า', 'field-selectionToUse-label': 'การเลือกใช้', 'field-sort-label': 'เรียงตาม', + 'field-sort-order-label': 'เรียงลำดับตาม', 'selectionToUse-allDocuments': 'ใช้เอกสารทั้งหมด', 'selectionToUse-currentFilters': 'ใช้ตัวกรองปัจจุบัน', 'selectionToUse-currentSelection': 'ใช้การเลือกปัจจุบัน', diff --git a/packages/plugin-import-export/src/translations/languages/tr.ts b/packages/plugin-import-export/src/translations/languages/tr.ts index 9b7512e56..fb8888a06 100644 --- a/packages/plugin-import-export/src/translations/languages/tr.ts +++ b/packages/plugin-import-export/src/translations/languages/tr.ts @@ -15,6 +15,7 @@ export const trTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Sayfa', 'field-selectionToUse-label': 'Kullanılacak seçim', 'field-sort-label': 'Sırala', + 'field-sort-order-label': 'Sıralama düzeni', 'selectionToUse-allDocuments': 'Tüm belgeleri kullanın', 'selectionToUse-currentFilters': 'Mevcut filtreleri kullanın', 'selectionToUse-currentSelection': 'Mevcut seçimi kullanın', diff --git a/packages/plugin-import-export/src/translations/languages/translation-schema.json b/packages/plugin-import-export/src/translations/languages/translation-schema.json index 00abea91f..05e106cc1 100644 --- a/packages/plugin-import-export/src/translations/languages/translation-schema.json +++ b/packages/plugin-import-export/src/translations/languages/translation-schema.json @@ -58,6 +58,9 @@ "field-sort-label": { "type": "string" }, + "field-sort-order-label": { + "type": "string" + }, "no": { "type": "string" }, @@ -96,6 +99,7 @@ "field-name-label", "field-selectionToUse-label", "field-sort-label", + "field-sort-order-label", "no", "preview", "selectionToUse-allDocuments", diff --git a/packages/plugin-import-export/src/translations/languages/uk.ts b/packages/plugin-import-export/src/translations/languages/uk.ts index 3d7ffec54..a822195ca 100644 --- a/packages/plugin-import-export/src/translations/languages/uk.ts +++ b/packages/plugin-import-export/src/translations/languages/uk.ts @@ -15,6 +15,7 @@ export const ukTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Сторінка', 'field-selectionToUse-label': 'Вибір для використання', 'field-sort-label': 'Сортувати за', + 'field-sort-order-label': 'Сортувати за порядком', 'selectionToUse-allDocuments': 'Використовуйте всі документи', 'selectionToUse-currentFilters': 'Використовувати поточні фільтри', 'selectionToUse-currentSelection': 'Використовуйте поточний вибір', diff --git a/packages/plugin-import-export/src/translations/languages/vi.ts b/packages/plugin-import-export/src/translations/languages/vi.ts index 0eee6b2cb..a7727945e 100644 --- a/packages/plugin-import-export/src/translations/languages/vi.ts +++ b/packages/plugin-import-export/src/translations/languages/vi.ts @@ -15,6 +15,7 @@ export const viTranslations: PluginDefaultTranslationsObject = { 'field-page-label': 'Trang', 'field-selectionToUse-label': 'Lựa chọn để sử dụng', 'field-sort-label': 'Sắp xếp theo', + 'field-sort-order-label': 'Sắp xếp theo thứ tự', 'selectionToUse-allDocuments': 'Sử dụng tất cả các tài liệu', 'selectionToUse-currentFilters': 'Sử dụng bộ lọc hiện tại', 'selectionToUse-currentSelection': 'Sử dụng lựa chọn hiện tại', diff --git a/packages/plugin-import-export/src/translations/languages/zh.ts b/packages/plugin-import-export/src/translations/languages/zh.ts index 820a694fb..535e5ea2a 100644 --- a/packages/plugin-import-export/src/translations/languages/zh.ts +++ b/packages/plugin-import-export/src/translations/languages/zh.ts @@ -15,6 +15,7 @@ export const zhTranslations: PluginDefaultTranslationsObject = { 'field-page-label': '页面', 'field-selectionToUse-label': '选择范围', 'field-sort-label': '排序方式', + 'field-sort-order-label': '排序顺序', 'selectionToUse-allDocuments': '使用所有文档', 'selectionToUse-currentFilters': '使用当前过滤条件', 'selectionToUse-currentSelection': '使用当前选择', diff --git a/packages/plugin-import-export/src/translations/languages/zhTw.ts b/packages/plugin-import-export/src/translations/languages/zhTw.ts index f9b5503f2..ff8ece9d4 100644 --- a/packages/plugin-import-export/src/translations/languages/zhTw.ts +++ b/packages/plugin-import-export/src/translations/languages/zhTw.ts @@ -15,6 +15,7 @@ export const zhTwTranslations: PluginDefaultTranslationsObject = { 'field-page-label': '頁面', 'field-selectionToUse-label': '使用的選取範圍', 'field-sort-label': '排序方式', + 'field-sort-order-label': '排序順序', 'selectionToUse-allDocuments': '使用所有文件', 'selectionToUse-currentFilters': '使用目前篩選條件', 'selectionToUse-currentSelection': '使用目前選取內容', diff --git a/packages/plugin-import-export/src/translations/types.ts b/packages/plugin-import-export/src/translations/types.ts index 1c3126e99..c269732d5 100644 --- a/packages/plugin-import-export/src/translations/types.ts +++ b/packages/plugin-import-export/src/translations/types.ts @@ -16,6 +16,7 @@ export type PluginLanguage = Language<{ 'field-page-label': string 'field-selectionToUse-label': string 'field-sort-label': string + 'field-sort-order-label': string 'selectionToUse-allDocuments': string 'selectionToUse-currentFilters': string 'selectionToUse-currentSelection': string diff --git a/packages/plugin-import-export/src/utilities/sortHelpers.ts b/packages/plugin-import-export/src/utilities/sortHelpers.ts new file mode 100644 index 000000000..ba60d2b4b --- /dev/null +++ b/packages/plugin-import-export/src/utilities/sortHelpers.ts @@ -0,0 +1,6 @@ +/** Remove a leading '-' from a sort value (e.g. "-title" -> "title") */ +export const stripSortDash = (v?: null | string): string => (v ? v.replace(/^-/, '') : '') + +/** Apply order to a base field (("title","desc") -> "-title") */ +export const applySortOrder = (field: string, order: 'asc' | 'desc'): string => + order === 'desc' ? `-${field}` : field diff --git a/test/plugin-import-export/int.spec.ts b/test/plugin-import-export/int.spec.ts index 08c159bc4..571c8bc68 100644 --- a/test/plugin-import-export/int.spec.ts +++ b/test/plugin-import-export/int.spec.ts @@ -227,6 +227,60 @@ describe('@payloadcms/plugin-import-export', () => { ).rejects.toThrow(/Limit/) }) + it('should export results sorted ASC by title when sort="title"', async () => { + let doc = await payload.create({ + collection: 'exports', + user, + data: { + collectionSlug: 'pages', + format: 'csv', + sort: 'title', + where: { + or: [{ title: { contains: 'Title' } }, { title: { contains: 'Array' } }], + }, + }, + }) + + doc = await payload.findByID({ + collection: 'exports', + id: doc.id, + }) + + expect(doc.filename).toBeDefined() + const expectedPath = path.join(dirname, './uploads', doc.filename as string) + const data = await readCSV(expectedPath) + + expect(data[0].id).toBeDefined() + expect(data[0].title).toStrictEqual('Array 0') + }) + + it('should export results sorted DESC by title when sort="-title"', async () => { + let doc = await payload.create({ + collection: 'exports', + user, + data: { + collectionSlug: 'pages', + format: 'csv', + sort: '-title', + where: { + or: [{ title: { contains: 'Title' } }, { title: { contains: 'Array' } }], + }, + }, + }) + + doc = await payload.findByID({ + collection: 'exports', + id: doc.id, + }) + + expect(doc.filename).toBeDefined() + const expectedPath = path.join(dirname, './uploads', doc.filename as string) + const data = await readCSV(expectedPath) + + expect(data[0].id).toBeDefined() + expect(data[0].title).toStrictEqual('Title 4') + }) + it('should create a file for collection csv with draft data', async () => { const draftPage = await payload.create({ collection: 'pages', diff --git a/test/plugin-import-export/payload-types.ts b/test/plugin-import-export/payload-types.ts index d70fd878f..6f45ffbfc 100644 --- a/test/plugin-import-export/payload-types.ts +++ b/test/plugin-import-export/payload-types.ts @@ -270,6 +270,7 @@ export interface Export { limit?: number | null; page?: number | null; sort?: string | null; + sortOrder?: ('asc' | 'desc') | null; locale?: ('all' | 'en' | 'es' | 'de') | null; drafts?: ('yes' | 'no') | null; selectionToUse?: ('currentSelection' | 'currentFilters' | 'all') | null; @@ -307,6 +308,7 @@ export interface ExportsTask { limit?: number | null; page?: number | null; sort?: string | null; + sortOrder?: ('asc' | 'desc') | null; locale?: ('all' | 'en' | 'es' | 'de') | null; drafts?: ('yes' | 'no') | null; selectionToUse?: ('currentSelection' | 'currentFilters' | 'all') | null; @@ -609,6 +611,7 @@ export interface ExportsSelect { limit?: T; page?: T; sort?: T; + sortOrder?: T; locale?: T; drafts?: T; selectionToUse?: T; @@ -637,6 +640,7 @@ export interface ExportsTasksSelect { limit?: T; page?: T; sort?: T; + sortOrder?: T; locale?: T; drafts?: T; selectionToUse?: T; @@ -729,6 +733,7 @@ export interface TaskCreateCollectionExport { limit?: number | null; page?: number | null; sort?: string | null; + sortOrder?: ('asc' | 'desc') | null; locale?: ('all' | 'en' | 'es' | 'de') | null; drafts?: ('yes' | 'no') | null; selectionToUse?: ('currentSelection' | 'currentFilters' | 'all') | null;