@strapi/upload 5.52.0 → 5.52.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/future/components/TruncatedText.js +76 -0
- package/dist/admin/future/components/TruncatedText.js.map +1 -0
- package/dist/admin/future/components/TruncatedText.mjs +74 -0
- package/dist/admin/future/components/TruncatedText.mjs.map +1 -0
- package/dist/admin/future/components/UploadProgressDialog.js +36 -1
- package/dist/admin/future/components/UploadProgressDialog.js.map +1 -1
- package/dist/admin/future/components/UploadProgressDialog.mjs +37 -2
- package/dist/admin/future/components/UploadProgressDialog.mjs.map +1 -1
- package/dist/admin/future/hooks/useApiErrorMessage.js +61 -0
- package/dist/admin/future/hooks/useApiErrorMessage.js.map +1 -0
- package/dist/admin/future/hooks/useApiErrorMessage.mjs +39 -0
- package/dist/admin/future/hooks/useApiErrorMessage.mjs.map +1 -0
- package/dist/admin/future/hooks/useTracking.js +57 -0
- package/dist/admin/future/hooks/useTracking.js.map +1 -0
- package/dist/admin/future/hooks/useTracking.mjs +53 -0
- package/dist/admin/future/hooks/useTracking.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/AssetsPage.js +31 -0
- package/dist/admin/future/pages/Assets/AssetsPage.js.map +1 -1
- package/dist/admin/future/pages/Assets/AssetsPage.mjs +31 -0
- package/dist/admin/future/pages/Assets/AssetsPage.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.js +13 -11
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.mjs +13 -11
- package/dist/admin/future/pages/Assets/components/AssetActionsMenu.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +62 -51
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +62 -51
- package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsGrid.js +3 -4
- package/dist/admin/future/pages/Assets/components/AssetsGrid.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs +4 -5
- package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.js +11 -1
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.mjs +11 -1
- package/dist/admin/future/pages/Assets/components/AssetsSearchInput.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsTable.js +6 -4
- package/dist/admin/future/pages/Assets/components/AssetsTable.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/AssetsTable.mjs +6 -4
- package/dist/admin/future/pages/Assets/components/AssetsTable.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.js +10 -1
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs +10 -1
- package/dist/admin/future/pages/Assets/components/BulkActionsBar.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/BulkMoveDialog.js +3 -2
- package/dist/admin/future/pages/Assets/components/BulkMoveDialog.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/BulkMoveDialog.mjs +3 -2
- package/dist/admin/future/pages/Assets/components/BulkMoveDialog.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js +4 -2
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs +4 -2
- package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/FilterMenu.js +18 -2
- package/dist/admin/future/pages/Assets/components/FilterMenu.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/FilterMenu.mjs +18 -2
- package/dist/admin/future/pages/Assets/components/FilterMenu.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.js +9 -7
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.mjs +9 -7
- package/dist/admin/future/pages/Assets/components/FolderActionsMenu.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderFormDialog.js +12 -0
- package/dist/admin/future/pages/Assets/components/FolderFormDialog.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderFormDialog.mjs +12 -0
- package/dist/admin/future/pages/Assets/components/FolderFormDialog.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.js +21 -38
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.mjs +23 -40
- package/dist/admin/future/pages/Assets/components/FolderTree/FolderTree.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/components/SortMenu.js +14 -0
- package/dist/admin/future/pages/Assets/components/SortMenu.js.map +1 -1
- package/dist/admin/future/pages/Assets/components/SortMenu.mjs +14 -0
- package/dist/admin/future/pages/Assets/components/SortMenu.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.js +5 -0
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.js.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.mjs +6 -1
- package/dist/admin/future/pages/Assets/hooks/useAssetSelection.mjs.map +1 -1
- package/dist/admin/future/pages/Assets/hooks/useIsAssetDetailsOpen.js +30 -0
- package/dist/admin/future/pages/Assets/hooks/useIsAssetDetailsOpen.js.map +1 -0
- package/dist/admin/future/pages/Assets/hooks/useIsAssetDetailsOpen.mjs +26 -0
- package/dist/admin/future/pages/Assets/hooks/useIsAssetDetailsOpen.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/utils/selection.js +17 -0
- package/dist/admin/future/pages/Assets/utils/selection.js.map +1 -1
- package/dist/admin/future/pages/Assets/utils/selection.mjs +17 -1
- package/dist/admin/future/pages/Assets/utils/selection.mjs.map +1 -1
- package/dist/admin/future/services/api.js +123 -19
- package/dist/admin/future/services/api.js.map +1 -1
- package/dist/admin/future/services/api.mjs +125 -21
- package/dist/admin/future/services/api.mjs.map +1 -1
- package/dist/admin/future/services/assets.js +11 -23
- package/dist/admin/future/services/assets.js.map +1 -1
- package/dist/admin/future/services/assets.mjs +11 -23
- package/dist/admin/future/services/assets.mjs.map +1 -1
- package/dist/admin/future/services/uploadFileViaXHR.js +9 -3
- package/dist/admin/future/services/uploadFileViaXHR.js.map +1 -1
- package/dist/admin/future/services/uploadFileViaXHR.mjs +9 -3
- package/dist/admin/future/services/uploadFileViaXHR.mjs.map +1 -1
- package/dist/admin/future/store/uploadProgress.js +44 -5
- package/dist/admin/future/store/uploadProgress.js.map +1 -1
- package/dist/admin/future/store/uploadProgress.mjs +43 -6
- package/dist/admin/future/store/uploadProgress.mjs.map +1 -1
- package/dist/admin/future/utils/getApiErrorMessage.js +20 -0
- package/dist/admin/future/utils/getApiErrorMessage.js.map +1 -0
- package/dist/admin/future/utils/getApiErrorMessage.mjs +18 -0
- package/dist/admin/future/utils/getApiErrorMessage.mjs.map +1 -0
- package/dist/admin/hooks/useAIMetadataJob.js +1 -1
- package/dist/admin/hooks/useAIMetadataJob.js.map +1 -1
- package/dist/admin/hooks/useAIMetadataJob.mjs +1 -1
- package/dist/admin/hooks/useAIMetadataJob.mjs.map +1 -1
- package/dist/admin/pages/SettingsPage/SettingsPage.js +2 -2
- package/dist/admin/pages/SettingsPage/SettingsPage.js.map +1 -1
- package/dist/admin/pages/SettingsPage/SettingsPage.mjs +2 -2
- package/dist/admin/pages/SettingsPage/SettingsPage.mjs.map +1 -1
- package/dist/admin/src/future/components/TruncatedText.d.ts +32 -0
- package/dist/admin/src/future/hooks/useApiErrorMessage.d.ts +17 -0
- package/dist/admin/src/future/hooks/useTracking.d.ts +29 -0
- package/dist/admin/src/future/pages/Assets/components/AssetActionsMenu.d.ts +5 -3
- package/dist/admin/src/future/pages/Assets/components/FolderActionsMenu.d.ts +5 -4
- package/dist/admin/src/future/pages/Assets/hooks/useAssetSelection.d.ts +2 -0
- package/dist/admin/src/future/pages/Assets/hooks/useIsAssetDetailsOpen.d.ts +18 -0
- package/dist/admin/src/future/pages/Assets/utils/selection.d.ts +10 -0
- package/dist/admin/src/future/services/api.d.ts +6 -7
- package/dist/admin/src/future/services/uploadFileViaXHR.d.ts +6 -1
- package/dist/admin/src/future/store/uploadProgress.d.ts +16 -1
- package/dist/admin/src/future/utils/getApiErrorMessage.d.ts +1 -0
- package/dist/admin/translations/ca.json.js +1 -1
- package/dist/admin/translations/ca.json.mjs +1 -1
- package/dist/admin/translations/de.json.js +1 -1
- package/dist/admin/translations/de.json.mjs +1 -1
- package/dist/admin/translations/en.json.js +2 -1
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +2 -1
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/admin/translations/es.json.js +1 -1
- package/dist/admin/translations/es.json.mjs +1 -1
- package/dist/admin/translations/fr.json.js +1 -1
- package/dist/admin/translations/fr.json.mjs +1 -1
- package/dist/admin/translations/ja.json.js +1 -1
- package/dist/admin/translations/ja.json.mjs +1 -1
- package/dist/admin/translations/ko.json.js +1 -1
- package/dist/admin/translations/ko.json.mjs +1 -1
- package/dist/admin/translations/nl.json.js +1 -1
- package/dist/admin/translations/nl.json.mjs +1 -1
- package/dist/admin/translations/pl.json.js +1 -1
- package/dist/admin/translations/pl.json.mjs +1 -1
- package/dist/admin/translations/pt-BR.json.js +1 -1
- package/dist/admin/translations/pt-BR.json.mjs +1 -1
- package/dist/admin/translations/ru.json.js +1 -1
- package/dist/admin/translations/ru.json.mjs +1 -1
- package/dist/admin/translations/sk.json.js +1 -1
- package/dist/admin/translations/sk.json.mjs +1 -1
- package/dist/admin/translations/tr.json.js +1 -1
- package/dist/admin/translations/tr.json.mjs +1 -1
- package/dist/admin/translations/uk.json.js +1 -1
- package/dist/admin/translations/uk.json.mjs +1 -1
- package/dist/admin/translations/zh-Hans.json.js +1 -1
- package/dist/admin/translations/zh-Hans.json.mjs +1 -1
- package/dist/admin/translations/zh.json.js +1 -1
- package/dist/admin/translations/zh.json.mjs +1 -1
- package/dist/server/controllers/admin-file.js +27 -9
- package/dist/server/controllers/admin-file.js.map +1 -1
- package/dist/server/controllers/admin-file.mjs +27 -9
- package/dist/server/controllers/admin-file.mjs.map +1 -1
- package/dist/server/controllers/admin-upload.js +24 -8
- package/dist/server/controllers/admin-upload.js.map +1 -1
- package/dist/server/controllers/admin-upload.mjs +24 -8
- package/dist/server/controllers/admin-upload.mjs.map +1 -1
- package/dist/server/routes/admin.js +41 -21
- package/dist/server/routes/admin.js.map +1 -1
- package/dist/server/routes/admin.mjs +41 -21
- package/dist/server/routes/admin.mjs.map +1 -1
- package/dist/server/services/ai-metadata.js +25 -5
- package/dist/server/services/ai-metadata.js.map +1 -1
- package/dist/server/services/ai-metadata.mjs +1 -1
- package/dist/server/services/ai-metadata.mjs.map +1 -1
- package/dist/server/services/upload.js +4 -0
- package/dist/server/services/upload.js.map +1 -1
- package/dist/server/services/upload.mjs +4 -0
- package/dist/server/services/upload.mjs.map +1 -1
- package/dist/server/src/controllers/admin-file.d.ts +29 -8
- package/dist/server/src/controllers/admin-file.d.ts.map +1 -1
- package/dist/server/src/controllers/admin-upload.d.ts +20 -4
- package/dist/server/src/controllers/admin-upload.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts +4 -4
- package/dist/server/src/index.d.ts +4 -4
- package/dist/server/src/routes/admin.d.ts.map +1 -1
- package/dist/server/src/services/ai-metadata.d.ts +2 -2
- package/dist/server/src/services/ai-metadata.d.ts.map +1 -1
- package/dist/server/src/services/upload.d.ts.map +1 -1
- package/dist/shared/contracts/ai-metadata-jobs.d.ts +10 -32
- package/dist/shared/contracts/ai-metadata-jobs.d.ts.map +1 -1
- package/dist/shared/contracts/files.d.ts +10 -10
- package/dist/shared/contracts/files.d.ts.map +1 -1
- package/package.json +7 -7
- package/dist/admin/future/utils/getBulkMoveErrorMessage.js +0 -23
- package/dist/admin/future/utils/getBulkMoveErrorMessage.js.map +0 -1
- package/dist/admin/future/utils/getBulkMoveErrorMessage.mjs +0 -21
- package/dist/admin/future/utils/getBulkMoveErrorMessage.mjs.map +0 -1
- package/dist/admin/src/future/utils/getBulkMoveErrorMessage.d.ts +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilterMenu.mjs","sources":["../../../../../../admin/src/future/pages/Assets/components/FilterMenu.tsx"],"sourcesContent":["import { useState } from 'react';\n\nimport { useIsMobile } from '@strapi/admin/strapi-admin';\nimport { Badge, Box, Checkbox, Flex, Menu } from '@strapi/design-system';\nimport { Check, ChevronDown, Filter as FilterIcon } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { getTranslationKey } from '../../../utils/translations';\nimport {\n DATE_PRESETS,\n TYPE_VALUES,\n type DateField,\n type DatePreset,\n type ListFilters,\n type TypeValue,\n} from '../hooks/useListFilters';\n\nimport { DateRangeCalendar } from './DateRangeCalendar';\n\nimport type { MessageDescriptor } from 'react-intl';\n\nexport const TYPE_LABELS: Record<TypeValue, MessageDescriptor> = {\n folder: { id: getTranslationKey('list.filters.type.folder'), defaultMessage: 'Folder' },\n picture: { id: getTranslationKey('list.filters.type.picture'), defaultMessage: 'Picture' },\n audio: { id: getTranslationKey('list.filters.type.audio'), defaultMessage: 'Audio' },\n video: { id: getTranslationKey('list.filters.type.video'), defaultMessage: 'Video' },\n document: { id: getTranslationKey('list.filters.type.document'), defaultMessage: 'Document' },\n};\n\nexport const PRESET_LABELS: Record<DatePreset, MessageDescriptor> = {\n '1day': { id: getTranslationKey('list.filters.preset.1day'), defaultMessage: '1 day ago' },\n '3days': { id: getTranslationKey('list.filters.preset.3days'), defaultMessage: '3 days ago' },\n '1week': { id: getTranslationKey('list.filters.preset.1week'), defaultMessage: '1 week ago' },\n '1month': { id: getTranslationKey('list.filters.preset.1month'), defaultMessage: '1 month ago' },\n '3months': {\n id: getTranslationKey('list.filters.preset.3months'),\n defaultMessage: '3 months ago',\n },\n '6months': {\n id: getTranslationKey('list.filters.preset.6months'),\n defaultMessage: '6 months ago',\n },\n '1year': { id: getTranslationKey('list.filters.preset.1year'), defaultMessage: '1 year ago' },\n};\n\nexport const DATE_FIELD_LABELS: Record<DateField, MessageDescriptor> = {\n createdAt: {\n id: getTranslationKey('list.filters.field.created'),\n defaultMessage: 'Creation date',\n },\n updatedAt: {\n id: getTranslationKey('list.filters.field.updated'),\n defaultMessage: 'Last modified',\n },\n};\n\n// The DS SubTrigger renders its chevron inline right after the label — push it\n// to the far edge so every field row reads label · · · ›, like the mock.\nconst FieldSubTrigger = styled(Menu.SubTrigger)`\n width: 100%;\n justify-content: space-between;\n`;\n\n/** Every panel of the filter tree shares this fixed width (design). */\nexport const FILTER_PANEL_WIDTH = '24.2rem';\n\n// dvh, not vh: on a phone `vh` ignores the browser chrome, so a 70vh panel can\n// extend past the visual viewport and leave its lower rows (the last field, and\n// anything under the date-range calendar) stranded under the URL bar with no way\n// to scroll to them. Same reason the drawer caps on dvh.\nconst PANEL_MAX_HEIGHT = '70dvh';\n\n// Mobile uses one flat panel (accordion), so it never needs room for a side\n// flyout — cap it to the viewport so it can't overflow a narrow screen.\nconst MOBILE_PANEL_WIDTH = `min(${FILTER_PANEL_WIDTH}, calc(100dvw - 2rem))`;\n\n// Mobile accordion: the field row is a plain menu item that expands its options\n// inline below it (Radix sub-menus can only fly out sideways, off a phone).\nconst FieldToggle = styled(Menu.Item)`\n width: 100%;\n`;\n\n// The options revealed under a field row.\n//\n// `width: 100%` is load-bearing: Menu.Content is a column flex with\n// `align-items: flex-start`, so a child shrink-wraps to its content unless it\n// sets a width explicitly. Without it the group collapsed to the widest option\n// label and the rows' own `width: 100%` resolved against that, so a selected row\n// highlighted only part of the panel.\n//\n// The indent then lives on each row's padding rather than on this wrapper —\n// padding here would inset the rows, and the highlight with them.\nconst OptionGroup = styled(Box)`\n width: 100%;\n\n > * {\n width: 100%;\n }\n\n /* menuitem, menuitemradio and menuitemcheckbox — every option row, plus the\n \"Select date range\" toggle, which sits at the same level. */\n > [role^='menuitem'] {\n padding-left: ${({ theme }) => theme.spaces[6]};\n }\n`;\n\n// Rotates the chevron when its section is open.\nconst Chevron = styled(ChevronDown)<{ $open: boolean }>`\n transition: transform 0.2s ease;\n transform: rotate(${({ $open }) => ($open ? '180deg' : '0deg')});\n`;\n\n// Sub panels: fixed width, no 15rem clamp (the DS default folds the calendar),\n// and a negative top margin cancelling the parent panel's padding + border so\n// the sub panel's top edge lines up with the parent panel, not the item.\nconst SubPanel = styled(Menu.SubContent)`\n margin-top: calc(-1 * (${({ theme }) => theme.spaces[1]} + 1px));\n`;\n\nconst CountBadge = styled(Badge)`\n height: 1.6rem;\n min-width: auto;\n padding: 0 0.4rem;\n`;\n\ninterface FilterMenuProps {\n listFilters: ListFilters;\n}\n\n/**\n * Toolbar \"Filter\" dropdown. Picking anything ADDS a badge (editing happens on\n * the badge itself, see FilterBadges):\n *\n * - Type → keep-open checkbox list; the badge is created/updated live with the\n * checked set (`is` by default, condition editable on the badge).\n * - Creation date / Last modified → preset list (single pick, `within the\n * last` by default) + \"Select date range\" (creation date only) opening the\n * range calendar; a completed range adds an `is` range badge.\n *\n * Closing behaviour follows how many values a field can hold: a date is one\n * value, so picking a preset (or committing a range) closes the menu; Type is a\n * set, so it stays open until dismissed.\n */\nexport const FilterMenu = ({ listFilters }: FilterMenuProps) => {\n const { formatMessage } = useIntl();\n const [isOpen, setIsOpen] = useState(false);\n const { filters, addFilter, updateFilter, removeFilter } = listFilters;\n\n // The Type submenu edits the LAST type badge in place while the menu stays\n // open (checking values accumulates into one badge, per design).\n let lastTypeIndex = -1;\n for (let i = filters.length - 1; i >= 0; i -= 1) {\n if (filters[i].kind === 'type') {\n lastTypeIndex = i;\n break;\n }\n }\n const lastTypeFilter = lastTypeIndex >= 0 ? filters[lastTypeIndex] : null;\n const checkedValues =\n lastTypeFilter && lastTypeFilter.kind === 'type' ? lastTypeFilter.values : [];\n\n const toggleTypeValue = (value: TypeValue) => {\n const nextValues = checkedValues.includes(value)\n ? checkedValues.filter((v) => v !== value)\n : [...checkedValues, value];\n\n if (lastTypeFilter && lastTypeFilter.kind === 'type') {\n if (nextValues.length === 0) {\n // Unchecking the final value removes the badge outright — a type\n // filter with no values is not a state (it would serialize to a\n // malformed `type:is:` the parser drops anyway).\n removeFilter(lastTypeIndex);\n } else {\n updateFilter(lastTypeIndex, { ...lastTypeFilter, values: nextValues });\n }\n } else if (nextValues.length > 0) {\n addFilter({ kind: 'type', condition: 'is', values: nextValues });\n }\n };\n\n // Creation date / Last modified are single-select (per design): selecting a\n // preset replaces the field's existing preset badge in place (keeping its\n // condition) rather than adding another pill; a badge is created only when the\n // field has none yet.\n const addPreset = (field: DateField, preset: DatePreset) => {\n for (let i = filters.length - 1; i >= 0; i -= 1) {\n const f = filters[i];\n if (f.kind === 'date' && f.mode === 'preset' && f.field === field) {\n updateFilter(i, { ...f, preset });\n return;\n }\n }\n addFilter({ kind: 'date', field, mode: 'preset', condition: 'withinLast', preset });\n };\n\n const addRange = (from: string, to: string) => {\n addFilter({ kind: 'date', field: 'createdAt', mode: 'range', condition: 'is', from, to });\n // The calendar is not a Menu.Item — close the menu explicitly on commit.\n setIsOpen(false);\n };\n\n const isMobile = useIsMobile();\n // Mobile accordion state: which field is expanded, and whether its date-range\n // calendar is open. Both reset when the whole menu closes.\n const [openField, setOpenField] = useState<'type' | 'createdAt' | 'updatedAt' | null>(null);\n const [rangeOpen, setRangeOpen] = useState(false);\n\n const handleOpenChange = (next: boolean) => {\n setIsOpen(next);\n if (!next) {\n setOpenField(null);\n setRangeOpen(false);\n }\n };\n\n const toggleField = (field: 'type' | 'createdAt' | 'updatedAt') => {\n setOpenField((current) => (current === field ? null : field));\n setRangeOpen(false);\n };\n\n // Option lists, shared by the desktop flyouts and the mobile accordion.\n // Multi-select semantics: menuitemcheckbox + aria-checked carry the state for\n // assistive tech; the Checkbox is purely decorative (aria-hidden, unfocusable)\n // — the Menu.Item is the control.\n const typeItems = TYPE_VALUES.map((value) => (\n <Menu.Item\n key={value}\n role=\"menuitemcheckbox\"\n aria-checked={checkedValues.includes(value)}\n onSelect={(e: Event) => {\n e.preventDefault();\n toggleTypeValue(value);\n }}\n startIcon={<Checkbox checked={checkedValues.includes(value)} tabIndex={-1} aria-hidden />}\n >\n {formatMessage(TYPE_LABELS[value])}\n </Menu.Item>\n ));\n\n // The field's currently-selected preset (single-select), so the menu can mark\n // it with a check.\n const selectedPresetForField = (field: DateField): DatePreset | null => {\n for (let i = filters.length - 1; i >= 0; i -= 1) {\n const f = filters[i];\n if (f.kind === 'date' && f.mode === 'preset' && f.field === field) {\n return f.preset;\n }\n }\n return null;\n };\n\n const presetItems = (field: DateField) => {\n const selected = selectedPresetForField(field);\n\n return DATE_PRESETS.map((preset) => (\n <Menu.Item\n key={preset}\n role=\"menuitemradio\"\n aria-checked={selected === preset}\n onSelect={() => {\n // No preventDefault, unlike Type: a date field holds exactly one\n // value, so the pick is complete and the menu closes on it. Type stays\n // open because the user may still be building up a multi-value set.\n addPreset(field, preset);\n }}\n endIcon={\n selected === preset ? (\n <Check aria-hidden width=\"1.6rem\" height=\"1.6rem\" fill=\"primary600\" />\n ) : null\n }\n >\n {formatMessage(PRESET_LABELS[preset])}\n </Menu.Item>\n ));\n };\n\n const typeLabel = formatMessage({\n id: getTranslationKey('list.filters.field.type'),\n defaultMessage: 'Type',\n });\n const selectDateRangeLabel = formatMessage({\n id: getTranslationKey('list.filters.select-date-range'),\n defaultMessage: 'Select date range',\n });\n\n return (\n <Menu.Root open={isOpen} onOpenChange={handleOpenChange}>\n {/* endIcon={null} drops the DS default chevron — the mock has none. */}\n <Menu.Trigger variant=\"tertiary\" startIcon={<FilterIcon aria-hidden />} endIcon={null}>\n <Flex gap={2} alignItems=\"center\" tag=\"span\">\n {formatMessage({\n id: getTranslationKey('list.filters.trigger'),\n defaultMessage: 'Filter',\n })}\n {filters.length > 0 && <CountBadge>{filters.length}</CountBadge>}\n </Flex>\n </Menu.Trigger>\n <Menu.Content\n popoverPlacement=\"bottom-start\"\n zIndex={2}\n maxHeight={PANEL_MAX_HEIGHT}\n width={isMobile ? MOBILE_PANEL_WIDTH : FILTER_PANEL_WIDTH}\n >\n {isMobile ? (\n // Mobile: one flat panel. Each field expands its options inline below\n // itself — Radix sub-menus can only fly out sideways, off a phone.\n <>\n <FieldToggle\n aria-expanded={openField === 'type'}\n onSelect={(e: Event) => {\n e.preventDefault();\n toggleField('type');\n }}\n endIcon={<Chevron $open={openField === 'type'} aria-hidden />}\n >\n {typeLabel}\n </FieldToggle>\n {openField === 'type' && <OptionGroup>{typeItems}</OptionGroup>}\n\n {(['createdAt', 'updatedAt'] as const).map((field) => (\n <Box key={field} width=\"100%\">\n <FieldToggle\n aria-expanded={openField === field}\n onSelect={(e: Event) => {\n e.preventDefault();\n toggleField(field);\n }}\n endIcon={<Chevron $open={openField === field} aria-hidden />}\n >\n {formatMessage(DATE_FIELD_LABELS[field])}\n </FieldToggle>\n {openField === field && (\n <OptionGroup>\n {presetItems(field)}\n {/* Only Creation date offers a range from the UI (design). */}\n {field === 'createdAt' && (\n <>\n <FieldToggle\n aria-expanded={rangeOpen}\n onSelect={(e: Event) => {\n e.preventDefault();\n setRangeOpen((open) => !open);\n }}\n endIcon={<Chevron $open={rangeOpen} aria-hidden />}\n >\n {selectDateRangeLabel}\n </FieldToggle>\n {rangeOpen && (\n <Box paddingLeft={2}>\n <DateRangeCalendar onSelect={addRange} />\n </Box>\n )}\n </>\n )}\n </OptionGroup>\n )}\n </Box>\n ))}\n </>\n ) : (\n <>\n <Menu.SubRoot>\n <FieldSubTrigger>{typeLabel}</FieldSubTrigger>\n <SubPanel zIndex={2} maxHeight={PANEL_MAX_HEIGHT} width={FILTER_PANEL_WIDTH}>\n {typeItems}\n </SubPanel>\n </Menu.SubRoot>\n\n {(['createdAt', 'updatedAt'] as const).map((field) => (\n <Menu.SubRoot key={field}>\n <FieldSubTrigger>{formatMessage(DATE_FIELD_LABELS[field])}</FieldSubTrigger>\n <SubPanel zIndex={2} maxHeight={PANEL_MAX_HEIGHT} width={FILTER_PANEL_WIDTH}>\n {presetItems(field)}\n {/* Design constraint: only Creation date offers a range from the\n UI. The URL codec and the badges support ranges on both date\n fields (`updated:rangeis:…` works when hand-crafted) so this\n stays a one-line change if design extends it later. */}\n {field === 'createdAt' && (\n <Menu.SubRoot>\n <FieldSubTrigger>{selectDateRangeLabel}</FieldSubTrigger>\n <SubPanel zIndex={2} maxHeight=\"none\" width={FILTER_PANEL_WIDTH}>\n <DateRangeCalendar onSelect={addRange} />\n </SubPanel>\n </Menu.SubRoot>\n )}\n </SubPanel>\n </Menu.SubRoot>\n ))}\n </>\n )}\n </Menu.Content>\n </Menu.Root>\n );\n};\n"],"names":["TYPE_LABELS","folder","id","getTranslationKey","defaultMessage","picture","audio","video","document","PRESET_LABELS","DATE_FIELD_LABELS","createdAt","updatedAt","FieldSubTrigger","styled","Menu","SubTrigger","FILTER_PANEL_WIDTH","PANEL_MAX_HEIGHT","MOBILE_PANEL_WIDTH","FieldToggle","Item","OptionGroup","Box","theme","spaces","Chevron","ChevronDown","$open","SubPanel","SubContent","CountBadge","Badge","FilterMenu","listFilters","formatMessage","useIntl","isOpen","setIsOpen","useState","filters","addFilter","updateFilter","removeFilter","lastTypeIndex","i","length","kind","lastTypeFilter","checkedValues","values","toggleTypeValue","value","nextValues","includes","filter","v","condition","addPreset","field","preset","f","mode","addRange","from","to","isMobile","useIsMobile","openField","setOpenField","rangeOpen","setRangeOpen","handleOpenChange","next","toggleField","current","typeItems","TYPE_VALUES","map","_jsx","role","aria-checked","onSelect","e","preventDefault","startIcon","Checkbox","checked","tabIndex","aria-hidden","selectedPresetForField","presetItems","selected","DATE_PRESETS","endIcon","Check","width","height","fill","typeLabel","selectDateRangeLabel","_jsxs","Root","open","onOpenChange","Trigger","variant","FilterIcon","Flex","gap","alignItems","tag","Content","popoverPlacement","zIndex","maxHeight","_Fragment","aria-expanded","paddingLeft","DateRangeCalendar","SubRoot"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FilterMenu.mjs","sources":["../../../../../../admin/src/future/pages/Assets/components/FilterMenu.tsx"],"sourcesContent":["import { useState } from 'react';\n\nimport { useIsMobile } from '@strapi/admin/strapi-admin';\nimport { Badge, Box, Checkbox, Flex, Menu } from '@strapi/design-system';\nimport { Check, ChevronDown, Filter as FilterIcon } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useTracking, MEDIA_LIBRARY_LOCATION } from '../../../hooks/useTracking';\nimport { getTranslationKey } from '../../../utils/translations';\nimport {\n DATE_PRESETS,\n TYPE_VALUES,\n type DateField,\n type DatePreset,\n type ListFilters,\n type TypeValue,\n} from '../hooks/useListFilters';\n\nimport { DateRangeCalendar } from './DateRangeCalendar';\n\nimport type { MessageDescriptor } from 'react-intl';\n\nexport const TYPE_LABELS: Record<TypeValue, MessageDescriptor> = {\n folder: { id: getTranslationKey('list.filters.type.folder'), defaultMessage: 'Folder' },\n picture: { id: getTranslationKey('list.filters.type.picture'), defaultMessage: 'Picture' },\n audio: { id: getTranslationKey('list.filters.type.audio'), defaultMessage: 'Audio' },\n video: { id: getTranslationKey('list.filters.type.video'), defaultMessage: 'Video' },\n document: { id: getTranslationKey('list.filters.type.document'), defaultMessage: 'Document' },\n};\n\nexport const PRESET_LABELS: Record<DatePreset, MessageDescriptor> = {\n '1day': { id: getTranslationKey('list.filters.preset.1day'), defaultMessage: '1 day ago' },\n '3days': { id: getTranslationKey('list.filters.preset.3days'), defaultMessage: '3 days ago' },\n '1week': { id: getTranslationKey('list.filters.preset.1week'), defaultMessage: '1 week ago' },\n '1month': { id: getTranslationKey('list.filters.preset.1month'), defaultMessage: '1 month ago' },\n '3months': {\n id: getTranslationKey('list.filters.preset.3months'),\n defaultMessage: '3 months ago',\n },\n '6months': {\n id: getTranslationKey('list.filters.preset.6months'),\n defaultMessage: '6 months ago',\n },\n '1year': { id: getTranslationKey('list.filters.preset.1year'), defaultMessage: '1 year ago' },\n};\n\nexport const DATE_FIELD_LABELS: Record<DateField, MessageDescriptor> = {\n createdAt: {\n id: getTranslationKey('list.filters.field.created'),\n defaultMessage: 'Creation date',\n },\n updatedAt: {\n id: getTranslationKey('list.filters.field.updated'),\n defaultMessage: 'Last modified',\n },\n};\n\n// The DS SubTrigger renders its chevron inline right after the label — push it\n// to the far edge so every field row reads label · · · ›, like the mock.\nconst FieldSubTrigger = styled(Menu.SubTrigger)`\n width: 100%;\n justify-content: space-between;\n`;\n\n/** Every panel of the filter tree shares this fixed width (design). */\nexport const FILTER_PANEL_WIDTH = '24.2rem';\n\n// dvh, not vh: on a phone `vh` ignores the browser chrome, so a 70vh panel can\n// extend past the visual viewport and leave its lower rows (the last field, and\n// anything under the date-range calendar) stranded under the URL bar with no way\n// to scroll to them. Same reason the drawer caps on dvh.\nconst PANEL_MAX_HEIGHT = '70dvh';\n\n// Mobile uses one flat panel (accordion), so it never needs room for a side\n// flyout — cap it to the viewport so it can't overflow a narrow screen.\nconst MOBILE_PANEL_WIDTH = `min(${FILTER_PANEL_WIDTH}, calc(100dvw - 2rem))`;\n\n// Mobile accordion: the field row is a plain menu item that expands its options\n// inline below it (Radix sub-menus can only fly out sideways, off a phone).\nconst FieldToggle = styled(Menu.Item)`\n width: 100%;\n`;\n\n// The options revealed under a field row.\n//\n// `width: 100%` is load-bearing: Menu.Content is a column flex with\n// `align-items: flex-start`, so a child shrink-wraps to its content unless it\n// sets a width explicitly. Without it the group collapsed to the widest option\n// label and the rows' own `width: 100%` resolved against that, so a selected row\n// highlighted only part of the panel.\n//\n// The indent then lives on each row's padding rather than on this wrapper —\n// padding here would inset the rows, and the highlight with them.\nconst OptionGroup = styled(Box)`\n width: 100%;\n\n > * {\n width: 100%;\n }\n\n /* menuitem, menuitemradio and menuitemcheckbox — every option row, plus the\n \"Select date range\" toggle, which sits at the same level. */\n > [role^='menuitem'] {\n padding-left: ${({ theme }) => theme.spaces[6]};\n }\n`;\n\n// Rotates the chevron when its section is open.\nconst Chevron = styled(ChevronDown)<{ $open: boolean }>`\n transition: transform 0.2s ease;\n transform: rotate(${({ $open }) => ($open ? '180deg' : '0deg')});\n`;\n\n// Sub panels: fixed width, no 15rem clamp (the DS default folds the calendar),\n// and a negative top margin cancelling the parent panel's padding + border so\n// the sub panel's top edge lines up with the parent panel, not the item.\nconst SubPanel = styled(Menu.SubContent)`\n margin-top: calc(-1 * (${({ theme }) => theme.spaces[1]} + 1px));\n`;\n\nconst CountBadge = styled(Badge)`\n height: 1.6rem;\n min-width: auto;\n padding: 0 0.4rem;\n`;\n\ninterface FilterMenuProps {\n listFilters: ListFilters;\n}\n\n/**\n * Toolbar \"Filter\" dropdown. Picking anything ADDS a badge (editing happens on\n * the badge itself, see FilterBadges):\n *\n * - Type → keep-open checkbox list; the badge is created/updated live with the\n * checked set (`is` by default, condition editable on the badge).\n * - Creation date / Last modified → preset list (single pick, `within the\n * last` by default) + \"Select date range\" (creation date only) opening the\n * range calendar; a completed range adds an `is` range badge.\n *\n * Closing behaviour follows how many values a field can hold: a date is one\n * value, so picking a preset (or committing a range) closes the menu; Type is a\n * set, so it stays open until dismissed.\n */\nexport const FilterMenu = ({ listFilters }: FilterMenuProps) => {\n const { formatMessage } = useIntl();\n const { trackUsage } = useTracking();\n const [isOpen, setIsOpen] = useState(false);\n const { filters, addFilter, updateFilter, removeFilter } = listFilters;\n\n // Fired whenever a filter facet is turned on (not on removal). `filter` names\n // the facet, mirroring the legacy field-key payload.\n const trackFilter = (filter: string) =>\n trackUsage('didFilterMediaLibraryElements', { location: MEDIA_LIBRARY_LOCATION, filter });\n\n // The Type submenu edits the LAST type badge in place while the menu stays\n // open (checking values accumulates into one badge, per design).\n let lastTypeIndex = -1;\n for (let i = filters.length - 1; i >= 0; i -= 1) {\n if (filters[i].kind === 'type') {\n lastTypeIndex = i;\n break;\n }\n }\n const lastTypeFilter = lastTypeIndex >= 0 ? filters[lastTypeIndex] : null;\n const checkedValues =\n lastTypeFilter && lastTypeFilter.kind === 'type' ? lastTypeFilter.values : [];\n\n const toggleTypeValue = (value: TypeValue) => {\n const isAdding = !checkedValues.includes(value);\n const nextValues = isAdding\n ? [...checkedValues, value]\n : checkedValues.filter((v) => v !== value);\n\n if (isAdding) {\n trackFilter('type');\n }\n\n if (lastTypeFilter && lastTypeFilter.kind === 'type') {\n if (nextValues.length === 0) {\n // Unchecking the final value removes the badge outright — a type\n // filter with no values is not a state (it would serialize to a\n // malformed `type:is:` the parser drops anyway).\n removeFilter(lastTypeIndex);\n } else {\n updateFilter(lastTypeIndex, { ...lastTypeFilter, values: nextValues });\n }\n } else if (nextValues.length > 0) {\n addFilter({ kind: 'type', condition: 'is', values: nextValues });\n }\n };\n\n // Creation date / Last modified are single-select (per design): selecting a\n // preset replaces the field's existing preset badge in place (keeping its\n // condition) rather than adding another pill; a badge is created only when the\n // field has none yet.\n const addPreset = (field: DateField, preset: DatePreset) => {\n // Fired before the replace path returns: swapping a field's preset is still\n // the user filtering, same as adding the badge in the first place.\n trackFilter(field);\n\n for (let i = filters.length - 1; i >= 0; i -= 1) {\n const f = filters[i];\n if (f.kind === 'date' && f.mode === 'preset' && f.field === field) {\n updateFilter(i, { ...f, preset });\n return;\n }\n }\n\n addFilter({ kind: 'date', field, mode: 'preset', condition: 'withinLast', preset });\n };\n\n const addRange = (from: string, to: string) => {\n trackFilter('createdAt');\n addFilter({ kind: 'date', field: 'createdAt', mode: 'range', condition: 'is', from, to });\n // The calendar is not a Menu.Item — close the menu explicitly on commit.\n setIsOpen(false);\n };\n\n const isMobile = useIsMobile();\n // Mobile accordion state: which field is expanded, and whether its date-range\n // calendar is open. Both reset when the whole menu closes.\n const [openField, setOpenField] = useState<'type' | 'createdAt' | 'updatedAt' | null>(null);\n const [rangeOpen, setRangeOpen] = useState(false);\n\n const handleOpenChange = (next: boolean) => {\n setIsOpen(next);\n if (!next) {\n setOpenField(null);\n setRangeOpen(false);\n }\n };\n\n const toggleField = (field: 'type' | 'createdAt' | 'updatedAt') => {\n setOpenField((current) => (current === field ? null : field));\n setRangeOpen(false);\n };\n\n // Option lists, shared by the desktop flyouts and the mobile accordion.\n // Multi-select semantics: menuitemcheckbox + aria-checked carry the state for\n // assistive tech; the Checkbox is purely decorative (aria-hidden, unfocusable)\n // — the Menu.Item is the control.\n const typeItems = TYPE_VALUES.map((value) => (\n <Menu.Item\n key={value}\n role=\"menuitemcheckbox\"\n aria-checked={checkedValues.includes(value)}\n onSelect={(e: Event) => {\n e.preventDefault();\n toggleTypeValue(value);\n }}\n startIcon={<Checkbox checked={checkedValues.includes(value)} tabIndex={-1} aria-hidden />}\n >\n {formatMessage(TYPE_LABELS[value])}\n </Menu.Item>\n ));\n\n // The field's currently-selected preset (single-select), so the menu can mark\n // it with a check.\n const selectedPresetForField = (field: DateField): DatePreset | null => {\n for (let i = filters.length - 1; i >= 0; i -= 1) {\n const f = filters[i];\n if (f.kind === 'date' && f.mode === 'preset' && f.field === field) {\n return f.preset;\n }\n }\n return null;\n };\n\n const presetItems = (field: DateField) => {\n const selected = selectedPresetForField(field);\n\n return DATE_PRESETS.map((preset) => (\n <Menu.Item\n key={preset}\n role=\"menuitemradio\"\n aria-checked={selected === preset}\n onSelect={() => {\n // No preventDefault, unlike Type: a date field holds exactly one\n // value, so the pick is complete and the menu closes on it. Type stays\n // open because the user may still be building up a multi-value set.\n addPreset(field, preset);\n }}\n endIcon={\n selected === preset ? (\n <Check aria-hidden width=\"1.6rem\" height=\"1.6rem\" fill=\"primary600\" />\n ) : null\n }\n >\n {formatMessage(PRESET_LABELS[preset])}\n </Menu.Item>\n ));\n };\n\n const typeLabel = formatMessage({\n id: getTranslationKey('list.filters.field.type'),\n defaultMessage: 'Type',\n });\n const selectDateRangeLabel = formatMessage({\n id: getTranslationKey('list.filters.select-date-range'),\n defaultMessage: 'Select date range',\n });\n\n return (\n <Menu.Root open={isOpen} onOpenChange={handleOpenChange}>\n {/* endIcon={null} drops the DS default chevron — the mock has none. */}\n <Menu.Trigger variant=\"tertiary\" startIcon={<FilterIcon aria-hidden />} endIcon={null}>\n <Flex gap={2} alignItems=\"center\" tag=\"span\">\n {formatMessage({\n id: getTranslationKey('list.filters.trigger'),\n defaultMessage: 'Filter',\n })}\n {filters.length > 0 && <CountBadge>{filters.length}</CountBadge>}\n </Flex>\n </Menu.Trigger>\n <Menu.Content\n popoverPlacement=\"bottom-start\"\n zIndex={2}\n maxHeight={PANEL_MAX_HEIGHT}\n width={isMobile ? MOBILE_PANEL_WIDTH : FILTER_PANEL_WIDTH}\n >\n {isMobile ? (\n // Mobile: one flat panel. Each field expands its options inline below\n // itself — Radix sub-menus can only fly out sideways, off a phone.\n <>\n <FieldToggle\n aria-expanded={openField === 'type'}\n onSelect={(e: Event) => {\n e.preventDefault();\n toggleField('type');\n }}\n endIcon={<Chevron $open={openField === 'type'} aria-hidden />}\n >\n {typeLabel}\n </FieldToggle>\n {openField === 'type' && <OptionGroup>{typeItems}</OptionGroup>}\n\n {(['createdAt', 'updatedAt'] as const).map((field) => (\n <Box key={field} width=\"100%\">\n <FieldToggle\n aria-expanded={openField === field}\n onSelect={(e: Event) => {\n e.preventDefault();\n toggleField(field);\n }}\n endIcon={<Chevron $open={openField === field} aria-hidden />}\n >\n {formatMessage(DATE_FIELD_LABELS[field])}\n </FieldToggle>\n {openField === field && (\n <OptionGroup>\n {presetItems(field)}\n {/* Only Creation date offers a range from the UI (design). */}\n {field === 'createdAt' && (\n <>\n <FieldToggle\n aria-expanded={rangeOpen}\n onSelect={(e: Event) => {\n e.preventDefault();\n setRangeOpen((open) => !open);\n }}\n endIcon={<Chevron $open={rangeOpen} aria-hidden />}\n >\n {selectDateRangeLabel}\n </FieldToggle>\n {rangeOpen && (\n <Box paddingLeft={2}>\n <DateRangeCalendar onSelect={addRange} />\n </Box>\n )}\n </>\n )}\n </OptionGroup>\n )}\n </Box>\n ))}\n </>\n ) : (\n <>\n <Menu.SubRoot>\n <FieldSubTrigger>{typeLabel}</FieldSubTrigger>\n <SubPanel zIndex={2} maxHeight={PANEL_MAX_HEIGHT} width={FILTER_PANEL_WIDTH}>\n {typeItems}\n </SubPanel>\n </Menu.SubRoot>\n\n {(['createdAt', 'updatedAt'] as const).map((field) => (\n <Menu.SubRoot key={field}>\n <FieldSubTrigger>{formatMessage(DATE_FIELD_LABELS[field])}</FieldSubTrigger>\n <SubPanel zIndex={2} maxHeight={PANEL_MAX_HEIGHT} width={FILTER_PANEL_WIDTH}>\n {presetItems(field)}\n {/* Design constraint: only Creation date offers a range from the\n UI. The URL codec and the badges support ranges on both date\n fields (`updated:rangeis:…` works when hand-crafted) so this\n stays a one-line change if design extends it later. */}\n {field === 'createdAt' && (\n <Menu.SubRoot>\n <FieldSubTrigger>{selectDateRangeLabel}</FieldSubTrigger>\n <SubPanel zIndex={2} maxHeight=\"none\" width={FILTER_PANEL_WIDTH}>\n <DateRangeCalendar onSelect={addRange} />\n </SubPanel>\n </Menu.SubRoot>\n )}\n </SubPanel>\n </Menu.SubRoot>\n ))}\n </>\n )}\n </Menu.Content>\n </Menu.Root>\n );\n};\n"],"names":["TYPE_LABELS","folder","id","getTranslationKey","defaultMessage","picture","audio","video","document","PRESET_LABELS","DATE_FIELD_LABELS","createdAt","updatedAt","FieldSubTrigger","styled","Menu","SubTrigger","FILTER_PANEL_WIDTH","PANEL_MAX_HEIGHT","MOBILE_PANEL_WIDTH","FieldToggle","Item","OptionGroup","Box","theme","spaces","Chevron","ChevronDown","$open","SubPanel","SubContent","CountBadge","Badge","FilterMenu","listFilters","formatMessage","useIntl","trackUsage","useTracking","isOpen","setIsOpen","useState","filters","addFilter","updateFilter","removeFilter","trackFilter","filter","location","MEDIA_LIBRARY_LOCATION","lastTypeIndex","i","length","kind","lastTypeFilter","checkedValues","values","toggleTypeValue","value","isAdding","includes","nextValues","v","condition","addPreset","field","preset","f","mode","addRange","from","to","isMobile","useIsMobile","openField","setOpenField","rangeOpen","setRangeOpen","handleOpenChange","next","toggleField","current","typeItems","TYPE_VALUES","map","_jsx","role","aria-checked","onSelect","e","preventDefault","startIcon","Checkbox","checked","tabIndex","aria-hidden","selectedPresetForField","presetItems","selected","DATE_PRESETS","endIcon","Check","width","height","fill","typeLabel","selectDateRangeLabel","_jsxs","Root","open","onOpenChange","Trigger","variant","FilterIcon","Flex","gap","alignItems","tag","Content","popoverPlacement","zIndex","maxHeight","_Fragment","aria-expanded","paddingLeft","DateRangeCalendar","SubRoot"],"mappings":"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"}
|
|
@@ -8,6 +8,7 @@ var icons = require('@strapi/icons');
|
|
|
8
8
|
var reactIntl = require('react-intl');
|
|
9
9
|
var translations = require('../../../utils/translations.js');
|
|
10
10
|
var useAssetSelection = require('../hooks/useAssetSelection.js');
|
|
11
|
+
var selection = require('../utils/selection.js');
|
|
11
12
|
var ActionsMenuContent = require('./ActionsMenuContent.js');
|
|
12
13
|
var BulkMoveDialog = require('./BulkMoveDialog.js');
|
|
13
14
|
var DeleteItemsDialog = require('./DeleteItemsDialog.js');
|
|
@@ -19,15 +20,16 @@ var FolderFormDialog = require('./FolderFormDialog.js');
|
|
|
19
20
|
* affordance). It reuses the shared move and delete dialogs, which mount only
|
|
20
21
|
* while open.
|
|
21
22
|
*
|
|
22
|
-
* A successful move or delete
|
|
23
|
-
* RTK tags, so without it a
|
|
24
|
-
*
|
|
25
|
-
*
|
|
23
|
+
* A successful move or delete deselects this one folder and leaves the rest of
|
|
24
|
+
* the selection intact: they only invalidate RTK tags, so without it a
|
|
25
|
+
* `folder:<id>` key for a folder that no longer lives where the selection thinks
|
|
26
|
+
* it does would linger. A rename leaves the id valid and the folder in place, so
|
|
27
|
+
* it touches the selection not at all.
|
|
26
28
|
*/ const FolderActionsMenu = ({ folder, dragData })=>{
|
|
27
29
|
const { formatMessage } = reactIntl.useIntl();
|
|
28
30
|
const { copy } = strapiAdmin.useClipboard();
|
|
29
31
|
const { toggleNotification } = strapiAdmin.useNotification();
|
|
30
|
-
const {
|
|
32
|
+
const { deselect } = useAssetSelection.useAssetSelection();
|
|
31
33
|
const [isRenameOpen, setIsRenameOpen] = React.useState(false);
|
|
32
34
|
const [isMoveOpen, setIsMoveOpen] = React.useState(false);
|
|
33
35
|
const [isDeleteOpen, setIsDeleteOpen] = React.useState(false);
|
|
@@ -123,7 +125,7 @@ var FolderFormDialog = require('./FolderFormDialog.js');
|
|
|
123
125
|
open: true,
|
|
124
126
|
onClose: ()=>setIsMoveOpen(false),
|
|
125
127
|
items: moveItems,
|
|
126
|
-
onSuccess:
|
|
128
|
+
onSuccess: ()=>deselect(selection.folderKey(folder.id))
|
|
127
129
|
}),
|
|
128
130
|
isDeleteOpen && /*#__PURE__*/ jsxRuntime.jsx(DeleteItemsDialog.DeleteItemsDialog, {
|
|
129
131
|
open: true,
|
|
@@ -134,7 +136,7 @@ var FolderFormDialog = require('./FolderFormDialog.js');
|
|
|
134
136
|
folder.id
|
|
135
137
|
]
|
|
136
138
|
},
|
|
137
|
-
onSuccess:
|
|
139
|
+
onSuccess: ()=>deselect(selection.folderKey(folder.id))
|
|
138
140
|
})
|
|
139
141
|
]
|
|
140
142
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FolderActionsMenu.js","sources":["../../../../../../admin/src/future/pages/Assets/components/FolderActionsMenu.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\n\nimport { useClipboard, useNotification } from '@strapi/admin/strapi-admin';\nimport { IconButton, Menu } from '@strapi/design-system';\nimport { ArrowRight, Link, More, Pencil, Trash } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { getTranslationKey } from '../../../utils/translations';\nimport { useAssetSelection } from '../hooks/useAssetSelection';\n\nimport { ActionsMenuContent } from './ActionsMenuContent';\nimport { BulkMoveDialog } from './BulkMoveDialog';\nimport { DeleteItemsDialog } from './DeleteItemsDialog';\nimport { FolderFormDialog } from './FolderFormDialog';\n\nimport type { Folder } from '../../../../../../shared/contracts/folders';\nimport type { DragFolderData } from '../../../types/dnd';\n\ninterface FolderActionsMenuProps {\n folder: Folder;\n /** Drag data for this folder, so the move dialog validates against its real parent. */\n dragData: DragFolderData;\n}\n\n/**\n * The \"...\" menu on a folder row/card. Always acts on that one folder, whatever\n * the current multi-selection is (the bulk actions bar is the selection-scoped\n * affordance). It reuses the shared move and delete dialogs, which mount only\n * while open.\n *\n * A successful move or delete clears the whole selection: they only invalidate\n * RTK tags, so without it a `folder:<id>` key for a folder that no longer lives\n * where the selection thinks it does would linger. A rename leaves the id\n * valid, so it deliberately keeps the selection.\n */\nexport const FolderActionsMenu = ({ folder, dragData }: FolderActionsMenuProps) => {\n const { formatMessage } = useIntl();\n const { copy } = useClipboard();\n const { toggleNotification } = useNotification();\n const { clear } = useAssetSelection();\n const [isRenameOpen, setIsRenameOpen] = useState(false);\n const [isMoveOpen, setIsMoveOpen] = useState(false);\n const [isDeleteOpen, setIsDeleteOpen] = useState(false);\n\n // Stable identity: the move dialog memoizes its destination walk on it.\n const moveItems = useMemo(() => [dragData], [dragData]);\n\n // Built from window.location so the link inherits whatever path the library is\n // mounted at. Every other query param (search, sort, open drawer) is dropped —\n // this is a clean deep-link to the folder.\n const handleCopyLink = async () => {\n const url = `${window.location.origin}${window.location.pathname}?folder=${folder.id}`;\n const didCopy = await copy(url);\n\n toggleNotification({\n type: didCopy ? 'success' : 'danger',\n message: formatMessage(\n didCopy\n ? {\n id: getTranslationKey('list.folder.actions.copy-link.success'),\n defaultMessage: 'Folder link copied.',\n }\n : {\n id: getTranslationKey('list.folder.actions.copy-link.error'),\n defaultMessage: 'Failed to copy the folder link.',\n }\n ),\n });\n };\n\n return (\n <>\n {/* See AssetActionsMenu: non-modal so clicking another row's trigger\n closes this menu and opens that one in a single click. */}\n <Menu.Root modal={false}>\n <Menu.Trigger\n tag={IconButton}\n icon={<More />}\n variant=\"ghost\"\n label={formatMessage({\n id: getTranslationKey('control-card.more-actions'),\n defaultMessage: 'More actions',\n })}\n />\n {/* See ActionsMenuContent: the design system's 15rem default clamps the\n menu against a hidden scrollbar, so items can be silently cut off\n near the viewport edge. This one is shorter, but kept in sync. */}\n <ActionsMenuContent popoverPlacement=\"bottom-end\" zIndex={2} minWidth=\"22rem\">\n <Menu.Item startIcon={<Link />} onSelect={handleCopyLink}>\n {formatMessage({\n id: getTranslationKey('list.folder.actions.copy-link'),\n defaultMessage: 'Copy link to folder',\n })}\n </Menu.Item>\n <Menu.Separator />\n {/* TODO: gate Rename, Move and Delete on `assets.canUpdate` CMS-387 */}\n <Menu.Item startIcon={<Pencil />} onSelect={() => setIsRenameOpen(true)}>\n {formatMessage({\n id: getTranslationKey('list.folder.actions.rename'),\n defaultMessage: 'Rename folder',\n })}\n </Menu.Item>\n <Menu.Item startIcon={<ArrowRight />} onSelect={() => setIsMoveOpen(true)}>\n {formatMessage({\n id: getTranslationKey('list.folder.actions.move'),\n defaultMessage: 'Move to folder',\n })}\n </Menu.Item>\n <Menu.Item startIcon={<Trash />} variant=\"danger\" onSelect={() => setIsDeleteOpen(true)}>\n {formatMessage({\n id: getTranslationKey('list.folder.actions.delete'),\n defaultMessage: 'Delete folder',\n })}\n </Menu.Item>\n </ActionsMenuContent>\n </Menu.Root>\n {/* These dialogs live inside the row, so a background refetch that drops\n the row would take an open dialog with it. Nothing invalidates until\n the mutation resolves, and the dialog closes in the same tick, so the\n flows themselves can't trigger it. */}\n {isRenameOpen && (\n <FolderFormDialog\n open\n mode=\"rename\"\n folderId={folder.id}\n initialName={folder.name}\n parentFolderId={dragData.parentId}\n onClose={() => setIsRenameOpen(false)}\n />\n )}\n {isMoveOpen && (\n <BulkMoveDialog\n open\n onClose={() => setIsMoveOpen(false)}\n items={moveItems}\n onSuccess={clear}\n />\n )}\n {isDeleteOpen && (\n <DeleteItemsDialog\n open\n onClose={() => setIsDeleteOpen(false)}\n target={{ fileIds: [], folderIds: [folder.id] }}\n onSuccess={clear}\n />\n )}\n </>\n );\n};\n"],"names":["FolderActionsMenu","folder","dragData","formatMessage","useIntl","copy","useClipboard","toggleNotification","useNotification","clear","useAssetSelection","isRenameOpen","setIsRenameOpen","useState","isMoveOpen","setIsMoveOpen","isDeleteOpen","setIsDeleteOpen","moveItems","useMemo","handleCopyLink","url","window","location","origin","pathname","id","didCopy","type","message","getTranslationKey","defaultMessage","_jsxs","_Fragment","Menu","Root","modal","_jsx","Trigger","tag","IconButton","icon","More","variant","label","ActionsMenuContent","popoverPlacement","zIndex","minWidth","Item","startIcon","Link","onSelect","Separator","Pencil","ArrowRight","Trash","FolderFormDialog","open","mode","folderId","initialName","name","parentFolderId","parentId","onClose","BulkMoveDialog","items","onSuccess","DeleteItemsDialog","target","fileIds","folderIds"],"mappings":";;;;;;;;;;;;;;;AAwBA;;;;;;;;;;UAWaA,iBAAAA,GAAoB,CAAC,EAAEC,MAAM,EAAEC,QAAQ,EAA0B,GAAA;IAC5E,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;IAC1B,MAAM,EAAEC,IAAI,EAAE,GAAGC,wBAAAA,EAAAA;IACjB,MAAM,EAAEC,kBAAkB,EAAE,GAAGC,2BAAAA,EAAAA;IAC/B,MAAM,EAAEC,KAAK,EAAE,GAAGC,mCAAAA,EAAAA;AAClB,IAAA,MAAM,CAACC,YAAAA,EAAcC,eAAAA,CAAgB,GAAGC,cAAAA,CAAS,KAAA,CAAA;AACjD,IAAA,MAAM,CAACC,UAAAA,EAAYC,aAAAA,CAAc,GAAGF,cAAAA,CAAS,KAAA,CAAA;AAC7C,IAAA,MAAM,CAACG,YAAAA,EAAcC,eAAAA,CAAgB,GAAGJ,cAAAA,CAAS,KAAA,CAAA;;IAGjD,MAAMK,SAAAA,GAAYC,cAAQ,IAAM;AAACjB,YAAAA;SAAS,EAAE;AAACA,QAAAA;AAAS,KAAA,CAAA;;;;AAKtD,IAAA,MAAMkB,cAAAA,GAAiB,UAAA;AACrB,QAAA,MAAMC,MAAM,CAAA,EAAGC,MAAAA,CAAOC,QAAQ,CAACC,MAAM,CAAA,EAAGF,MAAAA,CAAOC,QAAQ,CAACE,QAAQ,CAAC,QAAQ,EAAExB,MAAAA,CAAOyB,EAAE,CAAA,CAAE;QACtF,MAAMC,OAAAA,GAAU,MAAMtB,IAAAA,CAAKgB,GAAAA,CAAAA;QAE3Bd,kBAAAA,CAAmB;AACjBqB,YAAAA,IAAAA,EAAMD,UAAU,SAAA,GAAY,QAAA;AAC5BE,YAAAA,OAAAA,EAAS1B,cACPwB,OAAAA,GACI;AACED,gBAAAA,EAAAA,EAAII,8BAAAA,CAAkB,uCAAA,CAAA;gBACtBC,cAAAA,EAAgB;aAClB,GACA;AACEL,gBAAAA,EAAAA,EAAII,8BAAAA,CAAkB,qCAAA,CAAA;gBACtBC,cAAAA,EAAgB;AAClB,aAAA;AAER,SAAA,CAAA;AACF,IAAA,CAAA;IAEA,qBACEC,eAAA,CAAAC,mBAAA,EAAA;;AAGE,0BAAAD,eAAA,CAACE,kBAAKC,IAAI,EAAA;gBAACC,KAAAA,EAAO,KAAA;;AAChB,kCAAAC,cAAA,CAACH,kBAAKI,OAAO,EAAA;wBACXC,GAAAA,EAAKC,uBAAAA;AACLC,wBAAAA,IAAAA,gBAAMJ,cAAA,CAACK,UAAAA,EAAAA,EAAAA,CAAAA;wBACPC,OAAAA,EAAQ,OAAA;AACRC,wBAAAA,KAAAA,EAAOzC,aAAAA,CAAc;AACnBuB,4BAAAA,EAAAA,EAAII,8BAAAA,CAAkB,2BAAA,CAAA;4BACtBC,cAAAA,EAAgB;AAClB,yBAAA;;kCAKFC,eAAA,CAACa,qCAAAA,EAAAA;wBAAmBC,gBAAAA,EAAiB,YAAA;wBAAaC,MAAAA,EAAQ,CAAA;wBAAGC,QAAAA,EAAS,OAAA;;AACpE,0CAAAX,cAAA,CAACH,kBAAKe,IAAI,EAAA;AAACC,gCAAAA,SAAAA,gBAAWb,cAAA,CAACc,UAAAA,EAAAA,EAAAA,CAAAA;gCAASC,QAAAA,EAAUhC,cAAAA;0CACvCjB,aAAAA,CAAc;AACbuB,oCAAAA,EAAAA,EAAII,8BAAAA,CAAkB,+BAAA,CAAA;oCACtBC,cAAAA,EAAgB;AAClB,iCAAA;;AAEF,0CAAAM,cAAA,CAACH,kBAAKmB,SAAS,EAAA,EAAA,CAAA;AAEf,0CAAAhB,cAAA,CAACH,kBAAKe,IAAI,EAAA;AAACC,gCAAAA,SAAAA,gBAAWb,cAAA,CAACiB,YAAAA,EAAAA,EAAAA,CAAAA;AAAWF,gCAAAA,QAAAA,EAAU,IAAMxC,eAAAA,CAAgB,IAAA,CAAA;0CAC/DT,aAAAA,CAAc;AACbuB,oCAAAA,EAAAA,EAAII,8BAAAA,CAAkB,4BAAA,CAAA;oCACtBC,cAAAA,EAAgB;AAClB,iCAAA;;AAEF,0CAAAM,cAAA,CAACH,kBAAKe,IAAI,EAAA;AAACC,gCAAAA,SAAAA,gBAAWb,cAAA,CAACkB,gBAAAA,EAAAA,EAAAA,CAAAA;AAAeH,gCAAAA,QAAAA,EAAU,IAAMrC,aAAAA,CAAc,IAAA,CAAA;0CACjEZ,aAAAA,CAAc;AACbuB,oCAAAA,EAAAA,EAAII,8BAAAA,CAAkB,0BAAA,CAAA;oCACtBC,cAAAA,EAAgB;AAClB,iCAAA;;AAEF,0CAAAM,cAAA,CAACH,kBAAKe,IAAI,EAAA;AAACC,gCAAAA,SAAAA,gBAAWb,cAAA,CAACmB,WAAAA,EAAAA,EAAAA,CAAAA;gCAAUb,OAAAA,EAAQ,QAAA;AAASS,gCAAAA,QAAAA,EAAU,IAAMnC,eAAAA,CAAgB,IAAA,CAAA;0CAC/Ed,aAAAA,CAAc;AACbuB,oCAAAA,EAAAA,EAAII,8BAAAA,CAAkB,4BAAA,CAAA;oCACtBC,cAAAA,EAAgB;AAClB,iCAAA;;;;;;AAQLpB,YAAAA,YAAAA,kBACC0B,cAAA,CAACoB,iCAAAA,EAAAA;gBACCC,IAAI,EAAA,IAAA;gBACJC,IAAAA,EAAK,QAAA;AACLC,gBAAAA,QAAAA,EAAU3D,OAAOyB,EAAE;AACnBmC,gBAAAA,WAAAA,EAAa5D,OAAO6D,IAAI;AACxBC,gBAAAA,cAAAA,EAAgB7D,SAAS8D,QAAQ;AACjCC,gBAAAA,OAAAA,EAAS,IAAMrD,eAAAA,CAAgB,KAAA;;AAGlCE,YAAAA,UAAAA,kBACCuB,cAAA,CAAC6B,6BAAAA,EAAAA;gBACCR,IAAI,EAAA,IAAA;AACJO,gBAAAA,OAAAA,EAAS,IAAMlD,aAAAA,CAAc,KAAA,CAAA;gBAC7BoD,KAAAA,EAAOjD,SAAAA;gBACPkD,SAAAA,EAAW3D;;AAGdO,YAAAA,YAAAA,kBACCqB,cAAA,CAACgC,mCAAAA,EAAAA;gBACCX,IAAI,EAAA,IAAA;AACJO,gBAAAA,OAAAA,EAAS,IAAMhD,eAAAA,CAAgB,KAAA,CAAA;gBAC/BqD,MAAAA,EAAQ;AAAEC,oBAAAA,OAAAA,EAAS,EAAE;oBAAEC,SAAAA,EAAW;AAACvE,wBAAAA,MAAAA,CAAOyB;AAAG;AAAC,iBAAA;gBAC9C0C,SAAAA,EAAW3D;;;;AAKrB;;;;"}
|
|
1
|
+
{"version":3,"file":"FolderActionsMenu.js","sources":["../../../../../../admin/src/future/pages/Assets/components/FolderActionsMenu.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\n\nimport { useClipboard, useNotification } from '@strapi/admin/strapi-admin';\nimport { IconButton, Menu } from '@strapi/design-system';\nimport { ArrowRight, Link, More, Pencil, Trash } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { getTranslationKey } from '../../../utils/translations';\nimport { useAssetSelection } from '../hooks/useAssetSelection';\nimport { folderKey } from '../utils/selection';\n\nimport { ActionsMenuContent } from './ActionsMenuContent';\nimport { BulkMoveDialog } from './BulkMoveDialog';\nimport { DeleteItemsDialog } from './DeleteItemsDialog';\nimport { FolderFormDialog } from './FolderFormDialog';\n\nimport type { Folder } from '../../../../../../shared/contracts/folders';\nimport type { DragFolderData } from '../../../types/dnd';\n\ninterface FolderActionsMenuProps {\n folder: Folder;\n /** Drag data for this folder, so the move dialog validates against its real parent. */\n dragData: DragFolderData;\n}\n\n/**\n * The \"...\" menu on a folder row/card. Always acts on that one folder, whatever\n * the current multi-selection is (the bulk actions bar is the selection-scoped\n * affordance). It reuses the shared move and delete dialogs, which mount only\n * while open.\n *\n * A successful move or delete deselects this one folder and leaves the rest of\n * the selection intact: they only invalidate RTK tags, so without it a\n * `folder:<id>` key for a folder that no longer lives where the selection thinks\n * it does would linger. A rename leaves the id valid and the folder in place, so\n * it touches the selection not at all.\n */\nexport const FolderActionsMenu = ({ folder, dragData }: FolderActionsMenuProps) => {\n const { formatMessage } = useIntl();\n const { copy } = useClipboard();\n const { toggleNotification } = useNotification();\n const { deselect } = useAssetSelection();\n const [isRenameOpen, setIsRenameOpen] = useState(false);\n const [isMoveOpen, setIsMoveOpen] = useState(false);\n const [isDeleteOpen, setIsDeleteOpen] = useState(false);\n\n // Stable identity: the move dialog memoizes its destination walk on it.\n const moveItems = useMemo(() => [dragData], [dragData]);\n\n // Built from window.location so the link inherits whatever path the library is\n // mounted at. Every other query param (search, sort, open drawer) is dropped —\n // this is a clean deep-link to the folder.\n const handleCopyLink = async () => {\n const url = `${window.location.origin}${window.location.pathname}?folder=${folder.id}`;\n const didCopy = await copy(url);\n\n toggleNotification({\n type: didCopy ? 'success' : 'danger',\n message: formatMessage(\n didCopy\n ? {\n id: getTranslationKey('list.folder.actions.copy-link.success'),\n defaultMessage: 'Folder link copied.',\n }\n : {\n id: getTranslationKey('list.folder.actions.copy-link.error'),\n defaultMessage: 'Failed to copy the folder link.',\n }\n ),\n });\n };\n\n return (\n <>\n {/* See AssetActionsMenu: non-modal so clicking another row's trigger\n closes this menu and opens that one in a single click. */}\n <Menu.Root modal={false}>\n <Menu.Trigger\n tag={IconButton}\n icon={<More />}\n variant=\"ghost\"\n label={formatMessage({\n id: getTranslationKey('control-card.more-actions'),\n defaultMessage: 'More actions',\n })}\n />\n {/* See ActionsMenuContent: the design system's 15rem default clamps the\n menu against a hidden scrollbar, so items can be silently cut off\n near the viewport edge. This one is shorter, but kept in sync. */}\n <ActionsMenuContent popoverPlacement=\"bottom-end\" zIndex={2} minWidth=\"22rem\">\n <Menu.Item startIcon={<Link />} onSelect={handleCopyLink}>\n {formatMessage({\n id: getTranslationKey('list.folder.actions.copy-link'),\n defaultMessage: 'Copy link to folder',\n })}\n </Menu.Item>\n <Menu.Separator />\n {/* TODO: gate Rename, Move and Delete on `assets.canUpdate` CMS-387 */}\n <Menu.Item startIcon={<Pencil />} onSelect={() => setIsRenameOpen(true)}>\n {formatMessage({\n id: getTranslationKey('list.folder.actions.rename'),\n defaultMessage: 'Rename folder',\n })}\n </Menu.Item>\n <Menu.Item startIcon={<ArrowRight />} onSelect={() => setIsMoveOpen(true)}>\n {formatMessage({\n id: getTranslationKey('list.folder.actions.move'),\n defaultMessage: 'Move to folder',\n })}\n </Menu.Item>\n <Menu.Item startIcon={<Trash />} variant=\"danger\" onSelect={() => setIsDeleteOpen(true)}>\n {formatMessage({\n id: getTranslationKey('list.folder.actions.delete'),\n defaultMessage: 'Delete folder',\n })}\n </Menu.Item>\n </ActionsMenuContent>\n </Menu.Root>\n {/* These dialogs live inside the row, so a background refetch that drops\n the row would take an open dialog with it. Nothing invalidates until\n the mutation resolves, and the dialog closes in the same tick, so the\n flows themselves can't trigger it. */}\n {isRenameOpen && (\n <FolderFormDialog\n open\n mode=\"rename\"\n folderId={folder.id}\n initialName={folder.name}\n parentFolderId={dragData.parentId}\n onClose={() => setIsRenameOpen(false)}\n />\n )}\n {isMoveOpen && (\n <BulkMoveDialog\n open\n onClose={() => setIsMoveOpen(false)}\n items={moveItems}\n onSuccess={() => deselect(folderKey(folder.id))}\n />\n )}\n {isDeleteOpen && (\n <DeleteItemsDialog\n open\n onClose={() => setIsDeleteOpen(false)}\n target={{ fileIds: [], folderIds: [folder.id] }}\n onSuccess={() => deselect(folderKey(folder.id))}\n />\n )}\n </>\n );\n};\n"],"names":["FolderActionsMenu","folder","dragData","formatMessage","useIntl","copy","useClipboard","toggleNotification","useNotification","deselect","useAssetSelection","isRenameOpen","setIsRenameOpen","useState","isMoveOpen","setIsMoveOpen","isDeleteOpen","setIsDeleteOpen","moveItems","useMemo","handleCopyLink","url","window","location","origin","pathname","id","didCopy","type","message","getTranslationKey","defaultMessage","_jsxs","_Fragment","Menu","Root","modal","_jsx","Trigger","tag","IconButton","icon","More","variant","label","ActionsMenuContent","popoverPlacement","zIndex","minWidth","Item","startIcon","Link","onSelect","Separator","Pencil","ArrowRight","Trash","FolderFormDialog","open","mode","folderId","initialName","name","parentFolderId","parentId","onClose","BulkMoveDialog","items","onSuccess","folderKey","DeleteItemsDialog","target","fileIds","folderIds"],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ import { More, Link, Pencil, ArrowRight, Trash } from '@strapi/icons';
|
|
|
6
6
|
import { useIntl } from 'react-intl';
|
|
7
7
|
import { getTranslationKey } from '../../../utils/translations.mjs';
|
|
8
8
|
import { useAssetSelection } from '../hooks/useAssetSelection.mjs';
|
|
9
|
+
import { folderKey } from '../utils/selection.mjs';
|
|
9
10
|
import { ActionsMenuContent } from './ActionsMenuContent.mjs';
|
|
10
11
|
import { BulkMoveDialog } from './BulkMoveDialog.mjs';
|
|
11
12
|
import { DeleteItemsDialog } from './DeleteItemsDialog.mjs';
|
|
@@ -17,15 +18,16 @@ import { FolderFormDialog } from './FolderFormDialog.mjs';
|
|
|
17
18
|
* affordance). It reuses the shared move and delete dialogs, which mount only
|
|
18
19
|
* while open.
|
|
19
20
|
*
|
|
20
|
-
* A successful move or delete
|
|
21
|
-
* RTK tags, so without it a
|
|
22
|
-
*
|
|
23
|
-
*
|
|
21
|
+
* A successful move or delete deselects this one folder and leaves the rest of
|
|
22
|
+
* the selection intact: they only invalidate RTK tags, so without it a
|
|
23
|
+
* `folder:<id>` key for a folder that no longer lives where the selection thinks
|
|
24
|
+
* it does would linger. A rename leaves the id valid and the folder in place, so
|
|
25
|
+
* it touches the selection not at all.
|
|
24
26
|
*/ const FolderActionsMenu = ({ folder, dragData })=>{
|
|
25
27
|
const { formatMessage } = useIntl();
|
|
26
28
|
const { copy } = useClipboard();
|
|
27
29
|
const { toggleNotification } = useNotification();
|
|
28
|
-
const {
|
|
30
|
+
const { deselect } = useAssetSelection();
|
|
29
31
|
const [isRenameOpen, setIsRenameOpen] = useState(false);
|
|
30
32
|
const [isMoveOpen, setIsMoveOpen] = useState(false);
|
|
31
33
|
const [isDeleteOpen, setIsDeleteOpen] = useState(false);
|
|
@@ -121,7 +123,7 @@ import { FolderFormDialog } from './FolderFormDialog.mjs';
|
|
|
121
123
|
open: true,
|
|
122
124
|
onClose: ()=>setIsMoveOpen(false),
|
|
123
125
|
items: moveItems,
|
|
124
|
-
onSuccess:
|
|
126
|
+
onSuccess: ()=>deselect(folderKey(folder.id))
|
|
125
127
|
}),
|
|
126
128
|
isDeleteOpen && /*#__PURE__*/ jsx(DeleteItemsDialog, {
|
|
127
129
|
open: true,
|
|
@@ -132,7 +134,7 @@ import { FolderFormDialog } from './FolderFormDialog.mjs';
|
|
|
132
134
|
folder.id
|
|
133
135
|
]
|
|
134
136
|
},
|
|
135
|
-
onSuccess:
|
|
137
|
+
onSuccess: ()=>deselect(folderKey(folder.id))
|
|
136
138
|
})
|
|
137
139
|
]
|
|
138
140
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FolderActionsMenu.mjs","sources":["../../../../../../admin/src/future/pages/Assets/components/FolderActionsMenu.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\n\nimport { useClipboard, useNotification } from '@strapi/admin/strapi-admin';\nimport { IconButton, Menu } from '@strapi/design-system';\nimport { ArrowRight, Link, More, Pencil, Trash } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { getTranslationKey } from '../../../utils/translations';\nimport { useAssetSelection } from '../hooks/useAssetSelection';\n\nimport { ActionsMenuContent } from './ActionsMenuContent';\nimport { BulkMoveDialog } from './BulkMoveDialog';\nimport { DeleteItemsDialog } from './DeleteItemsDialog';\nimport { FolderFormDialog } from './FolderFormDialog';\n\nimport type { Folder } from '../../../../../../shared/contracts/folders';\nimport type { DragFolderData } from '../../../types/dnd';\n\ninterface FolderActionsMenuProps {\n folder: Folder;\n /** Drag data for this folder, so the move dialog validates against its real parent. */\n dragData: DragFolderData;\n}\n\n/**\n * The \"...\" menu on a folder row/card. Always acts on that one folder, whatever\n * the current multi-selection is (the bulk actions bar is the selection-scoped\n * affordance). It reuses the shared move and delete dialogs, which mount only\n * while open.\n *\n * A successful move or delete clears the whole selection: they only invalidate\n * RTK tags, so without it a `folder:<id>` key for a folder that no longer lives\n * where the selection thinks it does would linger. A rename leaves the id\n * valid, so it deliberately keeps the selection.\n */\nexport const FolderActionsMenu = ({ folder, dragData }: FolderActionsMenuProps) => {\n const { formatMessage } = useIntl();\n const { copy } = useClipboard();\n const { toggleNotification } = useNotification();\n const { clear } = useAssetSelection();\n const [isRenameOpen, setIsRenameOpen] = useState(false);\n const [isMoveOpen, setIsMoveOpen] = useState(false);\n const [isDeleteOpen, setIsDeleteOpen] = useState(false);\n\n // Stable identity: the move dialog memoizes its destination walk on it.\n const moveItems = useMemo(() => [dragData], [dragData]);\n\n // Built from window.location so the link inherits whatever path the library is\n // mounted at. Every other query param (search, sort, open drawer) is dropped —\n // this is a clean deep-link to the folder.\n const handleCopyLink = async () => {\n const url = `${window.location.origin}${window.location.pathname}?folder=${folder.id}`;\n const didCopy = await copy(url);\n\n toggleNotification({\n type: didCopy ? 'success' : 'danger',\n message: formatMessage(\n didCopy\n ? {\n id: getTranslationKey('list.folder.actions.copy-link.success'),\n defaultMessage: 'Folder link copied.',\n }\n : {\n id: getTranslationKey('list.folder.actions.copy-link.error'),\n defaultMessage: 'Failed to copy the folder link.',\n }\n ),\n });\n };\n\n return (\n <>\n {/* See AssetActionsMenu: non-modal so clicking another row's trigger\n closes this menu and opens that one in a single click. */}\n <Menu.Root modal={false}>\n <Menu.Trigger\n tag={IconButton}\n icon={<More />}\n variant=\"ghost\"\n label={formatMessage({\n id: getTranslationKey('control-card.more-actions'),\n defaultMessage: 'More actions',\n })}\n />\n {/* See ActionsMenuContent: the design system's 15rem default clamps the\n menu against a hidden scrollbar, so items can be silently cut off\n near the viewport edge. This one is shorter, but kept in sync. */}\n <ActionsMenuContent popoverPlacement=\"bottom-end\" zIndex={2} minWidth=\"22rem\">\n <Menu.Item startIcon={<Link />} onSelect={handleCopyLink}>\n {formatMessage({\n id: getTranslationKey('list.folder.actions.copy-link'),\n defaultMessage: 'Copy link to folder',\n })}\n </Menu.Item>\n <Menu.Separator />\n {/* TODO: gate Rename, Move and Delete on `assets.canUpdate` CMS-387 */}\n <Menu.Item startIcon={<Pencil />} onSelect={() => setIsRenameOpen(true)}>\n {formatMessage({\n id: getTranslationKey('list.folder.actions.rename'),\n defaultMessage: 'Rename folder',\n })}\n </Menu.Item>\n <Menu.Item startIcon={<ArrowRight />} onSelect={() => setIsMoveOpen(true)}>\n {formatMessage({\n id: getTranslationKey('list.folder.actions.move'),\n defaultMessage: 'Move to folder',\n })}\n </Menu.Item>\n <Menu.Item startIcon={<Trash />} variant=\"danger\" onSelect={() => setIsDeleteOpen(true)}>\n {formatMessage({\n id: getTranslationKey('list.folder.actions.delete'),\n defaultMessage: 'Delete folder',\n })}\n </Menu.Item>\n </ActionsMenuContent>\n </Menu.Root>\n {/* These dialogs live inside the row, so a background refetch that drops\n the row would take an open dialog with it. Nothing invalidates until\n the mutation resolves, and the dialog closes in the same tick, so the\n flows themselves can't trigger it. */}\n {isRenameOpen && (\n <FolderFormDialog\n open\n mode=\"rename\"\n folderId={folder.id}\n initialName={folder.name}\n parentFolderId={dragData.parentId}\n onClose={() => setIsRenameOpen(false)}\n />\n )}\n {isMoveOpen && (\n <BulkMoveDialog\n open\n onClose={() => setIsMoveOpen(false)}\n items={moveItems}\n onSuccess={clear}\n />\n )}\n {isDeleteOpen && (\n <DeleteItemsDialog\n open\n onClose={() => setIsDeleteOpen(false)}\n target={{ fileIds: [], folderIds: [folder.id] }}\n onSuccess={clear}\n />\n )}\n </>\n );\n};\n"],"names":["FolderActionsMenu","folder","dragData","formatMessage","useIntl","copy","useClipboard","toggleNotification","useNotification","clear","useAssetSelection","isRenameOpen","setIsRenameOpen","useState","isMoveOpen","setIsMoveOpen","isDeleteOpen","setIsDeleteOpen","moveItems","useMemo","handleCopyLink","url","window","location","origin","pathname","id","didCopy","type","message","getTranslationKey","defaultMessage","_jsxs","_Fragment","Menu","Root","modal","_jsx","Trigger","tag","IconButton","icon","More","variant","label","ActionsMenuContent","popoverPlacement","zIndex","minWidth","Item","startIcon","Link","onSelect","Separator","Pencil","ArrowRight","Trash","FolderFormDialog","open","mode","folderId","initialName","name","parentFolderId","parentId","onClose","BulkMoveDialog","items","onSuccess","DeleteItemsDialog","target","fileIds","folderIds"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FolderActionsMenu.mjs","sources":["../../../../../../admin/src/future/pages/Assets/components/FolderActionsMenu.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\n\nimport { useClipboard, useNotification } from '@strapi/admin/strapi-admin';\nimport { IconButton, Menu } from '@strapi/design-system';\nimport { ArrowRight, Link, More, Pencil, Trash } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { getTranslationKey } from '../../../utils/translations';\nimport { useAssetSelection } from '../hooks/useAssetSelection';\nimport { folderKey } from '../utils/selection';\n\nimport { ActionsMenuContent } from './ActionsMenuContent';\nimport { BulkMoveDialog } from './BulkMoveDialog';\nimport { DeleteItemsDialog } from './DeleteItemsDialog';\nimport { FolderFormDialog } from './FolderFormDialog';\n\nimport type { Folder } from '../../../../../../shared/contracts/folders';\nimport type { DragFolderData } from '../../../types/dnd';\n\ninterface FolderActionsMenuProps {\n folder: Folder;\n /** Drag data for this folder, so the move dialog validates against its real parent. */\n dragData: DragFolderData;\n}\n\n/**\n * The \"...\" menu on a folder row/card. Always acts on that one folder, whatever\n * the current multi-selection is (the bulk actions bar is the selection-scoped\n * affordance). It reuses the shared move and delete dialogs, which mount only\n * while open.\n *\n * A successful move or delete deselects this one folder and leaves the rest of\n * the selection intact: they only invalidate RTK tags, so without it a\n * `folder:<id>` key for a folder that no longer lives where the selection thinks\n * it does would linger. A rename leaves the id valid and the folder in place, so\n * it touches the selection not at all.\n */\nexport const FolderActionsMenu = ({ folder, dragData }: FolderActionsMenuProps) => {\n const { formatMessage } = useIntl();\n const { copy } = useClipboard();\n const { toggleNotification } = useNotification();\n const { deselect } = useAssetSelection();\n const [isRenameOpen, setIsRenameOpen] = useState(false);\n const [isMoveOpen, setIsMoveOpen] = useState(false);\n const [isDeleteOpen, setIsDeleteOpen] = useState(false);\n\n // Stable identity: the move dialog memoizes its destination walk on it.\n const moveItems = useMemo(() => [dragData], [dragData]);\n\n // Built from window.location so the link inherits whatever path the library is\n // mounted at. Every other query param (search, sort, open drawer) is dropped —\n // this is a clean deep-link to the folder.\n const handleCopyLink = async () => {\n const url = `${window.location.origin}${window.location.pathname}?folder=${folder.id}`;\n const didCopy = await copy(url);\n\n toggleNotification({\n type: didCopy ? 'success' : 'danger',\n message: formatMessage(\n didCopy\n ? {\n id: getTranslationKey('list.folder.actions.copy-link.success'),\n defaultMessage: 'Folder link copied.',\n }\n : {\n id: getTranslationKey('list.folder.actions.copy-link.error'),\n defaultMessage: 'Failed to copy the folder link.',\n }\n ),\n });\n };\n\n return (\n <>\n {/* See AssetActionsMenu: non-modal so clicking another row's trigger\n closes this menu and opens that one in a single click. */}\n <Menu.Root modal={false}>\n <Menu.Trigger\n tag={IconButton}\n icon={<More />}\n variant=\"ghost\"\n label={formatMessage({\n id: getTranslationKey('control-card.more-actions'),\n defaultMessage: 'More actions',\n })}\n />\n {/* See ActionsMenuContent: the design system's 15rem default clamps the\n menu against a hidden scrollbar, so items can be silently cut off\n near the viewport edge. This one is shorter, but kept in sync. */}\n <ActionsMenuContent popoverPlacement=\"bottom-end\" zIndex={2} minWidth=\"22rem\">\n <Menu.Item startIcon={<Link />} onSelect={handleCopyLink}>\n {formatMessage({\n id: getTranslationKey('list.folder.actions.copy-link'),\n defaultMessage: 'Copy link to folder',\n })}\n </Menu.Item>\n <Menu.Separator />\n {/* TODO: gate Rename, Move and Delete on `assets.canUpdate` CMS-387 */}\n <Menu.Item startIcon={<Pencil />} onSelect={() => setIsRenameOpen(true)}>\n {formatMessage({\n id: getTranslationKey('list.folder.actions.rename'),\n defaultMessage: 'Rename folder',\n })}\n </Menu.Item>\n <Menu.Item startIcon={<ArrowRight />} onSelect={() => setIsMoveOpen(true)}>\n {formatMessage({\n id: getTranslationKey('list.folder.actions.move'),\n defaultMessage: 'Move to folder',\n })}\n </Menu.Item>\n <Menu.Item startIcon={<Trash />} variant=\"danger\" onSelect={() => setIsDeleteOpen(true)}>\n {formatMessage({\n id: getTranslationKey('list.folder.actions.delete'),\n defaultMessage: 'Delete folder',\n })}\n </Menu.Item>\n </ActionsMenuContent>\n </Menu.Root>\n {/* These dialogs live inside the row, so a background refetch that drops\n the row would take an open dialog with it. Nothing invalidates until\n the mutation resolves, and the dialog closes in the same tick, so the\n flows themselves can't trigger it. */}\n {isRenameOpen && (\n <FolderFormDialog\n open\n mode=\"rename\"\n folderId={folder.id}\n initialName={folder.name}\n parentFolderId={dragData.parentId}\n onClose={() => setIsRenameOpen(false)}\n />\n )}\n {isMoveOpen && (\n <BulkMoveDialog\n open\n onClose={() => setIsMoveOpen(false)}\n items={moveItems}\n onSuccess={() => deselect(folderKey(folder.id))}\n />\n )}\n {isDeleteOpen && (\n <DeleteItemsDialog\n open\n onClose={() => setIsDeleteOpen(false)}\n target={{ fileIds: [], folderIds: [folder.id] }}\n onSuccess={() => deselect(folderKey(folder.id))}\n />\n )}\n </>\n );\n};\n"],"names":["FolderActionsMenu","folder","dragData","formatMessage","useIntl","copy","useClipboard","toggleNotification","useNotification","deselect","useAssetSelection","isRenameOpen","setIsRenameOpen","useState","isMoveOpen","setIsMoveOpen","isDeleteOpen","setIsDeleteOpen","moveItems","useMemo","handleCopyLink","url","window","location","origin","pathname","id","didCopy","type","message","getTranslationKey","defaultMessage","_jsxs","_Fragment","Menu","Root","modal","_jsx","Trigger","tag","IconButton","icon","More","variant","label","ActionsMenuContent","popoverPlacement","zIndex","minWidth","Item","startIcon","Link","onSelect","Separator","Pencil","ArrowRight","Trash","FolderFormDialog","open","mode","folderId","initialName","name","parentFolderId","parentId","onClose","BulkMoveDialog","items","onSuccess","folderKey","DeleteItemsDialog","target","fileIds","folderIds"],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ var strapiAdmin = require('@strapi/admin/strapi-admin');
|
|
|
6
6
|
var designSystem = require('@strapi/design-system');
|
|
7
7
|
var reactIntl = require('react-intl');
|
|
8
8
|
var styledComponents = require('styled-components');
|
|
9
|
+
var useTracking = require('../../../hooks/useTracking.js');
|
|
9
10
|
var folders = require('../../../services/folders.js');
|
|
10
11
|
var translations = require('../../../utils/translations.js');
|
|
11
12
|
|
|
@@ -17,6 +18,7 @@ const FolderFormDialog = (props)=>{
|
|
|
17
18
|
const initialName = props.mode === 'rename' ? props.initialName : '';
|
|
18
19
|
const { formatMessage } = reactIntl.useIntl();
|
|
19
20
|
const { toggleNotification } = strapiAdmin.useNotification();
|
|
21
|
+
const { trackUsage } = useTracking.useTracking();
|
|
20
22
|
const [name, setName] = React.useState(initialName);
|
|
21
23
|
const [fieldError, setFieldError] = React.useState();
|
|
22
24
|
const inputRef = React.useRef(null);
|
|
@@ -55,11 +57,21 @@ const FolderFormDialog = (props)=>{
|
|
|
55
57
|
name: trimmedName,
|
|
56
58
|
parent: parentFolderId
|
|
57
59
|
}).unwrap();
|
|
60
|
+
// Matches the legacy folder-edit payload. This dialog only renames
|
|
61
|
+
// (parent is fixed), so the location never changes here.
|
|
62
|
+
trackUsage('didEditMediaLibraryElements', {
|
|
63
|
+
location: useTracking.MEDIA_LIBRARY_LOCATION,
|
|
64
|
+
type: 'folder',
|
|
65
|
+
changeLocation: false
|
|
66
|
+
});
|
|
58
67
|
} else {
|
|
59
68
|
await createFolder({
|
|
60
69
|
name: trimmedName,
|
|
61
70
|
parent: parentFolderId
|
|
62
71
|
}).unwrap();
|
|
72
|
+
trackUsage('didAddMediaLibraryFolders', {
|
|
73
|
+
location: useTracking.MEDIA_LIBRARY_LOCATION
|
|
74
|
+
});
|
|
63
75
|
}
|
|
64
76
|
toggleNotification({
|
|
65
77
|
type: 'success',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FolderFormDialog.js","sources":["../../../../../../admin/src/future/pages/Assets/components/FolderFormDialog.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\n\nimport { useNotification } from '@strapi/admin/strapi-admin';\nimport { Button, Field, Flex, Modal, TextInput } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useCreateFolderMutation, useUpdateFolderMutation } from '../../../services/folders';\nimport { getTranslationKey } from '../../../utils/translations';\n\ninterface FolderFormDialogBaseProps {\n open: boolean;\n onClose: () => void;\n /** Sent as `parent`. Create: the folder being created in. Rename: the folder's existing parent. */\n parentFolderId: number | null;\n}\n\ntype FolderFormDialogProps = FolderFormDialogBaseProps &\n (\n | { mode: 'create'; parentFolderName: string }\n | { mode: 'rename'; folderId: number; initialName: string }\n );\n\nconst StyledModalContent = styled(Modal.Content)`\n max-width: 51.6rem;\n`;\n\nexport const FolderFormDialog = (props: FolderFormDialogProps) => {\n const { open, parentFolderId, onClose, mode } = props;\n const initialName = props.mode === 'rename' ? props.initialName : '';\n\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const [name, setName] = useState(initialName);\n const [fieldError, setFieldError] = useState<string | undefined>();\n const inputRef = useRef<HTMLInputElement>(null);\n const [createFolder, { isLoading: isCreating }] = useCreateFolderMutation();\n const [updateFolder, { isLoading: isUpdating }] = useUpdateFolderMutation();\n\n const isLoading = mode === 'rename' ? isUpdating : isCreating;\n\n useEffect(() => {\n if (open) {\n setName(initialName);\n setFieldError(undefined);\n\n // Renaming starts from the current name, so select it: typing replaces\n // the whole thing, as in Finder / VS Code / GitHub.\n if (mode === 'rename') {\n inputRef.current?.select();\n }\n }\n }, [open, initialName, mode]);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n\n const trimmedName = name.trim();\n\n if (!trimmedName) {\n setFieldError(\n formatMessage({\n id: getTranslationKey('folder.create.form.error.name-required'),\n defaultMessage: 'Name is required',\n })\n );\n return;\n }\n\n try {\n if (props.mode === 'rename') {\n await updateFolder({\n id: props.folderId,\n name: trimmedName,\n parent: parentFolderId,\n }).unwrap();\n } else {\n await createFolder({ name: trimmedName, parent: parentFolderId }).unwrap();\n }\n\n toggleNotification({\n type: 'success',\n message:\n mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.success'),\n defaultMessage: 'Folder has been renamed',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.success'),\n defaultMessage: 'Folder has been created',\n }),\n });\n\n onClose();\n } catch (err) {\n const apiError = err as { message?: string };\n\n if (apiError?.message) {\n setFieldError(apiError.message);\n } else {\n toggleNotification({\n type: 'danger',\n message:\n mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.form.error.unknown'),\n defaultMessage: 'An error occurred while renaming the folder',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.form.error.unknown'),\n defaultMessage: 'An error occurred while creating the folder',\n }),\n });\n }\n }\n };\n\n return (\n <Modal.Root open={open} onOpenChange={onClose}>\n <StyledModalContent>\n <Modal.Header>\n <Modal.Title>\n {props.mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.title'),\n defaultMessage: 'Rename folder',\n })\n : formatMessage(\n {\n id: getTranslationKey('folder.create.title-in'),\n defaultMessage: 'New folder in {folderName}',\n },\n { folderName: props.parentFolderName }\n )}\n </Modal.Title>\n </Modal.Header>\n <form onSubmit={handleSubmit}>\n <Modal.Body>\n <Field.Root error={fieldError} name=\"name\" required>\n <Field.Label>\n {formatMessage({\n id: getTranslationKey('folder.form.name.label'),\n defaultMessage: 'Folder name',\n })}\n </Field.Label>\n <TextInput\n ref={inputRef}\n value={name}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n setName(e.target.value);\n setFieldError(undefined);\n }}\n autoFocus\n />\n <Field.Error />\n </Field.Root>\n </Modal.Body>\n <Modal.Footer>\n <Flex gap={2} justifyContent=\"space-between\" width=\"100%\">\n <Button variant=\"tertiary\" onClick={onClose} type=\"button\">\n {formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'Cancel' })}\n </Button>\n <Button\n type=\"submit\"\n loading={isLoading}\n disabled={mode === 'rename' && name.trim() === initialName.trim()}\n >\n {mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.submit'),\n defaultMessage: 'Save',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.submit'),\n defaultMessage: 'Create folder',\n })}\n </Button>\n </Flex>\n </Modal.Footer>\n </form>\n </StyledModalContent>\n </Modal.Root>\n );\n};\n"],"names":["StyledModalContent","styled","Modal","Content","FolderFormDialog","props","open","parentFolderId","onClose","mode","initialName","formatMessage","useIntl","toggleNotification","useNotification","name","setName","useState","fieldError","setFieldError","inputRef","useRef","createFolder","isLoading","isCreating","useCreateFolderMutation","updateFolder","isUpdating","useUpdateFolderMutation","useEffect","undefined","current","select","handleSubmit","e","preventDefault","trimmedName","trim","id","getTranslationKey","defaultMessage","folderId","parent","unwrap","type","message","err","apiError","_jsx","Root","onOpenChange","_jsxs","Header","Title","folderName","parentFolderName","form","onSubmit","Body","Field","error","required","Label","TextInput","ref","value","onChange","target","autoFocus","Error","Footer","Flex","gap","justifyContent","width","Button","variant","onClick","loading","disabled"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FolderFormDialog.js","sources":["../../../../../../admin/src/future/pages/Assets/components/FolderFormDialog.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\n\nimport { useNotification } from '@strapi/admin/strapi-admin';\nimport { Button, Field, Flex, Modal, TextInput } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useTracking, MEDIA_LIBRARY_LOCATION } from '../../../hooks/useTracking';\nimport { useCreateFolderMutation, useUpdateFolderMutation } from '../../../services/folders';\nimport { getTranslationKey } from '../../../utils/translations';\n\ninterface FolderFormDialogBaseProps {\n open: boolean;\n onClose: () => void;\n /** Sent as `parent`. Create: the folder being created in. Rename: the folder's existing parent. */\n parentFolderId: number | null;\n}\n\ntype FolderFormDialogProps = FolderFormDialogBaseProps &\n (\n | { mode: 'create'; parentFolderName: string }\n | { mode: 'rename'; folderId: number; initialName: string }\n );\n\nconst StyledModalContent = styled(Modal.Content)`\n max-width: 51.6rem;\n`;\n\nexport const FolderFormDialog = (props: FolderFormDialogProps) => {\n const { open, parentFolderId, onClose, mode } = props;\n const initialName = props.mode === 'rename' ? props.initialName : '';\n\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const { trackUsage } = useTracking();\n const [name, setName] = useState(initialName);\n const [fieldError, setFieldError] = useState<string | undefined>();\n const inputRef = useRef<HTMLInputElement>(null);\n const [createFolder, { isLoading: isCreating }] = useCreateFolderMutation();\n const [updateFolder, { isLoading: isUpdating }] = useUpdateFolderMutation();\n\n const isLoading = mode === 'rename' ? isUpdating : isCreating;\n\n useEffect(() => {\n if (open) {\n setName(initialName);\n setFieldError(undefined);\n\n // Renaming starts from the current name, so select it: typing replaces\n // the whole thing, as in Finder / VS Code / GitHub.\n if (mode === 'rename') {\n inputRef.current?.select();\n }\n }\n }, [open, initialName, mode]);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n\n const trimmedName = name.trim();\n\n if (!trimmedName) {\n setFieldError(\n formatMessage({\n id: getTranslationKey('folder.create.form.error.name-required'),\n defaultMessage: 'Name is required',\n })\n );\n return;\n }\n\n try {\n if (props.mode === 'rename') {\n await updateFolder({\n id: props.folderId,\n name: trimmedName,\n parent: parentFolderId,\n }).unwrap();\n // Matches the legacy folder-edit payload. This dialog only renames\n // (parent is fixed), so the location never changes here.\n trackUsage('didEditMediaLibraryElements', {\n location: MEDIA_LIBRARY_LOCATION,\n type: 'folder',\n changeLocation: false,\n });\n } else {\n await createFolder({ name: trimmedName, parent: parentFolderId }).unwrap();\n trackUsage('didAddMediaLibraryFolders', { location: MEDIA_LIBRARY_LOCATION });\n }\n\n toggleNotification({\n type: 'success',\n message:\n mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.success'),\n defaultMessage: 'Folder has been renamed',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.success'),\n defaultMessage: 'Folder has been created',\n }),\n });\n\n onClose();\n } catch (err) {\n const apiError = err as { message?: string };\n\n if (apiError?.message) {\n setFieldError(apiError.message);\n } else {\n toggleNotification({\n type: 'danger',\n message:\n mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.form.error.unknown'),\n defaultMessage: 'An error occurred while renaming the folder',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.form.error.unknown'),\n defaultMessage: 'An error occurred while creating the folder',\n }),\n });\n }\n }\n };\n\n return (\n <Modal.Root open={open} onOpenChange={onClose}>\n <StyledModalContent>\n <Modal.Header>\n <Modal.Title>\n {props.mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.title'),\n defaultMessage: 'Rename folder',\n })\n : formatMessage(\n {\n id: getTranslationKey('folder.create.title-in'),\n defaultMessage: 'New folder in {folderName}',\n },\n { folderName: props.parentFolderName }\n )}\n </Modal.Title>\n </Modal.Header>\n <form onSubmit={handleSubmit}>\n <Modal.Body>\n <Field.Root error={fieldError} name=\"name\" required>\n <Field.Label>\n {formatMessage({\n id: getTranslationKey('folder.form.name.label'),\n defaultMessage: 'Folder name',\n })}\n </Field.Label>\n <TextInput\n ref={inputRef}\n value={name}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n setName(e.target.value);\n setFieldError(undefined);\n }}\n autoFocus\n />\n <Field.Error />\n </Field.Root>\n </Modal.Body>\n <Modal.Footer>\n <Flex gap={2} justifyContent=\"space-between\" width=\"100%\">\n <Button variant=\"tertiary\" onClick={onClose} type=\"button\">\n {formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'Cancel' })}\n </Button>\n <Button\n type=\"submit\"\n loading={isLoading}\n disabled={mode === 'rename' && name.trim() === initialName.trim()}\n >\n {mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.submit'),\n defaultMessage: 'Save',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.submit'),\n defaultMessage: 'Create folder',\n })}\n </Button>\n </Flex>\n </Modal.Footer>\n </form>\n </StyledModalContent>\n </Modal.Root>\n );\n};\n"],"names":["StyledModalContent","styled","Modal","Content","FolderFormDialog","props","open","parentFolderId","onClose","mode","initialName","formatMessage","useIntl","toggleNotification","useNotification","trackUsage","useTracking","name","setName","useState","fieldError","setFieldError","inputRef","useRef","createFolder","isLoading","isCreating","useCreateFolderMutation","updateFolder","isUpdating","useUpdateFolderMutation","useEffect","undefined","current","select","handleSubmit","e","preventDefault","trimmedName","trim","id","getTranslationKey","defaultMessage","folderId","parent","unwrap","location","MEDIA_LIBRARY_LOCATION","type","changeLocation","message","err","apiError","_jsx","Root","onOpenChange","_jsxs","Header","Title","folderName","parentFolderName","form","onSubmit","Body","Field","error","required","Label","TextInput","ref","value","onChange","target","autoFocus","Error","Footer","Flex","gap","justifyContent","width","Button","variant","onClick","loading","disabled"],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@ import { useNotification } from '@strapi/admin/strapi-admin';
|
|
|
4
4
|
import { Modal, Field, TextInput, Flex, Button } from '@strapi/design-system';
|
|
5
5
|
import { useIntl } from 'react-intl';
|
|
6
6
|
import { styled } from 'styled-components';
|
|
7
|
+
import { useTracking, MEDIA_LIBRARY_LOCATION } from '../../../hooks/useTracking.mjs';
|
|
7
8
|
import { useCreateFolderMutation, useUpdateFolderMutation } from '../../../services/folders.mjs';
|
|
8
9
|
import { getTranslationKey } from '../../../utils/translations.mjs';
|
|
9
10
|
|
|
@@ -15,6 +16,7 @@ const FolderFormDialog = (props)=>{
|
|
|
15
16
|
const initialName = props.mode === 'rename' ? props.initialName : '';
|
|
16
17
|
const { formatMessage } = useIntl();
|
|
17
18
|
const { toggleNotification } = useNotification();
|
|
19
|
+
const { trackUsage } = useTracking();
|
|
18
20
|
const [name, setName] = useState(initialName);
|
|
19
21
|
const [fieldError, setFieldError] = useState();
|
|
20
22
|
const inputRef = useRef(null);
|
|
@@ -53,11 +55,21 @@ const FolderFormDialog = (props)=>{
|
|
|
53
55
|
name: trimmedName,
|
|
54
56
|
parent: parentFolderId
|
|
55
57
|
}).unwrap();
|
|
58
|
+
// Matches the legacy folder-edit payload. This dialog only renames
|
|
59
|
+
// (parent is fixed), so the location never changes here.
|
|
60
|
+
trackUsage('didEditMediaLibraryElements', {
|
|
61
|
+
location: MEDIA_LIBRARY_LOCATION,
|
|
62
|
+
type: 'folder',
|
|
63
|
+
changeLocation: false
|
|
64
|
+
});
|
|
56
65
|
} else {
|
|
57
66
|
await createFolder({
|
|
58
67
|
name: trimmedName,
|
|
59
68
|
parent: parentFolderId
|
|
60
69
|
}).unwrap();
|
|
70
|
+
trackUsage('didAddMediaLibraryFolders', {
|
|
71
|
+
location: MEDIA_LIBRARY_LOCATION
|
|
72
|
+
});
|
|
61
73
|
}
|
|
62
74
|
toggleNotification({
|
|
63
75
|
type: 'success',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FolderFormDialog.mjs","sources":["../../../../../../admin/src/future/pages/Assets/components/FolderFormDialog.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\n\nimport { useNotification } from '@strapi/admin/strapi-admin';\nimport { Button, Field, Flex, Modal, TextInput } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useCreateFolderMutation, useUpdateFolderMutation } from '../../../services/folders';\nimport { getTranslationKey } from '../../../utils/translations';\n\ninterface FolderFormDialogBaseProps {\n open: boolean;\n onClose: () => void;\n /** Sent as `parent`. Create: the folder being created in. Rename: the folder's existing parent. */\n parentFolderId: number | null;\n}\n\ntype FolderFormDialogProps = FolderFormDialogBaseProps &\n (\n | { mode: 'create'; parentFolderName: string }\n | { mode: 'rename'; folderId: number; initialName: string }\n );\n\nconst StyledModalContent = styled(Modal.Content)`\n max-width: 51.6rem;\n`;\n\nexport const FolderFormDialog = (props: FolderFormDialogProps) => {\n const { open, parentFolderId, onClose, mode } = props;\n const initialName = props.mode === 'rename' ? props.initialName : '';\n\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const [name, setName] = useState(initialName);\n const [fieldError, setFieldError] = useState<string | undefined>();\n const inputRef = useRef<HTMLInputElement>(null);\n const [createFolder, { isLoading: isCreating }] = useCreateFolderMutation();\n const [updateFolder, { isLoading: isUpdating }] = useUpdateFolderMutation();\n\n const isLoading = mode === 'rename' ? isUpdating : isCreating;\n\n useEffect(() => {\n if (open) {\n setName(initialName);\n setFieldError(undefined);\n\n // Renaming starts from the current name, so select it: typing replaces\n // the whole thing, as in Finder / VS Code / GitHub.\n if (mode === 'rename') {\n inputRef.current?.select();\n }\n }\n }, [open, initialName, mode]);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n\n const trimmedName = name.trim();\n\n if (!trimmedName) {\n setFieldError(\n formatMessage({\n id: getTranslationKey('folder.create.form.error.name-required'),\n defaultMessage: 'Name is required',\n })\n );\n return;\n }\n\n try {\n if (props.mode === 'rename') {\n await updateFolder({\n id: props.folderId,\n name: trimmedName,\n parent: parentFolderId,\n }).unwrap();\n } else {\n await createFolder({ name: trimmedName, parent: parentFolderId }).unwrap();\n }\n\n toggleNotification({\n type: 'success',\n message:\n mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.success'),\n defaultMessage: 'Folder has been renamed',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.success'),\n defaultMessage: 'Folder has been created',\n }),\n });\n\n onClose();\n } catch (err) {\n const apiError = err as { message?: string };\n\n if (apiError?.message) {\n setFieldError(apiError.message);\n } else {\n toggleNotification({\n type: 'danger',\n message:\n mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.form.error.unknown'),\n defaultMessage: 'An error occurred while renaming the folder',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.form.error.unknown'),\n defaultMessage: 'An error occurred while creating the folder',\n }),\n });\n }\n }\n };\n\n return (\n <Modal.Root open={open} onOpenChange={onClose}>\n <StyledModalContent>\n <Modal.Header>\n <Modal.Title>\n {props.mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.title'),\n defaultMessage: 'Rename folder',\n })\n : formatMessage(\n {\n id: getTranslationKey('folder.create.title-in'),\n defaultMessage: 'New folder in {folderName}',\n },\n { folderName: props.parentFolderName }\n )}\n </Modal.Title>\n </Modal.Header>\n <form onSubmit={handleSubmit}>\n <Modal.Body>\n <Field.Root error={fieldError} name=\"name\" required>\n <Field.Label>\n {formatMessage({\n id: getTranslationKey('folder.form.name.label'),\n defaultMessage: 'Folder name',\n })}\n </Field.Label>\n <TextInput\n ref={inputRef}\n value={name}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n setName(e.target.value);\n setFieldError(undefined);\n }}\n autoFocus\n />\n <Field.Error />\n </Field.Root>\n </Modal.Body>\n <Modal.Footer>\n <Flex gap={2} justifyContent=\"space-between\" width=\"100%\">\n <Button variant=\"tertiary\" onClick={onClose} type=\"button\">\n {formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'Cancel' })}\n </Button>\n <Button\n type=\"submit\"\n loading={isLoading}\n disabled={mode === 'rename' && name.trim() === initialName.trim()}\n >\n {mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.submit'),\n defaultMessage: 'Save',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.submit'),\n defaultMessage: 'Create folder',\n })}\n </Button>\n </Flex>\n </Modal.Footer>\n </form>\n </StyledModalContent>\n </Modal.Root>\n );\n};\n"],"names":["StyledModalContent","styled","Modal","Content","FolderFormDialog","props","open","parentFolderId","onClose","mode","initialName","formatMessage","useIntl","toggleNotification","useNotification","name","setName","useState","fieldError","setFieldError","inputRef","useRef","createFolder","isLoading","isCreating","useCreateFolderMutation","updateFolder","isUpdating","useUpdateFolderMutation","useEffect","undefined","current","select","handleSubmit","e","preventDefault","trimmedName","trim","id","getTranslationKey","defaultMessage","folderId","parent","unwrap","type","message","err","apiError","_jsx","Root","onOpenChange","_jsxs","Header","Title","folderName","parentFolderName","form","onSubmit","Body","Field","error","required","Label","TextInput","ref","value","onChange","target","autoFocus","Error","Footer","Flex","gap","justifyContent","width","Button","variant","onClick","loading","disabled"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FolderFormDialog.mjs","sources":["../../../../../../admin/src/future/pages/Assets/components/FolderFormDialog.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\n\nimport { useNotification } from '@strapi/admin/strapi-admin';\nimport { Button, Field, Flex, Modal, TextInput } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useTracking, MEDIA_LIBRARY_LOCATION } from '../../../hooks/useTracking';\nimport { useCreateFolderMutation, useUpdateFolderMutation } from '../../../services/folders';\nimport { getTranslationKey } from '../../../utils/translations';\n\ninterface FolderFormDialogBaseProps {\n open: boolean;\n onClose: () => void;\n /** Sent as `parent`. Create: the folder being created in. Rename: the folder's existing parent. */\n parentFolderId: number | null;\n}\n\ntype FolderFormDialogProps = FolderFormDialogBaseProps &\n (\n | { mode: 'create'; parentFolderName: string }\n | { mode: 'rename'; folderId: number; initialName: string }\n );\n\nconst StyledModalContent = styled(Modal.Content)`\n max-width: 51.6rem;\n`;\n\nexport const FolderFormDialog = (props: FolderFormDialogProps) => {\n const { open, parentFolderId, onClose, mode } = props;\n const initialName = props.mode === 'rename' ? props.initialName : '';\n\n const { formatMessage } = useIntl();\n const { toggleNotification } = useNotification();\n const { trackUsage } = useTracking();\n const [name, setName] = useState(initialName);\n const [fieldError, setFieldError] = useState<string | undefined>();\n const inputRef = useRef<HTMLInputElement>(null);\n const [createFolder, { isLoading: isCreating }] = useCreateFolderMutation();\n const [updateFolder, { isLoading: isUpdating }] = useUpdateFolderMutation();\n\n const isLoading = mode === 'rename' ? isUpdating : isCreating;\n\n useEffect(() => {\n if (open) {\n setName(initialName);\n setFieldError(undefined);\n\n // Renaming starts from the current name, so select it: typing replaces\n // the whole thing, as in Finder / VS Code / GitHub.\n if (mode === 'rename') {\n inputRef.current?.select();\n }\n }\n }, [open, initialName, mode]);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n\n const trimmedName = name.trim();\n\n if (!trimmedName) {\n setFieldError(\n formatMessage({\n id: getTranslationKey('folder.create.form.error.name-required'),\n defaultMessage: 'Name is required',\n })\n );\n return;\n }\n\n try {\n if (props.mode === 'rename') {\n await updateFolder({\n id: props.folderId,\n name: trimmedName,\n parent: parentFolderId,\n }).unwrap();\n // Matches the legacy folder-edit payload. This dialog only renames\n // (parent is fixed), so the location never changes here.\n trackUsage('didEditMediaLibraryElements', {\n location: MEDIA_LIBRARY_LOCATION,\n type: 'folder',\n changeLocation: false,\n });\n } else {\n await createFolder({ name: trimmedName, parent: parentFolderId }).unwrap();\n trackUsage('didAddMediaLibraryFolders', { location: MEDIA_LIBRARY_LOCATION });\n }\n\n toggleNotification({\n type: 'success',\n message:\n mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.success'),\n defaultMessage: 'Folder has been renamed',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.success'),\n defaultMessage: 'Folder has been created',\n }),\n });\n\n onClose();\n } catch (err) {\n const apiError = err as { message?: string };\n\n if (apiError?.message) {\n setFieldError(apiError.message);\n } else {\n toggleNotification({\n type: 'danger',\n message:\n mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.form.error.unknown'),\n defaultMessage: 'An error occurred while renaming the folder',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.form.error.unknown'),\n defaultMessage: 'An error occurred while creating the folder',\n }),\n });\n }\n }\n };\n\n return (\n <Modal.Root open={open} onOpenChange={onClose}>\n <StyledModalContent>\n <Modal.Header>\n <Modal.Title>\n {props.mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.title'),\n defaultMessage: 'Rename folder',\n })\n : formatMessage(\n {\n id: getTranslationKey('folder.create.title-in'),\n defaultMessage: 'New folder in {folderName}',\n },\n { folderName: props.parentFolderName }\n )}\n </Modal.Title>\n </Modal.Header>\n <form onSubmit={handleSubmit}>\n <Modal.Body>\n <Field.Root error={fieldError} name=\"name\" required>\n <Field.Label>\n {formatMessage({\n id: getTranslationKey('folder.form.name.label'),\n defaultMessage: 'Folder name',\n })}\n </Field.Label>\n <TextInput\n ref={inputRef}\n value={name}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n setName(e.target.value);\n setFieldError(undefined);\n }}\n autoFocus\n />\n <Field.Error />\n </Field.Root>\n </Modal.Body>\n <Modal.Footer>\n <Flex gap={2} justifyContent=\"space-between\" width=\"100%\">\n <Button variant=\"tertiary\" onClick={onClose} type=\"button\">\n {formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'Cancel' })}\n </Button>\n <Button\n type=\"submit\"\n loading={isLoading}\n disabled={mode === 'rename' && name.trim() === initialName.trim()}\n >\n {mode === 'rename'\n ? formatMessage({\n id: getTranslationKey('folder.rename.submit'),\n defaultMessage: 'Save',\n })\n : formatMessage({\n id: getTranslationKey('folder.create.submit'),\n defaultMessage: 'Create folder',\n })}\n </Button>\n </Flex>\n </Modal.Footer>\n </form>\n </StyledModalContent>\n </Modal.Root>\n );\n};\n"],"names":["StyledModalContent","styled","Modal","Content","FolderFormDialog","props","open","parentFolderId","onClose","mode","initialName","formatMessage","useIntl","toggleNotification","useNotification","trackUsage","useTracking","name","setName","useState","fieldError","setFieldError","inputRef","useRef","createFolder","isLoading","isCreating","useCreateFolderMutation","updateFolder","isUpdating","useUpdateFolderMutation","useEffect","undefined","current","select","handleSubmit","e","preventDefault","trimmedName","trim","id","getTranslationKey","defaultMessage","folderId","parent","unwrap","location","MEDIA_LIBRARY_LOCATION","type","changeLocation","message","err","apiError","_jsx","Root","onOpenChange","_jsxs","Header","Title","folderName","parentFolderName","form","onSubmit","Body","Field","error","required","Label","TextInput","ref","value","onChange","target","autoFocus","Error","Footer","Flex","gap","justifyContent","width","Button","variant","onClick","loading","disabled"],"mappings":"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"}
|