diff --git a/docs/source/configuration/settings-reference.md b/docs/source/configuration/settings-reference.md index 3dbc111b0e..63290c20c6 100644 --- a/docs/source/configuration/settings-reference.md +++ b/docs/source/configuration/settings-reference.md @@ -425,6 +425,22 @@ okRoute ```jsx config.settings.okRoute = '/site-is-ok' ``` + +siteTitleFormat + Volto lets you modify how the site title is built. + By default the site title only includes the title of the current page. + + By modifying this configuration setting, you can decide whether to use the title of the navigation root (either the site root or the language root folder) as the second part of the title. + + You can also decide the separator character between the current page title and the site title. + + ```jsx + siteTitleFormat: { + includeSiteTitle: true, + titleAndSiteTitleSeparator: '-', + } + ``` + ``` ## Views settings diff --git a/locales/ca/LC_MESSAGES/volto.po b/locales/ca/LC_MESSAGES/volto.po index d197af6a01..3538b2a89d 100644 --- a/locales/ca/LC_MESSAGES/volto.po +++ b/locales/ca/LC_MESSAGES/volto.po @@ -617,6 +617,7 @@ msgid "Choose Target" msgstr "Trieu Destí" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Choose a file msgid "Choose a file" msgstr "Trieu un fitxer" @@ -1118,16 +1119,19 @@ msgid "Drag and drop files from your computer onto this area or click the “Bro msgstr "Arrossegueu i deixeu anar fitxers des del vostre ordinador a aquesta àrea o feu clic al botó 'Examinar'." #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to replace the existing file msgid "Drop file here to replace the existing file" msgstr "Deixeu anar el fitxer aquí per substituir el fitxer existent" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to upload a new file msgid "Drop file here to upload a new file" msgstr "Deixeu anar el fitxer aquí per pujar un fitxer nou" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop files here ... msgid "Drop files here ..." msgstr "Deixeu fitxers aquí..." @@ -2591,11 +2595,6 @@ msgstr "" msgid "Plone Foundation" msgstr "Fundació Plone" -#: components/theme/Logo/Logo -# defaultMessage: Plone Site -msgid "Plone Site" -msgstr "Lloc de Plone" - #: components/theme/Footer/Footer # defaultMessage: Plone{reg} Open Source CMS/WCM msgid "Plone{reg} Open Source CMS/WCM" @@ -2837,6 +2836,7 @@ msgid "Repeat on" msgstr "Repetiu" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Replace existing file msgid "Replace existing file" msgstr "Substitueix el fitxer existent" @@ -3279,11 +3279,6 @@ msgstr "Redueix la barra d'eines" msgid "Sign in to start session" msgstr "Inicieu la sessió per iniciar la sessió" -#: components/theme/Logo/Logo -# defaultMessage: Site -msgid "Site" -msgstr "Lloc" - #: components/theme/NotFound/NotFound #: components/theme/Unauthorized/Unauthorized # defaultMessage: Site Administration diff --git a/locales/de/LC_MESSAGES/volto.po b/locales/de/LC_MESSAGES/volto.po index f4db91efd4..977225a343 100644 --- a/locales/de/LC_MESSAGES/volto.po +++ b/locales/de/LC_MESSAGES/volto.po @@ -614,6 +614,7 @@ msgid "Choose Target" msgstr "Ziel auswählen" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Choose a file msgid "Choose a file" msgstr "Datei auswählen" @@ -1115,16 +1116,19 @@ msgid "Drag and drop files from your computer onto this area or click the “Bro msgstr "Ziehen Sie Dateien von Ihrem Computer auf diesen Bereich oder drücken Sie den “Durchsuchen”-Knopf." #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to replace the existing file msgid "Drop file here to replace the existing file" msgstr "Datei hier ablegen um die bestehende Datei zu ersetzen" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to upload a new file msgid "Drop file here to upload a new file" msgstr "Datei hier ablegen um eine neue Datei hochzuladen" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop files here ... msgid "Drop files here ..." msgstr "Datei hier ablegen um die bestehende Datei zu ersetzen" @@ -2588,11 +2592,6 @@ msgstr "Bitte upgraden Sie auf plone.restapi >= 8.39.0." msgid "Plone Foundation" msgstr "Plone Foundation" -#: components/theme/Logo/Logo -# defaultMessage: Plone Site -msgid "Plone Site" -msgstr "Website" - #: components/theme/Footer/Footer # defaultMessage: Plone{reg} Open Source CMS/WCM msgid "Plone{reg} Open Source CMS/WCM" @@ -2834,6 +2833,7 @@ msgid "Repeat on" msgstr "Wiederhole am" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Replace existing file msgid "Replace existing file" msgstr "Bestehende Datei ersetzen" @@ -3276,11 +3276,6 @@ msgstr "Toolbar verkleinern" msgid "Sign in to start session" msgstr "Loggen Sie sich ein" -#: components/theme/Logo/Logo -# defaultMessage: Site -msgid "Site" -msgstr "Website" - #: components/theme/NotFound/NotFound #: components/theme/Unauthorized/Unauthorized # defaultMessage: Site Administration diff --git a/locales/en/LC_MESSAGES/volto.po b/locales/en/LC_MESSAGES/volto.po index 8171152488..54f0a3f7c6 100644 --- a/locales/en/LC_MESSAGES/volto.po +++ b/locales/en/LC_MESSAGES/volto.po @@ -608,6 +608,7 @@ msgid "Choose Target" msgstr "" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Choose a file msgid "Choose a file" msgstr "" @@ -1109,16 +1110,19 @@ msgid "Drag and drop files from your computer onto this area or click the “Bro msgstr "" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to replace the existing file msgid "Drop file here to replace the existing file" msgstr "" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to upload a new file msgid "Drop file here to upload a new file" msgstr "" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop files here ... msgid "Drop files here ..." msgstr "" @@ -2582,11 +2586,6 @@ msgstr "" msgid "Plone Foundation" msgstr "" -#: components/theme/Logo/Logo -# defaultMessage: Plone Site -msgid "Plone Site" -msgstr "" - #: components/theme/Footer/Footer # defaultMessage: Plone{reg} Open Source CMS/WCM msgid "Plone{reg} Open Source CMS/WCM" @@ -2828,6 +2827,7 @@ msgid "Repeat on" msgstr "" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Replace existing file msgid "Replace existing file" msgstr "" @@ -3270,11 +3270,6 @@ msgstr "" msgid "Sign in to start session" msgstr "" -#: components/theme/Logo/Logo -# defaultMessage: Site -msgid "Site" -msgstr "" - #: components/theme/NotFound/NotFound #: components/theme/Unauthorized/Unauthorized # defaultMessage: Site Administration diff --git a/locales/es/LC_MESSAGES/volto.po b/locales/es/LC_MESSAGES/volto.po index b937a85540..5f8187240d 100644 --- a/locales/es/LC_MESSAGES/volto.po +++ b/locales/es/LC_MESSAGES/volto.po @@ -619,6 +619,7 @@ msgid "Choose Target" msgstr "Seleccione destino" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Choose a file msgid "Choose a file" msgstr "Seleccionar Archivo" @@ -1120,16 +1121,19 @@ msgid "Drag and drop files from your computer onto this area or click the “Bro msgstr "Arrastre y suelte los archivos desde su computador en esta área o haga clic al botón “Seleccionar”." #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to replace the existing file msgid "Drop file here to replace the existing file" msgstr "Arrastre aquí el archivo para reemplazar el actual" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to upload a new file msgid "Drop file here to upload a new file" msgstr "Arrastre aquí el archivo para añadir un nuevo" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop files here ... msgid "Drop files here ..." msgstr "Arrastrar archivos aquí..." @@ -2593,11 +2597,6 @@ msgstr "Por favor, actualice a plone.restapi >= 8.39.0." msgid "Plone Foundation" msgstr "Fundación Plone" -#: components/theme/Logo/Logo -# defaultMessage: Plone Site -msgid "Plone Site" -msgstr "Sitio Plone" - #: components/theme/Footer/Footer # defaultMessage: Plone{reg} Open Source CMS/WCM msgid "Plone{reg} Open Source CMS/WCM" @@ -2839,6 +2838,7 @@ msgid "Repeat on" msgstr "Repetir el" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Replace existing file msgid "Replace existing file" msgstr "Sustituir el archivo actual" @@ -3281,11 +3281,6 @@ msgstr "Contraer barra de herramientas" msgid "Sign in to start session" msgstr "Acceda para iniciar sesión" -#: components/theme/Logo/Logo -# defaultMessage: Site -msgid "Site" -msgstr "Sitio" - #: components/theme/NotFound/NotFound #: components/theme/Unauthorized/Unauthorized # defaultMessage: Site Administration diff --git a/locales/eu/LC_MESSAGES/volto.po b/locales/eu/LC_MESSAGES/volto.po index 02d807f7e0..9db7472952 100644 --- a/locales/eu/LC_MESSAGES/volto.po +++ b/locales/eu/LC_MESSAGES/volto.po @@ -615,6 +615,7 @@ msgid "Choose Target" msgstr "Aukeratu helburua" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Choose a file msgid "Choose a file" msgstr "Aukeratu fitxategia" @@ -1116,16 +1117,19 @@ msgid "Drag and drop files from your computer onto this area or click the “Bro msgstr "Arrastatu fitxategiak hona edo erabili Arakatu botoia." #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to replace the existing file msgid "Drop file here to replace the existing file" msgstr "Arrastatu fitxategia hona orain dagoena ordezkatzeko" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to upload a new file msgid "Drop file here to upload a new file" msgstr "Arrastatu fitxategia hona fitxategi berria kargatzeko" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop files here ... msgid "Drop files here ..." msgstr "Arrastatu fitxategiak hona..." @@ -2589,11 +2593,6 @@ msgstr "" msgid "Plone Foundation" msgstr "Plone Fundazioa" -#: components/theme/Logo/Logo -# defaultMessage: Plone Site -msgid "Plone Site" -msgstr "Plone Ataria" - #: components/theme/Footer/Footer # defaultMessage: Plone{reg} Open Source CMS/WCM msgid "Plone{reg} Open Source CMS/WCM" @@ -2835,6 +2834,7 @@ msgid "Repeat on" msgstr "Egun honetan errepikatu" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Replace existing file msgid "Replace existing file" msgstr "Ordezkatu fitxategia" @@ -3277,11 +3277,6 @@ msgstr "Txikitu tresna-barra" msgid "Sign in to start session" msgstr "Sartu saioa hasteko" -#: components/theme/Logo/Logo -# defaultMessage: Site -msgid "Site" -msgstr "Ataria" - #: components/theme/NotFound/NotFound #: components/theme/Unauthorized/Unauthorized # defaultMessage: Site Administration diff --git a/locales/fi/LC_MESSAGES/volto.po b/locales/fi/LC_MESSAGES/volto.po index afb67c9006..75fd878ad1 100644 --- a/locales/fi/LC_MESSAGES/volto.po +++ b/locales/fi/LC_MESSAGES/volto.po @@ -619,6 +619,7 @@ msgid "Choose Target" msgstr "Valitse sisältö" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Choose a file msgid "Choose a file" msgstr "Valitse tiedosto" @@ -1120,16 +1121,19 @@ msgid "Drag and drop files from your computer onto this area or click the “Bro msgstr "Raahaa ja pudota tiedostoja tietokoneeltasi tähän tai paina “Selaa”." #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to replace the existing file msgid "Drop file here to replace the existing file" msgstr "Pudota tiedosto tähän korvataksesi olemassaolevan tiedoston" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to upload a new file msgid "Drop file here to upload a new file" msgstr "Pudota tiedosto tähän ladataksesi uuden tiedoston" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop files here ... msgid "Drop files here ..." msgstr "Pudota tiedosto tänne... " @@ -2593,11 +2597,6 @@ msgstr "" msgid "Plone Foundation" msgstr "Plone-säätiön" -#: components/theme/Logo/Logo -# defaultMessage: Plone Site -msgid "Plone Site" -msgstr "Plone-sivusto" - #: components/theme/Footer/Footer # defaultMessage: Plone{reg} Open Source CMS/WCM msgid "Plone{reg} Open Source CMS/WCM" @@ -2839,6 +2838,7 @@ msgid "Repeat on" msgstr "Toista" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Replace existing file msgid "Replace existing file" msgstr "Korvaa olemassaoleva tiedosto" @@ -3281,11 +3281,6 @@ msgstr "Kutista työkalupalkki" msgid "Sign in to start session" msgstr "Kirjaudu sisään" -#: components/theme/Logo/Logo -# defaultMessage: Site -msgid "Site" -msgstr "Sivusto" - #: components/theme/NotFound/NotFound #: components/theme/Unauthorized/Unauthorized # defaultMessage: Site Administration diff --git a/locales/fr/LC_MESSAGES/volto.po b/locales/fr/LC_MESSAGES/volto.po index dc469ad9ae..3ae148bbf9 100644 --- a/locales/fr/LC_MESSAGES/volto.po +++ b/locales/fr/LC_MESSAGES/volto.po @@ -625,6 +625,7 @@ msgid "Choose Target" msgstr "Choisir une cible" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Choose a file msgid "Choose a file" msgstr "Choisissez un fichier" @@ -1126,16 +1127,19 @@ msgid "Drag and drop files from your computer onto this area or click the “Bro msgstr "Glisser et déposer les fichiers depuis votre ordinateur dans la zone ou cliquer sur le bouton “Explore“" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to replace the existing file msgid "Drop file here to replace the existing file" msgstr "Déposez le fichier ici pour remplacer le fichier existant" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to upload a new file msgid "Drop file here to upload a new file" msgstr "Déposez le fichier ici pour télécharger un nouveau fichier" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop files here ... msgid "Drop files here ..." msgstr "Déposez les fichiers ici ..." @@ -2599,11 +2603,6 @@ msgstr "" msgid "Plone Foundation" msgstr "Fondation Plone" -#: components/theme/Logo/Logo -# defaultMessage: Plone Site -msgid "Plone Site" -msgstr "Site Plone" - #: components/theme/Footer/Footer # defaultMessage: Plone{reg} Open Source CMS/WCM msgid "Plone{reg} Open Source CMS/WCM" @@ -2845,6 +2844,7 @@ msgid "Repeat on" msgstr "Répétition le" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Replace existing file msgid "Replace existing file" msgstr "Remplacer le fichier existant" @@ -3287,11 +3287,6 @@ msgstr "Réduire la barre d'outils" msgid "Sign in to start session" msgstr "Connectez-vous pour démarrer la session" -#: components/theme/Logo/Logo -# defaultMessage: Site -msgid "Site" -msgstr "Site" - #: components/theme/NotFound/NotFound #: components/theme/Unauthorized/Unauthorized # defaultMessage: Site Administration diff --git a/locales/it/LC_MESSAGES/volto.po b/locales/it/LC_MESSAGES/volto.po index bbeafaf016..6e4a15f1a7 100644 --- a/locales/it/LC_MESSAGES/volto.po +++ b/locales/it/LC_MESSAGES/volto.po @@ -608,6 +608,7 @@ msgid "Choose Target" msgstr "Seleziona la destinazione" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Choose a file msgid "Choose a file" msgstr "Scegli un file" @@ -1109,16 +1110,19 @@ msgid "Drag and drop files from your computer onto this area or click the “Bro msgstr "Trascina in quest'area i file dal tuo computer o clicca su “Sfoglia”." #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to replace the existing file msgid "Drop file here to replace the existing file" msgstr "Rilascia un file qui per sostituire quello esistente" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to upload a new file msgid "Drop file here to upload a new file" msgstr "Rilascia un file qui per caricare un nuovo file" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop files here ... msgid "Drop files here ..." msgstr "Rilascia file qui..." @@ -2582,11 +2586,6 @@ msgstr "Effettua l'aggiornamento a plone.restapi >= 8.39.0" msgid "Plone Foundation" msgstr "Plone Foundation" -#: components/theme/Logo/Logo -# defaultMessage: Plone Site -msgid "Plone Site" -msgstr "Sito Plone" - #: components/theme/Footer/Footer # defaultMessage: Plone{reg} Open Source CMS/WCM msgid "Plone{reg} Open Source CMS/WCM" @@ -2828,6 +2827,7 @@ msgid "Repeat on" msgstr "Ripeti ogni" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Replace existing file msgid "Replace existing file" msgstr "Sostituisci file esistente" @@ -3270,11 +3270,6 @@ msgstr "Riduci la toolbar" msgid "Sign in to start session" msgstr "Accedi per iniziare la sessione" -#: components/theme/Logo/Logo -# defaultMessage: Site -msgid "Site" -msgstr "Sito" - #: components/theme/NotFound/NotFound #: components/theme/Unauthorized/Unauthorized # defaultMessage: Site Administration diff --git a/locales/ja/LC_MESSAGES/volto.po b/locales/ja/LC_MESSAGES/volto.po index 32198dfc3f..a7c0665a8b 100644 --- a/locales/ja/LC_MESSAGES/volto.po +++ b/locales/ja/LC_MESSAGES/volto.po @@ -616,6 +616,7 @@ msgid "Choose Target" msgstr "ターゲットを選択" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Choose a file msgid "Choose a file" msgstr "ファイルを選択" @@ -1117,16 +1118,19 @@ msgid "Drag and drop files from your computer onto this area or click the “Bro msgstr "ここにファイルをドラッグ、または「参照」ボタンをクリック" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to replace the existing file msgid "Drop file here to replace the existing file" msgstr "ファイルをここにドロップして、既存のファイルを置き換え" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to upload a new file msgid "Drop file here to upload a new file" msgstr "ファイルをここにドロップして、新しいファイルをアップロード" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop files here ... msgid "Drop files here ..." msgstr "ファイルをここにドロップ" @@ -2590,11 +2594,6 @@ msgstr "" msgid "Plone Foundation" msgstr "Plone Foundation" -#: components/theme/Logo/Logo -# defaultMessage: Plone Site -msgid "Plone Site" -msgstr "Ploneサイト" - #: components/theme/Footer/Footer # defaultMessage: Plone{reg} Open Source CMS/WCM msgid "Plone{reg} Open Source CMS/WCM" @@ -2836,6 +2835,7 @@ msgid "Repeat on" msgstr "日または曜日" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Replace existing file msgid "Replace existing file" msgstr "ファイルの置き換え" @@ -3278,11 +3278,6 @@ msgstr "ツールバーを閉じる" msgid "Sign in to start session" msgstr "ログインしてセッションを開始" -#: components/theme/Logo/Logo -# defaultMessage: Site -msgid "Site" -msgstr "サイト" - #: components/theme/NotFound/NotFound #: components/theme/Unauthorized/Unauthorized # defaultMessage: Site Administration diff --git a/locales/nl/LC_MESSAGES/volto.po b/locales/nl/LC_MESSAGES/volto.po index 6d031b47a7..d8c1028fb9 100644 --- a/locales/nl/LC_MESSAGES/volto.po +++ b/locales/nl/LC_MESSAGES/volto.po @@ -627,6 +627,7 @@ msgid "Choose Target" msgstr "" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Choose a file msgid "Choose a file" msgstr "" @@ -1128,16 +1129,19 @@ msgid "Drag and drop files from your computer onto this area or click the “Bro msgstr "Drag en drop bestanden van uw computer naar dit gebied of klik op de “Bladeren” knop." #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to replace the existing file msgid "Drop file here to replace the existing file" msgstr "" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to upload a new file msgid "Drop file here to upload a new file" msgstr "" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop files here ... msgid "Drop files here ..." msgstr "" @@ -2601,11 +2605,6 @@ msgstr "" msgid "Plone Foundation" msgstr "Plone Foundation" -#: components/theme/Logo/Logo -# defaultMessage: Plone Site -msgid "Plone Site" -msgstr "Plone website" - #: components/theme/Footer/Footer # defaultMessage: Plone{reg} Open Source CMS/WCM msgid "Plone{reg} Open Source CMS/WCM" @@ -2847,6 +2846,7 @@ msgid "Repeat on" msgstr "" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Replace existing file msgid "Replace existing file" msgstr "" @@ -3289,11 +3289,6 @@ msgstr "" msgid "Sign in to start session" msgstr "" -#: components/theme/Logo/Logo -# defaultMessage: Site -msgid "Site" -msgstr "Website" - #: components/theme/NotFound/NotFound #: components/theme/Unauthorized/Unauthorized # defaultMessage: Site Administration diff --git a/locales/pt/LC_MESSAGES/volto.po b/locales/pt/LC_MESSAGES/volto.po index 743fe4ecef..3c9373c837 100644 --- a/locales/pt/LC_MESSAGES/volto.po +++ b/locales/pt/LC_MESSAGES/volto.po @@ -616,6 +616,7 @@ msgid "Choose Target" msgstr "Escolha Alvo" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Choose a file msgid "Choose a file" msgstr "" @@ -1117,16 +1118,19 @@ msgid "Drag and drop files from your computer onto this area or click the “Bro msgstr "Arraste e largue ficheiros do seu computador para esta área ou clique no botão “Procurar”." #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to replace the existing file msgid "Drop file here to replace the existing file" msgstr "" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to upload a new file msgid "Drop file here to upload a new file" msgstr "" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop files here ... msgid "Drop files here ..." msgstr "" @@ -2590,11 +2594,6 @@ msgstr "" msgid "Plone Foundation" msgstr "Fundação Plone" -#: components/theme/Logo/Logo -# defaultMessage: Plone Site -msgid "Plone Site" -msgstr "Sítio Plone" - #: components/theme/Footer/Footer # defaultMessage: Plone{reg} Open Source CMS/WCM msgid "Plone{reg} Open Source CMS/WCM" @@ -2836,6 +2835,7 @@ msgid "Repeat on" msgstr "" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Replace existing file msgid "Replace existing file" msgstr "" @@ -3278,11 +3278,6 @@ msgstr "" msgid "Sign in to start session" msgstr "Inicie a sessão" -#: components/theme/Logo/Logo -# defaultMessage: Site -msgid "Site" -msgstr "Sítio" - #: components/theme/NotFound/NotFound #: components/theme/Unauthorized/Unauthorized # defaultMessage: Site Administration diff --git a/locales/pt_BR/LC_MESSAGES/volto.po b/locales/pt_BR/LC_MESSAGES/volto.po index 4e5bb61eb0..7c988bf514 100644 --- a/locales/pt_BR/LC_MESSAGES/volto.po +++ b/locales/pt_BR/LC_MESSAGES/volto.po @@ -618,6 +618,7 @@ msgid "Choose Target" msgstr "Escolha Alvo" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Choose a file msgid "Choose a file" msgstr "Escolha um arquivo" @@ -1119,16 +1120,19 @@ msgid "Drag and drop files from your computer onto this area or click the “Bro msgstr "Arraste e solte arquivos do seu computador para esta área, ou clique no botão ‘Procurar’." #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to replace the existing file msgid "Drop file here to replace the existing file" msgstr "Solte um arquivo aqui para substituir o arquivo existente" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to upload a new file msgid "Drop file here to upload a new file" msgstr "Solte um arquivo aqui para enviar um novo arquivo" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop files here ... msgid "Drop files here ..." msgstr "Soltar aquivos aqui…" @@ -2592,11 +2596,6 @@ msgstr "Por favor atualize a plone.restapi para versão 8.39.0 ou superior." msgid "Plone Foundation" msgstr "Fundação Plone" -#: components/theme/Logo/Logo -# defaultMessage: Plone Site -msgid "Plone Site" -msgstr "Site Plone" - #: components/theme/Footer/Footer # defaultMessage: Plone{reg} Open Source CMS/WCM msgid "Plone{reg} Open Source CMS/WCM" @@ -2838,6 +2837,7 @@ msgid "Repeat on" msgstr "Repete em" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Replace existing file msgid "Replace existing file" msgstr "Substituir arquivo existente" @@ -3280,11 +3280,6 @@ msgstr "Recolher barra de ferramentas" msgid "Sign in to start session" msgstr "Faça login para iniciar a sessão" -#: components/theme/Logo/Logo -# defaultMessage: Site -msgid "Site" -msgstr "Site" - #: components/theme/NotFound/NotFound #: components/theme/Unauthorized/Unauthorized # defaultMessage: Site Administration diff --git a/locales/ro/LC_MESSAGES/volto.po b/locales/ro/LC_MESSAGES/volto.po index cbf003e233..d5812dc14a 100644 --- a/locales/ro/LC_MESSAGES/volto.po +++ b/locales/ro/LC_MESSAGES/volto.po @@ -608,6 +608,7 @@ msgid "Choose Target" msgstr "Alegeți ținta" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Choose a file msgid "Choose a file" msgstr "Alegeți un fișier" @@ -1109,16 +1110,19 @@ msgid "Drag and drop files from your computer onto this area or click the “Bro msgstr "Trageți și fixați fișierele de pe computer în această zonă sau faceți clic pe butonul Răsfoiește." #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to replace the existing file msgid "Drop file here to replace the existing file" msgstr "Trageți fișierul aici pentru a înlocui fișierul existent" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to upload a new file msgid "Drop file here to upload a new file" msgstr "Trageți fișierul aici pentru a încărca un fișier nou" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop files here ... msgid "Drop files here ..." msgstr "Trageți fișierele aici..." @@ -2582,11 +2586,6 @@ msgstr "" msgid "Plone Foundation" msgstr "Fundația Plone" -#: components/theme/Logo/Logo -# defaultMessage: Plone Site -msgid "Plone Site" -msgstr "Site Plone" - #: components/theme/Footer/Footer # defaultMessage: Plone{reg} Open Source CMS/WCM msgid "Plone{reg} Open Source CMS/WCM" @@ -2828,6 +2827,7 @@ msgid "Repeat on" msgstr "Repetați pe" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Replace existing file msgid "Replace existing file" msgstr "Înlocuiește fișierul existent" @@ -3270,11 +3270,6 @@ msgstr "Reduceti bara de instrumente" msgid "Sign in to start session" msgstr "Conectați-vă pentru a începe sesiunea" -#: components/theme/Logo/Logo -# defaultMessage: Site -msgid "Site" -msgstr "Site" - #: components/theme/NotFound/NotFound #: components/theme/Unauthorized/Unauthorized # defaultMessage: Site Administration diff --git a/locales/volto.pot b/locales/volto.pot index 90c27b7603..bfd6b55b0d 100644 --- a/locales/volto.pot +++ b/locales/volto.pot @@ -610,6 +610,7 @@ msgid "Choose Target" msgstr "" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Choose a file msgid "Choose a file" msgstr "" @@ -1111,16 +1112,19 @@ msgid "Drag and drop files from your computer onto this area or click the “Bro msgstr "" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to replace the existing file msgid "Drop file here to replace the existing file" msgstr "" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to upload a new file msgid "Drop file here to upload a new file" msgstr "" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop files here ... msgid "Drop files here ..." msgstr "" @@ -2584,11 +2588,6 @@ msgstr "" msgid "Plone Foundation" msgstr "" -#: components/theme/Logo/Logo -# defaultMessage: Plone Site -msgid "Plone Site" -msgstr "" - #: components/theme/Footer/Footer # defaultMessage: Plone{reg} Open Source CMS/WCM msgid "Plone{reg} Open Source CMS/WCM" @@ -2830,6 +2829,7 @@ msgid "Repeat on" msgstr "" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Replace existing file msgid "Replace existing file" msgstr "" @@ -3272,11 +3272,6 @@ msgstr "" msgid "Sign in to start session" msgstr "" -#: components/theme/Logo/Logo -# defaultMessage: Site -msgid "Site" -msgstr "" - #: components/theme/NotFound/NotFound #: components/theme/Unauthorized/Unauthorized # defaultMessage: Site Administration diff --git a/locales/zh_CN/LC_MESSAGES/volto.po b/locales/zh_CN/LC_MESSAGES/volto.po index ed63fbdba1..2be1957f98 100644 --- a/locales/zh_CN/LC_MESSAGES/volto.po +++ b/locales/zh_CN/LC_MESSAGES/volto.po @@ -614,6 +614,7 @@ msgid "Choose Target" msgstr "选择目标" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Choose a file msgid "Choose a file" msgstr "选择一个文件" @@ -1115,16 +1116,19 @@ msgid "Drag and drop files from your computer onto this area or click the “Bro msgstr "从你的电脑中拖放文件到此区域或单击 “浏览” 按钮" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to replace the existing file msgid "Drop file here to replace the existing file" msgstr "在此处放置文件以替换现有文件" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop file here to upload a new file msgid "Drop file here to upload a new file" msgstr "在此处放置文件来上传新文件" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Drop files here ... msgid "Drop files here ..." msgstr "在此处放置文件 ..." @@ -2588,11 +2592,6 @@ msgstr "" msgid "Plone Foundation" msgstr "" -#: components/theme/Logo/Logo -# defaultMessage: Plone Site -msgid "Plone Site" -msgstr "Plone站点" - #: components/theme/Footer/Footer # defaultMessage: Plone{reg} Open Source CMS/WCM msgid "Plone{reg} Open Source CMS/WCM" @@ -2834,6 +2833,7 @@ msgid "Repeat on" msgstr "" #: components/manage/Widgets/FileWidget +#: components/manage/Widgets/RegistryImageWidget # defaultMessage: Replace existing file msgid "Replace existing file" msgstr "替换现有文件" @@ -3276,11 +3276,6 @@ msgstr "缩小工具栏" msgid "Sign in to start session" msgstr "登录以开始session会话" -#: components/theme/Logo/Logo -# defaultMessage: Site -msgid "Site" -msgstr "网站" - #: components/theme/NotFound/NotFound #: components/theme/Unauthorized/Unauthorized # defaultMessage: Site Administration diff --git a/news/3537.feature b/news/3537.feature new file mode 100644 index 0000000000..30adb55219 --- /dev/null +++ b/news/3537.feature @@ -0,0 +1,5 @@ +Use the `@navroot` endpoint to build the `title` tag. @erral + +Use the `@site` endpoint to render the logo. @erral + +Register a widget to set the logo in the site control panel. @erral diff --git a/src/actions/index.js b/src/actions/index.js index 289ffd34b9..037fffa346 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -172,3 +172,5 @@ export { } from './workingcopy/workingcopy'; export { getUserSchema } from './userschema/userschema'; export { getUpgradeInformation, runUpgrade } from './upgrade/upgrade'; +export { getSite } from './site/site'; +export { getNavroot } from './navroot/navroot'; diff --git a/src/actions/navroot/navroot.js b/src/actions/navroot/navroot.js new file mode 100644 index 0000000000..c9d50c2e6d --- /dev/null +++ b/src/actions/navroot/navroot.js @@ -0,0 +1,16 @@ +import { GET_NAVROOT } from '@plone/volto/constants/ActionTypes'; + +/** + * Get the navigation root information. + * @function getNavroot + * @returns {Object} navroot + */ +export function getNavroot(url) { + return { + type: GET_NAVROOT, + request: { + op: 'get', + path: `${url}/@navroot`, + }, + }; +} diff --git a/src/actions/navroot/navroot.test.js b/src/actions/navroot/navroot.test.js new file mode 100644 index 0000000000..7d9cb606e4 --- /dev/null +++ b/src/actions/navroot/navroot.test.js @@ -0,0 +1,15 @@ +import { getNavroot } from './navroot'; +import { GET_NAVROOT } from '@plone/volto/constants/ActionTypes'; + +describe('Breadcrumbs action', () => { + describe('getBreadcrumbs', () => { + it('should create an action to get the breadcrumbs', () => { + const url = 'http://localhost'; + const action = getNavroot(url); + + expect(action.type).toEqual(GET_NAVROOT); + expect(action.request.op).toEqual('get'); + expect(action.request.path).toEqual(`${url}/@navroot`); + }); + }); +}); diff --git a/src/actions/site/site.js b/src/actions/site/site.js new file mode 100644 index 0000000000..eb4d4f6032 --- /dev/null +++ b/src/actions/site/site.js @@ -0,0 +1,16 @@ +import { GET_SITE } from '@plone/volto/constants/ActionTypes'; + +/** + * Get the Site information. + * @function getSite + * @returns {Object} site info + */ +export function getSite() { + return { + type: GET_SITE, + request: { + op: 'get', + path: '/@site', + }, + }; +} diff --git a/src/actions/site/site.test.js b/src/actions/site/site.test.js new file mode 100644 index 0000000000..4c53cc65bc --- /dev/null +++ b/src/actions/site/site.test.js @@ -0,0 +1,15 @@ +import { getSite } from './site'; +import { GET_SITE } from '@plone/volto/constants/ActionTypes'; + +describe('Site action', () => { + describe('getSite', () => { + it('should create an action to get the site config', () => { + const url = 'http://localhost'; + const action = getSite(url); + + expect(action.type).toEqual(GET_SITE); + expect(action.request.op).toEqual('get'); + expect(action.request.path).toEqual(`/@site`); + }); + }); +}); diff --git a/src/components/manage/Widgets/RegistryImageWidget.jsx b/src/components/manage/Widgets/RegistryImageWidget.jsx new file mode 100644 index 0000000000..4045d66ab3 --- /dev/null +++ b/src/components/manage/Widgets/RegistryImageWidget.jsx @@ -0,0 +1,210 @@ +/** + * RegistryImageWidget component. + * @module components/manage/Widgets/RegistryImageWidget + */ + +import React from 'react'; +import PropTypes from 'prop-types'; +import { Button, Image, Dimmer } from 'semantic-ui-react'; +import { readAsDataURL } from 'promise-file-reader'; +import { injectIntl } from 'react-intl'; +import deleteSVG from '@plone/volto/icons/delete.svg'; +import { Icon, FormFieldWrapper } from '@plone/volto/components'; +import loadable from '@loadable/component'; +import { defineMessages, useIntl } from 'react-intl'; +import { toPublicURL, validateFileUploadSize } from '@plone/volto/helpers'; + +const imageMimetypes = [ + 'image/png', + 'image/jpeg', + 'image/webp', + 'image/jpg', + 'image/gif', + 'image/svg+xml', +]; +const Dropzone = loadable(() => import('react-dropzone')); + +const messages = defineMessages({ + releaseDrag: { + id: 'Drop files here ...', + defaultMessage: 'Drop files here ...', + }, + editFile: { + id: 'Drop file here to replace the existing file', + defaultMessage: 'Drop file here to replace the existing file', + }, + fileDrag: { + id: 'Drop file here to upload a new file', + defaultMessage: 'Drop file here to upload a new file', + }, + replaceFile: { + id: 'Replace existing file', + defaultMessage: 'Replace existing file', + }, + addNewFile: { + id: 'Choose a file', + defaultMessage: 'Choose a file', + }, +}); + +/** + * RegistryImageWidget component class. + * @function RegistryImageWidget + * @returns {string} Markup of the component. + * + * To use it, in schema properties, declare a field like: + * + * ```jsx + * { + * title: "File", + * widget: 'file', + * } + * ``` + * or: + * + * ```jsx + * { + * title: "File", + * type: 'object', + * } + * ``` + * + */ +const RegistryImageWidget = (props) => { + const { id, value, onChange, isDisabled } = props; + const intl = useIntl(); + + const fileName = value?.split(';')[0]; + const imgsrc = fileName + ? `${toPublicURL('/')}@@site-logo/${atob( + fileName.replace('filenameb64:', ''), + )}` + : ''; + + /** + * Drop handler + * @method onDrop + * @param {array} files File objects + * @returns {undefined} + */ + const onDrop = (files) => { + const file = files[0]; + if (!validateFileUploadSize(file, intl.formatMessage)) return; + + readAsDataURL(file).then((data) => { + const fields = data.match(/^data:(.*);(.*),(.*)$/); + onChange(id, `filenameb64:${btoa(file.name)};datab64:${fields[3]}}`); + }); + + let reader = new FileReader(); + reader.onload = function () { + const fields = reader.result.match(/^data:(.*);(.*),(.*)$/); + if (imageMimetypes.includes(fields[1])) { + let imagePreview = document.getElementById(`field-${id}-image`); + imagePreview.src = reader.result; + } + }; + reader.readAsDataURL(files[0]); + }; + + return ( + + + {({ getRootProps, getInputProps, isDragActive }) => ( +
+ {isDragActive && } + {imgsrc ? ( + + ) : ( +
+ {isDragActive ? ( +

+ {intl.formatMessage(messages.releaseDrag)} +

+ ) : value ? ( +

+ {intl.formatMessage(messages.editFile)} +

+ ) : ( +

+ {intl.formatMessage(messages.fileDrag)} +

+ )} +
+ )} + + + +
+ )} +
+
+ {value && ( + + )} +
+
+ ); +}; + +/** + * Property types. + * @property {Object} propTypes Property types. + * @static + */ +RegistryImageWidget.propTypes = { + id: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + description: PropTypes.string, + required: PropTypes.bool, + error: PropTypes.arrayOf(PropTypes.string), + value: PropTypes.shape({ + '@type': PropTypes.string, + title: PropTypes.string, + }), + onChange: PropTypes.func.isRequired, + wrapped: PropTypes.bool, +}; + +/** + * Default properties. + * @property {Object} defaultProps Default properties. + * @static + */ +RegistryImageWidget.defaultProps = { + description: null, + required: false, + error: [], + value: null, +}; + +export default injectIntl(RegistryImageWidget); diff --git a/src/components/manage/Widgets/RegistryImageWidget.test.jsx b/src/components/manage/Widgets/RegistryImageWidget.test.jsx new file mode 100644 index 0000000000..51c9564a70 --- /dev/null +++ b/src/components/manage/Widgets/RegistryImageWidget.test.jsx @@ -0,0 +1,91 @@ +import React from 'react'; +import { Provider } from 'react-intl-redux'; +import { render, waitFor } from '@testing-library/react'; +import configureStore from 'redux-mock-store'; + +import RegistryImageWidget from './RegistryImageWidget'; + +import config from '@plone/volto/registry'; + +jest.spyOn(global.Date, 'now').mockImplementation(() => '0'); + +const mockStore = configureStore(); + +beforeAll(() => { + config.settings.publicURL = 'http://localhost:3000'; +}); + +describe('RegistryImageWidget', () => { + test('renders an empty file widget component', async () => { + const store = mockStore({ + intl: { + locale: 'en', + messages: {}, + }, + }); + + const { container } = render( + + {}} + /> + , + ); + + await waitFor(() => {}); + expect(container).toMatchSnapshot(); + }); + test('renders a file widget component with value', async () => { + const store = mockStore({ + intl: { + locale: 'en', + messages: {}, + }, + }); + + const { container } = render( + + {}} + value={ + 'filenameb64:bG9nby5jYWI5NDVkOC5zdmc=;datab64:PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjE1OC4yNTNweCIgaGVpZ2h0PSI0MC42ODZweCIgdmlld0JveD0iMCAwIDE1OC4yNTMgNDAuNjg2IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxNTguMjUzIDQwLjY4NiIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CiAgICAgICAgICAgICAgICAgICAgPGc+PHBhdGggZmlsbD0iIzAwODZDMyIgZD0iTTY1LjMyNywyMy4yMDhoLTYuNTg5djExLjM4OGgtNC4zOTNWNS42MzhoMTAuOTgxYzUuNjUzLDAsOS4yNzEsMy43NDIsOS4yNzEsOC43ODUgICAgICAgICAgICAgICAgIFM3MC45NzksMjMuMjA4LDY1LjMyNywyMy4yMDh6IE02NS4wODIsOS41ODNoLTYuMzQ1djkuNjM5aDYuMzQ1YzMuMDUsMCw1LjEyNC0xLjc0OSw1LjEyNC00Ljc5OSAgICAgICAgICAgICAgICAgQzcwLjIwNiwxMS4zNzIsNjguMTMyLDkuNTgzLDY1LjA4Miw5LjU4M3oiLz48cGF0aCBmaWxsPSIjMDA4NkMzIiBkPSJNODMuOTY5LDM0LjU5NmMtMy45MDQsMC01LjY1Mi0yLjY0NC01LjY1Mi01LjY5M1Y1LjYzOGg0LjE0OHYyMy4wMjFjMCwxLjU4NywwLjU2NywyLjM5OSwyLjIzNSwyLjM5OWgxLjgzICAgICAgICAgICAgICAgICB2My41MzhIODMuOTY5eiIvPjxwYXRoIGZpbGw9IiMwMDg2QzMiIGQ9Ik0xMDQuNzYyLDMyLjM5OWMtMS4zNDQsMS4zODQtMy4zNzcsMi40NC02LjE4NCwyLjQ0Yy0yLjgwNSwwLTQuNzk5LTEuMDU4LTYuMTQxLTIuNDQgICAgICAgICAgICAgICAgIGMtMS45NTEtMi4wMzItMi40MzktNC42MzctMi40MzktOC4xMzRjMC0zLjQ1NywwLjQ4OC02LjA2MSwyLjQzOS04LjA5NGMxLjM0Mi0xLjM4MywzLjMzNi0yLjQ0LDYuMTQxLTIuNDQgICAgICAgICAgICAgICAgIGMyLjgwNywwLDQuODQsMS4wNTksNi4xODQsMi40NGMxLjk1MSwyLjAzMywyLjQzOSw0LjYzNywyLjQzOSw4LjA5NEMxMDcuMjAzLDI3Ljc2MywxMDYuNzEzLDMwLjM2NiwxMDQuNzYyLDMyLjM5OXogICAgICAgICAgICAgICAgICBNMTAxLjYyOSwxOC42MTNjLTAuNzczLTAuNzczLTEuODMtMS4xODEtMy4wNTEtMS4xODFjLTEuMjE5LDAtMi4yMzYsMC40MDYtMy4wMSwxLjE4MWMtMS4yNiwxLjI2MS0xLjQyMiwzLjQxNi0xLjQyMiw1LjY1MiAgICAgICAgICAgICAgICAgczAuMTYyLDQuMzkzLDEuNDIyLDUuNjUzYzAuNzczLDAuNzcxLDEuNzkxLDEuMjIsMy4wMSwxLjIyYzEuMjIxLDAsMi4yNzctMC40NDcsMy4wNTEtMS4yMmMxLjI2Mi0xLjI2MiwxLjQyNC0zLjQxNywxLjQyNC01LjY1MyAgICAgICAgICAgICAgICAgUzEwMi44OTEsMTkuODczLDEwMS42MjksMTguNjEzeiIvPjxwYXRoIGZpbGw9IiMwMDg2QzMiIGQ9Ik0xMjMuNjQzLDM0LjU5NlYyMi4wMjljMC0zLjIxNC0xLjgzLTQuNTk3LTQuMTQ3LTQuNTk3cy00LjI3MSwxLjQyMy00LjI3MSw0LjU5N3YxMi41NjZoLTQuMTQ3di0yMC42MiAgICAgICAgICAgICAgICAgaDQuMDY1djIuMDc0YzEuNDI1LTEuNTQ2LDMuNDE2LTIuMzE4LDUuNDktMi4zMThjMi4xMTUsMCwzLjg2NSwwLjY5MSw1LjA4NCwxLjg3MWMxLjU4NiwxLjU0NSwyLjA3NCwzLjQ5NywyLjA3NCw1LjgxNXYxMy4xNzggICAgICAgICAgICAgICAgIEwxMjMuNjQzLDM0LjU5NkwxMjMuNjQzLDM0LjU5NnoiLz48cGF0aCBmaWxsPSIjMDA4NkMzIiBkPSJNMTM1Ljc3MiwyNS40ODZjMCwzLjUzNywxLjg3MSw1Ljc3NCw1LjI0Niw1Ljc3NGMyLjMxNywwLDMuNTM5LTAuNjQ5LDUuMDA0LTIuMTE1bDIuNjQzLDIuNDgxICAgICAgICAgICAgICAgICBjLTIuMTE1LDIuMTE0LTQuMTA3LDMuMjEzLTcuNzI3LDMuMjEzYy01LjE2NiwwLTkuMjczLTIuNzI1LTkuMjczLTEwLjU3NGMwLTYuNjcxLDMuNDU3LTEwLjUzNCw4Ljc0NC0xMC41MzQgICAgICAgICAgICAgICAgIGM1LjUzMSwwLDguNzQ0LDQuMDY3LDguNzQ0LDkuOTI1djEuODNIMTM1Ljc3MnogTTE0NC40NzUsMTkuNzkxYy0wLjY1LTEuNTQ1LTIuMTEzLTIuNjA0LTQuMDY2LTIuNjA0ICAgICAgICAgICAgICAgICBjLTEuOTUxLDAtMy40NTcsMS4wNTktNC4xMDcsMi42MDRjLTAuNDA2LDAuOTM2LTAuNDg4LDEuNTQ2LTAuNTI5LDIuODA3aDkuMjczQzE0NS4wMDMsMjEuMzM3LDE0NC44ODMsMjAuNzI2LDE0NC40NzUsMTkuNzkxeiIvPjxjaXJjbGUgZmlsbD0iIzAwODZDMyIgY3g9IjE3LjgxNSIgY3k9IjExLjUxNiIgcj0iNC40MDIiLz48cGF0aCBmaWxsPSIjMDA4NkMzIiBkPSJNMzEuMTY3LDIwLjMxMWMwLDIuNDMzLTEuOTY5LDQuNDAxLTQuNDAzLDQuNDAxYy0yLjQyNywwLTQuNDAxLTEuOTctNC40MDEtNC40MDEgICAgICAgICAgICAgICAgIGMwLTIuNDMzLDEuOTc1LTQuNDAxLDQuNDAxLTQuNDAxQzI5LjIsMTUuOTA5LDMxLjE2NywxNy44NzksMzEuMTY3LDIwLjMxMXoiLz48Y2lyY2xlIGZpbGw9IiMwMDg2QzMiIGN4PSIxNy44MDEiIGN5PSIyOS4xMzEiIHI9IjQuNDAyIi8+PGc+PHBhdGggZmlsbD0iIzAwODZDMyIgZD0iTTIwLjQ0MS0wLjA0NUM5LjIwNy0wLjA0NCwwLjEsOS4wNjMsMC4wOTksMjAuMjk4QzAuMSwzMS41MzIsOS4yMDcsNDAuNjM5LDIwLjQ0MSw0MC42NDEgICAgICAgICAgICAgICAgICAgICBjMTEuMjM1LTAuMDAyLDIwLjM0MS05LjEwNywyMC4zNDMtMjAuMzQzQzQwLjc4Myw5LjA2MywzMS42NzctMC4wNDQsMjAuNDQxLTAuMDQ1eiBNMzEuODkxLDMxLjc0NyAgICAgICAgICAgICAgICAgICAgIGMtMi45MzcsMi45MzQtNi45NzIsNC43NDItMTEuNDUsNC43NDNjLTQuNDc4LTAuMDAxLTguNTEzLTEuODExLTExLjQ1LTQuNzQzQzYuMDU4LDI4LjgxLDQuMjUsMjQuNzc1LDQuMjQ5LDIwLjI5OCAgICAgICAgICAgICAgICAgICAgIGMwLjAwMS00LjQ3OCwxLjgwOS04LjUxMyw0Ljc0My0xMS40NWMyLjkzNy0yLjkzNCw2Ljk3Mi00Ljc0MiwxMS40NS00Ljc0M2M0LjQ3OCwwLjAwMSw4LjUxMywxLjgxLDExLjQ1LDQuNzQzICAgICAgICAgICAgICAgICAgICAgYzIuOTM0LDIuOTM4LDQuNzQyLDYuOTczLDQuNzQzLDExLjQ1QzM2LjYzMywyNC43NzUsMzQuODI1LDI4LjgxLDMxLjg5MSwzMS43NDd6Ii8+PC9nPjxnPjxwYXRoIGZpbGw9IiMwMDg2QzMiIGQ9Ik0xNTMuOTg1LDkuOTVjLTEuMTk1LDAtMi4xNjQsMC45NzEtMi4xNjQsMi4xNjhjMC4wMDIsMS4xOTcsMC45NjksMi4xNjgsMi4xNjQsMi4xNjggICAgICAgICAgICAgICAgICAgICBjMS4xOTksMCwyLjE3Mi0wLjk3MSwyLjE3Mi0yLjE2OFMxNTUuMTg0LDkuOTUsMTUzLjk4NSw5Ljk1eiBNMTUzLjk4NSwxMy45NjhjLTEuMDIxLTAuMDAyLTEuODQ2LTAuODI3LTEuODQ2LTEuODUgICAgICAgICAgICAgICAgICAgICBjMC4wMDItMS4wMjEsMC44MjUtMS44NDksMS44NDYtMS44NTFjMS4wMjMsMC4wMDIsMS44NTIsMC44MjgsMS44NTQsMS44NTFDMTU1LjgzNiwxMy4xNDEsMTU1LjAwOCwxMy45NjYsMTUzLjk4NSwxMy45Njh6Ii8+PC9nPjxnPjxwYXRoIGZpbGw9IiMwMDg2QzMiIGQ9Ik0xNTQuNTA3LDEzLjQwOWwtMC41NC0xLjA4aC0wLjQ4NnYxLjA4aC0wLjM4OXYtMi41NjRoMC45OTRjMC40ODQsMCwwLjc5NiwwLjMxMywwLjc5NiwwLjc1ICAgICAgICAgICAgICAgICAgICAgYzAsMC4zNjctMC4yMjQsMC42MDItMC41MTMsMC42OGwwLjU5MiwxLjEzNkwxNTQuNTA3LDEzLjQwOUwxNTQuNTA3LDEzLjQwOXogTTE1NC4wNTYsMTEuMTk1aC0wLjU3NXYwLjgwM2gwLjU3NSBjMC4yNjEsMCwwLjQzNy0wLjE0NywwLjQzNy0wLjM5OVMxNTQuMzE3LDExLjE5NSwxNTQuMDU2LDExLjE5NXoiLz48L2c+PC9nPgogICAgICAgICAgICAgICAgICA8L3N2Zz4=}' + } + /> + , + ); + + await waitFor(() => {}); + expect(container).toMatchSnapshot(); + }); + // test('renders a file widget component with value in raw data', async () => { + // const store = mockStore({ + // intl: { + // locale: 'en', + // messages: {}, + // }, + // }); + + // const { container } = render( + // + // {}} + // value={ + // 'filenameb64:bG9nby5jYWI5NDVkOC5zdmc=;datab64:PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjE1OC4yNTNweCIgaGVpZ2h0PSI0MC42ODZweCIgdmlld0JveD0iMCAwIDE1OC4yNTMgNDAuNjg2IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxNTguMjUzIDQwLjY4NiIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CiAgICAgICAgICAgICAgICAgICAgPGc+PHBhdGggZmlsbD0iIzAwODZDMyIgZD0iTTY1LjMyNywyMy4yMDhoLTYuNTg5djExLjM4OGgtNC4zOTNWNS42MzhoMTAuOTgxYzUuNjUzLDAsOS4yNzEsMy43NDIsOS4yNzEsOC43ODUgICAgICAgICAgICAgICAgIFM3MC45NzksMjMuMjA4LDY1LjMyNywyMy4yMDh6IE02NS4wODIsOS41ODNoLTYuMzQ1djkuNjM5aDYuMzQ1YzMuMDUsMCw1LjEyNC0xLjc0OSw1LjEyNC00Ljc5OSAgICAgICAgICAgICAgICAgQzcwLjIwNiwxMS4zNzIsNjguMTMyLDkuNTgzLDY1LjA4Miw5LjU4M3oiLz48cGF0aCBmaWxsPSIjMDA4NkMzIiBkPSJNODMuOTY5LDM0LjU5NmMtMy45MDQsMC01LjY1Mi0yLjY0NC01LjY1Mi01LjY5M1Y1LjYzOGg0LjE0OHYyMy4wMjFjMCwxLjU4NywwLjU2NywyLjM5OSwyLjIzNSwyLjM5OWgxLjgzICAgICAgICAgICAgICAgICB2My41MzhIODMuOTY5eiIvPjxwYXRoIGZpbGw9IiMwMDg2QzMiIGQ9Ik0xMDQuNzYyLDMyLjM5OWMtMS4zNDQsMS4zODQtMy4zNzcsMi40NC02LjE4NCwyLjQ0Yy0yLjgwNSwwLTQuNzk5LTEuMDU4LTYuMTQxLTIuNDQgICAgICAgICAgICAgICAgIGMtMS45NTEtMi4wMzItMi40MzktNC42MzctMi40MzktOC4xMzRjMC0zLjQ1NywwLjQ4OC02LjA2MSwyLjQzOS04LjA5NGMxLjM0Mi0xLjM4MywzLjMzNi0yLjQ0LDYuMTQxLTIuNDQgICAgICAgICAgICAgICAgIGMyLjgwNywwLDQuODQsMS4wNTksNi4xODQsMi40NGMxLjk1MSwyLjAzMywyLjQzOSw0LjYzNywyLjQzOSw4LjA5NEMxMDcuMjAzLDI3Ljc2MywxMDYuNzEzLDMwLjM2NiwxMDQuNzYyLDMyLjM5OXogICAgICAgICAgICAgICAgICBNMTAxLjYyOSwxOC42MTNjLTAuNzczLTAuNzczLTEuODMtMS4xODEtMy4wNTEtMS4xODFjLTEuMjE5LDAtMi4yMzYsMC40MDYtMy4wMSwxLjE4MWMtMS4yNiwxLjI2MS0xLjQyMiwzLjQxNi0xLjQyMiw1LjY1MiAgICAgICAgICAgICAgICAgczAuMTYyLDQuMzkzLDEuNDIyLDUuNjUzYzAuNzczLDAuNzcxLDEuNzkxLDEuMjIsMy4wMSwxLjIyYzEuMjIxLDAsMi4yNzctMC40NDcsMy4wNTEtMS4yMmMxLjI2Mi0xLjI2MiwxLjQyNC0zLjQxNywxLjQyNC01LjY1MyAgICAgICAgICAgICAgICAgUzEwMi44OTEsMTkuODczLDEwMS42MjksMTguNjEzeiIvPjxwYXRoIGZpbGw9IiMwMDg2QzMiIGQ9Ik0xMjMuNjQzLDM0LjU5NlYyMi4wMjljMC0zLjIxNC0xLjgzLTQuNTk3LTQuMTQ3LTQuNTk3cy00LjI3MSwxLjQyMy00LjI3MSw0LjU5N3YxMi41NjZoLTQuMTQ3di0yMC42MiAgICAgICAgICAgICAgICAgaDQuMDY1djIuMDc0YzEuNDI1LTEuNTQ2LDMuNDE2LTIuMzE4LDUuNDktMi4zMThjMi4xMTUsMCwzLjg2NSwwLjY5MSw1LjA4NCwxLjg3MWMxLjU4NiwxLjU0NSwyLjA3NCwzLjQ5NywyLjA3NCw1LjgxNXYxMy4xNzggICAgICAgICAgICAgICAgIEwxMjMuNjQzLDM0LjU5NkwxMjMuNjQzLDM0LjU5NnoiLz48cGF0aCBmaWxsPSIjMDA4NkMzIiBkPSJNMTM1Ljc3MiwyNS40ODZjMCwzLjUzNywxLjg3MSw1Ljc3NCw1LjI0Niw1Ljc3NGMyLjMxNywwLDMuNTM5LTAuNjQ5LDUuMDA0LTIuMTE1bDIuNjQzLDIuNDgxICAgICAgICAgICAgICAgICBjLTIuMTE1LDIuMTE0LTQuMTA3LDMuMjEzLTcuNzI3LDMuMjEzYy01LjE2NiwwLTkuMjczLTIuNzI1LTkuMjczLTEwLjU3NGMwLTYuNjcxLDMuNDU3LTEwLjUzNCw4Ljc0NC0xMC41MzQgICAgICAgICAgICAgICAgIGM1LjUzMSwwLDguNzQ0LDQuMDY3LDguNzQ0LDkuOTI1djEuODNIMTM1Ljc3MnogTTE0NC40NzUsMTkuNzkxYy0wLjY1LTEuNTQ1LTIuMTEzLTIuNjA0LTQuMDY2LTIuNjA0ICAgICAgICAgICAgICAgICBjLTEuOTUxLDAtMy40NTcsMS4wNTktNC4xMDcsMi42MDRjLTAuNDA2LDAuOTM2LTAuNDg4LDEuNTQ2LTAuNTI5LDIuODA3aDkuMjczQzE0NS4wMDMsMjEuMzM3LDE0NC44ODMsMjAuNzI2LDE0NC40NzUsMTkuNzkxeiIvPjxjaXJjbGUgZmlsbD0iIzAwODZDMyIgY3g9IjE3LjgxNSIgY3k9IjExLjUxNiIgcj0iNC40MDIiLz48cGF0aCBmaWxsPSIjMDA4NkMzIiBkPSJNMzEuMTY3LDIwLjMxMWMwLDIuNDMzLTEuOTY5LDQuNDAxLTQuNDAzLDQuNDAxYy0yLjQyNywwLTQuNDAxLTEuOTctNC40MDEtNC40MDEgICAgICAgICAgICAgICAgIGMwLTIuNDMzLDEuOTc1LTQuNDAxLDQuNDAxLTQuNDAxQzI5LjIsMTUuOTA5LDMxLjE2NywxNy44NzksMzEuMTY3LDIwLjMxMXoiLz48Y2lyY2xlIGZpbGw9IiMwMDg2QzMiIGN4PSIxNy44MDEiIGN5PSIyOS4xMzEiIHI9IjQuNDAyIi8+PGc+PHBhdGggZmlsbD0iIzAwODZDMyIgZD0iTTIwLjQ0MS0wLjA0NUM5LjIwNy0wLjA0NCwwLjEsOS4wNjMsMC4wOTksMjAuMjk4QzAuMSwzMS41MzIsOS4yMDcsNDAuNjM5LDIwLjQ0MSw0MC42NDEgICAgICAgICAgICAgICAgICAgICBjMTEuMjM1LTAuMDAyLDIwLjM0MS05LjEwNywyMC4zNDMtMjAuMzQzQzQwLjc4Myw5LjA2MywzMS42NzctMC4wNDQsMjAuNDQxLTAuMDQ1eiBNMzEuODkxLDMxLjc0NyAgICAgICAgICAgICAgICAgICAgIGMtMi45MzcsMi45MzQtNi45NzIsNC43NDItMTEuNDUsNC43NDNjLTQuNDc4LTAuMDAxLTguNTEzLTEuODExLTExLjQ1LTQuNzQzQzYuMDU4LDI4LjgxLDQuMjUsMjQuNzc1LDQuMjQ5LDIwLjI5OCAgICAgICAgICAgICAgICAgICAgIGMwLjAwMS00LjQ3OCwxLjgwOS04LjUxMyw0Ljc0My0xMS40NWMyLjkzNy0yLjkzNCw2Ljk3Mi00Ljc0MiwxMS40NS00Ljc0M2M0LjQ3OCwwLjAwMSw4LjUxMywxLjgxLDExLjQ1LDQuNzQzICAgICAgICAgICAgICAgICAgICAgYzIuOTM0LDIuOTM4LDQuNzQyLDYuOTczLDQuNzQzLDExLjQ1QzM2LjYzMywyNC43NzUsMzQuODI1LDI4LjgxLDMxLjg5MSwzMS43NDd6Ii8+PC9nPjxnPjxwYXRoIGZpbGw9IiMwMDg2QzMiIGQ9Ik0xNTMuOTg1LDkuOTVjLTEuMTk1LDAtMi4xNjQsMC45NzEtMi4xNjQsMi4xNjhjMC4wMDIsMS4xOTcsMC45NjksMi4xNjgsMi4xNjQsMi4xNjggICAgICAgICAgICAgICAgICAgICBjMS4xOTksMCwyLjE3Mi0wLjk3MSwyLjE3Mi0yLjE2OFMxNTUuMTg0LDkuOTUsMTUzLjk4NSw5Ljk1eiBNMTUzLjk4NSwxMy45NjhjLTEuMDIxLTAuMDAyLTEuODQ2LTAuODI3LTEuODQ2LTEuODUgICAgICAgICAgICAgICAgICAgICBjMC4wMDItMS4wMjEsMC44MjUtMS44NDksMS44NDYtMS44NTFjMS4wMjMsMC4wMDIsMS44NTIsMC44MjgsMS44NTQsMS44NTFDMTU1LjgzNiwxMy4xNDEsMTU1LjAwOCwxMy45NjYsMTUzLjk4NSwxMy45Njh6Ii8+PC9nPjxnPjxwYXRoIGZpbGw9IiMwMDg2QzMiIGQ9Ik0xNTQuNTA3LDEzLjQwOWwtMC41NC0xLjA4aC0wLjQ4NnYxLjA4aC0wLjM4OXYtMi41NjRoMC45OTRjMC40ODQsMCwwLjc5NiwwLjMxMywwLjc5NiwwLjc1ICAgICAgICAgICAgICAgICAgICAgYzAsMC4zNjctMC4yMjQsMC42MDItMC41MTMsMC42OGwwLjU5MiwxLjEzNkwxNTQuNTA3LDEzLjQwOUwxNTQuNTA3LDEzLjQwOXogTTE1NC4wNTYsMTEuMTk1aC0wLjU3NXYwLjgwM2gwLjU3NSBjMC4yNjEsMCwwLjQzNy0wLjE0NywwLjQzNy0wLjM5OVMxNTQuMzE3LDExLjE5NSwxNTQuMDU2LDExLjE5NXoiLz48L2c+PC9nPgogICAgICAgICAgICAgICAgICA8L3N2Zz4=}' + // } + // /> + // , + // ); + + // await waitFor(() => {}); + // expect(container).toMatchSnapshot(); + // }); +}); diff --git a/src/components/manage/Widgets/__snapshots__/RegistryImageWidget.test.jsx.snap b/src/components/manage/Widgets/__snapshots__/RegistryImageWidget.test.jsx.snap new file mode 100644 index 0000000000..03a62b60b6 --- /dev/null +++ b/src/components/manage/Widgets/__snapshots__/RegistryImageWidget.test.jsx.snap @@ -0,0 +1,141 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`RegistryImageWidget renders a file widget component with value 1`] = ` +
+
+
+
+
+
+ +
+
+
+
+ + + +
+
+ +
+
+
+
+
+
+`; + +exports[`RegistryImageWidget renders an empty file widget component 1`] = ` +
+
+
+
+
+
+ +
+
+
+
+
+

+ Drop file here to upload a new file +

+
+ + +
+
+
+
+
+
+
+`; diff --git a/src/components/theme/ContentMetadataTags/ContentMetadataTags.jsx b/src/components/theme/ContentMetadataTags/ContentMetadataTags.jsx index 6ab3955f12..70aa549b6c 100644 --- a/src/components/theme/ContentMetadataTags/ContentMetadataTags.jsx +++ b/src/components/theme/ContentMetadataTags/ContentMetadataTags.jsx @@ -1,6 +1,13 @@ -import React from 'react'; -import { toPublicURL, Helmet } from '@plone/volto/helpers'; +import React, { useEffect } from 'react'; +import { + toPublicURL, + Helmet, + hasApiExpander, + getBaseUrl, +} from '@plone/volto/helpers'; +import { getNavroot } from '@plone/volto/actions'; import config from '@plone/volto/registry'; +import { useDispatch, useSelector } from 'react-redux'; const ContentMetadataTags = (props) => { const { @@ -14,6 +21,17 @@ const ContentMetadataTags = (props) => { description, } = props.content; + const dispatch = useDispatch(); + const pathname = useSelector((state) => state.router.location.pathname); + const navroot = useSelector((state) => state.navroot?.data?.navroot); + const site = useSelector((state) => state.site?.data); + + useEffect(() => { + if (pathname && !hasApiExpander('navroot', getBaseUrl(pathname))) { + dispatch(getNavroot(getBaseUrl(pathname))); + } + }, [dispatch, pathname]); + const getContentImageInfo = () => { const { contentMetadataTagsImageField } = config.settings; const image = props.content[contentMetadataTagsImageField]; @@ -45,10 +63,26 @@ const ContentMetadataTags = (props) => { const contentImageInfo = getContentImageInfo(); + const getTitle = () => { + const includeSiteTitle = + config?.settings?.siteTitleFormat?.includeSiteTitle || false; + const titleAndSiteTitleSeparator = + config?.settings?.titleAndSiteTitleSeparator || '-'; + const navRootTitle = navroot?.title; + const siteRootTitle = site?.['plone.site_title']; + const titlePart = navRootTitle || siteRootTitle; + + if (includeSiteTitle && titlePart && titlePart !== title) { + return seo_title || `${title} ${titleAndSiteTitleSeparator} ${titlePart}`; + } else { + return seo_title || title; + } + }; + return ( <> - {(seo_title || title)?.replace(/\u00AD/g, '')} + {getTitle()?.replace(/\u00AD/g, '')} { const mockStore = configureStore(); describe('Multilingual Logo', () => { - it('renders a logo component with multilingual', () => { + it('renders a logo component in a multilingual site root', () => { const store = mockStore({ intl: { locale: 'en', messages: {}, }, + navroot: { + data: { + id: 'http://localhost:3000/@navroot', + navroot: { + '@id': 'http://localhost:3000', + title: 'Plone Site', + }, + }, + }, + router: { + location: { + pathname: '/', + }, + }, + site: { + data: {}, + }, + }); + const component = renderer.create( + + + + + , + ); + const json = component.toJSON(); + expect(json).toMatchSnapshot(); + }); + + it('renders a logo component in a multilingual site language root', () => { + const store = mockStore({ + intl: { + locale: 'en', + messages: {}, + }, + navroot: { + data: { + id: 'http://localhost:3000/en/@navroot', + navroot: { + '@id': 'http://localhost:3000/en', + title: 'English', + }, + }, + }, + router: { + location: { + pathname: '/en', + }, + }, + site: { + data: { + 'plone.site_title': 'Plone Site', + }, + }, + }); + const component = renderer.create( + + + + + , + ); + const json = component.toJSON(); + expect(json).toMatchSnapshot(); + }); + + it('renders a logo component with a custom logo in a non-root url', () => { + const store = mockStore({ + intl: { + locale: 'en', + messages: {}, + }, + navroot: { + data: { + id: 'http://localhost:3000/en/@navroot', + navroot: { + '@id': 'http://localhost:3000/en', + title: 'English', + }, + }, + }, + router: { + location: { + pathname: '/en', + }, + }, + site: { + data: { + 'plone.site_logo': + 'http://localhost:3000/@@site-logo/logo.cab945d8.svg', + }, + }, + }); + const component = renderer.create( + + + + + , + ); + const json = component.toJSON(); + expect(json).toMatchSnapshot(); + }); + + it('renders a logo component with a custom logo in a non-root url with path', () => { + const store = mockStore({ + intl: { + locale: 'en', + messages: {}, + }, + navroot: { + data: { + id: 'http://localhost:3000/en/@navroot', + navroot: { + '@id': 'http://localhost:3000/en', + title: 'English', + }, + }, + }, + router: { + location: { + pathname: '/en/my/path', + }, + }, + site: { + data: { + 'plone.site_logo': + 'http://localhost:3000/@@site-logo/logo.cab945d8.svg', + }, + }, }); const component = renderer.create( diff --git a/src/components/theme/Logo/Logo.jsx b/src/components/theme/Logo/Logo.jsx index b1ab5b5f8b..aa29762582 100644 --- a/src/components/theme/Logo/Logo.jsx +++ b/src/components/theme/Logo/Logo.jsx @@ -2,25 +2,18 @@ * Logo component. * @module components/theme/Logo/Logo */ - -import { defineMessages, useIntl } from 'react-intl'; +import { useEffect } from 'react'; import { Image } from 'semantic-ui-react'; -import { useSelector } from 'react-redux'; -import config from '@plone/volto/registry'; -import { UniversalLink } from '@plone/volto/components'; -import { toBackendLang } from '@plone/volto/helpers'; +import { ConditionalLink } from '@plone/volto/components'; import LogoImage from '@plone/volto/components/theme/Logo/Logo.svg'; - -const messages = defineMessages({ - site: { - id: 'Site', - defaultMessage: 'Site', - }, - plonesite: { - id: 'Plone Site', - defaultMessage: 'Plone Site', - }, -}); +import { useSelector, useDispatch } from 'react-redux'; +import { getNavroot } from '@plone/volto/actions'; +import { + flattenToAppURL, + hasApiExpander, + getBaseUrl, + toPublicURL, +} from '@plone/volto/helpers'; /** * Logo component class. @@ -29,23 +22,36 @@ const messages = defineMessages({ * @returns {string} Markup of the component. */ const Logo = () => { - const { settings } = config; - const lang = useSelector((state) => state.intl.locale); - const intl = useIntl(); + const pathname = useSelector((state) => state.router.location.pathname); + const site = useSelector((state) => state.site.data); + const navroot = useSelector((state) => state.navroot.data); + const dispatch = useDispatch(); + + useEffect(() => { + if (pathname && !hasApiExpander('navroot', getBaseUrl(pathname))) { + dispatch(getNavroot(getBaseUrl(pathname))); + } + }, [dispatch, pathname]); + + // remove trailing slash + const currentURL = toPublicURL(pathname).replace(/\/$/, ''); return ( - {intl.formatMessage(messages.plonesite)} - + ); }; diff --git a/src/components/theme/Logo/Logo.test.jsx b/src/components/theme/Logo/Logo.test.jsx index 8066e58848..c89650c3cc 100644 --- a/src/components/theme/Logo/Logo.test.jsx +++ b/src/components/theme/Logo/Logo.test.jsx @@ -4,17 +4,151 @@ import configureStore from 'redux-mock-store'; import { Provider } from 'react-intl-redux'; import { MemoryRouter } from 'react-router-dom'; +import config from '@plone/volto/registry'; + import Logo from './Logo'; const mockStore = configureStore(); +beforeAll(() => { + config.settings.publicURL = 'http://localhost:3000'; +}); + describe('Logo', () => { - it('renders a logo component', () => { + it('renders a logo component with default config', () => { + const store = mockStore({ + intl: { + locale: 'en', + messages: {}, + }, + navroot: { + data: { + id: 'http://localhost:3000/@navroot', + navroot: { + '@id': 'http://localhost:3000', + title: 'Plone Site', + }, + }, + }, + router: { + location: { + pathname: '/', + }, + }, + site: { + data: {}, + }, + }); + const component = renderer.create( + + + + + , + ); + const json = component.toJSON(); + expect(json).toMatchSnapshot(); + }); + it('renders a logo component with a custom logo', () => { const store = mockStore({ intl: { locale: 'en', messages: {}, }, + navroot: { + data: { + id: 'http://localhost:3000/@navroot', + navroot: { + '@id': 'http://localhost:3000', + title: 'Plone Site', + }, + }, + }, + router: { + location: { + pathname: '/', + }, + }, + site: { + data: { + 'plone.site_logo': + 'http://localhost:3000/@@site-logo/logo.cab945d8.svg', + }, + }, + }); + const component = renderer.create( + + + + + , + ); + const json = component.toJSON(); + expect(json).toMatchSnapshot(); + }); + it('renders a logo component with default config in a non-root url', () => { + const store = mockStore({ + intl: { + locale: 'en', + messages: {}, + }, + navroot: { + data: { + id: 'http://localhost:3000/@navroot', + navroot: { + '@id': 'http://localhost:3000', + title: 'Plone Site', + }, + }, + }, + router: { + location: { + pathname: '/some-page', + }, + }, + site: { + data: { + 'plone.site_logo': + 'http://localhost:3000/@@site-logo/logo.cab945d8.svg', + }, + }, + }); + const component = renderer.create( + + + + + , + ); + const json = component.toJSON(); + expect(json).toMatchSnapshot(); + }); + it('renders a logo component with a custom logo in a non-root url', () => { + const store = mockStore({ + intl: { + locale: 'en', + messages: {}, + }, + navroot: { + data: { + id: 'http://localhost:3000/@navroot', + navroot: { + '@id': 'http://localhost:3000', + title: 'Plone Site', + }, + }, + }, + router: { + location: { + pathname: '/some-page', + }, + }, + site: { + data: { + 'plone.site_logo': + 'http://localhost:3000/@@site-logo/logo.cab945d8.svg', + }, + }, }); const component = renderer.create( diff --git a/src/components/theme/Logo/__snapshots__/Logo.Multilingual.test.jsx.snap b/src/components/theme/Logo/__snapshots__/Logo.Multilingual.test.jsx.snap index 5720c4fa59..4bc42b2a24 100644 --- a/src/components/theme/Logo/__snapshots__/Logo.Multilingual.test.jsx.snap +++ b/src/components/theme/Logo/__snapshots__/Logo.Multilingual.test.jsx.snap @@ -1,20 +1,45 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Multilingual Logo renders a logo component with multilingual 1`] = ` +exports[`Multilingual Logo renders a logo component in a multilingual site language root 1`] = ` +English +`; + +exports[`Multilingual Logo renders a logo component in a multilingual site root 1`] = ` +Plone Site +`; + +exports[`Multilingual Logo renders a logo component with a custom logo in a non-root url 1`] = ` +English +`; + +exports[`Multilingual Logo renders a logo component with a custom logo in a non-root url with path 1`] = ` Plone Site `; diff --git a/src/components/theme/Logo/__snapshots__/Logo.test.jsx.snap b/src/components/theme/Logo/__snapshots__/Logo.test.jsx.snap index a23f375bac..dfe8409855 100644 --- a/src/components/theme/Logo/__snapshots__/Logo.test.jsx.snap +++ b/src/components/theme/Logo/__snapshots__/Logo.test.jsx.snap @@ -1,20 +1,53 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Logo renders a logo component 1`] = ` +exports[`Logo renders a logo component with a custom logo 1`] = ` +Plone Site +`; + +exports[`Logo renders a logo component with a custom logo in a non-root url 1`] = ` + + Plone Site + +`; + +exports[`Logo renders a logo component with default config 1`] = ` +Plone Site +`; + +exports[`Logo renders a logo component with default config in a non-root url 1`] = ` Plone Site `; diff --git a/src/components/theme/SearchWidget/SearchWidget.jsx b/src/components/theme/SearchWidget/SearchWidget.jsx index b8f2008813..89db2a9a38 100644 --- a/src/components/theme/SearchWidget/SearchWidget.jsx +++ b/src/components/theme/SearchWidget/SearchWidget.jsx @@ -1,8 +1,11 @@ -import { useState } from 'react'; +import { useState, useEffect } from 'react'; import { useHistory } from 'react-router-dom'; import { Form, Input } from 'semantic-ui-react'; import { defineMessages, useIntl } from 'react-intl'; +import { useDispatch, useSelector } from 'react-redux'; +import { getNavroot } from '@plone/volto/actions'; +import { hasApiExpander, getBaseUrl } from '@plone/volto/helpers'; import { Icon } from '@plone/volto/components'; import zoomSVG from '@plone/volto/icons/zoom.svg'; @@ -19,6 +22,8 @@ const messages = defineMessages({ const SearchWidget = (props) => { const intl = useIntl(); + const dispatch = useDispatch(); + const [text, setText] = useState(''); const history = useHistory(); const onChangeText = (event, { value }) => { @@ -29,14 +34,21 @@ const SearchWidget = (props) => { const path = pathname?.length > 0 ? `&path=${encodeURIComponent(pathname)}` : ''; - history.push(`/search?SearchableText=${encodeURIComponent(text)}${path}`); + history.push(`./search?SearchableText=${encodeURIComponent(text)}${path}`); // reset input value setText(''); event.preventDefault(); }; + const navroot = useSelector((state) => state.navroot?.data); + useEffect(() => { + if (!hasApiExpander('navroot', getBaseUrl(pathname))) { + dispatch(getNavroot(getBaseUrl(pathname))); + } + }, [dispatch, pathname]); + return ( -
+ { locale: 'en', messages: {}, }, + navroot: { + data: { + '@id': 'http://localhost:3000/@navroot', + navroot: { + '@id': 'http://localhost:3000', + }, + }, + }, }); const component = renderer.create( diff --git a/src/components/theme/SearchWidget/__snapshots__/SearchWidget.test.jsx.snap b/src/components/theme/SearchWidget/__snapshots__/SearchWidget.test.jsx.snap index 5734af70ab..3861e4b6f7 100644 --- a/src/components/theme/SearchWidget/__snapshots__/SearchWidget.test.jsx.snap +++ b/src/components/theme/SearchWidget/__snapshots__/SearchWidget.test.jsx.snap @@ -2,7 +2,7 @@ exports[`SearchWidget renders a search widget component 1`] = ` diff --git a/src/components/theme/View/View.jsx b/src/components/theme/View/View.jsx index 0fb916922b..e836e452ab 100644 --- a/src/components/theme/View/View.jsx +++ b/src/components/theme/View/View.jsx @@ -123,6 +123,7 @@ class View extends Component { if (!hasApiExpander('actions', getBaseUrl(this.props.pathname))) { this.props.listActions(getBaseUrl(this.props.pathname)); } + this.props.getContent( getBaseUrl(this.props.pathname), this.props.versionId, @@ -142,6 +143,7 @@ class View extends Component { if (!hasApiExpander('actions', getBaseUrl(nextProps.pathname))) { this.props.listActions(getBaseUrl(nextProps.pathname)); } + this.props.getContent( getBaseUrl(nextProps.pathname), this.props.versionId, diff --git a/src/config/ControlPanels.js b/src/config/ControlPanels.js index b0bdb7d935..2f6a763986 100644 --- a/src/config/ControlPanels.js +++ b/src/config/ControlPanels.js @@ -75,7 +75,6 @@ export const filterControlPanelsSchema = (controlpanel) => { 'toolbar_position', 'toolbar_logo', 'default_page', - 'site_logo', 'site_favicon', 'site_favicon_mimetype', 'exposeDCMetaTags', diff --git a/src/config/Widgets.jsx b/src/config/Widgets.jsx index 3c1d391185..d51544e244 100644 --- a/src/config/Widgets.jsx +++ b/src/config/Widgets.jsx @@ -24,6 +24,7 @@ import InternalUrlWidget from '@plone/volto/components/manage/Widgets/InternalUr import EmailWidget from '@plone/volto/components/manage/Widgets/EmailWidget'; import NumberWidget from '@plone/volto/components/manage/Widgets/NumberWidget'; import ImageSizeWidget from '@plone/volto/components/manage/Widgets/ImageSizeWidget'; +import RegistryImageWidget from '@plone/volto/components/manage/Widgets/RegistryImageWidget'; import ReferenceWidget from '@plone/volto/components/manage/Widgets/ReferenceWidget'; import ObjectBrowserWidget from '@plone/volto/components/manage/Widgets/ObjectBrowserWidget'; @@ -72,6 +73,7 @@ export const widgetMapping = { recurrence: RecurrenceWidget, remoteUrl: UrlWidget, id: IdWidget, + site_logo: RegistryImageWidget, }, widget: { richtext: WysiwygWidget, diff --git a/src/config/index.js b/src/config/index.js index 4193f7aa1a..4053b10706 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -37,6 +37,8 @@ import applyAddonConfiguration, { addonsInfo } from 'load-volto-addons'; import ConfigRegistry from '@plone/volto/registry'; +import { getSiteAsyncPropExtender } from '@plone/volto/helpers'; + const host = process.env.HOST || 'localhost'; const port = process.env.PORT || '3000'; @@ -83,7 +85,13 @@ let config = { // https://6.docs.plone.org/volto/configuration/settings-reference.html#term-apiExpanders // { // match: '', - // GET_CONTENT: ['breadcrumbs', 'navigation', 'actions', 'types'], + // GET_CONTENT: [ + // 'breadcrumbs', + // 'navigation', + // 'actions', + // 'types', + // 'navroot', + // ], // }, ], // Internal proxy to bypass CORS *while developing*. NOT intended for production use. @@ -128,7 +136,7 @@ let config = { useEmailAsLogin: false, persistentReducers: ['blocksClipboard'], initialReducersBlacklist: [], // reducers in this list won't be hydrated in windows.__data - asyncPropsExtenders: [], // per route asyncConnect customizers + asyncPropsExtenders: [getSiteAsyncPropExtender], // per route asyncConnect customizers contentIcons: contentIcons, loadables, lazyBundles: { @@ -188,6 +196,10 @@ let config = { blockSettingsTabFieldsetsInitialStateOpen: true, excludeLinksAndReferencesMenuItem: false, containerBlockTypes: ['gridBlock'], + siteTitleFormat: { + includeSiteTitle: false, + titleAndSiteTitleSeparator: '-', + }, }, experimental: { addBlockButton: { @@ -223,7 +235,7 @@ config.settings.apiExpanders = [ ...config.settings.apiExpanders, { match: '', - GET_CONTENT: ['breadcrumbs', 'actions', 'types'], + GET_CONTENT: ['breadcrumbs', 'actions', 'types', 'navroot'], }, { match: '', diff --git a/src/constants/ActionTypes.js b/src/constants/ActionTypes.js index 426569f3a2..f3f68a9a6f 100644 --- a/src/constants/ActionTypes.js +++ b/src/constants/ActionTypes.js @@ -139,3 +139,5 @@ export const GET_USERSCHEMA = 'GET_USERSCHEMA'; export const GET_UPGRADE = 'GET_UPGRADE'; export const POST_UPGRADE = 'POST_UPGRADE'; export const RESET_LOGIN_REQUEST = 'RESET_LOGIN_REQUEST'; +export const GET_SITE = 'GET_SITE'; +export const GET_NAVROOT = 'GET_NAVROOT'; diff --git a/src/express-middleware/images.js b/src/express-middleware/images.js index f23f21408f..849996be72 100644 --- a/src/express-middleware/images.js +++ b/src/express-middleware/images.js @@ -28,6 +28,7 @@ export default function imagesMiddleware() { middleware.all(['**/@@images/*'], imageMiddlewareFn); middleware.all(['/@portrait/*'], imageMiddlewareFn); + middleware.all(['/@@site-logo/*'], imageMiddlewareFn); middleware.id = 'imageResourcesProcessor'; return middleware; } diff --git a/src/helpers/Site/index.js b/src/helpers/Site/index.js new file mode 100644 index 0000000000..9cc76ab746 --- /dev/null +++ b/src/helpers/Site/index.js @@ -0,0 +1,21 @@ +import { GET_SITE } from '@plone/volto/constants/ActionTypes'; +import { getSite } from '@plone/volto/actions'; + +const getSiteAsyncPropExtender = { + path: '/', + extend: (dispatchActions) => { + if ( + dispatchActions.filter((asyncAction) => asyncAction.key === GET_SITE) + .length === 0 + ) { + dispatchActions.push({ + key: GET_SITE, + promise: ({ location, store: { dispatch } }) => + __SERVER__ && dispatch(getSite()), + }); + } + return dispatchActions; + }, +}; + +export { getSiteAsyncPropExtender }; diff --git a/src/helpers/index.js b/src/helpers/index.js index 41a989c8d4..f8ab57ef38 100644 --- a/src/helpers/index.js +++ b/src/helpers/index.js @@ -121,3 +121,4 @@ export { getCurrentStateMapping, getWorkflowOptions, } from './Workflows/Workflows'; +export { getSiteAsyncPropExtender } from './Site'; diff --git a/src/reducers/index.js b/src/reducers/index.js index 64d203aca6..9f50e0527f 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -50,6 +50,8 @@ import workingCopy from './workingcopy/workingcopy'; import transactions from './transactions/transactions'; import upgrade from './upgrade/upgrade'; import userschema from './userschema/userschema'; +import site from './site/site'; +import navroot from './navroot/navroot'; /** * Root reducer. @@ -105,6 +107,8 @@ const reducers = { workingCopy, transactions, userschema, + site, + navroot, }; export default reducers; diff --git a/src/reducers/navroot/navroot.js b/src/reducers/navroot/navroot.js new file mode 100644 index 0000000000..5da33328b5 --- /dev/null +++ b/src/reducers/navroot/navroot.js @@ -0,0 +1,79 @@ +/** + * Navroot reducer. + * @module reducers/navroot/navroot + */ +import { + flattenToAppURL, + getBaseUrl, + hasApiExpander, +} from '@plone/volto/helpers'; + +import { GET_NAVROOT, GET_CONTENT } from '@plone/volto/constants/ActionTypes'; + +const initialState = { + error: null, + loaded: false, + loading: false, + data: {}, +}; + +/** + * navroot reducer. + * @function navroot + * @param {Object} state Current state. + * @param {Object} action Action to be handled. + * @returns {Object} New state. + */ +export default function navroot(state = initialState, action = {}) { + let hasExpander; + switch (action.type) { + case `${GET_NAVROOT}_PENDING`: + return { + ...state, + error: null, + loaded: false, + loading: true, + data: {}, + }; + case `${GET_CONTENT}_SUCCESS`: + hasExpander = hasApiExpander( + 'navroot', + getBaseUrl(flattenToAppURL(action.result['@id'])), + ); + if (hasExpander && !action.subrequest) { + return { + ...state, + error: null, + data: action.result['@components'].navroot, + loaded: true, + loading: false, + }; + } + return state; + case `${GET_NAVROOT}_SUCCESS`: + hasExpander = hasApiExpander( + 'navroot', + getBaseUrl(flattenToAppURL(action.result['@id'])), + ); + if (!hasExpander) { + return { + ...state, + error: null, + loaded: true, + loading: false, + data: action.result, + }; + } + return state; + case `${GET_NAVROOT}_FAIL`: + return { + ...state, + error: action.result, + loaded: false, + loading: false, + data: {}, + }; + default: + return state; + } +} diff --git a/src/reducers/navroot/navroot.test.js b/src/reducers/navroot/navroot.test.js new file mode 100644 index 0000000000..6fd0236360 --- /dev/null +++ b/src/reducers/navroot/navroot.test.js @@ -0,0 +1,110 @@ +import { GET_CONTENT, GET_NAVROOT } from '@plone/volto/constants/ActionTypes'; +import config from '@plone/volto/registry'; +import navroot from './navroot'; + +const { settings } = config; + +describe('Navroot reducer', () => { + it('should return the initial state', () => { + expect(navroot()).toEqual({ + error: null, + data: {}, + loaded: false, + loading: false, + }); + }); + + it('should handle GET_NAVROOT_PENDING', () => { + expect( + navroot(undefined, { + type: `${GET_NAVROOT}_PENDING`, + }), + ).toEqual({ + error: null, + data: {}, + loaded: false, + loading: true, + }); + }); + + it('should handle GET_NAVROOT_SUCCESS', () => { + expect( + navroot(undefined, { + type: `${GET_NAVROOT}_SUCCESS`, + result: { + title: 'Welcome to Plone!', + description: + 'Congratulations! You have successfully installed Plone.', + '@id': `${settings.apiPath}/front-page`, + }, + }), + ).toEqual({ + error: null, + data: { + '@id': `${settings.apiPath}/front-page`, + title: 'Welcome to Plone!', + description: 'Congratulations! You have successfully installed Plone.', + }, + + loaded: true, + loading: false, + }); + }); + + it('should handle GET_NAVROOT_FAIL', () => { + expect( + navroot(undefined, { + type: `${GET_NAVROOT}_FAIL`, + error: 'failed', + }), + ).toEqual({ + error: undefined, + data: {}, + loaded: false, + loading: false, + }); + }); +}); + +describe('Navroot reducer (NAVROOT)GET_CONTENT', () => { + beforeEach(() => { + config.settings.apiExpanders = [ + { + match: '', + GET_CONTENT: ['navroot'], + }, + ]; + }); + + it('should handle (NAVROOT)GET_CONTENT_SUCCESS', () => { + expect( + navroot(undefined, { + type: `${GET_CONTENT}_SUCCESS`, + result: { + '@components': { + navroot: { + navroot: { + title: 'Welcome to Plone!', + description: + 'Congratulations! You have successfully installed Plone.', + '@id': `${settings.apiPath}/front-page`, + }, + }, + }, + }, + }), + ).toEqual({ + error: null, + data: { + navroot: { + '@id': `${settings.apiPath}/front-page`, + title: 'Welcome to Plone!', + description: + 'Congratulations! You have successfully installed Plone.', + }, + }, + loaded: true, + loading: false, + }); + }); +}); diff --git a/src/reducers/site/site.js b/src/reducers/site/site.js new file mode 100644 index 0000000000..05c1a1480f --- /dev/null +++ b/src/reducers/site/site.js @@ -0,0 +1,51 @@ +/** + * Site reducer. + * @module reducers/site/site + */ + +import { GET_SITE } from '@plone/volto/constants/ActionTypes'; + +const initialState = { + error: null, + loaded: false, + loading: false, + data: {}, +}; + +/** + * Site reducer. + * @function site + * @param {Object} state Current state. + * @param {Object} action Action to be handled. + * @returns {Object} New state. + */ +export default function site(state = initialState, action = {}) { + switch (action.type) { + case `${GET_SITE}_PENDING`: + return { + ...state, + error: null, + loaded: false, + loading: true, + data: {}, + }; + case `${GET_SITE}_SUCCESS`: + return { + ...state, + error: null, + loaded: true, + loading: false, + data: action.result, + }; + case `${GET_SITE}_FAIL`: + return { + ...state, + error: action.result, + loaded: false, + loading: false, + data: {}, + }; + default: + return state; + } +} diff --git a/src/reducers/site/site.test.js b/src/reducers/site/site.test.js new file mode 100644 index 0000000000..1ca7b46635 --- /dev/null +++ b/src/reducers/site/site.test.js @@ -0,0 +1,67 @@ +import { GET_SITE } from '@plone/volto/constants/ActionTypes'; +import config from '@plone/volto/registry'; +import site from './site'; + +const { settings } = config; + +describe('Site reducer', () => { + it('should return the initial state', () => { + expect(site()).toEqual({ + error: null, + data: {}, + loaded: false, + loading: false, + }); + }); + + it('should handle GET_SITE_PENDING', () => { + expect( + site(undefined, { + type: `${GET_SITE}_PENDING`, + }), + ).toEqual({ + error: null, + data: {}, + loaded: false, + loading: true, + }); + }); + + it('should handle GET_SITE_SUCCESS', () => { + expect( + site(undefined, { + type: `${GET_SITE}_SUCCESS`, + result: { + title: 'Welcome to Plone!', + description: + 'Congratulations! You have successfully installed Plone.', + '@id': `${settings.apiPath}/front-page`, + }, + }), + ).toEqual({ + error: null, + data: { + '@id': `${settings.apiPath}/front-page`, + title: 'Welcome to Plone!', + description: 'Congratulations! You have successfully installed Plone.', + }, + + loaded: true, + loading: false, + }); + }); + + it('should handle GET_SITE_FAIL', () => { + expect( + site(undefined, { + type: `${GET_SITE}_FAIL`, + error: 'failed', + }), + ).toEqual({ + error: undefined, + data: {}, + loaded: false, + loading: false, + }); + }); +});