From 9e3b3ece8776cfd47b4dee20ab782375a839c43f Mon Sep 17 00:00:00 2001 From: Gustav Hansen Date: Mon, 21 Mar 2022 13:54:13 +0100 Subject: [PATCH 01/30] ML: Use formatjs inline plural API, display folder count --- .../admin/src/pages/App/MediaLibrary.js | 24 +++++++------------ .../upload/admin/src/translations/de.json | 3 +-- .../upload/admin/src/translations/dk.json | 4 +--- .../upload/admin/src/translations/en.json | 3 +-- .../upload/admin/src/translations/es.json | 4 +--- .../upload/admin/src/translations/fr.json | 4 +--- .../upload/admin/src/translations/he.json | 4 +--- .../upload/admin/src/translations/it.json | 4 +--- .../upload/admin/src/translations/ja.json | 4 +--- .../upload/admin/src/translations/ko.json | 4 +--- .../upload/admin/src/translations/ms.json | 4 +--- .../upload/admin/src/translations/pl.json | 4 +--- .../upload/admin/src/translations/pt-BR.json | 4 +--- .../upload/admin/src/translations/ru.json | 4 +--- .../upload/admin/src/translations/sk.json | 4 +--- .../upload/admin/src/translations/th.json | 4 +--- .../upload/admin/src/translations/uk.json | 4 +--- .../admin/src/translations/zh-Hans.json | 4 +--- .../upload/admin/src/translations/zh.json | 4 +--- 19 files changed, 27 insertions(+), 67 deletions(-) diff --git a/packages/core/upload/admin/src/pages/App/MediaLibrary.js b/packages/core/upload/admin/src/pages/App/MediaLibrary.js index d2a06942a6..206f233d13 100644 --- a/packages/core/upload/admin/src/pages/App/MediaLibrary.js +++ b/packages/core/upload/admin/src/pages/App/MediaLibrary.js @@ -50,20 +50,21 @@ export const MediaLibrary = () => { skipWhen: !canRead, }); - const handleChangeSort = value => { + const handleChangeSort = (value) => { setQuery({ sort: value }); }; const [showUploadAssetDialog, setShowUploadAssetDialog] = useState(false); const [assetToEdit, setAssetToEdit] = useState(undefined); const [selected, { selectOne, selectAll }] = useSelectionState('id', []); - const toggleUploadAssetDialog = () => setShowUploadAssetDialog(prev => !prev); + const toggleUploadAssetDialog = () => setShowUploadAssetDialog((prev) => !prev); useFocusWhenNavigate(); const loading = isLoadingPermissions || isLoading; const assets = data?.results; const assetCount = data?.pagination?.total || 0; + const folderCount = 0; const isFiltering = Boolean(query._q || query.filters); return ( @@ -76,14 +77,11 @@ export const MediaLibrary = () => { })} subtitle={formatMessage( { - id: getTrad( - assetCount > 0 - ? 'header.content.assets-multiple' - : 'header.content.assets.assets-single' - ), - defaultMessage: '0 assets', + id: getTrad('header.content.assets'), + defaultMessage: + '{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {1 asset} other {# assets}}', }, - { number: assetCount } + { numberAssets: assetCount, numberFolders: folderCount } )} primaryAction={ canCreate ? ( @@ -93,9 +91,7 @@ export const MediaLibrary = () => { defaultMessage: 'Add new assets', })} - ) : ( - undefined - ) + ) : undefined } /> @@ -161,9 +157,7 @@ export const MediaLibrary = () => { defaultMessage: 'Add new assets', })} - ) : ( - undefined - ) + ) : undefined } content={ // eslint-disable-next-line no-nested-ternary diff --git a/packages/core/upload/admin/src/translations/de.json b/packages/core/upload/admin/src/translations/de.json index 68ef1acdb0..0d5e361073 100644 --- a/packages/core/upload/admin/src/translations/de.json +++ b/packages/core/upload/admin/src/translations/de.json @@ -24,8 +24,7 @@ "header.actions.upload-assets": "Dateien hochladen", "header.actions.upload-new-asset": "Neue Dateien hochladen", "header.content.assets-empty": "Keine Dateien", - "header.content.assets-multiple": "{number} Dateien", - "header.content.assets-single": "1 Datei", + "header.content.assets": "{numberFolders} Ordner - {numberAssets, plural, one {1 Datei} other {# Dateien}}", "input.button.label": "Dateien durchsuchen", "input.label": "Dateien hierhin ziehen oder", "input.label-bold": "Drag & Drop", diff --git a/packages/core/upload/admin/src/translations/dk.json b/packages/core/upload/admin/src/translations/dk.json index a9041419c1..2c1e77ce17 100644 --- a/packages/core/upload/admin/src/translations/dk.json +++ b/packages/core/upload/admin/src/translations/dk.json @@ -22,9 +22,7 @@ "form.upload-url.error.url.invalids": "{number} URLer er ugyldige", "header.actions.upload-assets": "Upload medier", "header.actions.upload-new-asset": "Upload medie", - "header.content.assets-empty": "Ingen medier", - "header.content.assets-multiple": "{number} medier", - "header.content.assets-single": "1 medie", + "header.content.assets": "{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {1 medie} other {# medier}}", "input.button.label": "Vælg filer", "input.label": "Drag & Drop her eller", "input.label-bold": "Drag & drop", diff --git a/packages/core/upload/admin/src/translations/en.json b/packages/core/upload/admin/src/translations/en.json index 96d39dd4af..f453fa994c 100644 --- a/packages/core/upload/admin/src/translations/en.json +++ b/packages/core/upload/admin/src/translations/en.json @@ -24,8 +24,7 @@ "header.actions.upload-assets": "Upload assets", "header.actions.upload-new-asset": "Upload new asset", "header.content.assets-empty": "No assets", - "header.content.assets-multiple": "{number} assets", - "header.content.assets-single": "1 asset", + "header.content.assets": "{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {1 asset} other {# assets}}", "input.button.label": "Browse files", "input.label": "Drag & Drop here or", "input.label-bold": "Drag & drop", diff --git a/packages/core/upload/admin/src/translations/es.json b/packages/core/upload/admin/src/translations/es.json index 391a65033c..a020249d5b 100644 --- a/packages/core/upload/admin/src/translations/es.json +++ b/packages/core/upload/admin/src/translations/es.json @@ -22,9 +22,7 @@ "form.upload-url.error.url.invalids": "{number} URL no son válidas", "header.actions.upload-assets": "Subir recursos", "header.actions.upload-new-asset": "Subir nuevo recurso", - "header.content.assets-empty": "Sin recursos", - "header.content.assets-multiple": "{number} recursos", - "header.content.assets-single": "1 recurso", + "header.content.assets": "{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {1 recurso} other {# recursos}}", "input.button.label": "Buscar archivos", "input.label": "Arrastra y suelta aquí o", "input.label-bold": "Arrastrar", diff --git a/packages/core/upload/admin/src/translations/fr.json b/packages/core/upload/admin/src/translations/fr.json index 1384b99fb6..c09df346c3 100644 --- a/packages/core/upload/admin/src/translations/fr.json +++ b/packages/core/upload/admin/src/translations/fr.json @@ -19,9 +19,7 @@ "form.upload-url.error.url.invalid": "Une URL n'est pas valide", "form.upload-url.error.url.invalids": "{number} URLs ne sont pas valides", "header.actions.upload-assets": "Importer des médias", - "header.content.assets-empty": "Aucun média", - "header.content.assets-multiple": "{number} médias", - "header.content.assets-single": "1 média", + "header.content.assets": "{numberFolders, plural, one {1 dossier} other {# dossiers}} - {numberAssets, plural, one {1 média} other {# médias}}", "input.button.label": "Parcourir les fichiers", "input.label-bold": "Glissez & déposez", "input.label-normal": "pour importer ou", diff --git a/packages/core/upload/admin/src/translations/he.json b/packages/core/upload/admin/src/translations/he.json index 968cbd2e4b..f82f61101a 100644 --- a/packages/core/upload/admin/src/translations/he.json +++ b/packages/core/upload/admin/src/translations/he.json @@ -19,9 +19,7 @@ "form.upload-url.error.url.invalid": "כתובת URL אחת אינה חוקית", "form.upload-url.error.url.invalids": "{number} כתובות URL שגויות", "header.actions.upload-assets": "העלה נכסים", - "header.content.assets-empty": "אין נכסים", - "header.content.assets-multiple": "{number} נכסים", - "header.content.assets-single": "נכס 1", + "header.content.assets": "{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {1 נכס} other {# נכסים}}", "input.button.label": "עיין בקבצים", "input.label-bold": "גרור ושחרר", "input.label-normal": "להעלות או", diff --git a/packages/core/upload/admin/src/translations/it.json b/packages/core/upload/admin/src/translations/it.json index d36da24d3a..ca67e1d657 100644 --- a/packages/core/upload/admin/src/translations/it.json +++ b/packages/core/upload/admin/src/translations/it.json @@ -19,9 +19,7 @@ "form.upload-url.error.url.invalid": "Un URL non è valido", "form.upload-url.error.url.invalids": "{number} URL non sono validi", "header.actions.upload-assets": "Carica risorse", - "header.content.assets-empty": "Nessuna risorsa", - "header.content.assets-multiple": "{number} risorse", - "header.content.assets-single": "1 risorsa", + "header.content.assets": "{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {1 risorsa} other {# risorse}}", "input.button.label": "Sfoglia file", "input.label-bold": "Trascina & rilascia", "input.label-normal": "per caricare oppure", diff --git a/packages/core/upload/admin/src/translations/ja.json b/packages/core/upload/admin/src/translations/ja.json index 37399e155e..5fff8f15f7 100644 --- a/packages/core/upload/admin/src/translations/ja.json +++ b/packages/core/upload/admin/src/translations/ja.json @@ -19,9 +19,7 @@ "form.upload-url.error.url.invalid": "1つのURLが無効です", "form.upload-url.error.url.invalids": "{number}つのURLは無効です", "header.actions.upload-assets": "アップロード", - "header.content.assets-empty": "アセットはありません", - "header.content.assets-multiple": "{number} アセット", - "header.content.assets-single": "1 アセット", + "header.content.assets": "{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {1 アセット} other {# アセット}}", "input.button.label": "ファイルを選択", "input.label-bold": "ドラッグ&ドロップ", "input.label-normal": "でアップロードするか", diff --git a/packages/core/upload/admin/src/translations/ko.json b/packages/core/upload/admin/src/translations/ko.json index 38d6fa8c7f..7b2bc52be7 100644 --- a/packages/core/upload/admin/src/translations/ko.json +++ b/packages/core/upload/admin/src/translations/ko.json @@ -23,9 +23,7 @@ "header.actions.add-assets": "새 에셋 추가", "header.actions.upload-assets": "에셋 업로드", "header.actions.upload-new-asset": "새 에셋 업로드", - "header.content.assets-empty": "에셋 없음", - "header.content.assets-multiple": "{number} 에셋", - "header.content.assets-single": "1 에셋", + "header.content.assets": "{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {1 에셋} other {# 에셋}}", "input.button.label": "파일 선택", "input.label": "여기에 드래그 & 드롭 하거나", "input.label-bold": "드래그 & 드롭", diff --git a/packages/core/upload/admin/src/translations/ms.json b/packages/core/upload/admin/src/translations/ms.json index d7e212cb4f..3be79705c6 100644 --- a/packages/core/upload/admin/src/translations/ms.json +++ b/packages/core/upload/admin/src/translations/ms.json @@ -17,9 +17,7 @@ "form.upload-url.error.url.invalid": "Satu URL tidak sah", "form.upload-url.error.url.invalids": "{number} URL tidak sah", "header.actions.upload-assets": "Muat naik aset", - "header.content.assets-empty": "Tiada aset", - "header.content.assets-multiple": "{number} aset", - "header.content.assets-single": "1 aset", + "header.content.assets": "{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets} aset}", "input.button.label": "Pilih fail", "input.label-bold": "Tarik & Lepas", "input.label-normal": "untuk memuat naik atau", diff --git a/packages/core/upload/admin/src/translations/pl.json b/packages/core/upload/admin/src/translations/pl.json index c491cef147..41b73cb2c3 100644 --- a/packages/core/upload/admin/src/translations/pl.json +++ b/packages/core/upload/admin/src/translations/pl.json @@ -19,9 +19,7 @@ "form.upload-url.error.url.invalid": "Jeden link URL jest niepoprawny", "form.upload-url.error.url.invalids": "{number} linków URL jest niepoprawnych", "header.actions.upload-assets": "Prześlij zasób", - "header.content.assets-empty": "Brak zasobów", - "header.content.assets-multiple": "{number} zasobów", - "header.content.assets-single": "1 zasób", + "header.content.assets": "{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {1 zasób} other {# zasobów}}", "input.button.label": "Przeglądaj pliki", "input.label-bold": "Przeciągnij & upuść", "input.label-normal": "do przesłania lub", diff --git a/packages/core/upload/admin/src/translations/pt-BR.json b/packages/core/upload/admin/src/translations/pt-BR.json index 33c9f86dd8..0d2da8557b 100644 --- a/packages/core/upload/admin/src/translations/pt-BR.json +++ b/packages/core/upload/admin/src/translations/pt-BR.json @@ -19,9 +19,7 @@ "form.upload-url.error.url.invalid": "Uma URL é inválida", "form.upload-url.error.url.invalids": "{number} URLs são inválidas", "header.actions.upload-assets": "Enviar arquivos", - "header.content.assets-empty": "Nenhum arquivo", - "header.content.assets-multiple": "{number} arquivos", - "header.content.assets-single": "1 arquivo", + "header.content.assets": "{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {1 arquivo} other {# arquivos}}", "input.button.label": "Navegue pelos arquivos", "input.label-bold": "Arraste e solte", "input.label-normal": "para enviar ou", diff --git a/packages/core/upload/admin/src/translations/ru.json b/packages/core/upload/admin/src/translations/ru.json index ef45da63b4..5fa848ad10 100644 --- a/packages/core/upload/admin/src/translations/ru.json +++ b/packages/core/upload/admin/src/translations/ru.json @@ -19,9 +19,7 @@ "form.upload-url.error.url.invalid": "Один URL неверен", "form.upload-url.error.url.invalids": "{number} URL-ов неверно", "header.actions.upload-assets": "Добавить ресурсы", - "header.content.assets-empty": "Нет ресурсов", - "header.content.assets-multiple": "{number} ресурсов", - "header.content.assets-single": "1 ресурс", + "header.content.assets": "{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {1 ресурс} other {# ресурсов}}", "input.button.label": "Обзор файлов", "input.label-bold": "Перетащите", "input.label-normal": "чтобы загрузить или", diff --git a/packages/core/upload/admin/src/translations/sk.json b/packages/core/upload/admin/src/translations/sk.json index c50049b09c..0390ca27d4 100644 --- a/packages/core/upload/admin/src/translations/sk.json +++ b/packages/core/upload/admin/src/translations/sk.json @@ -19,9 +19,7 @@ "form.upload-url.error.url.invalid": "Jedna URL adresa je neplatná", "form.upload-url.error.url.invalids": "{number} URL adresy/ies sú/je neplatné/ých ", "header.actions.upload-assets": "Nahrať súbor", - "header.content.assets-empty": "Žiadne súbory", - "header.content.assets-multiple": "{number} súbory/ov", - "header.content.assets-single": "1 súbor", + "header.content.assets": "{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {1 súbor} other {# súbory/ov}}", "input.button.label": "Prehliadať súbory", "input.label-bold": "Drag & drop", "input.label-normal": "pre nahratie alebo", diff --git a/packages/core/upload/admin/src/translations/th.json b/packages/core/upload/admin/src/translations/th.json index e3b200f216..2b4fe353d2 100644 --- a/packages/core/upload/admin/src/translations/th.json +++ b/packages/core/upload/admin/src/translations/th.json @@ -19,9 +19,7 @@ "form.upload-url.error.url.invalid": "URL ไม่ถูกต้อง", "form.upload-url.error.url.invalids": "{number} URL ไม่ถูกต้อง", "header.actions.upload-assets": "อัพโหลดไฟล์", - "header.content.assets-empty": "ไม่มีไฟล์", - "header.content.assets-multiple": "{number} ไฟล์", - "header.content.assets-single": "1 ไฟล์", + "header.content.assets": "{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {1 ไฟล์} other {# ไฟล์}}", "input.button.label": "เรียกดูไฟล์", "input.label-bold": "ลาก & ปล่อย", "input.label-normal": "เพื่ออัพโหลดหรือ", diff --git a/packages/core/upload/admin/src/translations/uk.json b/packages/core/upload/admin/src/translations/uk.json index 1b77bf1217..731243e110 100644 --- a/packages/core/upload/admin/src/translations/uk.json +++ b/packages/core/upload/admin/src/translations/uk.json @@ -18,9 +18,7 @@ "form.upload-url.error.url.invalid": "Одина URL-адреса неправильна", "form.upload-url.error.url.invalids": "{number} URL-адреси неправильні", "header.actions.upload-assets": "Завантажити файл", - "header.content.assets-empty": "Немає файлів", - "header.content.assets-multiple": "{number} файлів", - "header.content.assets-single": "1 файл", + "header.content.assets": "{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {1 файл} other {# файлів}}", "input.button.label": "Перегляд файлів", "input.label-bold": "Перетягніть сюди", "input.label-normal": "щоб завантажити або", diff --git a/packages/core/upload/admin/src/translations/zh-Hans.json b/packages/core/upload/admin/src/translations/zh-Hans.json index f1caa9203b..e1e9c6d890 100644 --- a/packages/core/upload/admin/src/translations/zh-Hans.json +++ b/packages/core/upload/admin/src/translations/zh-Hans.json @@ -19,9 +19,7 @@ "form.upload-url.error.url.invalid": "有一个链接格式不合法", "form.upload-url.error.url.invalids": "{number}个链接格式不合法", "header.actions.upload-assets": "上传素材", - "header.content.assets-empty": "无素材", - "header.content.assets-multiple": "{number}个素材", - "header.content.assets-single": "1个素材", + "header.content.assets": "{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {1 个素材} other {# 个素材}}", "input.button.label": "浏览文件", "input.label-bold": "拖拽至此", "input.label-normal": "并上传", diff --git a/packages/core/upload/admin/src/translations/zh.json b/packages/core/upload/admin/src/translations/zh.json index 1acef3688e..40708adab8 100644 --- a/packages/core/upload/admin/src/translations/zh.json +++ b/packages/core/upload/admin/src/translations/zh.json @@ -19,9 +19,7 @@ "form.upload-url.error.url.invalid": "連結不合法", "form.upload-url.error.url.invalids": "{number} 個連結不合法", "header.actions.upload-assets": "上傳素材", - "header.content.assets-empty": "無素材", - "header.content.assets-multiple": "{number} 個素材", - "header.content.assets-single": "1 個素材", + "header.content.assets": "{numberFolders, plural, one {1 folder} other {# folders}} - {numberAssets, plural, one {個素材} other {# 個素材}}", "input.button.label": "瀏覽檔案", "input.label-bold": "拖曳", "input.label-normal": "並上傳", From fc5e52792b6975087e5c07102769fe4b12b16420 Mon Sep 17 00:00:00 2001 From: Gustav Hansen Date: Tue, 22 Mar 2022 11:14:40 +0100 Subject: [PATCH 02/30] ML: Add tests for useAssets() --- .../admin/src/hooks/tests/useAssets.test.js | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 packages/core/upload/admin/src/hooks/tests/useAssets.test.js diff --git a/packages/core/upload/admin/src/hooks/tests/useAssets.test.js b/packages/core/upload/admin/src/hooks/tests/useAssets.test.js new file mode 100644 index 0000000000..f3aa26a1fc --- /dev/null +++ b/packages/core/upload/admin/src/hooks/tests/useAssets.test.js @@ -0,0 +1,120 @@ +/* eslint-disable import/order */ +/* eslint-disable import/first */ + +import React from 'react'; +import { IntlProvider } from 'react-intl'; +import { QueryClientProvider, QueryClient } from 'react-query'; +import { renderHook, act } from '@testing-library/react-hooks'; +import { BrowserRouter as Router, Route } from 'react-router-dom'; + +import { NotificationsProvider, useNotification } from '@strapi/helper-plugin'; + +import { useAssets } from '../useAssets'; + +const notifyStatusMock = jest.fn(); + +jest.mock('@strapi/design-system/LiveRegions', () => ({ + ...jest.requireActual('@strapi/design-system/LiveRegions'), + useNotifyAT: () => ({ + notifyStatus: notifyStatusMock, + }), +})); + +import { useNotifyAT } from '@strapi/design-system/LiveRegions'; + +jest.mock('../../utils', () => ({ + ...jest.requireActual('../../utils'), + axiosInstance: { + get: jest.fn().mockResolvedValue({ + data: { + id: 1, + }, + }), + }, +})); + +import { axiosInstance } from '../../utils'; + +const notificationStatusMock = jest.fn(); + +jest.mock('@strapi/helper-plugin', () => ({ + ...jest.requireActual('@strapi/helper-plugin'), + useNotification: () => notificationStatusMock, +})); + +const client = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, +}); + +// eslint-disable-next-line react/prop-types +function ComponentFixture({ children }) { + return ( + + + + jest.fn()}> + + {children} + + + + + + ); +} + +function setup(...args) { + return new Promise(resolve => { + act(() => { + resolve(renderHook(() => useAssets(...args), { wrapper: ComponentFixture })); + }); + }); +} + +describe('useAssets', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + test('fetches data from the right URL', async () => { + const { result, waitFor } = await setup({}); + + await waitFor(() => result.current.isSuccess); + + expect(axiosInstance.get).toBeCalledWith('/upload/files'); + }); + + test('it does not fetch, if skipWhen is set', async () => { + const { result, waitFor } = await setup({ skipWhen: true }); + + await waitFor(() => result.current.isSuccess); + + expect(axiosInstance.get).toBeCalledTimes(0); + }); + + test('calls notifyStatus in case of success', async () => { + const { notifyStatus } = useNotifyAT(); + const toggleNotification = useNotification(); + const { waitForNextUpdate } = await setup({}); + + await waitForNextUpdate(); + + expect(notifyStatus).toBeCalledWith('The assets have finished loading.'); + expect(toggleNotification).toBeCalledTimes(0); + }); + + test('calls toggleNotification in case of error', async () => { + axiosInstance.get.mockRejectedValueOnce(new Error('Jest mock error')); + + const { notifyStatus } = useNotifyAT(); + const toggleNotification = useNotification(); + const { waitFor } = await setup({}); + + await waitFor(() => expect(toggleNotification).toBeCalled()); + await waitFor(() => expect(notifyStatus).not.toBeCalled()); + }); +}); From 8fe9488b753019319be1083a54000c5a72733f42 Mon Sep 17 00:00:00 2001 From: Gustav Hansen Date: Tue, 22 Mar 2022 11:15:01 +0100 Subject: [PATCH 03/30] ML: Add useFolders() hook and tests --- .../admin/src/hooks/tests/useFolders.test.js | 122 ++++++++++++++++++ .../core/upload/admin/src/hooks/useFolders.js | 48 +++++++ 2 files changed, 170 insertions(+) create mode 100644 packages/core/upload/admin/src/hooks/tests/useFolders.test.js create mode 100644 packages/core/upload/admin/src/hooks/useFolders.js diff --git a/packages/core/upload/admin/src/hooks/tests/useFolders.test.js b/packages/core/upload/admin/src/hooks/tests/useFolders.test.js new file mode 100644 index 0000000000..33fe91a6a6 --- /dev/null +++ b/packages/core/upload/admin/src/hooks/tests/useFolders.test.js @@ -0,0 +1,122 @@ +/* eslint-disable import/no-duplicates */ +/* eslint-disable import/order */ +/* eslint-disable import/first */ + +import React from 'react'; +import { IntlProvider } from 'react-intl'; +import { QueryClientProvider, QueryClient } from 'react-query'; +import { renderHook, act } from '@testing-library/react-hooks'; +import { BrowserRouter as Router, Route } from 'react-router-dom'; +import { NotificationsProvider } from '@strapi/helper-plugin'; + +import { useFolders } from '../useFolders'; + +const notifyStatusMock = jest.fn(); + +jest.mock('@strapi/design-system/LiveRegions', () => ({ + ...jest.requireActual('@strapi/design-system/LiveRegions'), + useNotifyAT: () => ({ + notifyStatus: notifyStatusMock, + }), +})); + +import { useNotifyAT } from '@strapi/design-system/LiveRegions'; + +jest.mock('../../utils', () => ({ + ...jest.requireActual('../../utils'), + axiosInstance: { + get: jest.fn().mockResolvedValue({ + data: { + id: 1, + }, + }), + }, +})); + +import { axiosInstance } from '../../utils'; + +const notificationStatusMock = jest.fn(); + +jest.mock('@strapi/helper-plugin', () => ({ + ...jest.requireActual('@strapi/helper-plugin'), + useNotification: () => notificationStatusMock, +})); + +import { useNotification } from '@strapi/helper-plugin'; + +const client = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, +}); + +// eslint-disable-next-line react/prop-types +function ComponentFixture({ children }) { + return ( + + + + jest.fn()}> + + {children} + + + + + + ); +} + +function setup(...args) { + return new Promise(resolve => { + act(() => { + resolve(renderHook(() => useFolders(...args), { wrapper: ComponentFixture })); + }); + }); +} + +describe('useFolders', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + test('fetches data from the right URL', async () => { + const { result, waitFor } = await setup({}); + + await waitFor(() => result.current.isSuccess); + + expect(axiosInstance.get).toBeCalledWith('/upload/folders'); + }); + + test('it does not fetch, if enabled is set to false', async () => { + const { result, waitFor } = await setup({ enabled: false }); + + await waitFor(() => result.current.isSuccess); + + expect(axiosInstance.get).toBeCalledTimes(0); + }); + + test('calls notifyStatus in case of success', async () => { + const { notifyStatus } = useNotifyAT(); + const toggleNotification = useNotification(); + const { waitForNextUpdate } = await setup({}); + + await waitForNextUpdate(); + + expect(notifyStatus).toBeCalledWith('The folders have finished loading.'); + expect(toggleNotification).toBeCalledTimes(0); + }); + + test('calls toggleNotification in case of error', async () => { + axiosInstance.get.mockRejectedValueOnce(new Error('Jest mock error')); + + const { notifyStatus } = useNotifyAT(); + const toggleNotification = useNotification(); + const { waitFor } = await setup({}); + + await waitFor(() => expect(toggleNotification).toBeCalled()); + await waitFor(() => expect(notifyStatus).not.toBeCalled()); + }); +}); diff --git a/packages/core/upload/admin/src/hooks/useFolders.js b/packages/core/upload/admin/src/hooks/useFolders.js new file mode 100644 index 0000000000..33acd601e0 --- /dev/null +++ b/packages/core/upload/admin/src/hooks/useFolders.js @@ -0,0 +1,48 @@ +import { useEffect } from 'react'; +import { useQuery } from 'react-query'; +import { useNotifyAT } from '@strapi/design-system/LiveRegions'; +import { useNotification, useQueryParams } from '@strapi/helper-plugin'; +import { useIntl } from 'react-intl'; +import { axiosInstance, getRequestUrl } from '../utils'; + +export const useFolders = ({ enabled = true }) => { + const { formatMessage } = useIntl(); + const toggleNotification = useNotification(); + const { notifyStatus } = useNotifyAT(); + const [{ rawQuery }] = useQueryParams(); + const dataRequestURL = getRequestUrl('folders'); + + const fetchFolders = async () => { + const { data } = await axiosInstance.get(`${dataRequestURL}${rawQuery}`); + + return data; + }; + + const { data, error, isLoading } = useQuery([`folders`, rawQuery], fetchFolders, { + enabled, + staleTime: 0, + cacheTime: 0, + }); + + useEffect(() => { + if (data) { + notifyStatus( + formatMessage({ + id: 'list.asset.at.finished', + defaultMessage: 'The folders have finished loading.', + }) + ); + } + }, [data, notifyStatus, formatMessage]); + + useEffect(() => { + if (error) { + toggleNotification({ + type: 'warning', + message: { id: 'notification.error' }, + }); + } + }, [error, toggleNotification]); + + return { data, error, isLoading }; +}; From e49a99692f3e94d5c13c6f4f6cfe02b3d668f75d Mon Sep 17 00:00:00 2001 From: Gustav Hansen Date: Wed, 23 Mar 2022 13:02:56 +0100 Subject: [PATCH 04/30] ML: Resolve ignored eslint rules --- .../admin/src/hooks/tests/useAssets.test.js | 9 ++------- .../admin/src/hooks/tests/useFolders.test.js | 15 ++++----------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/packages/core/upload/admin/src/hooks/tests/useAssets.test.js b/packages/core/upload/admin/src/hooks/tests/useAssets.test.js index f3aa26a1fc..c5711fde57 100644 --- a/packages/core/upload/admin/src/hooks/tests/useAssets.test.js +++ b/packages/core/upload/admin/src/hooks/tests/useAssets.test.js @@ -1,6 +1,3 @@ -/* eslint-disable import/order */ -/* eslint-disable import/first */ - import React from 'react'; import { IntlProvider } from 'react-intl'; import { QueryClientProvider, QueryClient } from 'react-query'; @@ -8,7 +5,9 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { BrowserRouter as Router, Route } from 'react-router-dom'; import { NotificationsProvider, useNotification } from '@strapi/helper-plugin'; +import { useNotifyAT } from '@strapi/design-system/LiveRegions'; +import { axiosInstance } from '../../utils'; import { useAssets } from '../useAssets'; const notifyStatusMock = jest.fn(); @@ -20,8 +19,6 @@ jest.mock('@strapi/design-system/LiveRegions', () => ({ }), })); -import { useNotifyAT } from '@strapi/design-system/LiveRegions'; - jest.mock('../../utils', () => ({ ...jest.requireActual('../../utils'), axiosInstance: { @@ -33,8 +30,6 @@ jest.mock('../../utils', () => ({ }, })); -import { axiosInstance } from '../../utils'; - const notificationStatusMock = jest.fn(); jest.mock('@strapi/helper-plugin', () => ({ diff --git a/packages/core/upload/admin/src/hooks/tests/useFolders.test.js b/packages/core/upload/admin/src/hooks/tests/useFolders.test.js index 33fe91a6a6..96f6f61e75 100644 --- a/packages/core/upload/admin/src/hooks/tests/useFolders.test.js +++ b/packages/core/upload/admin/src/hooks/tests/useFolders.test.js @@ -1,14 +1,13 @@ -/* eslint-disable import/no-duplicates */ -/* eslint-disable import/order */ -/* eslint-disable import/first */ - import React from 'react'; import { IntlProvider } from 'react-intl'; import { QueryClientProvider, QueryClient } from 'react-query'; import { renderHook, act } from '@testing-library/react-hooks'; import { BrowserRouter as Router, Route } from 'react-router-dom'; -import { NotificationsProvider } from '@strapi/helper-plugin'; +import { NotificationsProvider, useNotification } from '@strapi/helper-plugin'; +import { useNotifyAT } from '@strapi/design-system/LiveRegions'; + +import { axiosInstance } from '../../utils'; import { useFolders } from '../useFolders'; const notifyStatusMock = jest.fn(); @@ -20,8 +19,6 @@ jest.mock('@strapi/design-system/LiveRegions', () => ({ }), })); -import { useNotifyAT } from '@strapi/design-system/LiveRegions'; - jest.mock('../../utils', () => ({ ...jest.requireActual('../../utils'), axiosInstance: { @@ -33,8 +30,6 @@ jest.mock('../../utils', () => ({ }, })); -import { axiosInstance } from '../../utils'; - const notificationStatusMock = jest.fn(); jest.mock('@strapi/helper-plugin', () => ({ @@ -42,8 +37,6 @@ jest.mock('@strapi/helper-plugin', () => ({ useNotification: () => notificationStatusMock, })); -import { useNotification } from '@strapi/helper-plugin'; - const client = new QueryClient({ defaultOptions: { queries: { From 0193911e3c643682d4d0c54a28f5608797bf011e Mon Sep 17 00:00:00 2001 From: Gustav Hansen Date: Wed, 23 Mar 2022 13:10:44 +0100 Subject: [PATCH 05/30] ML: Simplify useAssets() and useFolders() hooks --- .../core/upload/admin/src/hooks/useAssets.js | 41 ++++++++----------- .../core/upload/admin/src/hooks/useFolders.js | 41 ++++++++----------- 2 files changed, 36 insertions(+), 46 deletions(-) diff --git a/packages/core/upload/admin/src/hooks/useAssets.js b/packages/core/upload/admin/src/hooks/useAssets.js index ddb2343d3a..76d6fa0434 100644 --- a/packages/core/upload/admin/src/hooks/useAssets.js +++ b/packages/core/upload/admin/src/hooks/useAssets.js @@ -1,4 +1,3 @@ -import { useEffect } from 'react'; import { useQuery } from 'react-query'; import { useNotifyAT } from '@strapi/design-system/LiveRegions'; import { useNotification, useQueryParams } from '@strapi/helper-plugin'; @@ -13,9 +12,25 @@ export const useAssets = ({ skipWhen }) => { const dataRequestURL = getRequestUrl('files'); const getAssets = async () => { - const { data } = await axiosInstance.get(`${dataRequestURL}${rawQuery}`); + try { + const { data } = await axiosInstance.get(`${dataRequestURL}${rawQuery}`); - return data; + notifyStatus( + formatMessage({ + id: 'list.asset.at.finished', + defaultMessage: 'The assets have finished loading.', + }) + ); + + return data; + } catch (err) { + toggleNotification({ + type: 'warning', + message: { id: 'notification.error' }, + }); + + throw err; + } }; const { data, error, isLoading } = useQuery([`assets`, rawQuery], getAssets, { @@ -24,25 +39,5 @@ export const useAssets = ({ skipWhen }) => { cacheTime: 0, }); - useEffect(() => { - if (data) { - notifyStatus( - formatMessage({ - id: 'list.asset.at.finished', - defaultMessage: 'The assets have finished loading.', - }) - ); - } - }, [data, notifyStatus, formatMessage]); - - useEffect(() => { - if (error) { - toggleNotification({ - type: 'warning', - message: { id: 'notification.error' }, - }); - } - }, [error, toggleNotification]); - return { data, error, isLoading }; }; diff --git a/packages/core/upload/admin/src/hooks/useFolders.js b/packages/core/upload/admin/src/hooks/useFolders.js index 33acd601e0..084aea004a 100644 --- a/packages/core/upload/admin/src/hooks/useFolders.js +++ b/packages/core/upload/admin/src/hooks/useFolders.js @@ -1,4 +1,3 @@ -import { useEffect } from 'react'; import { useQuery } from 'react-query'; import { useNotifyAT } from '@strapi/design-system/LiveRegions'; import { useNotification, useQueryParams } from '@strapi/helper-plugin'; @@ -13,9 +12,25 @@ export const useFolders = ({ enabled = true }) => { const dataRequestURL = getRequestUrl('folders'); const fetchFolders = async () => { - const { data } = await axiosInstance.get(`${dataRequestURL}${rawQuery}`); + try { + const { data } = await axiosInstance.get(`${dataRequestURL}${rawQuery}`); - return data; + notifyStatus( + formatMessage({ + id: 'list.asset.at.finished', + defaultMessage: 'The folders have finished loading.', + }) + ); + + return data; + } catch (err) { + toggleNotification({ + type: 'warning', + message: { id: 'notification.error' }, + }); + + throw err; + } }; const { data, error, isLoading } = useQuery([`folders`, rawQuery], fetchFolders, { @@ -24,25 +39,5 @@ export const useFolders = ({ enabled = true }) => { cacheTime: 0, }); - useEffect(() => { - if (data) { - notifyStatus( - formatMessage({ - id: 'list.asset.at.finished', - defaultMessage: 'The folders have finished loading.', - }) - ); - } - }, [data, notifyStatus, formatMessage]); - - useEffect(() => { - if (error) { - toggleNotification({ - type: 'warning', - message: { id: 'notification.error' }, - }); - } - }, [error, toggleNotification]); - return { data, error, isLoading }; }; From 408d40a6b852d50d00c69c4c73fdd6ebdb881577 Mon Sep 17 00:00:00 2001 From: Gustav Hansen Date: Mon, 14 Mar 2022 08:40:20 +0100 Subject: [PATCH 06/30] ML: Add FolderCard component --- .../src/components/FolderCard/FolderCard.js | 92 +++++++++++ .../components/FolderCard/FolderCardBody.js | 25 +++ .../FolderCard/FolderCardCheckbox.js | 14 ++ .../FolderCard/FolderCardContext.js | 7 + .../components/FolderCard/FolderCardLink.js | 7 + .../admin/src/components/FolderCard/index.js | 4 + .../FolderCard/tests/FolderCard.test.js | 65 ++++++++ .../__snapshots__/FolderCard.test.js.snap | 149 ++++++++++++++++++ .../FolderCard/utils/tests/useId.test.js | 42 +++++ .../src/components/FolderCard/utils/useId.js | 13 ++ 10 files changed, 418 insertions(+) create mode 100644 packages/core/upload/admin/src/components/FolderCard/FolderCard.js create mode 100644 packages/core/upload/admin/src/components/FolderCard/FolderCardBody.js create mode 100644 packages/core/upload/admin/src/components/FolderCard/FolderCardCheckbox.js create mode 100644 packages/core/upload/admin/src/components/FolderCard/FolderCardContext.js create mode 100644 packages/core/upload/admin/src/components/FolderCard/FolderCardLink.js create mode 100644 packages/core/upload/admin/src/components/FolderCard/index.js create mode 100644 packages/core/upload/admin/src/components/FolderCard/tests/FolderCard.test.js create mode 100644 packages/core/upload/admin/src/components/FolderCard/tests/__snapshots__/FolderCard.test.js.snap create mode 100644 packages/core/upload/admin/src/components/FolderCard/utils/tests/useId.test.js create mode 100644 packages/core/upload/admin/src/components/FolderCard/utils/useId.js diff --git a/packages/core/upload/admin/src/components/FolderCard/FolderCard.js b/packages/core/upload/admin/src/components/FolderCard/FolderCard.js new file mode 100644 index 0000000000..a297ffa2ba --- /dev/null +++ b/packages/core/upload/admin/src/components/FolderCard/FolderCard.js @@ -0,0 +1,92 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import styled from 'styled-components'; + +import { pxToRem } from '@strapi/helper-plugin'; +import { Box } from '@strapi/design-system/Box'; +import { Stack } from '@strapi/design-system/Stack'; +import Folder from '@strapi/icons/Folder'; + +import { FolderCardContext } from './FolderCardContext'; +import useId from './utils/useId'; + +const FauxClickWrapper = styled.button` + height: 100%; + left: 0; + position: absolute; + opacity: 0; + top: 0; + width: 100%; + + &:hover, + &:focus { + text-decoration: none; + } +`; + +const StyledFolder = styled(Folder)` + path { + fill: currentColor; + } +`; + +export const FolderCard = ({ children, id, startAction, ariaLabel, onDoubleClick, ...props }) => { + const generatedId = useId(id); + + return ( + + + event.preventDefault()} + onDoubleClick={onDoubleClick} + zIndex={1} + tabIndex={-1} + aria-label={ariaLabel} + aria-hidden + /> + + + {startAction} + + + + + + {children} + + + + ); +}; + +FolderCard.defaultProps = { + id: undefined, +}; + +FolderCard.propTypes = { + ariaLabel: PropTypes.string.isRequired, + children: PropTypes.node.isRequired, + id: PropTypes.string, + onDoubleClick: PropTypes.func.isRequired, + startAction: PropTypes.element.isRequired, +}; diff --git a/packages/core/upload/admin/src/components/FolderCard/FolderCardBody.js b/packages/core/upload/admin/src/components/FolderCard/FolderCardBody.js new file mode 100644 index 0000000000..bd7ecb5cb5 --- /dev/null +++ b/packages/core/upload/admin/src/components/FolderCard/FolderCardBody.js @@ -0,0 +1,25 @@ +import React from 'react'; +import styled from 'styled-components'; + +import { Flex } from '@strapi/design-system/Flex'; + +import { useFolderCard } from './FolderCardContext'; + +const StyledBox = styled(Flex)` + user-select: none; +`; + +export const FolderCardBody = props => { + const { id } = useFolderCard(); + + return ( + + ); +}; diff --git a/packages/core/upload/admin/src/components/FolderCard/FolderCardCheckbox.js b/packages/core/upload/admin/src/components/FolderCard/FolderCardCheckbox.js new file mode 100644 index 0000000000..ced28a17cc --- /dev/null +++ b/packages/core/upload/admin/src/components/FolderCard/FolderCardCheckbox.js @@ -0,0 +1,14 @@ +import React from 'react'; +import { Box } from '@strapi/design-system/Box'; +import { BaseCheckbox } from '@strapi/design-system/BaseCheckbox'; +import { useFolderCard } from './FolderCardContext'; + +export const FolderCardCheckbox = props => { + const { id } = useFolderCard(); + + return ( + + + + ); +}; diff --git a/packages/core/upload/admin/src/components/FolderCard/FolderCardContext.js b/packages/core/upload/admin/src/components/FolderCard/FolderCardContext.js new file mode 100644 index 0000000000..985ae836d9 --- /dev/null +++ b/packages/core/upload/admin/src/components/FolderCard/FolderCardContext.js @@ -0,0 +1,7 @@ +import { createContext, useContext } from 'react'; + +export const FolderCardContext = createContext(); + +export function useFolderCard() { + return useContext(FolderCardContext); +} diff --git a/packages/core/upload/admin/src/components/FolderCard/FolderCardLink.js b/packages/core/upload/admin/src/components/FolderCard/FolderCardLink.js new file mode 100644 index 0000000000..f5cf80ceb5 --- /dev/null +++ b/packages/core/upload/admin/src/components/FolderCard/FolderCardLink.js @@ -0,0 +1,7 @@ +import styled from 'styled-components'; + +import { BaseLink } from '@strapi/design-system/BaseLink'; + +export const FolderCardLink = styled(BaseLink)` + text-decoration: none; +`; diff --git a/packages/core/upload/admin/src/components/FolderCard/index.js b/packages/core/upload/admin/src/components/FolderCard/index.js new file mode 100644 index 0000000000..4da01d2615 --- /dev/null +++ b/packages/core/upload/admin/src/components/FolderCard/index.js @@ -0,0 +1,4 @@ +export { FolderCard } from './FolderCard'; +export { FolderCardBody } from './FolderCardBody'; +export { FolderCardCheckbox } from './FolderCardCheckbox'; +export { FolderCardLink } from './FolderCardLink'; diff --git a/packages/core/upload/admin/src/components/FolderCard/tests/FolderCard.test.js b/packages/core/upload/admin/src/components/FolderCard/tests/FolderCard.test.js new file mode 100644 index 0000000000..e91e4408d5 --- /dev/null +++ b/packages/core/upload/admin/src/components/FolderCard/tests/FolderCard.test.js @@ -0,0 +1,65 @@ +import React from 'react'; +import { BaseLink } from '@strapi/design-system/BaseLink'; +import { Flex } from '@strapi/design-system/Flex'; +import { ThemeProvider, lightTheme } from '@strapi/design-system'; +import { Typography } from '@strapi/design-system/Typography'; +import { render, fireEvent } from '@testing-library/react'; + +import { FolderCard } from '../FolderCard'; +import { FolderCardBody } from '../FolderCardBody'; +import { FolderCardCheckbox } from '../FolderCardCheckbox'; + +const ID_FIXTURE = 'folder-1'; + +// eslint-disable-next-line react/prop-types +const ComponentFixture = ({ children, ...props }) => { + return ( + + } + onDoubleClick={() => {}} + {...props} + > + {children || ''} + + + ); +}; + +describe('FolderCard', () => { + it('renders and matches the snapshot', () => { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); + + it('properly calls the onDoubleClick callback', () => { + const callback = jest.fn(); + const { container } = render(); + + fireEvent(container.querySelector('a'), new MouseEvent('dblclick', { bubbles: true })); + + expect(callback).toHaveBeenCalledTimes(1); + }); + + it('has all required ids set when rendering a start action', () => { + const { container } = render( + }> + + + + + Pictures + + + + + + ); + + expect(container.querySelector(`[id="${ID_FIXTURE}-title"]`)).toBeInTheDocument(); + expect(container.querySelector(`[aria-labelledby="${ID_FIXTURE}-title"]`)).toBeInTheDocument(); + }); +}); diff --git a/packages/core/upload/admin/src/components/FolderCard/tests/__snapshots__/FolderCard.test.js.snap b/packages/core/upload/admin/src/components/FolderCard/tests/__snapshots__/FolderCard.test.js.snap new file mode 100644 index 0000000000..2851e7ab2a --- /dev/null +++ b/packages/core/upload/admin/src/components/FolderCard/tests/__snapshots__/FolderCard.test.js.snap @@ -0,0 +1,149 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`FolderCard renders and matches the snapshot 1`] = ` +.c1 { + cursor: pointer; +} + +.c8 { + border: 0; + -webkit-clip: rect(0 0 0 0); + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} + +.c0 { + position: relative; +} + +.c6 { + background: #eaf5ff; + color: #66b7f1; + padding-top: 8px; + padding-right: 12px; + padding-bottom: 8px; + padding-left: 12px; + border-radius: 4px; +} + +.c3 { + background: #ffffff; + padding-top: 12px; + padding-right: 16px; + padding-bottom: 12px; + padding-left: 16px; + border-radius: 4px; + box-shadow: 0px 1px 4px rgba(33,33,52,0.1); + cursor: pointer; + cursor: pointer; +} + +.c4 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.c5 > * { + margin-left: 0; + margin-right: 0; +} + +.c5 > * + * { + margin-left: 12px; +} + +.c2 { + height: 100%; + left: 0; + position: absolute; + opacity: 0; + top: 0; + width: 100%; +} + +.c2:hover, +.c2:focus { + -webkit-text-decoration: none; + text-decoration: none; +} + +.c7 path { + fill: currentColor; +} + + +`; + +exports[`FolderCard renders and matches the snapshot 1`] = ` +.c10 { + cursor: pointer; +} + +.c7 { + position: relative; + z-index: 3; +} + +.c8 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; +} + +.c12 { + border: 0; + -webkit-clip: rect(0 0 0 0); + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} + +.c11 { + font-weight: 500; + color: #32324d; + font-size: 0.875rem; + line-height: 1.43; +} + +.c0 { + position: relative; +} + +.c5 { + background: #eaf5ff; + color: #66b7f1; + padding-top: 8px; + padding-right: 12px; + padding-bottom: 8px; + padding-left: 12px; + border-radius: 4px; +} + +.c2 { + background: #ffffff; + padding-top: 12px; + padding-right: 16px; + padding-bottom: 12px; + padding-left: 16px; + border-radius: 4px; + box-shadow: 0px 1px 4px rgba(33,33,52,0.1); + cursor: pointer; + cursor: pointer; +} + +.c3 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.c4 > * { + margin-left: 0; + margin-right: 0; +} + +.c4 > * + * { + margin-left: 12px; +} + +.c1 { + height: 100%; + left: 0; + position: absolute; + opacity: 0; + top: 0; + width: 100%; +} + +.c1:hover, +.c1:focus { + -webkit-text-decoration: none; + text-decoration: none; +} + +.c6 path { + fill: currentColor; +} + +.c9 { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +
+
+
+

Date: Thu, 24 Mar 2022 17:31:44 +0100 Subject: [PATCH 08/30] FolderCard: Restructure component files --- .../components/FolderCard/{ => FolderCard}/FolderCard.js | 6 +++--- .../admin/src/components/FolderCard/FolderCard/index.js | 1 + .../FolderCard/{ => FolderCardBody}/FolderCardBody.js | 2 +- .../src/components/FolderCard/FolderCardBody/index.js | 1 + .../{ => FolderCardCheckbox}/FolderCardCheckbox.js | 2 +- .../src/components/FolderCard/FolderCardCheckbox/index.js | 1 + .../{FolderCardContext.js => contexts/FolderCard.js} | 2 +- .../FolderCard/{utils => hooks}/tests/useId.test.js | 0 .../src/components/FolderCard/{utils => hooks}/useId.js | 4 ++-- .../core/upload/admin/src/components/FolderCard/index.js | 3 ++- .../FolderCard/{FolderCardLink.js => styled.js} | 0 .../src/components/FolderCard/tests/FolderCard.test.js | 3 +-- .../tests/__snapshots__/FolderCard.test.js.snap | 8 +++----- 13 files changed, 17 insertions(+), 16 deletions(-) rename packages/core/upload/admin/src/components/FolderCard/{ => FolderCard}/FolderCard.js (93%) create mode 100644 packages/core/upload/admin/src/components/FolderCard/FolderCard/index.js rename packages/core/upload/admin/src/components/FolderCard/{ => FolderCardBody}/FolderCardBody.js (88%) create mode 100644 packages/core/upload/admin/src/components/FolderCard/FolderCardBody/index.js rename packages/core/upload/admin/src/components/FolderCard/{ => FolderCardCheckbox}/FolderCardCheckbox.js (86%) create mode 100644 packages/core/upload/admin/src/components/FolderCard/FolderCardCheckbox/index.js rename packages/core/upload/admin/src/components/FolderCard/{FolderCardContext.js => contexts/FolderCard.js} (71%) rename packages/core/upload/admin/src/components/FolderCard/{utils => hooks}/tests/useId.test.js (100%) rename packages/core/upload/admin/src/components/FolderCard/{utils => hooks}/useId.js (55%) rename packages/core/upload/admin/src/components/FolderCard/{FolderCardLink.js => styled.js} (100%) diff --git a/packages/core/upload/admin/src/components/FolderCard/FolderCard.js b/packages/core/upload/admin/src/components/FolderCard/FolderCard/FolderCard.js similarity index 93% rename from packages/core/upload/admin/src/components/FolderCard/FolderCard.js rename to packages/core/upload/admin/src/components/FolderCard/FolderCard/FolderCard.js index a297ffa2ba..462412cd6d 100644 --- a/packages/core/upload/admin/src/components/FolderCard/FolderCard.js +++ b/packages/core/upload/admin/src/components/FolderCard/FolderCard/FolderCard.js @@ -7,8 +7,8 @@ import { Box } from '@strapi/design-system/Box'; import { Stack } from '@strapi/design-system/Stack'; import Folder from '@strapi/icons/Folder'; -import { FolderCardContext } from './FolderCardContext'; -import useId from './utils/useId'; +import { FolderCardContext } from '../contexts/FolderCard'; +import useId from '../hooks/useId'; const FauxClickWrapper = styled.button` height: 100%; @@ -31,7 +31,7 @@ const StyledFolder = styled(Folder)` `; export const FolderCard = ({ children, id, startAction, ariaLabel, onDoubleClick, ...props }) => { - const generatedId = useId(id); + const generatedId = useId('folder', id); return ( diff --git a/packages/core/upload/admin/src/components/FolderCard/FolderCard/index.js b/packages/core/upload/admin/src/components/FolderCard/FolderCard/index.js new file mode 100644 index 0000000000..1aad1f19f4 --- /dev/null +++ b/packages/core/upload/admin/src/components/FolderCard/FolderCard/index.js @@ -0,0 +1 @@ +export * from './FolderCard'; diff --git a/packages/core/upload/admin/src/components/FolderCard/FolderCardBody.js b/packages/core/upload/admin/src/components/FolderCard/FolderCardBody/FolderCardBody.js similarity index 88% rename from packages/core/upload/admin/src/components/FolderCard/FolderCardBody.js rename to packages/core/upload/admin/src/components/FolderCard/FolderCardBody/FolderCardBody.js index bd7ecb5cb5..41a9d1d3da 100644 --- a/packages/core/upload/admin/src/components/FolderCard/FolderCardBody.js +++ b/packages/core/upload/admin/src/components/FolderCard/FolderCardBody/FolderCardBody.js @@ -3,7 +3,7 @@ import styled from 'styled-components'; import { Flex } from '@strapi/design-system/Flex'; -import { useFolderCard } from './FolderCardContext'; +import { useFolderCard } from '../contexts/FolderCard'; const StyledBox = styled(Flex)` user-select: none; diff --git a/packages/core/upload/admin/src/components/FolderCard/FolderCardBody/index.js b/packages/core/upload/admin/src/components/FolderCard/FolderCardBody/index.js new file mode 100644 index 0000000000..0368e72b9c --- /dev/null +++ b/packages/core/upload/admin/src/components/FolderCard/FolderCardBody/index.js @@ -0,0 +1 @@ +export * from './FolderCardBody'; diff --git a/packages/core/upload/admin/src/components/FolderCard/FolderCardCheckbox.js b/packages/core/upload/admin/src/components/FolderCard/FolderCardCheckbox/FolderCardCheckbox.js similarity index 86% rename from packages/core/upload/admin/src/components/FolderCard/FolderCardCheckbox.js rename to packages/core/upload/admin/src/components/FolderCard/FolderCardCheckbox/FolderCardCheckbox.js index ced28a17cc..8e0102f5da 100644 --- a/packages/core/upload/admin/src/components/FolderCard/FolderCardCheckbox.js +++ b/packages/core/upload/admin/src/components/FolderCard/FolderCardCheckbox/FolderCardCheckbox.js @@ -1,7 +1,7 @@ import React from 'react'; import { Box } from '@strapi/design-system/Box'; import { BaseCheckbox } from '@strapi/design-system/BaseCheckbox'; -import { useFolderCard } from './FolderCardContext'; +import { useFolderCard } from '../contexts/FolderCard'; export const FolderCardCheckbox = props => { const { id } = useFolderCard(); diff --git a/packages/core/upload/admin/src/components/FolderCard/FolderCardCheckbox/index.js b/packages/core/upload/admin/src/components/FolderCard/FolderCardCheckbox/index.js new file mode 100644 index 0000000000..90201eab84 --- /dev/null +++ b/packages/core/upload/admin/src/components/FolderCard/FolderCardCheckbox/index.js @@ -0,0 +1 @@ +export * from './FolderCardCheckbox'; diff --git a/packages/core/upload/admin/src/components/FolderCard/FolderCardContext.js b/packages/core/upload/admin/src/components/FolderCard/contexts/FolderCard.js similarity index 71% rename from packages/core/upload/admin/src/components/FolderCard/FolderCardContext.js rename to packages/core/upload/admin/src/components/FolderCard/contexts/FolderCard.js index 985ae836d9..27aaa7dc0b 100644 --- a/packages/core/upload/admin/src/components/FolderCard/FolderCardContext.js +++ b/packages/core/upload/admin/src/components/FolderCard/contexts/FolderCard.js @@ -1,6 +1,6 @@ import { createContext, useContext } from 'react'; -export const FolderCardContext = createContext(); +export const FolderCardContext = createContext({}); export function useFolderCard() { return useContext(FolderCardContext); diff --git a/packages/core/upload/admin/src/components/FolderCard/utils/tests/useId.test.js b/packages/core/upload/admin/src/components/FolderCard/hooks/tests/useId.test.js similarity index 100% rename from packages/core/upload/admin/src/components/FolderCard/utils/tests/useId.test.js rename to packages/core/upload/admin/src/components/FolderCard/hooks/tests/useId.test.js diff --git a/packages/core/upload/admin/src/components/FolderCard/utils/useId.js b/packages/core/upload/admin/src/components/FolderCard/hooks/useId.js similarity index 55% rename from packages/core/upload/admin/src/components/FolderCard/utils/useId.js rename to packages/core/upload/admin/src/components/FolderCard/hooks/useId.js index 91b8b43377..aeef81cfb7 100644 --- a/packages/core/upload/admin/src/components/FolderCard/utils/useId.js +++ b/packages/core/upload/admin/src/components/FolderCard/hooks/useId.js @@ -4,8 +4,8 @@ let id = 0; const genId = () => ++id; -const useId = (prefix, initialId) => { - const idRef = useRef(initialId || `${prefix}-${genId()}`); +const useId = initialId => { + const idRef = useRef(`${initialId}-${genId()}`); return idRef.current; }; diff --git a/packages/core/upload/admin/src/components/FolderCard/index.js b/packages/core/upload/admin/src/components/FolderCard/index.js index 4da01d2615..0d973c3898 100644 --- a/packages/core/upload/admin/src/components/FolderCard/index.js +++ b/packages/core/upload/admin/src/components/FolderCard/index.js @@ -1,4 +1,5 @@ export { FolderCard } from './FolderCard'; export { FolderCardBody } from './FolderCardBody'; export { FolderCardCheckbox } from './FolderCardCheckbox'; -export { FolderCardLink } from './FolderCardLink'; + +export { FolderCardLink } from './styled'; diff --git a/packages/core/upload/admin/src/components/FolderCard/FolderCardLink.js b/packages/core/upload/admin/src/components/FolderCard/styled.js similarity index 100% rename from packages/core/upload/admin/src/components/FolderCard/FolderCardLink.js rename to packages/core/upload/admin/src/components/FolderCard/styled.js diff --git a/packages/core/upload/admin/src/components/FolderCard/tests/FolderCard.test.js b/packages/core/upload/admin/src/components/FolderCard/tests/FolderCard.test.js index a46955a338..8fcf24e54e 100644 --- a/packages/core/upload/admin/src/components/FolderCard/tests/FolderCard.test.js +++ b/packages/core/upload/admin/src/components/FolderCard/tests/FolderCard.test.js @@ -9,7 +9,7 @@ import { FolderCard } from '../FolderCard'; import { FolderCardBody } from '../FolderCardBody'; import { FolderCardCheckbox } from '../FolderCardCheckbox'; -const ID_FIXTURE = 'folder-1'; +const ID_FIXTURE = 'folder'; // eslint-disable-next-line react/prop-types const ComponentFixture = props => { @@ -18,7 +18,6 @@ const ComponentFixture = props => { } onDoubleClick={() => {}} {...props} diff --git a/packages/core/upload/admin/src/components/FolderCard/tests/__snapshots__/FolderCard.test.js.snap b/packages/core/upload/admin/src/components/FolderCard/tests/__snapshots__/FolderCard.test.js.snap index 33208d3da0..f8c8111206 100644 --- a/packages/core/upload/admin/src/components/FolderCard/tests/__snapshots__/FolderCard.test.js.snap +++ b/packages/core/upload/admin/src/components/FolderCard/tests/__snapshots__/FolderCard.test.js.snap @@ -194,7 +194,6 @@ exports[`FolderCard has all required ids set when rendering a start action 1`] =

+
+

+
+
+

+

+

+
+ , + "container":
+
+ +
+
+
+ Select... +
+
+
+ +
+
+
+
+
+ +
+
+
+
+

+

+

+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; diff --git a/packages/core/upload/admin/src/components/SelectTree/utils/flattenTree.js b/packages/core/upload/admin/src/components/SelectTree/utils/flattenTree.js new file mode 100644 index 0000000000..059a1faa39 --- /dev/null +++ b/packages/core/upload/admin/src/components/SelectTree/utils/flattenTree.js @@ -0,0 +1,7 @@ +export default function flattenTree(tree, parent, depth = 1) { + return tree.flatMap(item => + item.children + ? [{ ...item, parent: parent?.value, depth }, ...flattenTree(item.children, item, depth + 1)] + : { ...item, depth, parent: parent?.value } + ); +} diff --git a/packages/core/upload/admin/src/components/SelectTree/utils/tests/__snapshots__/flattenTree.test.js.snap b/packages/core/upload/admin/src/components/SelectTree/utils/tests/__snapshots__/flattenTree.test.js.snap new file mode 100644 index 0000000000..4be0a38986 --- /dev/null +++ b/packages/core/upload/admin/src/components/SelectTree/utils/tests/__snapshots__/flattenTree.test.js.snap @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`flattenTree flattens the passed tree structure properly 1`] = ` +Array [ + Object { + "depth": 1, + "label": "Folder 1", + "parent": undefined, + "value": "f-1", + }, + Object { + "children": Array [ + Object { + "label": "Folder 2-1", + "value": "f-2-1", + }, + Object { + "children": Array [ + Object { + "label": "Folder 2-2-1", + "value": "f-2-2-1", + }, + ], + "label": "Folder 2-2", + "value": "f-2-2", + }, + ], + "depth": 1, + "label": "Folder 2", + "parent": undefined, + "value": "f-2", + }, + Object { + "depth": 2, + "label": "Folder 2-1", + "parent": "f-2", + "value": "f-2-1", + }, + Object { + "children": Array [ + Object { + "label": "Folder 2-2-1", + "value": "f-2-2-1", + }, + ], + "depth": 2, + "label": "Folder 2-2", + "parent": "f-2", + "value": "f-2-2", + }, + Object { + "depth": 3, + "label": "Folder 2-2-1", + "parent": "f-2-2", + "value": "f-2-2-1", + }, +] +`; diff --git a/packages/core/upload/admin/src/components/SelectTree/utils/tests/flattenTree.test.js b/packages/core/upload/admin/src/components/SelectTree/utils/tests/flattenTree.test.js new file mode 100644 index 0000000000..2ac9a71aaa --- /dev/null +++ b/packages/core/upload/admin/src/components/SelectTree/utils/tests/flattenTree.test.js @@ -0,0 +1,36 @@ +import flattenTree from '../flattenTree'; + +const FIXTURE = [ + { + value: 'f-1', + label: 'Folder 1', + }, + + { + value: 'f-2', + label: 'Folder 2', + children: [ + { + value: 'f-2-1', + label: 'Folder 2-1', + }, + + { + value: 'f-2-2', + label: 'Folder 2-2', + children: [ + { + value: 'f-2-2-1', + label: 'Folder 2-2-1', + }, + ], + }, + ], + }, +]; + +describe('flattenTree', () => { + test('flattens the passed tree structure properly', () => { + expect(flattenTree(FIXTURE)).toMatchSnapshot(); + }); +}); From bbacc0199394ed8a72840fd46ac20add29b58d32 Mon Sep 17 00:00:00 2001 From: Gustav Hansen Date: Wed, 6 Apr 2022 19:00:24 +0200 Subject: [PATCH 12/30] ReactSelect: Simplify handleToggle callback --- .../admin/src/components/SelectTree/SelectTree.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/core/upload/admin/src/components/SelectTree/SelectTree.js b/packages/core/upload/admin/src/components/SelectTree/SelectTree.js index ec4fe2b8c3..b8b886e850 100644 --- a/packages/core/upload/admin/src/components/SelectTree/SelectTree.js +++ b/packages/core/upload/admin/src/components/SelectTree/SelectTree.js @@ -46,34 +46,35 @@ const SelectTree = ({ options: defaultOptions, ...props }) => { }); }, [openValues, flatDefaultOptions, toplevelDefaultOptions]); - function handleToggle(e, data) { + function handleToggle(e, value) { e.preventDefault(); e.stopPropagation(); - if (openValues.includes(data.value)) { - setOpenValues(prev => prev.filter(prevData => prevData !== data.value)); + if (openValues.includes(value)) { + setOpenValues(prev => prev.filter(prevData => prevData !== value)); } else { - setOpenValues(prev => [...prev, data.value]); + setOpenValues(prev => [...prev, value]); } } const CustomOption = ({ children, data, ...props }) => { const hasChildren = data?.children?.length > 0; + const { depth, value } = data; return ( <> - {children} + {children} {hasChildren && ( - handleToggle(event, data)}> + handleToggle(event, value)}> )} From ba367622f9495e6b2e79d6fdc75a5d0e17c31b0e Mon Sep 17 00:00:00 2001 From: Gustav Hansen Date: Wed, 6 Apr 2022 19:01:19 +0200 Subject: [PATCH 13/30] ReactSelect: Cleanup import order --- .../core/upload/admin/src/components/SelectTree/SelectTree.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/upload/admin/src/components/SelectTree/SelectTree.js b/packages/core/upload/admin/src/components/SelectTree/SelectTree.js index b8b886e850..5d762aeb7a 100644 --- a/packages/core/upload/admin/src/components/SelectTree/SelectTree.js +++ b/packages/core/upload/admin/src/components/SelectTree/SelectTree.js @@ -7,11 +7,11 @@ import { components } from 'react-select'; import { Flex } from '@strapi/design-system/Flex'; import { Icon } from '@strapi/design-system/Icon'; +import { ReactSelect as Select, pxToRem } from '@strapi/helper-plugin'; import { Typography } from '@strapi/design-system/Typography'; import ChevronUp from '@strapi/icons/ChevronUp'; import ChevronDown from '@strapi/icons/ChevronDown'; -import { ReactSelect as Select, pxToRem } from '@strapi/helper-plugin'; import flattenTree from './utils/flattenTree'; const ToggleButton = styled.button` From d6792440b5e2ac71046c6f728bb014f8d0e18d17 Mon Sep 17 00:00:00 2001 From: Gustav Hansen Date: Wed, 6 Apr 2022 19:05:22 +0200 Subject: [PATCH 14/30] ReactSelect: Add maxDisplayDepth prop to determine max level of indention --- .../admin/src/components/SelectTree/SelectTree.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/core/upload/admin/src/components/SelectTree/SelectTree.js b/packages/core/upload/admin/src/components/SelectTree/SelectTree.js index 5d762aeb7a..6c037ff399 100644 --- a/packages/core/upload/admin/src/components/SelectTree/SelectTree.js +++ b/packages/core/upload/admin/src/components/SelectTree/SelectTree.js @@ -24,7 +24,7 @@ const hasParent = option => !option.parent; const hasParentOrMatchesValue = (option, value) => option.value === value || option.parent === value; -const SelectTree = ({ options: defaultOptions, ...props }) => { +const SelectTree = ({ options: defaultOptions, maxDisplayDepth, ...props }) => { const flatDefaultOptions = useMemo(() => flattenTree(defaultOptions), [defaultOptions]); const toplevelDefaultOptions = useMemo(() => flatDefaultOptions.filter(hasParent), [ flatDefaultOptions, @@ -60,13 +60,14 @@ const SelectTree = ({ options: defaultOptions, ...props }) => { const CustomOption = ({ children, data, ...props }) => { const hasChildren = data?.children?.length > 0; const { depth, value } = data; + const normalizedDepth = Math.min(depth, maxDisplayDepth); return ( <> - {children} + {children} {hasChildren && ( @@ -87,7 +88,12 @@ const SelectTree = ({ options: defaultOptions, ...props }) => { return ; }; +const OptionShape = PropTypes.shape({ + value: PropTypes.number.isRequired, + label: PropTypes.string.isRequired, + children: PropTypes.array, +}); + +OptionShape.children = PropTypes.arrayOf(PropTypes.shape(OptionShape)); + +OptionShape.defaultProps = { + children: undefined, +}; + SelectTree.defaultProps = { maxDisplayDepth: 5, }; SelectTree.propTypes = { maxDisplayDepth: PropTypes.number, - options: PropTypes.array.isRequired, + options: PropTypes.arrayOf(OptionShape).isRequired, }; export default SelectTree; From 2390640f41130f54cdd8694dfb85c3625fa9c3b8 Mon Sep 17 00:00:00 2001 From: Gustav Hansen Date: Thu, 7 Apr 2022 16:55:53 +0200 Subject: [PATCH 20/30] SelectTree: Move Option into it's own component --- .../admin/src/components/SelectTree/Option.js | 55 +++++++++++++++++ .../src/components/SelectTree/SelectTree.js | 60 ++++++------------- 2 files changed, 73 insertions(+), 42 deletions(-) create mode 100644 packages/core/upload/admin/src/components/SelectTree/Option.js diff --git a/packages/core/upload/admin/src/components/SelectTree/Option.js b/packages/core/upload/admin/src/components/SelectTree/Option.js new file mode 100644 index 0000000000..1d6c6ff31d --- /dev/null +++ b/packages/core/upload/admin/src/components/SelectTree/Option.js @@ -0,0 +1,55 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { components } from 'react-select'; +import styled from 'styled-components'; + +import { Flex } from '@strapi/design-system/Flex'; +import { Icon } from '@strapi/design-system/Icon'; +import { pxToRem } from '@strapi/helper-plugin'; +import { Typography } from '@strapi/design-system/Typography'; +import ChevronUp from '@strapi/icons/ChevronUp'; +import ChevronDown from '@strapi/icons/ChevronDown'; + +const ToggleButton = styled.button` + align-self: flex-end; + margin-left: auto; +`; + +const Option = ({ children, data, onToggle, isOpen, maxDisplayDepth, ...props }) => { + const hasChildren = data?.children?.length > 0; + const { depth, value } = data; + const normalizedDepth = Math.min(depth, maxDisplayDepth); + + return ( + <> + + + + {children} + + + {hasChildren && ( + onToggle(event, value)}> + + + )} + + + + ); +}; + +Option.defaultProps = { + isOpen: false, + maxDisplayDepth: 5, +}; + +Option.propTypes = { + children: PropTypes.arrayOf(PropTypes.element).isRequired, + data: PropTypes.object.isRequired, + isOpen: PropTypes.bool, + maxDisplayDepth: PropTypes.number, + onToggle: PropTypes.func.isRequired, +}; + +export default Option; diff --git a/packages/core/upload/admin/src/components/SelectTree/SelectTree.js b/packages/core/upload/admin/src/components/SelectTree/SelectTree.js index ecc4eef48c..b5d7b85297 100644 --- a/packages/core/upload/admin/src/components/SelectTree/SelectTree.js +++ b/packages/core/upload/admin/src/components/SelectTree/SelectTree.js @@ -1,24 +1,13 @@ /* eslint-disable react/prop-types */ import React, { useEffect, useState, useMemo } from 'react'; -import styled from 'styled-components'; import PropTypes from 'prop-types'; -import { components } from 'react-select'; +import { ReactSelect as Select } from '@strapi/helper-plugin'; -import { Flex } from '@strapi/design-system/Flex'; -import { Icon } from '@strapi/design-system/Icon'; -import { ReactSelect as Select, pxToRem } from '@strapi/helper-plugin'; -import { Typography } from '@strapi/design-system/Typography'; -import ChevronUp from '@strapi/icons/ChevronUp'; -import ChevronDown from '@strapi/icons/ChevronDown'; +import Option from './Option'; import flattenTree from './utils/flattenTree'; -const ToggleButton = styled.button` - align-self: flex-end; - margin-left: auto; -`; - const hasParent = option => !option.parent; const hasParentOrMatchesValue = (option, value) => @@ -57,35 +46,22 @@ const SelectTree = ({ options: defaultOptions, maxDisplayDepth, ...props }) => { } } - const CustomOption = ({ children, data, ...props }) => { - const hasChildren = data?.children?.length > 0; - const { depth, value } = data; - const normalizedDepth = Math.min(depth, maxDisplayDepth); - - return ( - <> - - - - {children} - - - {hasChildren && ( - handleToggle(event, value)}> - - - )} - - - - ); - }; - - return ( +