mirror of
https://github.com/strapi/strapi.git
synced 2025-11-02 02:44:55 +00:00
Merge branch 'features/webhooks' of github.com:strapi/strapi into front/webhooks-editview
This commit is contained in:
commit
4aeb5399ee
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -134,4 +134,4 @@ Check out our [roadmap](https://portal.productboard.com/strapi) to get informed
|
||||
|
||||
## License
|
||||
|
||||
[MIT License](LICENSE.md) Copyright (c) 2015-2019 [Strapi Solutions](https://strapi.io/).
|
||||
[MIT License](LICENSE.md) Copyright (c) 2015-2020 [Strapi Solutions](https://strapi.io/).
|
||||
|
||||
@ -14,9 +14,9 @@ You will also need another `string` field that contains the slugified value of y
|
||||
|
||||
Let's configure the layout of the **edit page** to make it more user friendly for the content editor.
|
||||
|
||||
- Click on the **Content Manager** link in the left menu.
|
||||
- Then on the `Article` Content Type.
|
||||
- And finally on the **Edit View** tab.
|
||||
- Click on the **Article** link in the left menu.
|
||||
- Then on the `+ Add New Article` button.
|
||||
- And finally on the `Configure the view` button.
|
||||
|
||||
Here we will be able to setup the `slug` field.
|
||||
|
||||
|
||||
@ -91,6 +91,23 @@ query {
|
||||
}
|
||||
```
|
||||
|
||||
### Fetch dynamic zone data
|
||||
|
||||
Dynamic zones are union types in graphql so you need to use fragments to query the fields.
|
||||
|
||||
```
|
||||
query {
|
||||
restaurants {
|
||||
dz {
|
||||
__typename
|
||||
... on ComponentDefaultClosingperiod {
|
||||
label
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Create a new entry
|
||||
|
||||
- `input`: Object
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
"app.components.BlockLink.code": "Příklady kódu",
|
||||
"app.components.BlockLink.code.content": "Naučte se na příkladech vytvořených komunitou.",
|
||||
"app.components.BlockLink.documentation": "Přečíst dokumentaci",
|
||||
"app.components.BlockLink.documentation.content": "Objevte koncepty, referenční průvodce a tutoriály.",
|
||||
"app.components.BlockLink.documentation.content": "Objevte koncepty, referenční průvodce a návody.",
|
||||
"app.components.Button.cancel": "Zrušit",
|
||||
"app.components.Button.save": "Uložit",
|
||||
"app.components.ComingSoonPage.comingSoon": "Již brzy",
|
||||
@ -34,7 +34,7 @@
|
||||
"app.components.HomePage.create": "Vytvořte svůj první Typ obsahu",
|
||||
"app.components.HomePage.createBlock.content.first": "Tento ",
|
||||
"app.components.HomePage.createBlock.content.second": " zásuvný modul vám pomůže definovat datovou strukturu vašich modelů. Pokud jste zde nový, velmi doporučujeme postupovat dle našeho ",
|
||||
"app.components.HomePage.createBlock.content.tutorial": " tutoriálu.",
|
||||
"app.components.HomePage.createBlock.content.tutorial": " návodu.",
|
||||
"app.components.HomePage.cta": "POTVRDIT",
|
||||
"app.components.HomePage.newsLetter": "Přihlaste se k odběru newsletteru a zůstaňte v kontaktu s projektem Strapi",
|
||||
"app.components.HomePage.support": "PODPOŘTE NÁS",
|
||||
@ -105,6 +105,9 @@
|
||||
"app.components.listPlugins.title.plural": "{number} zásuvných modulů je instalováno",
|
||||
"app.components.listPlugins.title.singular": "{number} zásuvný modul je nainstalován",
|
||||
"app.components.listPluginsPage.deletePlugin.error": "Došlo k chybě při odinstalaci zásuvného modulu",
|
||||
|
||||
"app.links.configure-view": "Upravit vzhled",
|
||||
|
||||
"app.utils.SelectOption.defaultMessage": " ",
|
||||
"app.utils.defaultMessage": " ",
|
||||
"app.utils.placeholder.defaultMessage": " ",
|
||||
@ -112,7 +115,7 @@
|
||||
"components.AutoReloadBlocker.header": "Pro tento zásuvný modul musí být zapnuta funkce znovu načítání.",
|
||||
"components.ErrorBoundary.title": "Něco se pokazilo...",
|
||||
"components.Input.error.attribute.key.taken": "Tato hodnota již existuje",
|
||||
"components.Input.error.attribute.sameKeyAndName": "Nemůže se rovnat",
|
||||
"components.Input.error.attribute.sameKeyAndName": "Hodnoty nesmí být stejné",
|
||||
"components.Input.error.attribute.taken": "Název tohoto pole již existuje",
|
||||
"components.Input.error.contentTypeName.taken": "Tento název již existuje",
|
||||
"components.Input.error.custom-error": "{errorMessage} ",
|
||||
@ -123,9 +126,11 @@
|
||||
"components.Input.error.validation.min": "Hodnota je příliš nízká.",
|
||||
"components.Input.error.validation.minLength": "Hodnota je příliš krátká.",
|
||||
"components.Input.error.validation.minSupMax": "Nemůže být nadřazený",
|
||||
"components.Input.error.validation.regex": "Hodnota neodpovídá regexu.",
|
||||
"components.Input.error.validation.regex": "Hodnota neodpovídá požadovanému vzoru.",
|
||||
"components.Input.error.validation.required": "Tato hodnota je povinná.",
|
||||
"components.Input.error.validation.unique": "Tato hodnota již byla použita.",
|
||||
"components.InputSelect.option.placeholder": "Vyberte zde",
|
||||
"component.Input.error.validation.integer": "Tato hodnota musí být celé číslo",
|
||||
"components.ListRow.empty": "Žádná data k zobrazení.",
|
||||
"components.OverlayBlocker.description": "Používáte funkcionalitu, která potřebuje restartovat server. Počkejte, až se server opět spustí.",
|
||||
"components.OverlayBlocker.description.serverError": "Server by měl být restartován, zkontrolujte prosím protokoly v terminálu.",
|
||||
|
||||
@ -97,7 +97,7 @@
|
||||
"app.components.PluginCard.compatible": "Compatible with your app",
|
||||
"app.components.PluginCard.compatibleCommunity": "Compatible with the community",
|
||||
"app.components.PluginCard.more-details": "More details",
|
||||
"app.components.PluginCard.PopUpWarning.install.impossible.autoReload.needed": "The autoReload feature needs to be unabled. Please start you app with `yarn develop`.",
|
||||
"app.components.PluginCard.PopUpWarning.install.impossible.autoReload.needed": "The autoReload feature needs to be enabled. Please start your app with `yarn develop`.",
|
||||
"app.components.PluginCard.PopUpWarning.install.impossible.environment": "For security reasons, a plugin can only be downloaded in a development environment.",
|
||||
"app.components.PluginCard.PopUpWarning.install.impossible.confirm": "I understand!",
|
||||
"app.components.PluginCard.PopUpWarning.install.impossible.title": "Downloading is impossible",
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ const fse = require('fs-extra');
|
||||
const chalk = require('chalk');
|
||||
const execa = require('execa');
|
||||
const ora = require('ora');
|
||||
const _ = require('lodash');
|
||||
|
||||
const stopProcess = require('./utils/stop-process');
|
||||
const { trackUsage, captureStderr } = require('./utils/usage');
|
||||
@ -42,7 +43,7 @@ module.exports = async function createProject(
|
||||
strapiDependencies: scope.strapiDependencies,
|
||||
additionalsDependencies: dependencies,
|
||||
strapiVersion: scope.strapiVersion,
|
||||
projectName: scope.name,
|
||||
projectName: _.kebabCase(scope.name),
|
||||
uuid: scope.uuid,
|
||||
}),
|
||||
{
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"welcome": "Vítejte"
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,15 +1,19 @@
|
||||
{
|
||||
"models": "Druhy obsahu",
|
||||
"models.numbered": "Druhy obsahu ({number})",
|
||||
"models": "Typy obsahu",
|
||||
"models.numbered": "Typy obsahu ({number})",
|
||||
"groups": "Skupiny",
|
||||
"groups.numbered": "Skupiny ({number})",
|
||||
"EditRelations.title": "Relační data",
|
||||
"components.AddFilterCTA.add": "Filtry",
|
||||
"components.AddFilterCTA.hide": "Filtry",
|
||||
"components.DraggableAttr.edit": "Klikněte pro úpravu",
|
||||
"components.DraggableAttr.edit": "Upravte kliknutím",
|
||||
"components.DynamicZone.add-compo": "Přidat do {componentName}",
|
||||
"components.DynamicZone.pick-compo": "Vyberte jeden komponent",
|
||||
"components.DynamicZone.missing.singular": "Chybějící komponenty: {count}",
|
||||
"components.DynamicZone.missing.plural": "Chybějící komponenty: {count}",
|
||||
"components.EmptyAttributesBlock.button": "Přejít k nastavení",
|
||||
"components.EmptyAttributesBlock.description": "Můžete upravit svá nastavení",
|
||||
"components.FieldItem.linkToGroupLayout": "Nastavit rozložení skupiny",
|
||||
"components.FieldItem.linkToComponentLayout": "Nastavit rozložení komponentu",
|
||||
"components.FilterOptions.FILTER_TYPES.=": "je",
|
||||
"components.FilterOptions.FILTER_TYPES._contains": "obsahuje",
|
||||
"components.FilterOptions.FILTER_TYPES._containss": "obsahuje (citlivé na velká písmena)",
|
||||
@ -26,12 +30,17 @@
|
||||
"components.FiltersPickWrapper.PluginHeader.description": "Nastavit pravidla aplikování filtrů na záznamy",
|
||||
"components.FiltersPickWrapper.PluginHeader.title.filter": "Filtry",
|
||||
"components.FiltersPickWrapper.hide": "Skrýt",
|
||||
"components.Group.notification.info.minimum-requirement": "Pole bylo přidáno do vaší skupiny aby byly splněna minimální kritéria validace.",
|
||||
"components.Group.notification.info.maximum-requirement": "Již jste dosáhli maximálního množství polí",
|
||||
"components.Group.empty.repeatable": "Zatím žádný záznam. Klikněte na tlačítko níže k jeho přidání.",
|
||||
"components.Group.reset": "Resetovat záznam",
|
||||
"components.notification.info.minimum-requirement": "Pole bylo přidáno pro splnění minimálních požadavků",
|
||||
"components.notification.info.maximum-requirement": "Již jste dosáhli maximálního počtu polí",
|
||||
"components.empty-repeatable": "Zatím zde není žádný záznam. Kliknutím na tlačítko níže jej přidáte.",
|
||||
"components.reset-entry": "Zrušit záznam",
|
||||
"components.LimitSelect.itemsPerPage": "Položek na stránku",
|
||||
"components.Search.placeholder": "Vyhledat záznam...",
|
||||
|
||||
"components.SettingsViewWrapper.pluginHeader.title": "Nastavit zobrazení - {name}",
|
||||
"components.SettingsViewWrapper.pluginHeader.description.edit-settings": "Upravit vzhled zobrazení úprav.",
|
||||
"components.SettingsViewWrapper.pluginHeader.description.list-settings": "Zvolte nastavení zobrazení záznamu.",
|
||||
|
||||
"components.TableDelete.delete": "Odstranit vše",
|
||||
"components.TableDelete.deleteSelected": "Odstranit výběr",
|
||||
"components.TableDelete.entries.plural": "{number} položek vybráno",
|
||||
@ -51,44 +60,53 @@
|
||||
"containers.Edit.submit": "Uložit",
|
||||
"containers.Edit.Link.Layout": "Nastavit rozložení",
|
||||
"containers.Edit.Link.Fields": "Upravit pole",
|
||||
"containers.Edit.Link.Model": "Upravit Typ obsahu",
|
||||
"containers.EditView.notification.errors": "Formulář obsahuje chyby",
|
||||
"containers.Home.introduction": "K úpravě vašich záznamů prosím přistupte skrz odkaz v levém menu. Tento zásuvný modul neobsahuje způsob jak upravit nastavení, stále na něm pracujeme.",
|
||||
"containers.Home.pluginHeaderDescription": "Spravujte své záznamy mocným a intuitivním rozhraním.",
|
||||
"containers.Home.pluginHeaderTitle": "Správce obsahu",
|
||||
|
||||
"containers.List.addAnEntry": "Přidat nový {entity}",
|
||||
"containers.List.errorFetchRecords": "Chyba",
|
||||
"containers.List.pluginHeaderDescription": "{label} záznamů nalezeno",
|
||||
"containers.List.pluginHeaderDescription.singular": "{label} záznam nalezen",
|
||||
"containers.ListPage.displayedFields": "Zobrazená pole",
|
||||
"containers.SettingPage.addField": "Přidat nové pole",
|
||||
"containers.SettingPage.addRelationalField": "Přidat nové relační pole",
|
||||
|
||||
"containers.ListSettingsView.modal-form.edit-label": "Upravit popisek",
|
||||
"containers.EditSettingsView.modal-form.edit-field": "Upravit pole",
|
||||
|
||||
"containers.SettingPage.add.field": "Vložit další pole",
|
||||
"containers.SettingPage.add.relational-field": "Vložit další relační pole",
|
||||
"containers.SettingPage.attributes": "Pole atributů",
|
||||
"containers.SettingPage.attributes.description": "Definovat pořadí atributů",
|
||||
"containers.SettingPage.attributes.description": "Nastavit pořadí atributů",
|
||||
"containers.SettingPage.editSettings.description": "Přesuňte pole k vybudování rozložení",
|
||||
"containers.SettingPage.editSettings.title": "Upravit pohled (nastavení)",
|
||||
"containers.SettingPage.editSettings.entry.title": "Název záznamu",
|
||||
"containers.SettingPage.editSettings.entry.title.description": "Nastavit zobrazená pole vašeho záznamu",
|
||||
"containers.SettingPage.listSettings.description": "Změnit nastavení pro tento druh obsahu",
|
||||
"containers.SettingPage.editSettings.entry.title.description": "Nastavit zobrazená pole záznamu",
|
||||
"containers.SettingPage.listSettings.description": "Změnit nastavení pro tento Typ obsahu",
|
||||
"containers.SettingPage.listSettings.title": "Zobrazení seznamu (nastavení)",
|
||||
"containers.SettingPage.pluginHeaderDescription": "Změnit výchozí nastavení pro tento Druh Obsahu",
|
||||
"containers.SettingPage.pluginHeaderDescription": "Změnit výchozí nastavení pro tento Typ obsahu",
|
||||
"containers.SettingPage.relations": "Relační pole",
|
||||
"containers.SettingPage.settings": "Nastavení",
|
||||
"containers.SettingPage.layout": "Rozložení",
|
||||
"containers.SettingPage.view": "Zobrazení",
|
||||
"containers.EditView.Group.add.new": "PŘIDAT NOVÝ ZÁZNAM",
|
||||
"containers.SettingViewModel.pluginHeader.title": "Správce Obsahu - {name}",
|
||||
"containers.EditView.components.missing.singular": "Chybějící komponenty: {count}",
|
||||
"containers.EditView.components.missing.plural": "Chybějící komponenty: {count}",
|
||||
"containers.SettingViewModel.pluginHeader.title": "Správce obsahu - {name}",
|
||||
"containers.SettingsPage.Block.contentType.description": "Upravit specifická nastavení",
|
||||
"containers.SettingsPage.Block.contentType.title": "Druhy obsahu",
|
||||
"containers.SettingsPage.Block.generalSettings.description": "Změnit výchozí nastavení pro váše Druhy Obsahu",
|
||||
"containers.SettingsPage.Block.contentType.title": "Typy obsahu",
|
||||
"containers.SettingsPage.Block.generalSettings.description": "Změnit výchozí nastavení pro váše Typy obsahu",
|
||||
"containers.SettingsPage.Block.generalSettings.title": "Obecné",
|
||||
"containers.SettingsPage.pluginHeaderDescription": "Upravit nastavení všech vašich Druhů obsahu a Skupin",
|
||||
"containers.SettingsPage.pluginHeaderDescription": "Upravit nastavení všech vašich Typů obsahu a Skupin",
|
||||
"containers.SettingsView.list.title": "Zobrazit nastavení",
|
||||
"containers.SettingsView.list.subtitle": "Upravit rozložení a zobrazení vašech druhů obsahu a skupin",
|
||||
"containers.SettingsView.list.subtitle": "Upravit rozložení a zobrazení vašich Typů obsahu a skupin",
|
||||
|
||||
"emptyAttributes.button": "Přejít na tvorbu obsahu",
|
||||
"emptyAttributes.description": "Přidejte své první pole do tohoto Druhu Obsahu",
|
||||
"emptyAttributes.description": "Přidejte své první pole do tohoto Typu obsahu",
|
||||
"emptyAttributes.title": "Zatím zde nejsou žádná pole",
|
||||
"error.attribute.key.taken": "Hodnota již existuje",
|
||||
"error.attribute.sameKeyAndName": "Nemůže se rovnat",
|
||||
"error.attribute.sameKeyAndName": "Hodnoty nesmí být stejné",
|
||||
"error.attribute.taken": "Pole se stejným názvem již existuje",
|
||||
"error.contentTypeName.taken": "Tento název již existuje",
|
||||
"error.model.fetch": "Při pokusu o načtení nastavení modelů došlo k chybě.",
|
||||
@ -117,7 +135,7 @@
|
||||
"form.Input.label": "Štítek",
|
||||
"form.Input.label.inputDescription": "Tato hodnota přepíše štítek zobrazený v hlavičce tabulky",
|
||||
"form.Input.pageEntries": "Záznamů na stránku",
|
||||
"form.Input.pageEntries.inputDescription": "Poznámka: Můžete přepsat tuto hodnotu v nastavení Druhů Obsahu.",
|
||||
"form.Input.pageEntries.inputDescription": "Poznámka: Můžete přepsat tuto hodnotu v nastavení Typů obsahu.",
|
||||
"form.Input.placeholder": "Moje hodnota",
|
||||
"form.Input.placeholder.placeholder": "Moje hodnota",
|
||||
"form.Input.search": "Povolit vyhledávání",
|
||||
@ -127,7 +145,7 @@
|
||||
|
||||
"global.displayedFields": "Zobrazená pole",
|
||||
|
||||
"notification.error.displayedFields": "Musíte mít alespoň jedno zobrazené pole",
|
||||
"notification.error.displayedFields": "Alespoň jedno pole musí být zobrazeno",
|
||||
"notification.error.relationship.fetch": "Při načítání relačních vazeb došlo k chybě.",
|
||||
"notification.info.SettingPage.disableSort": "Musíte mít alespoň jeden atribut s povolením řazením.",
|
||||
"pageNotFound": "Stránka nenalezena",
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
const { createModelConfigurationSchema } = require('./validation');
|
||||
const contentTypeService = require('../services/ContentTypes');
|
||||
const componentService = require('../services/Components');
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Returns the list of available components
|
||||
*/
|
||||
async listComponents(ctx) {
|
||||
const contentTypeService =
|
||||
strapi.plugins['content-manager'].services.contenttypes;
|
||||
|
||||
const data = Object.keys(strapi.components).map(uid => {
|
||||
return {
|
||||
category: strapi.components[uid].category,
|
||||
@ -35,6 +36,9 @@ module.exports = {
|
||||
return ctx.notFound('component.notFound');
|
||||
}
|
||||
|
||||
const componentService =
|
||||
strapi.plugins['content-manager'].services.components;
|
||||
|
||||
const data = await componentService.getComponentInformations(uid);
|
||||
|
||||
ctx.body = { data };
|
||||
@ -56,6 +60,11 @@ module.exports = {
|
||||
return ctx.notFound('component.notFound');
|
||||
}
|
||||
|
||||
const componentService =
|
||||
strapi.plugins['content-manager'].services.components;
|
||||
const contentTypeService =
|
||||
strapi.plugins['content-manager'].services.contenttypes;
|
||||
|
||||
const schema = contentTypeService.formatContentTypeSchema(component);
|
||||
let input;
|
||||
try {
|
||||
|
||||
@ -2,13 +2,15 @@
|
||||
|
||||
const _ = require('lodash');
|
||||
const parseMultipartBody = require('../utils/parse-multipart');
|
||||
const contentManagerService = require('../services/ContentManager');
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Returns a list of entities of a content-type matching the query parameters
|
||||
*/
|
||||
async find(ctx) {
|
||||
const contentManagerService =
|
||||
strapi.plugins['content-manager'].services.contentmanager;
|
||||
|
||||
let entities = [];
|
||||
if (_.has(ctx.request.query, '_q')) {
|
||||
entities = await contentManagerService.search(
|
||||
@ -28,6 +30,9 @@ module.exports = {
|
||||
* Returns an entity of a content type by id
|
||||
*/
|
||||
async findOne(ctx) {
|
||||
const contentManagerService =
|
||||
strapi.plugins['content-manager'].services.contentmanager;
|
||||
|
||||
const entry = await contentManagerService.fetch(ctx.params);
|
||||
|
||||
// Entry not found
|
||||
@ -42,6 +47,9 @@ module.exports = {
|
||||
* Returns a count of entities of a content type matching query parameters
|
||||
*/
|
||||
async count(ctx) {
|
||||
const contentManagerService =
|
||||
strapi.plugins['content-manager'].services.contentmanager;
|
||||
|
||||
let count;
|
||||
if (_.has(ctx.request.query, '_q')) {
|
||||
count = await contentManagerService.countSearch(
|
||||
@ -61,6 +69,9 @@ module.exports = {
|
||||
* Creates an entity of a content type
|
||||
*/
|
||||
async create(ctx) {
|
||||
const contentManagerService =
|
||||
strapi.plugins['content-manager'].services.contentmanager;
|
||||
|
||||
const { model } = ctx.params;
|
||||
|
||||
try {
|
||||
@ -96,6 +107,9 @@ module.exports = {
|
||||
async update(ctx) {
|
||||
const { id, model } = ctx.params;
|
||||
|
||||
const contentManagerService =
|
||||
strapi.plugins['content-manager'].services.contentmanager;
|
||||
|
||||
try {
|
||||
if (ctx.is('multipart')) {
|
||||
const { data, files } = parseMultipartBody(ctx);
|
||||
@ -125,6 +139,9 @@ module.exports = {
|
||||
* Deletes one entity of a content type matching a query
|
||||
*/
|
||||
async delete(ctx) {
|
||||
const contentManagerService =
|
||||
strapi.plugins['content-manager'].services.contentmanager;
|
||||
|
||||
ctx.body = await contentManagerService.delete(ctx.params);
|
||||
},
|
||||
|
||||
@ -132,6 +149,9 @@ module.exports = {
|
||||
* Deletes multiple entities of a content type matching a query
|
||||
*/
|
||||
async deleteMany(ctx) {
|
||||
const contentManagerService =
|
||||
strapi.plugins['content-manager'].services.contentmanager;
|
||||
|
||||
ctx.body = await contentManagerService.deleteMany(
|
||||
ctx.params,
|
||||
ctx.request.query
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
const { createModelConfigurationSchema } = require('./validation');
|
||||
const service = require('../services/ContentTypes');
|
||||
const componentService = require('../services/Components');
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Returns the list of available content types
|
||||
*/
|
||||
listContentTypes(ctx) {
|
||||
const service = strapi.plugins['content-manager'].services.contenttypes;
|
||||
|
||||
const contentTypes = Object.keys(strapi.contentTypes)
|
||||
.filter(uid => {
|
||||
if (uid.startsWith('strapi::')) return false;
|
||||
@ -42,6 +42,10 @@ module.exports = {
|
||||
return ctx.notFound('contentType.notFound');
|
||||
}
|
||||
|
||||
const service = strapi.plugins['content-manager'].services.contenttypes;
|
||||
const componentService =
|
||||
strapi.plugins['content-manager'].services.components;
|
||||
|
||||
const contentTypeConfigurations = await service.getConfiguration(uid);
|
||||
|
||||
const data = {
|
||||
@ -74,6 +78,8 @@ module.exports = {
|
||||
return ctx.notFound('contentType.notFound');
|
||||
}
|
||||
|
||||
const service = strapi.plugins['content-manager'].services.contenttypes;
|
||||
|
||||
const schema = service.formatContentTypeSchema(contentType);
|
||||
|
||||
let input;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -36,7 +36,6 @@ function EditViewButton(props) {
|
||||
: `${category}/${componentSlug}`;
|
||||
|
||||
const handleClick = () => {
|
||||
// TODO
|
||||
emitEvent('willEditEditLayout');
|
||||
props.push(`${baseUrl}/${suffixUrl}`);
|
||||
};
|
||||
|
||||
@ -44,7 +44,24 @@ const AttributeOption = forwardRef(({ tabIndex, type }, ref) => {
|
||||
const handleClick = () => {
|
||||
const forTarget = query.get('forTarget');
|
||||
const targetUid = query.get('targetUid');
|
||||
const headerDisplayName = query.get('headerDisplayName');
|
||||
const header_label_1 = query.get('header_label_1');
|
||||
const header_info_category_1 = query.get('header_info_category_1');
|
||||
const header_info_name_1 = query.get('header_info_name_1');
|
||||
const header_label_2 = query.get('header_label_2');
|
||||
const header_icon_name_2 = query.get('header_icon_name_2');
|
||||
const header_icon_isCustom_2 = query.get('header_icon_isCustom_2');
|
||||
const header_info_category_2 = query.get('header_info_category_2');
|
||||
const header_info_name_2 = query.get('header_info_name_2');
|
||||
const header_label_3 = query.get('header_label_3');
|
||||
const header_icon_name_3 = query.get('header_icon_name_3');
|
||||
const header_icon_isCustom_3 = query.get('header_icon_isCustom_3');
|
||||
const header_info_category_3 = query.get('header_info_category_3');
|
||||
const header_info_name_3 = query.get('header_info_name_3');
|
||||
const header_label_4 = query.get('header_label_4');
|
||||
const header_icon_name_4 = query.get('header_icon_name_4');
|
||||
const header_icon_isCustom_4 = query.get('header_icon_isCustom_4');
|
||||
const header_info_category_4 = query.get('header_info_category_4');
|
||||
const header_info_name_4 = query.get('header_info_name_4');
|
||||
|
||||
const search = makeSearch({
|
||||
modalType: 'attribute',
|
||||
@ -53,11 +70,28 @@ const AttributeOption = forwardRef(({ tabIndex, type }, ref) => {
|
||||
forTarget,
|
||||
targetUid,
|
||||
attributeType: type,
|
||||
headerDisplayName,
|
||||
step: type === 'component' ? '1' : null,
|
||||
headerDisplayCategory: query.get('headerDisplayCategory'),
|
||||
headerDisplaySubCategory: query.get('headerDisplaySubCategory'),
|
||||
subTargetUid: query.get('subTargetUid'),
|
||||
|
||||
header_label_1,
|
||||
header_info_name_1,
|
||||
header_info_category_1,
|
||||
header_label_2,
|
||||
header_icon_name_2,
|
||||
header_icon_isCustom_2,
|
||||
header_info_name_2,
|
||||
header_info_category_2,
|
||||
header_label_3,
|
||||
header_icon_name_3,
|
||||
header_icon_isCustom_3,
|
||||
header_info_name_3,
|
||||
header_info_category_3,
|
||||
header_label_4,
|
||||
header_icon_name_4,
|
||||
header_icon_isCustom_4,
|
||||
header_info_name_4,
|
||||
header_info_category_4,
|
||||
header_icon_isCustom_1: false,
|
||||
header_icon_name_1: type,
|
||||
});
|
||||
|
||||
if (forTarget === 'contentType') {
|
||||
|
||||
@ -15,8 +15,10 @@ import Td from '../Td';
|
||||
function ComponentList({
|
||||
customRowComponent,
|
||||
component,
|
||||
dzName,
|
||||
mainTypeName,
|
||||
isFromDynamicZone,
|
||||
isNestedInDZComponent,
|
||||
firstLoopComponentName,
|
||||
firstLoopComponentUid,
|
||||
}) {
|
||||
@ -32,6 +34,7 @@ function ComponentList({
|
||||
<Td colSpan={12} isChildOfDynamicZone={isFromDynamicZone}>
|
||||
<List
|
||||
customRowComponent={customRowComponent}
|
||||
dzName={dzName}
|
||||
items={convertAttrObjToArray(attributes)}
|
||||
targetUid={component}
|
||||
mainTypeName={mainTypeName}
|
||||
@ -39,6 +42,7 @@ function ComponentList({
|
||||
firstLoopComponentUid={firstLoopComponentUid || component}
|
||||
editTarget="components"
|
||||
isFromDynamicZone={isFromDynamicZone}
|
||||
isNestedInDZComponent={isNestedInDZComponent}
|
||||
isSub
|
||||
secondLoopComponentName={
|
||||
firstLoopComponentName ? componentName : null
|
||||
@ -53,15 +57,19 @@ function ComponentList({
|
||||
ComponentList.defaultProps = {
|
||||
component: null,
|
||||
customRowComponent: null,
|
||||
dzName: null,
|
||||
isFromDynamicZone: false,
|
||||
isNestedInDZComponent: false,
|
||||
};
|
||||
|
||||
ComponentList.propTypes = {
|
||||
component: PropTypes.string,
|
||||
customRowComponent: PropTypes.func,
|
||||
dzName: PropTypes.string,
|
||||
firstLoopComponentName: PropTypes.string,
|
||||
firstLoopComponentUid: PropTypes.string,
|
||||
isFromDynamicZone: PropTypes.bool,
|
||||
isNestedInDZComponent: PropTypes.bool,
|
||||
mainTypeName: PropTypes.string.isRequired,
|
||||
targetUid: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
@ -85,6 +85,7 @@ function DynamicZoneList({
|
||||
<ComponentList
|
||||
{...props}
|
||||
isFromDynamicZone
|
||||
dzName={name}
|
||||
mainTypeName={mainTypeName}
|
||||
targetUid={targetUid}
|
||||
key={component}
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { get } from 'lodash';
|
||||
import { useGlobalContext, ListButton } from 'strapi-helper-plugin';
|
||||
import { Button } from '@buffetjs/core';
|
||||
import { Plus } from '@buffetjs/icons';
|
||||
@ -26,34 +27,125 @@ function List({
|
||||
mainTypeName,
|
||||
editTarget,
|
||||
isFromDynamicZone,
|
||||
isNestedInDZComponent,
|
||||
isMain,
|
||||
firstLoopComponentName,
|
||||
firstLoopComponentUid,
|
||||
secondLoopComponentName,
|
||||
secondLoopComponentUid,
|
||||
isSub,
|
||||
dzName,
|
||||
}) {
|
||||
const { formatMessage } = useGlobalContext();
|
||||
const { isInDevelopmentMode } = useDataManager();
|
||||
const { isInDevelopmentMode, modifiedData } = useDataManager();
|
||||
const { openModalAddField } = useListView();
|
||||
const onClickAddField = () => {
|
||||
let headerDisplayName = mainTypeName;
|
||||
const firstComponentIcon = get(
|
||||
modifiedData,
|
||||
['components', firstLoopComponentUid, 'schema', 'icon'],
|
||||
''
|
||||
);
|
||||
const firstComponentCategory = get(
|
||||
modifiedData,
|
||||
['components', firstLoopComponentUid, 'category'],
|
||||
null
|
||||
);
|
||||
const firstComponentFriendlyName = get(
|
||||
modifiedData,
|
||||
['components', firstLoopComponentUid, 'schema', 'name'],
|
||||
null
|
||||
);
|
||||
const secondComponentCategory = get(
|
||||
modifiedData,
|
||||
['components', secondLoopComponentUid, 'category'],
|
||||
null
|
||||
);
|
||||
const secondComponentFriendlyName = get(
|
||||
modifiedData,
|
||||
['components', secondLoopComponentUid, 'schema', 'name'],
|
||||
null
|
||||
);
|
||||
const secondComponentIcon = get(
|
||||
modifiedData,
|
||||
['components', secondLoopComponentUid, 'schema', 'icon'],
|
||||
''
|
||||
);
|
||||
let firstHeaderObject = {
|
||||
header_label_1: mainTypeName,
|
||||
header_icon_name_1: editTarget,
|
||||
header_icon_isCustom_1: false,
|
||||
header_info_category_1: null,
|
||||
header_info_name_1: null,
|
||||
};
|
||||
let secondHeaderObject = {
|
||||
header_label_2: firstLoopComponentName,
|
||||
header_icon_name_2: 'component',
|
||||
header_icon_isCustom_2: false,
|
||||
header_info_category_2: firstComponentCategory,
|
||||
header_info_name_2: firstComponentFriendlyName,
|
||||
};
|
||||
let thirdHeaderObject = {
|
||||
header_icon_name_3: 'component',
|
||||
header_icon_isCustom_3: false,
|
||||
header_info_category_3: secondComponentCategory,
|
||||
header_info_name_3: secondComponentFriendlyName,
|
||||
};
|
||||
let fourthHeaderObject = {
|
||||
header_icon_name_4: null,
|
||||
header_icon_isCustom_4: false,
|
||||
header_info_category_4: secondComponentCategory,
|
||||
header_info_name_4: secondComponentFriendlyName,
|
||||
};
|
||||
|
||||
if (firstLoopComponentName) {
|
||||
headerDisplayName = firstLoopComponentName;
|
||||
firstHeaderObject = {
|
||||
...firstHeaderObject,
|
||||
header_icon_name_1: firstComponentIcon,
|
||||
header_icon_isCustom_1: true,
|
||||
};
|
||||
}
|
||||
|
||||
if (secondLoopComponentUid) {
|
||||
headerDisplayName = secondLoopComponentName;
|
||||
firstHeaderObject = {
|
||||
...firstHeaderObject,
|
||||
header_icon_name_1: secondComponentIcon,
|
||||
header_icon_isCustom_1: true,
|
||||
};
|
||||
thirdHeaderObject = {
|
||||
...thirdHeaderObject,
|
||||
header_label_3: secondLoopComponentName,
|
||||
};
|
||||
}
|
||||
|
||||
if (isFromDynamicZone || isNestedInDZComponent) {
|
||||
secondHeaderObject = {
|
||||
...secondHeaderObject,
|
||||
header_label_2: dzName,
|
||||
header_icon_name_2: 'dynamiczone',
|
||||
header_icon_isCustom_2: false,
|
||||
header_info_category_2: null,
|
||||
header_info_name_2: null,
|
||||
};
|
||||
thirdHeaderObject = {
|
||||
...thirdHeaderObject,
|
||||
header_icon_name_3: isNestedInDZComponent ? 'component' : null,
|
||||
header_label_3: firstLoopComponentName,
|
||||
header_info_category_3: firstComponentCategory,
|
||||
header_info_name_3: firstComponentFriendlyName,
|
||||
};
|
||||
fourthHeaderObject = {
|
||||
...fourthHeaderObject,
|
||||
header_label_4: secondLoopComponentName,
|
||||
};
|
||||
}
|
||||
|
||||
openModalAddField(
|
||||
editTarget,
|
||||
targetUid,
|
||||
headerDisplayName,
|
||||
firstLoopComponentUid ? mainTypeName : null,
|
||||
secondLoopComponentName ? firstLoopComponentName : null,
|
||||
secondLoopComponentUid ? firstLoopComponentUid : null
|
||||
firstHeaderObject,
|
||||
secondHeaderObject,
|
||||
thirdHeaderObject,
|
||||
fourthHeaderObject
|
||||
);
|
||||
};
|
||||
|
||||
@ -87,8 +179,9 @@ function List({
|
||||
<React.Fragment key={item.name}>
|
||||
<CustomRow
|
||||
{...item}
|
||||
dzName={dzName}
|
||||
isNestedInDZComponent={isNestedInDZComponent}
|
||||
targetUid={targetUid}
|
||||
// NEW props
|
||||
mainTypeName={mainTypeName}
|
||||
editTarget={editTarget}
|
||||
firstLoopComponentName={firstLoopComponentName}
|
||||
@ -103,8 +196,8 @@ function List({
|
||||
{...item}
|
||||
customRowComponent={customRowComponent}
|
||||
targetUid={targetUid}
|
||||
// NEW PROPS
|
||||
|
||||
dzName={dzName}
|
||||
isNestedInDZComponent={isFromDynamicZone}
|
||||
mainTypeName={mainTypeName}
|
||||
editTarget={editTarget}
|
||||
firstLoopComponentName={firstLoopComponentName}
|
||||
@ -153,9 +246,11 @@ List.defaultProps = {
|
||||
addComponentToDZ: () => {},
|
||||
className: null,
|
||||
customRowComponent: null,
|
||||
dzName: null,
|
||||
firstLoopComponentName: null,
|
||||
firstLoopComponentUid: null,
|
||||
isFromDynamicZone: false,
|
||||
isNestedInDZComponent: false,
|
||||
isMain: false,
|
||||
isSub: false,
|
||||
items: [],
|
||||
@ -168,10 +263,12 @@ List.propTypes = {
|
||||
addComponentToDZ: PropTypes.func,
|
||||
className: PropTypes.string,
|
||||
customRowComponent: PropTypes.func,
|
||||
dzName: PropTypes.string,
|
||||
editTarget: PropTypes.string.isRequired,
|
||||
firstLoopComponentName: PropTypes.string,
|
||||
firstLoopComponentUid: PropTypes.string,
|
||||
isFromDynamicZone: PropTypes.bool,
|
||||
isNestedInDZComponent: PropTypes.bool,
|
||||
isMain: PropTypes.bool,
|
||||
items: PropTypes.instanceOf(Array),
|
||||
mainTypeName: PropTypes.string.isRequired,
|
||||
|
||||
@ -6,6 +6,7 @@ import { AttributeIcon } from '@buffetjs/core';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import pluginId from '../../pluginId';
|
||||
import useDataManager from '../../hooks/useDataManager';
|
||||
import getAttributeDisplayedType from '../../utils/getAttributeDisplayedType';
|
||||
import getTrad from '../../utils/getTrad';
|
||||
import Curve from '../../icons/Curve';
|
||||
import UpperFist from '../UpperFirst';
|
||||
@ -14,6 +15,7 @@ import Wrapper from './Wrapper';
|
||||
function ListRow({
|
||||
configurable,
|
||||
name,
|
||||
dzName,
|
||||
nature,
|
||||
onClick,
|
||||
plugin,
|
||||
@ -28,12 +30,15 @@ function ListRow({
|
||||
repeatable,
|
||||
secondLoopComponentName,
|
||||
secondLoopComponentUid,
|
||||
isNestedInDZComponent,
|
||||
}) {
|
||||
const {
|
||||
contentTypes,
|
||||
isInDevelopmentMode,
|
||||
modifiedData,
|
||||
removeAttribute,
|
||||
} = useDataManager();
|
||||
|
||||
const ico = ['integer', 'biginteger', 'float', 'decimal'].includes(type)
|
||||
? 'number'
|
||||
: type;
|
||||
@ -54,15 +59,120 @@ function ListRow({
|
||||
|
||||
const handleClick = () => {
|
||||
if (configurable !== false) {
|
||||
const firstComponentCategory = get(
|
||||
modifiedData,
|
||||
['components', firstLoopComponentUid, 'category'],
|
||||
null
|
||||
);
|
||||
const secondComponentCategory = get(
|
||||
modifiedData,
|
||||
['components', secondLoopComponentUid, 'category'],
|
||||
null
|
||||
);
|
||||
|
||||
const attrType = nature ? 'relation' : type;
|
||||
let headerDisplayName = mainTypeName;
|
||||
const icoType = getAttributeDisplayedType(attrType);
|
||||
|
||||
let firstHeaderObject = {
|
||||
header_label_1: mainTypeName,
|
||||
header_icon_name_1: icoType,
|
||||
header_icon_isCustom_1: false,
|
||||
header_info_category_1: null,
|
||||
header_info_name_1: null,
|
||||
};
|
||||
let secondHeaderObject = {
|
||||
header_label_2: name,
|
||||
header_icon_name_2: null,
|
||||
header_icon_isCustom_2: false,
|
||||
header_info_category_2: null,
|
||||
header_info_name_2: null,
|
||||
};
|
||||
let thirdHeaderObject = {
|
||||
header_icon_name_3: 'component',
|
||||
header_icon_isCustom_3: false,
|
||||
header_info_category_3: null,
|
||||
header_info_name_3: null,
|
||||
};
|
||||
let fourthHeaderObject = {
|
||||
header_icon_name_4: null,
|
||||
header_icon_isCustom_4: false,
|
||||
header_info_category_4: null,
|
||||
header_info_name_4: null,
|
||||
};
|
||||
let fifthHeaderObject = {
|
||||
header_icon_name_5: null,
|
||||
header_icon_isCustom_5: false,
|
||||
header_info_category_5: null,
|
||||
header_info_name_5: null,
|
||||
};
|
||||
|
||||
if (firstLoopComponentName) {
|
||||
headerDisplayName = firstLoopComponentName;
|
||||
secondHeaderObject = {
|
||||
header_label_2: firstLoopComponentName,
|
||||
header_icon_name_2: 'component',
|
||||
header_icon_isCustom_2: false,
|
||||
header_info_category_2: firstComponentCategory,
|
||||
header_info_name_2: firstLoopComponentName,
|
||||
};
|
||||
|
||||
thirdHeaderObject = {
|
||||
...thirdHeaderObject,
|
||||
header_label_3: name,
|
||||
header_icon_name_3: null,
|
||||
};
|
||||
}
|
||||
|
||||
if (secondLoopComponentUid) {
|
||||
headerDisplayName = secondLoopComponentName;
|
||||
thirdHeaderObject = {
|
||||
...thirdHeaderObject,
|
||||
header_label_3: secondLoopComponentName,
|
||||
header_icon_name_3: 'component',
|
||||
header_info_category_3: secondComponentCategory,
|
||||
header_info_name_3: secondLoopComponentName,
|
||||
};
|
||||
fourthHeaderObject = {
|
||||
...fourthHeaderObject,
|
||||
header_label_4: name,
|
||||
header_icon_name_4: null,
|
||||
};
|
||||
}
|
||||
|
||||
if (isFromDynamicZone || isNestedInDZComponent) {
|
||||
secondHeaderObject = {
|
||||
header_label_2: dzName,
|
||||
header_icon_name_2: 'dynamiczone',
|
||||
header_icon_isCustom_2: false,
|
||||
header_info_name_2: null,
|
||||
header_info_category_2: null,
|
||||
};
|
||||
thirdHeaderObject = {
|
||||
header_icon_name_3: 'component',
|
||||
header_label_3: firstLoopComponentName,
|
||||
header_info_name_3: firstComponentCategory,
|
||||
header_info_category_3: firstComponentCategory,
|
||||
};
|
||||
|
||||
if (!isNestedInDZComponent) {
|
||||
fourthHeaderObject = {
|
||||
header_icon_name_4: null,
|
||||
header_icon_isCustom_4: false,
|
||||
header_info_category_4: null,
|
||||
header_label_4: name,
|
||||
};
|
||||
} else {
|
||||
fourthHeaderObject = {
|
||||
header_icon_name_4: 'components',
|
||||
header_icon_isCustom_4: false,
|
||||
header_info_category_4: secondComponentCategory,
|
||||
header_info_name_4: secondLoopComponentName,
|
||||
header_label_4: secondLoopComponentName,
|
||||
};
|
||||
|
||||
fifthHeaderObject = {
|
||||
...fifthHeaderObject,
|
||||
header_label_5: name,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
onClick(
|
||||
@ -74,10 +184,11 @@ function ListRow({
|
||||
name,
|
||||
// Type of the attribute
|
||||
attrType,
|
||||
headerDisplayName,
|
||||
firstLoopComponentUid ? mainTypeName : null,
|
||||
secondLoopComponentName ? firstLoopComponentName : null,
|
||||
secondLoopComponentUid ? firstLoopComponentUid : null
|
||||
firstHeaderObject,
|
||||
secondHeaderObject,
|
||||
thirdHeaderObject,
|
||||
fourthHeaderObject,
|
||||
fifthHeaderObject
|
||||
);
|
||||
}
|
||||
};
|
||||
@ -171,9 +282,11 @@ function ListRow({
|
||||
|
||||
ListRow.defaultProps = {
|
||||
configurable: true,
|
||||
dzName: null,
|
||||
firstLoopComponentName: null,
|
||||
firstLoopComponentUid: null,
|
||||
isFromDynamicZone: false,
|
||||
isNestedInDZComponent: false,
|
||||
nature: null,
|
||||
onClick: () => {},
|
||||
onClickDelete: () => {},
|
||||
@ -188,10 +301,12 @@ ListRow.defaultProps = {
|
||||
|
||||
ListRow.propTypes = {
|
||||
configurable: PropTypes.bool,
|
||||
dzName: PropTypes.string,
|
||||
editTarget: PropTypes.string.isRequired,
|
||||
firstLoopComponentName: PropTypes.string,
|
||||
firstLoopComponentUid: PropTypes.string,
|
||||
isFromDynamicZone: PropTypes.bool,
|
||||
isNestedInDZComponent: PropTypes.bool,
|
||||
mainTypeName: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
nature: PropTypes.string,
|
||||
|
||||
@ -1,33 +1,20 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { get, upperFirst } from 'lodash';
|
||||
import ComponentInfosWrapper from './ComponentInfosWrapper';
|
||||
import useDataManager from '../../hooks/useDataManager';
|
||||
import UpperFirst from '../UpperFirst';
|
||||
import ComponentInfosWrapper from './ComponentInfosWrapper';
|
||||
|
||||
const ComponentInfos = ({ uid }) => {
|
||||
// We might want to change to initialData...
|
||||
// @Aurelsicoko
|
||||
const { modifiedData } = useDataManager();
|
||||
const currentComponent = get(modifiedData, ['components', uid], {});
|
||||
const currentComponentCategory = get(currentComponent, 'category', '');
|
||||
const currentComponentFriendlyName = get(
|
||||
currentComponent,
|
||||
['schema', 'name'],
|
||||
''
|
||||
);
|
||||
|
||||
const ComponentInfos = ({ category, name }) => {
|
||||
return (
|
||||
<ComponentInfosWrapper>
|
||||
({upperFirst(currentComponentCategory)}
|
||||
—
|
||||
<UpperFirst content={currentComponentFriendlyName} />)
|
||||
(<UpperFirst content={category} /> —
|
||||
<UpperFirst content={name} />)
|
||||
</ComponentInfosWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
ComponentInfos.propTypes = {
|
||||
uid: PropTypes.string.isRequired,
|
||||
category: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default ComponentInfos;
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import UpperFirst from '../UpperFirst';
|
||||
import Icon from './Icon';
|
||||
import Item from './Item';
|
||||
import Menu from './Menu';
|
||||
import Toggle from './Toggle';
|
||||
import Wrapper from './Wrapper';
|
||||
|
||||
const DropdownInfos = ({ headers, shouldDisplaySecondHeader }) => {
|
||||
const [dropdownOpen, setDropdownOpen] = useState(false);
|
||||
|
||||
const toggle = () => setDropdownOpen(prevState => !prevState);
|
||||
return (
|
||||
<Wrapper isOpen={dropdownOpen} toggle={toggle} style={{ margin: 'auto 0' }}>
|
||||
<Toggle>...</Toggle>
|
||||
<Menu style={{ top: '8px' }}>
|
||||
{headers.map((header, index) => {
|
||||
if (!shouldDisplaySecondHeader && index === 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Item key={index}>
|
||||
<Icon type={header.icon.name} />
|
||||
<span>
|
||||
<UpperFirst content={header.label} />
|
||||
</span>
|
||||
</Item>
|
||||
);
|
||||
})}
|
||||
</Menu>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
DropdownInfos.defaultProps = {
|
||||
headers: [],
|
||||
shouldDisplaySecondHeader: false,
|
||||
};
|
||||
|
||||
DropdownInfos.propTypes = {
|
||||
headers: PropTypes.array,
|
||||
shouldDisplaySecondHeader: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default DropdownInfos;
|
||||
@ -1,69 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import UpperFirst from '../UpperFirst';
|
||||
import ComponentInfos from './ComponentInfos';
|
||||
import IconWrapper from './IconWrapper';
|
||||
|
||||
const Header = ({
|
||||
category,
|
||||
name,
|
||||
subCategory,
|
||||
target,
|
||||
targetUid,
|
||||
subTargetUid,
|
||||
}) => {
|
||||
const shouldDisplayComponentCatInfos = target === 'components';
|
||||
|
||||
const content = (
|
||||
<>
|
||||
<span>
|
||||
<UpperFirst content={category} />
|
||||
</span>
|
||||
<IconWrapper>
|
||||
<FontAwesomeIcon icon="chevron-right" />
|
||||
</IconWrapper>
|
||||
{subCategory && (
|
||||
<>
|
||||
<span>
|
||||
<UpperFirst content={subCategory} />
|
||||
</span>
|
||||
<ComponentInfos uid={subTargetUid} />
|
||||
<IconWrapper>
|
||||
<FontAwesomeIcon icon="chevron-right" />
|
||||
</IconWrapper>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{category && content}
|
||||
<span>
|
||||
<UpperFirst content={name} />
|
||||
</span>
|
||||
{shouldDisplayComponentCatInfos && <ComponentInfos uid={targetUid} />}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Header.defaultProps = {
|
||||
category: null,
|
||||
name: null,
|
||||
subCategory: null,
|
||||
subTargetUid: null,
|
||||
target: null,
|
||||
targetUid: null,
|
||||
};
|
||||
|
||||
Header.propTypes = {
|
||||
category: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
subCategory: PropTypes.string,
|
||||
subTargetUid: PropTypes.string,
|
||||
target: PropTypes.string,
|
||||
targetUid: PropTypes.string,
|
||||
};
|
||||
|
||||
export default Header;
|
||||
@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
import { AttributeIcon } from '@buffetjs/core';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const Icon = ({ type }) => (
|
||||
<AttributeIcon type={type} style={{ margin: 'auto 20px auto 0' }} />
|
||||
);
|
||||
|
||||
Icon.propTypes = {
|
||||
type: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default Icon;
|
||||
@ -0,0 +1,19 @@
|
||||
import styled from 'styled-components';
|
||||
import { DropdownItem } from 'reactstrap';
|
||||
|
||||
const Item = styled(DropdownItem)`
|
||||
display: flex;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
color: #3b3b3b;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
&:active,
|
||||
&:focus,
|
||||
&:hover {
|
||||
background-color: transparent;
|
||||
outline: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
export default Item;
|
||||
@ -0,0 +1,8 @@
|
||||
import styled from 'styled-components';
|
||||
import { DropdownMenu } from 'reactstrap';
|
||||
|
||||
const Menu = styled(DropdownMenu)`
|
||||
top: 8px;
|
||||
`;
|
||||
|
||||
export default Menu;
|
||||
@ -0,0 +1,14 @@
|
||||
import styled from 'styled-components';
|
||||
import { DropdownToggle } from 'reactstrap';
|
||||
|
||||
const Toggle = styled(DropdownToggle)`
|
||||
height: 12px;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
margin-top: -14px;
|
||||
color: #3b3b3b;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
`;
|
||||
|
||||
export default Toggle;
|
||||
@ -0,0 +1,12 @@
|
||||
import styled from 'styled-components';
|
||||
import { Dropdown } from 'reactstrap';
|
||||
|
||||
const Wrapper = styled(Dropdown)`
|
||||
.dropdown-menu {
|
||||
top: 8px !important;
|
||||
box-shadow: 0 2px 4px #e3e9f3;
|
||||
border: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
export default Wrapper;
|
||||
@ -1,89 +1,103 @@
|
||||
import React from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { HeaderModalTitle } from 'strapi-helper-plugin';
|
||||
import { get } from 'lodash';
|
||||
import { AttributeIcon } from '@buffetjs/core';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import useDataManager from '../../hooks/useDataManager';
|
||||
import pluginId from '../../pluginId';
|
||||
import ComponentIcon from './ComponentIcon';
|
||||
import Header from './Header';
|
||||
import ComponentInfos from './ComponentInfos';
|
||||
import Icon from './Icon';
|
||||
import IconWrapper from './IconWrapper';
|
||||
import UpperFirst from '../UpperFirst';
|
||||
import DropdownInfos from './DropdownInfos';
|
||||
|
||||
const ModalHeader = ({
|
||||
category,
|
||||
headerId,
|
||||
iconType,
|
||||
name,
|
||||
target,
|
||||
targetUid,
|
||||
subCategory,
|
||||
subTargetUid,
|
||||
}) => {
|
||||
const { modifiedData } = useDataManager();
|
||||
const currentComponent = get(modifiedData, ['components', targetUid], {});
|
||||
const shouldDisplayComponentCatInfos = target === 'components';
|
||||
const currentComponentIcon = get(currentComponent, ['schema', 'icon'], '');
|
||||
|
||||
let iconName;
|
||||
|
||||
if (iconType === 'components') {
|
||||
iconName = 'component';
|
||||
} else {
|
||||
iconName = iconType;
|
||||
}
|
||||
const ModalHeader = ({ headerId, headers }) => {
|
||||
const shouldDisplayDropDown = headers.length > 3;
|
||||
|
||||
return (
|
||||
<section>
|
||||
<HeaderModalTitle style={{ textTransform: 'none' }}>
|
||||
{shouldDisplayComponentCatInfos ? (
|
||||
<ComponentIcon isSelected>
|
||||
<FontAwesomeIcon icon={currentComponentIcon} />
|
||||
</ComponentIcon>
|
||||
) : (
|
||||
<AttributeIcon
|
||||
type={iconName}
|
||||
style={{ margin: 'auto 20px auto 0' }}
|
||||
/>
|
||||
)}
|
||||
{headerId && (
|
||||
<FormattedMessage id={`${pluginId}.${headerId}`} values={{ name }} />
|
||||
)}
|
||||
{!headerId && (
|
||||
<Header
|
||||
category={category}
|
||||
name={name}
|
||||
target={target}
|
||||
targetUid={targetUid}
|
||||
subCategory={subCategory}
|
||||
subTargetUid={subTargetUid}
|
||||
/>
|
||||
<>
|
||||
<Icon type={get(headers, [0, 'icon', 'name'], '')} />
|
||||
<FormattedMessage
|
||||
id={headerId}
|
||||
values={{ name: get(headers, [0, 'label'], '') }}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{!headerId &&
|
||||
headers.map((header, index) => {
|
||||
const iconName = get(header, ['icon', 'name'], '');
|
||||
const iconType = iconName === null ? '' : iconName;
|
||||
const icon = get(header, ['icon', 'isCustom'], false) ? (
|
||||
<ComponentIcon isSelected>
|
||||
<FontAwesomeIcon icon={iconType} />
|
||||
</ComponentIcon>
|
||||
) : (
|
||||
<Icon type={iconType} />
|
||||
);
|
||||
|
||||
if (shouldDisplayDropDown && index === 1) {
|
||||
return (
|
||||
<Fragment key={index}>
|
||||
<IconWrapper>
|
||||
<FontAwesomeIcon icon="chevron-right" />
|
||||
</IconWrapper>
|
||||
<DropdownInfos
|
||||
headers={[headers[1], headers[2]]}
|
||||
shouldDisplaySecondHeader={headers.length > 4}
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
if (shouldDisplayDropDown && index === 2 && headers.length > 4) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (index === 0) {
|
||||
return (
|
||||
<Fragment key={index}>
|
||||
{icon}
|
||||
<span>
|
||||
<UpperFirst content={get(header, ['label'], '')} />
|
||||
</span>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment key={index}>
|
||||
<IconWrapper>
|
||||
<FontAwesomeIcon icon="chevron-right" />
|
||||
</IconWrapper>
|
||||
|
||||
<span>
|
||||
<UpperFirst content={get(header, ['label'], '')} />
|
||||
</span>
|
||||
{header.info.category && (
|
||||
<ComponentInfos
|
||||
category={header.info.category}
|
||||
name={header.info.name}
|
||||
/>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</HeaderModalTitle>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
ModalHeader.defaultProps = {
|
||||
category: null,
|
||||
headerId: '',
|
||||
iconType: 'contentType',
|
||||
name: '',
|
||||
target: null,
|
||||
targetUid: null,
|
||||
subCategory: null,
|
||||
subTargetUid: null,
|
||||
headers: [],
|
||||
};
|
||||
|
||||
ModalHeader.propTypes = {
|
||||
category: PropTypes.string,
|
||||
headerId: PropTypes.string,
|
||||
iconType: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
target: PropTypes.string,
|
||||
targetUid: PropTypes.string,
|
||||
subCategory: PropTypes.string,
|
||||
subTargetUid: PropTypes.string,
|
||||
headers: PropTypes.array,
|
||||
};
|
||||
|
||||
export default ModalHeader;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { fromJS, OrderedMap } from 'immutable';
|
||||
import { get, has } from 'lodash';
|
||||
import retrieveComponentsFromSchema from './utils/retrieveComponentsFromSchema';
|
||||
import makeUnique from '../../utils/makeUnique';
|
||||
|
||||
const initialState = fromJS({
|
||||
@ -24,6 +25,47 @@ const getOppositeNature = originalNature => {
|
||||
}
|
||||
};
|
||||
|
||||
const addComponentsToState = (state, componentToAddUid, objToUpdate) => {
|
||||
let newObj = objToUpdate;
|
||||
const componentToAdd = state.getIn(['components', componentToAddUid]);
|
||||
const isTemporaryComponent = componentToAdd.get('isTemporary');
|
||||
const componentToAddSchema = componentToAdd.getIn(['schema', 'attributes']);
|
||||
const hasComponentAlreadyBeenAdded =
|
||||
state.getIn(['modifiedData', 'components', componentToAddUid]) !==
|
||||
undefined;
|
||||
|
||||
// created components are already in the modifiedData.components
|
||||
// We don't add them because all modifications will be lost
|
||||
if (isTemporaryComponent || hasComponentAlreadyBeenAdded) {
|
||||
return newObj;
|
||||
}
|
||||
|
||||
// Add the added components to the modifiedData.compontnes
|
||||
newObj = newObj.set(componentToAddUid, componentToAdd);
|
||||
const nestedComponents = retrieveComponentsFromSchema(
|
||||
componentToAddSchema.toJS(),
|
||||
state.get('components').toJS()
|
||||
);
|
||||
|
||||
// We need to add the nested components to the modifiedData.components as well
|
||||
nestedComponents.forEach(componentUid => {
|
||||
const isTemporary =
|
||||
state.getIn(['components', componentUid, 'isTemporary']) || false;
|
||||
const hasNestedComponentAlreadyBeenAdded =
|
||||
state.getIn(['modifiedData', 'components', componentUid]) !== undefined;
|
||||
|
||||
// Same logic here otherwise we will lose the modifications added to the components
|
||||
if (!isTemporary && !hasNestedComponentAlreadyBeenAdded) {
|
||||
newObj = newObj.set(
|
||||
componentUid,
|
||||
state.getIn(['components', componentUid])
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return newObj;
|
||||
};
|
||||
|
||||
const reducer = (state, action) => {
|
||||
switch (action.type) {
|
||||
case 'ADD_ATTRIBUTE': {
|
||||
@ -86,12 +128,7 @@ const reducer = (state, action) => {
|
||||
)
|
||||
.updateIn(['modifiedData', 'components'], existingCompos => {
|
||||
if (action.shouldAddComponentToData) {
|
||||
const componentToAdd = state.getIn(['components', rest.component]);
|
||||
|
||||
return existingCompos.update(
|
||||
componentToAdd.get('uid'),
|
||||
() => componentToAdd
|
||||
);
|
||||
return addComponentsToState(state, rest.component, existingCompos);
|
||||
}
|
||||
|
||||
return existingCompos;
|
||||
@ -138,15 +175,7 @@ const reducer = (state, action) => {
|
||||
)
|
||||
.updateIn(['modifiedData', 'components'], old => {
|
||||
const componentsSchema = newComponents.reduce((acc, current) => {
|
||||
const addedCompoSchema = state.getIn(['components', current]);
|
||||
const isTemporaryComponent = addedCompoSchema.get('isTemporary');
|
||||
|
||||
// created components are already in the modifiedData.components
|
||||
if (isTemporaryComponent) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
return acc.set(current, addedCompoSchema);
|
||||
return addComponentsToState(state, current, acc);
|
||||
}, old);
|
||||
|
||||
return componentsSchema;
|
||||
|
||||
@ -31,6 +31,8 @@ import getTrad from '../../utils/getTrad';
|
||||
import makeSearch from '../../utils/makeSearch';
|
||||
import getAttributes from './utils/attributes';
|
||||
import forms from './utils/forms';
|
||||
import createHeadersArray from './utils/createHeadersArray';
|
||||
import createHeadersObjectFromArray from './utils/createHeadersObjectFromArray';
|
||||
import { createComponentUid, createUid } from './utils/createUid';
|
||||
import getModalTitleSubHeader from './utils/getModalTitleSubHeader';
|
||||
import getNextSearch from './utils/getNextSearch';
|
||||
@ -75,18 +77,40 @@ const FormModal = () => {
|
||||
useEffect(() => {
|
||||
if (!isEmpty(search)) {
|
||||
const actionType = query.get('actionType');
|
||||
// Return 'null' if there isn't any attributeType search params
|
||||
// Returns 'null' if there isn't any attributeType search params
|
||||
const attributeName = query.get('attributeName');
|
||||
const attributeType = query.get('attributeType');
|
||||
const dynamicZoneTarget = query.get('dynamicZoneTarget');
|
||||
const forTarget = query.get('forTarget');
|
||||
const headerDisplayCategory = query.get('headerDisplayCategory');
|
||||
const headerDisplayName = query.get('headerDisplayName');
|
||||
const headerDisplaySubCategory = query.get('headerDisplaySubCategory');
|
||||
const modalType = query.get('modalType');
|
||||
const targetUid = query.get('targetUid');
|
||||
const settingType = query.get('settingType');
|
||||
const subTargetUid = query.get('subTargetUid');
|
||||
const headerId = query.get('headerId');
|
||||
const header_label_1 = query.get('header_label_1');
|
||||
const header_icon_name_1 = query.get('header_icon_name_1');
|
||||
const header_icon_isCustom_1 = query.get('header_icon_isCustom_1');
|
||||
const header_info_category_1 = query.get('header_info_category_1');
|
||||
const header_info_name_1 = query.get('header_info_name_1');
|
||||
const header_label_2 = query.get('header_label_2');
|
||||
const header_icon_name_2 = query.get('header_icon_name_2');
|
||||
const header_icon_isCustom_2 = query.get('header_icon_isCustom_2');
|
||||
const header_info_category_2 = query.get('header_info_category_2');
|
||||
const header_info_name_2 = query.get('header_info_name_2');
|
||||
const header_label_3 = query.get('header_label_3');
|
||||
const header_icon_name_3 = query.get('header_icon_name_3');
|
||||
const header_icon_isCustom_3 = query.get('header_icon_isCustom_3');
|
||||
const header_info_category_3 = query.get('header_info_category_3');
|
||||
const header_info_name_3 = query.get('header_info_name_3');
|
||||
const header_label_4 = query.get('header_label_4');
|
||||
const header_icon_name_4 = query.get('header_icon_name_4');
|
||||
const header_icon_isCustom_4 = query.get('header_icon_isCustom_4');
|
||||
const header_info_category_4 = query.get('header_info_category_4');
|
||||
const header_info_name_4 = query.get('header_info_name_4');
|
||||
const header_label_5 = query.get('header_label_5');
|
||||
const header_icon_name_5 = query.get('header_icon_name_5');
|
||||
const header_icon_isCustom_5 = query.get('header_icon_isCustom_5');
|
||||
const header_info_category_5 = query.get('header_info_category_5');
|
||||
const header_info_name_5 = query.get('header_info_name_5');
|
||||
const step = query.get('step');
|
||||
const pathToSchema =
|
||||
forTarget === 'contentType' || forTarget === 'component'
|
||||
@ -98,16 +122,38 @@ const FormModal = () => {
|
||||
attributeName,
|
||||
attributeType,
|
||||
dynamicZoneTarget,
|
||||
headerDisplayName,
|
||||
headerDisplayCategory,
|
||||
headerDisplaySubCategory,
|
||||
forTarget,
|
||||
modalType,
|
||||
pathToSchema,
|
||||
settingType,
|
||||
subTargetUid,
|
||||
step,
|
||||
targetUid,
|
||||
header_label_1,
|
||||
header_icon_name_1,
|
||||
header_icon_isCustom_1,
|
||||
header_info_name_1,
|
||||
header_info_category_1,
|
||||
header_label_2,
|
||||
header_icon_name_2,
|
||||
header_icon_isCustom_2,
|
||||
header_info_name_2,
|
||||
header_info_category_2,
|
||||
header_label_3,
|
||||
header_icon_name_3,
|
||||
header_icon_isCustom_3,
|
||||
header_info_name_3,
|
||||
header_info_category_3,
|
||||
header_label_4,
|
||||
header_icon_name_4,
|
||||
header_icon_isCustom_4,
|
||||
header_info_name_4,
|
||||
header_info_category_4,
|
||||
header_label_5,
|
||||
header_icon_name_5,
|
||||
header_icon_isCustom_5,
|
||||
header_info_name_5,
|
||||
header_info_category_5,
|
||||
headerId,
|
||||
});
|
||||
|
||||
// Reset all the modification when opening the edit category modal
|
||||
@ -280,19 +326,7 @@ const FormModal = () => {
|
||||
const form = get(forms, [state.modalType, 'form', state.settingType], () => ({
|
||||
items: [],
|
||||
}));
|
||||
|
||||
// TODO improve icon logic
|
||||
let iconType = ['component', 'contentType'].includes(state.modalType)
|
||||
? state.modalType
|
||||
: state.forTarget;
|
||||
|
||||
if (state.modalType === 'addComponentToDynamicZone') {
|
||||
iconType = 'dynamiczone';
|
||||
}
|
||||
|
||||
if (state.modalType === 'editCategory') {
|
||||
iconType = 'component';
|
||||
}
|
||||
const headers = createHeadersArray(state);
|
||||
|
||||
const isCreatingContentType = state.modalType === 'contentType';
|
||||
const isCreatingComponent = state.modalType === 'component';
|
||||
@ -310,14 +344,6 @@ const FormModal = () => {
|
||||
const isPickingAttribute = state.modalType === 'chooseAttribute';
|
||||
const uid = createUid(modifiedData.name || '');
|
||||
|
||||
let headerId = isCreating
|
||||
? `modalForm.${state.modalType}.header-create`
|
||||
: 'modalForm.header-edit';
|
||||
|
||||
if (!['contentType', 'component'].includes(state.modalType)) {
|
||||
headerId = null;
|
||||
}
|
||||
|
||||
const checkFormValidity = async () => {
|
||||
let schema;
|
||||
const dataToValidate =
|
||||
@ -532,6 +558,7 @@ const FormModal = () => {
|
||||
...rest,
|
||||
});
|
||||
};
|
||||
|
||||
const handleSubmit = async (e, shouldContinue = isCreating) => {
|
||||
e.preventDefault();
|
||||
|
||||
@ -541,17 +568,21 @@ const FormModal = () => {
|
||||
const targetUid =
|
||||
state.forTarget === 'components' ? state.targetUid : uid;
|
||||
|
||||
// TODO REMOVE and use makeSearch
|
||||
const createNextSearch = searchUid => {
|
||||
if (!shouldContinue) {
|
||||
return '';
|
||||
}
|
||||
const headerIcon = ['contentType', 'component'].includes(state.forTarget)
|
||||
? state.forTarget
|
||||
: get(
|
||||
allDataSchema,
|
||||
['components', state.targetUid, 'schema', 'icon'],
|
||||
''
|
||||
);
|
||||
|
||||
return `modalType=chooseAttribute&forTarget=${
|
||||
state.forTarget
|
||||
}&targetUid=${searchUid}&headerDisplayName=${state.headerDisplayName ||
|
||||
modifiedData.name}`;
|
||||
};
|
||||
// Remove the last header when editing
|
||||
if (state.actionType === 'edit') {
|
||||
headers.pop();
|
||||
}
|
||||
|
||||
const headersObject = createHeadersObjectFromArray(headers);
|
||||
const nextHeaderIndex = headers.length + 1;
|
||||
|
||||
if (isCreatingContentType) {
|
||||
// Create the content type schema
|
||||
@ -571,7 +602,9 @@ const FormModal = () => {
|
||||
modalType: 'chooseAttribute',
|
||||
forTarget: state.forTarget,
|
||||
targetUid,
|
||||
headerDisplayName: modifiedData.name,
|
||||
header_label_1: modifiedData.name,
|
||||
header_icon_name_1: 'contentType',
|
||||
header_icon_isCustom_1: null,
|
||||
}),
|
||||
});
|
||||
} else if (isCreatingComponent) {
|
||||
@ -590,7 +623,9 @@ const FormModal = () => {
|
||||
modalType: 'chooseAttribute',
|
||||
forTarget: state.forTarget,
|
||||
targetUid: componentUid,
|
||||
headerDisplayName: modifiedData.name,
|
||||
header_label_1: modifiedData.name,
|
||||
header_icon_name_1: 'contentType',
|
||||
header_icon_isCustom_1: null,
|
||||
}),
|
||||
pathname: `/plugins/${pluginId}/component-categories/${category}/${componentUid}`,
|
||||
});
|
||||
@ -604,6 +639,7 @@ const FormModal = () => {
|
||||
}
|
||||
} else if (isEditingCategory) {
|
||||
if (toLower(initialData.name) === toLower(modifiedData.name)) {
|
||||
// Close the modal
|
||||
push({ search: '' });
|
||||
|
||||
return;
|
||||
@ -629,20 +665,19 @@ const FormModal = () => {
|
||||
// Adding a component to a dynamiczone is not the same logic as creating a simple field
|
||||
// so the search is different
|
||||
|
||||
// For the modal header
|
||||
const displayCategory = state.headerDisplayName;
|
||||
const displayName = modifiedData.name;
|
||||
|
||||
const dzSearch = makeNextSearch({
|
||||
modalType: 'addComponentToDynamicZone',
|
||||
forTarget: 'contentType',
|
||||
targetUid: state.targetUid,
|
||||
headerDisplayName: displayName,
|
||||
headerDisplayCategory: displayCategory,
|
||||
|
||||
dynamicZoneTarget: modifiedData.name,
|
||||
settingType: 'base',
|
||||
step: '1',
|
||||
actionType: 'create',
|
||||
...headersObject,
|
||||
header_label_2: modifiedData.name,
|
||||
header_icon_name_2: null,
|
||||
header_icon_isCustom_2: false,
|
||||
});
|
||||
const nextSearch = isDynamicZoneAttribute
|
||||
? dzSearch
|
||||
@ -651,11 +686,12 @@ const FormModal = () => {
|
||||
modalType: 'chooseAttribute',
|
||||
forTarget: state.forTarget,
|
||||
targetUid,
|
||||
headerDisplayName: state.headerDisplayName,
|
||||
headerDisplayCategory: state.headerDisplayCategory,
|
||||
// keep the old state
|
||||
headerDisplaySubCategory: state.headerDisplaySubCategory,
|
||||
subTargetUid: state.subTargetUid,
|
||||
...headersObject,
|
||||
header_icon_isCustom_1: ![
|
||||
'contentType',
|
||||
'component',
|
||||
].includes(state.forTarget),
|
||||
header_icon_name_1: headerIcon,
|
||||
},
|
||||
shouldContinue
|
||||
);
|
||||
@ -680,7 +716,6 @@ const FormModal = () => {
|
||||
} else {
|
||||
if (isInFirstComponentStep) {
|
||||
// Navigate the user to step 2
|
||||
// TODO refacto
|
||||
const nextSearchObj = {
|
||||
modalType: 'attribute',
|
||||
actionType: state.actionType,
|
||||
@ -688,8 +723,12 @@ const FormModal = () => {
|
||||
forTarget: state.forTarget,
|
||||
targetUid: state.targetUid,
|
||||
attributeType: 'component',
|
||||
headerDisplayName: state.headerDisplayName,
|
||||
step: '2',
|
||||
...headersObject,
|
||||
header_icon_isCustom_1: !['contentType', 'component'].includes(
|
||||
state.forTarget
|
||||
),
|
||||
header_icon_name_1: headerIcon,
|
||||
};
|
||||
|
||||
push({
|
||||
@ -723,9 +762,18 @@ const FormModal = () => {
|
||||
// This way we can add fields to the added component (if it wasn't there already)
|
||||
true
|
||||
);
|
||||
const nextSearch = {
|
||||
modalType: 'chooseAttribute',
|
||||
forTarget: state.forTarget,
|
||||
targetUid: state.targetUid,
|
||||
...headersObject,
|
||||
header_icon_isCustom_1: !['contentType', 'component'].includes(
|
||||
state.forTarget
|
||||
),
|
||||
header_icon_name_1: headerIcon,
|
||||
};
|
||||
|
||||
// TODO change the search so the modal header is kept
|
||||
push({ search: shouldContinue ? createNextSearch(targetUid) : '' });
|
||||
push({ search: makeSearch(nextSearch, shouldContinue) });
|
||||
|
||||
// We don't need to end the loop here we want the reducer to be reinitialised
|
||||
}
|
||||
@ -736,7 +784,6 @@ const FormModal = () => {
|
||||
// even though the user didn't set any field
|
||||
// We need to prevent the component from being created if the user closes the modal at step 2 without any submission
|
||||
} else if (isCreatingAttribute && isCreatingComponentFromAView) {
|
||||
const { headerDisplayCategory } = state;
|
||||
// Step 1
|
||||
if (isInFirstComponentStep) {
|
||||
// Here the search could be refactored since it is the same as the case from above
|
||||
@ -749,18 +796,12 @@ const FormModal = () => {
|
||||
forTarget: state.forTarget,
|
||||
targetUid: state.targetUid,
|
||||
attributeType: 'component',
|
||||
headerDisplayName: state.headerDisplayName,
|
||||
step: '2',
|
||||
...headersObject,
|
||||
header_icon_isCustom_1: false,
|
||||
header_icon_name_1: 'component',
|
||||
};
|
||||
|
||||
// Modify the searchObj for the modal header
|
||||
// This case is happening when creating a nestedComponent after creating a component
|
||||
if (headerDisplayCategory) {
|
||||
searchObj.headerDisplayCategory = state.headerDisplayCategory;
|
||||
searchObj.headerDisplayName = state.headerDisplayName;
|
||||
searchObj.targetUid = state.targetUid;
|
||||
}
|
||||
|
||||
emitEvent('willCreateComponentFromAttributesModal');
|
||||
|
||||
push({
|
||||
@ -812,21 +853,16 @@ const FormModal = () => {
|
||||
modalType: 'chooseAttribute',
|
||||
forTarget: 'components',
|
||||
targetUid: componentUid,
|
||||
headerDisplayName: modifiedData.name,
|
||||
headerDisplayCategory:
|
||||
state.headerDisplayCategory || state.headerDisplayName,
|
||||
...headersObject,
|
||||
header_icon_isCustom_1: true,
|
||||
header_icon_name_1: componentToCreate.icon,
|
||||
[`header_label_${nextHeaderIndex}`]: modifiedData.name,
|
||||
[`header_icon_name_${nextHeaderIndex}`]: 'component',
|
||||
[`header_icon_isCustom_${nextHeaderIndex}`]: false,
|
||||
[`header_info_category_${nextHeaderIndex}`]: category,
|
||||
[`header_info_name_${nextHeaderIndex}`]: componentToCreate.name,
|
||||
};
|
||||
|
||||
// Then we inverse the headerDisplayName because it becomes the last one displayed
|
||||
// The case is created a component then created a nested one
|
||||
if (headerDisplayCategory) {
|
||||
// This is allows to modify the modal header
|
||||
searchToOpenModalAttributeToAddAttributesToAComponent.headerDisplaySubCategory =
|
||||
state.headerDisplayName;
|
||||
searchToOpenModalAttributeToAddAttributesToAComponent.subTargetUid =
|
||||
state.targetUid;
|
||||
}
|
||||
|
||||
push({
|
||||
search: makeNextSearch(
|
||||
searchToOpenModalAttributeToAddAttributesToAComponent,
|
||||
@ -869,13 +905,19 @@ const FormModal = () => {
|
||||
// The Dynamic Zone and the component is created created
|
||||
// Open the modal to add fields to the created component
|
||||
|
||||
// TODO search for modal header
|
||||
const searchToOpenAddField = {
|
||||
modalType: 'chooseAttribute',
|
||||
forTarget: 'components',
|
||||
targetUid: componentUid,
|
||||
headerDisplayName: modifiedData.componentToCreate.name,
|
||||
headerDisplayCategory: state.headerDisplayCategory,
|
||||
...headersObject,
|
||||
header_icon_isCustom_1: true,
|
||||
header_icon_name_1: modifiedData.componentToCreate.icon,
|
||||
[`header_label_${nextHeaderIndex}`]: modifiedData.name,
|
||||
[`header_icon_name_${nextHeaderIndex}`]: 'component',
|
||||
[`header_icon_isCustom_${nextHeaderIndex}`]: false,
|
||||
[`header_info_category_${nextHeaderIndex}`]: category,
|
||||
[`header_info_name_${nextHeaderIndex}`]: modifiedData
|
||||
.componentToCreate.name,
|
||||
};
|
||||
|
||||
push({ search: makeSearch(searchToOpenAddField, true) });
|
||||
@ -901,7 +943,6 @@ const FormModal = () => {
|
||||
type: 'RESET_PROPS',
|
||||
});
|
||||
} catch (err) {
|
||||
console.log({ err });
|
||||
const errors = getYupInnerErrors(err);
|
||||
|
||||
dispatch({
|
||||
@ -986,16 +1027,7 @@ const FormModal = () => {
|
||||
withoverflow={toString(state.modalType === 'addComponentToDynamicZone')}
|
||||
>
|
||||
<HeaderModal>
|
||||
<ModalHeader
|
||||
name={state.headerDisplayName}
|
||||
category={state.headerDisplayCategory}
|
||||
headerId={headerId}
|
||||
iconType={iconType || 'contentType'}
|
||||
subCategory={state.headerDisplaySubCategory}
|
||||
subTargetUid={state.subTargetUid}
|
||||
target={state.forTarget}
|
||||
targetUid={state.targetUid}
|
||||
/>
|
||||
<ModalHeader headerId={state.headerId} headers={headers} />
|
||||
<section>
|
||||
<HeaderModalTitle>
|
||||
<FormattedMessage
|
||||
@ -1160,7 +1192,7 @@ const FormModal = () => {
|
||||
return (
|
||||
<RelationForm
|
||||
key="relation"
|
||||
mainBoxHeader={state.headerDisplayName}
|
||||
mainBoxHeader={get(headers, [0, 'label'], '')}
|
||||
modifiedData={modifiedData}
|
||||
naturePickerType={state.forTarget}
|
||||
onChange={handleChange}
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
import { set } from 'lodash';
|
||||
|
||||
const ALLOWED_KEYS = [
|
||||
'header_label',
|
||||
'header_icon_name',
|
||||
'header_icon_isCustom',
|
||||
'header_info_category',
|
||||
'header_info_name',
|
||||
];
|
||||
const createHeadersArray = obj => {
|
||||
const array = Object.keys(obj).reduce((acc, current) => {
|
||||
const splitted = current.split('_');
|
||||
const currentKeys = splitted.filter((_, i) => i !== splitted.length - 1);
|
||||
|
||||
if (ALLOWED_KEYS.includes(currentKeys.join('_'))) {
|
||||
const currentKeysIndex = parseInt(splitted[splitted.length - 1] - 1, 10);
|
||||
const path = [
|
||||
currentKeysIndex,
|
||||
...currentKeys.filter(key => key !== 'header'),
|
||||
];
|
||||
|
||||
let value = obj[current];
|
||||
|
||||
if (current.includes('isCustom')) {
|
||||
value = obj[current] === 'true';
|
||||
}
|
||||
|
||||
set(acc, path, value);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
return array.filter(obj => obj.label !== null);
|
||||
};
|
||||
|
||||
export default createHeadersArray;
|
||||
@ -0,0 +1,27 @@
|
||||
import { isObject } from 'lodash';
|
||||
|
||||
const createHeadersObjectFromArray = array => {
|
||||
return array.reduce((acc, current, index) => {
|
||||
const createHeaderObject = (obj, i, middle = '') =>
|
||||
Object.keys(obj).reduce((acc1, current1) => {
|
||||
if (isObject(obj[current1])) {
|
||||
return {
|
||||
...acc1,
|
||||
...createHeaderObject(obj[current1], i, `_${current1}`),
|
||||
};
|
||||
}
|
||||
|
||||
const name = `header${middle}_${current1}_${i}`;
|
||||
|
||||
acc1[name] = obj[current1];
|
||||
|
||||
return acc1;
|
||||
}, {});
|
||||
|
||||
const headerObject = createHeaderObject(current, index + 1);
|
||||
|
||||
return { ...acc, ...headerObject };
|
||||
}, {});
|
||||
};
|
||||
|
||||
export default createHeadersObjectFromArray;
|
||||
@ -6,15 +6,37 @@ const INITIAL_STATE_DATA = {
|
||||
attributeType: null,
|
||||
dynamicZoneTarget: null,
|
||||
forTarget: null,
|
||||
headerDisplayCategory: null,
|
||||
headerDisplayName: null,
|
||||
headerDisplaySubCategory: null,
|
||||
modalType: null,
|
||||
pathToSchema: [],
|
||||
settingType: null,
|
||||
step: null,
|
||||
subTargetUid: null,
|
||||
targetUid: null,
|
||||
headerId: null,
|
||||
header_label_1: null,
|
||||
header_icon_name_1: null,
|
||||
header_icon_isCustom_1: null,
|
||||
header_info_category_1: null,
|
||||
header_info_name_1: null,
|
||||
header_label_2: null,
|
||||
header_icon_name_2: null,
|
||||
header_icon_isCustom_2: null,
|
||||
header_info_category_2: null,
|
||||
header_info_name_2: null,
|
||||
header_label_3: null,
|
||||
header_icon_name_3: null,
|
||||
header_icon_isCustom_3: null,
|
||||
header_info_category_3: null,
|
||||
header_info_name_3: null,
|
||||
header_label_4: null,
|
||||
header_icon_name_4: null,
|
||||
header_icon_isCustom_4: null,
|
||||
header_info_category_4: null,
|
||||
header_info_name_4: null,
|
||||
header_label_5: null,
|
||||
header_icon_name_5: null,
|
||||
header_icon_isCustom_5: null,
|
||||
header_info_category_5: null,
|
||||
header_info_name_5: null,
|
||||
};
|
||||
|
||||
export { NAVLINKS, INITIAL_STATE_DATA };
|
||||
|
||||
@ -0,0 +1,143 @@
|
||||
import createHeadersArray from '../createHeadersArray';
|
||||
|
||||
describe('FormModal | utils | createHeadersArray', () => {
|
||||
it('should return an empty array if no header key is set', () => {
|
||||
const data = {
|
||||
actionType: null,
|
||||
attributeName: null,
|
||||
attributeType: null,
|
||||
dynamicZoneTarget: null,
|
||||
forTarget: null,
|
||||
modalType: null,
|
||||
pathToSchema: [],
|
||||
settingType: null,
|
||||
step: null,
|
||||
targetUid: null,
|
||||
headerId: null,
|
||||
header_label_1: null,
|
||||
header_icon_name_1: null,
|
||||
header_icon_isCustom_1: null,
|
||||
header_info_category_1: null,
|
||||
header_info_name_1: null,
|
||||
header_label_2: null,
|
||||
header_icon_name_2: null,
|
||||
header_icon_isCustom_2: null,
|
||||
header_info_category_2: null,
|
||||
header_info_name_2: null,
|
||||
header_label_3: null,
|
||||
header_icon_name_3: null,
|
||||
header_icon_isCustom_3: null,
|
||||
header_info_category_3: null,
|
||||
header_info_name_3: null,
|
||||
};
|
||||
|
||||
expect(createHeadersArray(data)).toEqual([]);
|
||||
});
|
||||
|
||||
it('should return an array containing a header object', () => {
|
||||
const data = {
|
||||
actionType: 'something',
|
||||
attributeName: null,
|
||||
attributeType: null,
|
||||
dynamicZoneTarget: null,
|
||||
forTarget: null,
|
||||
|
||||
modalType: null,
|
||||
pathToSchema: [],
|
||||
settingType: null,
|
||||
step: null,
|
||||
targetUid: null,
|
||||
headerId: null,
|
||||
header_label_1: 'restaurant',
|
||||
header_icon_name_1: 'contentType',
|
||||
header_icon_isCustom_1: 'false',
|
||||
header_info_category_1: null,
|
||||
header_info_name_1: null,
|
||||
header_label_2: null,
|
||||
header_icon_name_2: null,
|
||||
header_icon_isCustom_2: null,
|
||||
header_info_category_2: null,
|
||||
header_info_name_2: null,
|
||||
header_label_3: null,
|
||||
header_icon_name_3: null,
|
||||
header_icon_isCustom_3: null,
|
||||
header_info_category_3: null,
|
||||
header_info_name_3: null,
|
||||
};
|
||||
const expected = [
|
||||
{
|
||||
label: 'restaurant',
|
||||
icon: {
|
||||
name: 'contentType',
|
||||
isCustom: false,
|
||||
},
|
||||
info: {
|
||||
name: null,
|
||||
category: null,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
expect(createHeadersArray(data)).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should handle multiple headers correctly', () => {
|
||||
const data = {
|
||||
actionType: 'something',
|
||||
attributeName: null,
|
||||
attributeType: null,
|
||||
dynamicZoneTarget: null,
|
||||
forTarget: null,
|
||||
|
||||
modalType: null,
|
||||
pathToSchema: [],
|
||||
settingType: null,
|
||||
step: null,
|
||||
|
||||
targetUid: null,
|
||||
headerId: null,
|
||||
header_label_1: 'restaurant',
|
||||
header_icon_name_1: 'bool',
|
||||
header_icon_isCustom_1: 'true',
|
||||
header_info_category_1: null,
|
||||
header_info_name_1: null,
|
||||
header_label_2: 'closing period',
|
||||
header_icon_name_2: null,
|
||||
header_icon_isCustom_2: null,
|
||||
header_info_category_2: 'default',
|
||||
header_info_name_2: 'closingperiod',
|
||||
header_label_3: null,
|
||||
header_icon_name_3: null,
|
||||
header_icon_isCustom_3: null,
|
||||
header_info_category_3: null,
|
||||
header_info_name_3: null,
|
||||
};
|
||||
|
||||
const expected = [
|
||||
{
|
||||
label: 'restaurant',
|
||||
icon: {
|
||||
name: 'bool',
|
||||
isCustom: true,
|
||||
},
|
||||
info: {
|
||||
name: null,
|
||||
category: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'closing period',
|
||||
icon: {
|
||||
name: null,
|
||||
isCustom: false,
|
||||
},
|
||||
info: {
|
||||
name: 'closingperiod',
|
||||
category: 'default',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
expect(createHeadersArray(data)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,45 @@
|
||||
import createHeadersObjectFromArray from '../createHeadersObjectFromArray';
|
||||
|
||||
describe('FormModal | utils | createHeadersArray', () => {
|
||||
it('should return a header object', () => {
|
||||
const data = [
|
||||
{
|
||||
label: 'test',
|
||||
icon: {
|
||||
name: 'contentType',
|
||||
isCustom: false,
|
||||
},
|
||||
info: {
|
||||
name: null,
|
||||
category: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'test2',
|
||||
icon: {
|
||||
name: 'book',
|
||||
isCustom: true,
|
||||
},
|
||||
info: {
|
||||
name: 'something',
|
||||
category: 'default',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const expected = {
|
||||
header_label_1: 'test',
|
||||
header_icon_name_1: 'contentType',
|
||||
header_icon_isCustom_1: false,
|
||||
header_info_name_1: null,
|
||||
header_info_category_1: null,
|
||||
header_label_2: 'test2',
|
||||
header_icon_name_2: 'book',
|
||||
header_icon_isCustom_2: true,
|
||||
header_info_name_2: 'something',
|
||||
header_info_category_2: 'default',
|
||||
};
|
||||
|
||||
expect(createHeadersObjectFromArray(data)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
@ -43,10 +43,19 @@ function LeftMenu({ wait }) {
|
||||
actionType: 'edit',
|
||||
modalType: 'editCategory',
|
||||
categoryName: data.name,
|
||||
headerDisplayName: data.name,
|
||||
headerDisplayCategory: formatMessage({
|
||||
header_label_1: formatMessage({
|
||||
id: getTrad('modalForm.header.categories'),
|
||||
}),
|
||||
header_icon_name_1: 'component',
|
||||
header_icon_isCustom_1: false,
|
||||
header_info_category_1: null,
|
||||
header_info_name_1: null,
|
||||
header_label_2: data.name,
|
||||
header_icon_name_2: null,
|
||||
header_icon_isCustom_2: false,
|
||||
header_info_category_2: null,
|
||||
header_info_name_2: null,
|
||||
|
||||
settingType: 'base',
|
||||
});
|
||||
|
||||
@ -86,7 +95,9 @@ function LeftMenu({ wait }) {
|
||||
|
||||
await wait();
|
||||
push({
|
||||
search: `modalType=${type}&actionType=create&settingType=base&forTarget=${type}`,
|
||||
search: `modalType=${type}&actionType=create&settingType=base&forTarget=${type}&headerId=${getTrad(
|
||||
`modalForm.${type}.header-create`
|
||||
)}&header_icon_name_1=${type}&header_icon_isCustom_1=false&header_label_1=null`,
|
||||
});
|
||||
} else {
|
||||
displayNotificationCTNotSaved();
|
||||
|
||||
@ -11,6 +11,7 @@ import {
|
||||
import { Header } from '@buffetjs/custom';
|
||||
import ListViewContext from '../../contexts/ListViewContext';
|
||||
import convertAttrObjToArray from '../../utils/convertAttrObjToArray';
|
||||
import getAttributeDisplayedType from '../../utils/getAttributeDisplayedType';
|
||||
import getTrad from '../../utils/getTrad';
|
||||
import makeSearch from '../../utils/makeSearch';
|
||||
import ListRow from '../../components/ListRow';
|
||||
@ -71,41 +72,49 @@ const ListView = () => {
|
||||
const hasModelBeenModified = !isEqual(modifiedData, initialData);
|
||||
const forTarget = isInContentTypeView ? 'contentType' : 'component';
|
||||
|
||||
const handleClickOpenModalAddField = async (
|
||||
const handleClickAddField = async (
|
||||
forTarget,
|
||||
targetUid,
|
||||
headerDisplayName,
|
||||
headerDisplayCategory = null,
|
||||
headerDisplaySubCategory = null,
|
||||
subTargetUid = null
|
||||
firstHeaderObj,
|
||||
secondHeaderObj,
|
||||
thirdHeaderObj,
|
||||
fourthHeaderObj
|
||||
) => {
|
||||
// disable the prompt
|
||||
await wait();
|
||||
|
||||
const searchObj = {
|
||||
modalType: 'chooseAttribute',
|
||||
forTarget,
|
||||
targetUid,
|
||||
headerDisplayName,
|
||||
headerDisplayCategory,
|
||||
headerDisplaySubCategory,
|
||||
subTargetUid,
|
||||
...firstHeaderObj,
|
||||
...secondHeaderObj,
|
||||
...thirdHeaderObj,
|
||||
...fourthHeaderObj,
|
||||
};
|
||||
|
||||
// Disable the prompt
|
||||
await wait();
|
||||
|
||||
push({ search: makeSearch(searchObj, true) });
|
||||
push({ search: makeSearch(searchObj) });
|
||||
};
|
||||
|
||||
const handleClickAddComponentToDZ = async dzName => {
|
||||
const firstHeaderObject = {
|
||||
header_label_1: currentDataName,
|
||||
header_icon_name_1: 'dynamiczone',
|
||||
header_icon_isCustom_1: false,
|
||||
};
|
||||
const secondHeaderObj = {
|
||||
header_label_2: dzName,
|
||||
};
|
||||
const search = {
|
||||
modalType: 'addComponentToDynamicZone',
|
||||
forTarget: 'contentType',
|
||||
targetUid,
|
||||
headerDisplayCategory: currentDataName,
|
||||
dynamicZoneTarget: dzName,
|
||||
settingType: 'base',
|
||||
step: '1',
|
||||
actionType: 'edit',
|
||||
headerDisplayName: dzName,
|
||||
...firstHeaderObject,
|
||||
...secondHeaderObj,
|
||||
};
|
||||
|
||||
await wait();
|
||||
@ -118,30 +127,13 @@ const ListView = () => {
|
||||
targetUid,
|
||||
attributeName,
|
||||
type,
|
||||
headerDisplayName,
|
||||
headerDisplayCategory = null,
|
||||
headerDisplaySubCategory = null,
|
||||
subTargetUid = null
|
||||
firstHeaderObj,
|
||||
secondHeaderObj,
|
||||
thirdHeaderObj,
|
||||
fourthHeaderObj,
|
||||
fifthHeaderObj
|
||||
) => {
|
||||
let attributeType;
|
||||
|
||||
switch (type) {
|
||||
case 'integer':
|
||||
case 'biginteger':
|
||||
case 'decimal':
|
||||
case 'float':
|
||||
attributeType = 'number';
|
||||
break;
|
||||
case 'string':
|
||||
case 'text':
|
||||
attributeType = 'text';
|
||||
break;
|
||||
case '':
|
||||
attributeType = 'relation';
|
||||
break;
|
||||
default:
|
||||
attributeType = type;
|
||||
}
|
||||
const attributeType = getAttributeDisplayedType(type);
|
||||
|
||||
await wait();
|
||||
|
||||
@ -153,11 +145,12 @@ const ListView = () => {
|
||||
targetUid,
|
||||
attributeName,
|
||||
attributeType,
|
||||
headerDisplayName,
|
||||
headerDisplayCategory,
|
||||
headerDisplaySubCategory,
|
||||
step: type === 'component' ? '2' : null,
|
||||
subTargetUid,
|
||||
...firstHeaderObj,
|
||||
...secondHeaderObj,
|
||||
...thirdHeaderObj,
|
||||
...fourthHeaderObj,
|
||||
...fifthHeaderObj,
|
||||
};
|
||||
|
||||
await wait();
|
||||
@ -181,6 +174,7 @@ const ListView = () => {
|
||||
|
||||
const wait = async () => {
|
||||
togglePrompt(false);
|
||||
|
||||
return new Promise(resolve => setTimeout(resolve, 100));
|
||||
};
|
||||
const label = get(modifiedData, [firstMainDataPath, 'schema', 'name'], '');
|
||||
@ -231,7 +225,10 @@ const ListView = () => {
|
||||
settingType: 'base',
|
||||
forTarget: firstMainDataPath,
|
||||
targetUid,
|
||||
headerDisplayName: label,
|
||||
header_label_1: label,
|
||||
header_icon_isCustom_1: false,
|
||||
header_icon_name_1: firstMainDataPath,
|
||||
headerId: getTrad('modalForm.header-edit'),
|
||||
}),
|
||||
});
|
||||
},
|
||||
@ -258,7 +255,12 @@ const ListView = () => {
|
||||
color: 'primary',
|
||||
label: formatMessage({ id: `${pluginId}.button.attributes.add.another` }),
|
||||
onClick: () => {
|
||||
handleClickOpenModalAddField(forTarget, targetUid, currentDataName);
|
||||
const headerDisplayObject = {
|
||||
header_label_1: currentDataName,
|
||||
header_icon_name_1: forTarget,
|
||||
header_icon_isCustom_1: false,
|
||||
};
|
||||
handleClickAddField(forTarget, targetUid, headerDisplayObject);
|
||||
},
|
||||
};
|
||||
const goToCMSettingsPage = () => {
|
||||
@ -281,8 +283,6 @@ const ListView = () => {
|
||||
? [{ ...configureButtonProps }, { ...addButtonProps }]
|
||||
: [configureButtonProps];
|
||||
|
||||
const handleClickOnTrashIcon = () => {};
|
||||
|
||||
const CustomRow = props => {
|
||||
const { name } = props;
|
||||
|
||||
@ -292,7 +292,6 @@ const ListView = () => {
|
||||
attributeName={name}
|
||||
name={name}
|
||||
onClick={handleClickEditField}
|
||||
onClickDelete={handleClickOnTrashIcon}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@ -307,7 +306,7 @@ const ListView = () => {
|
||||
|
||||
return (
|
||||
<ListViewContext.Provider
|
||||
value={{ openModalAddField: handleClickOpenModalAddField }}
|
||||
value={{ openModalAddField: handleClickAddField }}
|
||||
>
|
||||
<Wrapper>
|
||||
<BackHeader onClick={goBack} />
|
||||
|
||||
@ -0,0 +1,154 @@
|
||||
{
|
||||
"attribute.boolean": "Boolean",
|
||||
"attribute.boolean.description": "Yes/no, 1/0, true/false",
|
||||
"attribute.component": "Komponent",
|
||||
"attribute.component.description": "Skupina polí, které je možné opakovaně používat",
|
||||
"attribute.date": "Datum a čas",
|
||||
"attribute.date.description": "Dialog pro výběr datumu a času",
|
||||
"attribute.datetime": "Datum a čas",
|
||||
"attribute.dynamiczone": "Dynamická zóna",
|
||||
"attribute.dynamiczone.description": "Umožňuje dynamicky zvolit komponenty při úpravách obsahu",
|
||||
"attribute.email": "E-mailová adresa",
|
||||
"attribute.email.description": "Pole s automatickou validací formátu e-mailové adresy",
|
||||
"attribute.enumeration": "Výčet",
|
||||
"attribute.enumeration.description": "Seznam hodnot s výběrem jedné možnosti",
|
||||
"attribute.json": "JSON",
|
||||
"attribute.json.description": "Data vo formátu JSON",
|
||||
"attribute.media": "Soubory",
|
||||
"attribute.media.description": "Např. obrázky, videa, ...",
|
||||
"attribute.null": " ",
|
||||
"attribute.number": "Číslo",
|
||||
"attribute.number.description": "Čísla (celé, desetinné)",
|
||||
"attribute.password": "Heslo",
|
||||
"attribute.password.description": "Políčko pro zadání hesla",
|
||||
"attribute.relation": "Relace",
|
||||
"attribute.relation.description": "Určuje vztah k jinému Typu obsahu",
|
||||
"attribute.richtext": "Textový editor",
|
||||
"attribute.richtext.description": "Textové pole s možnostmi formátování",
|
||||
"attribute.text": "Text",
|
||||
"attribute.text.description": "Krátký nebo delší text",
|
||||
"attribute.time": "Čas",
|
||||
"attribute.uid": "Uuid",
|
||||
"attribute.uid.description": "Unikátní identifikátor",
|
||||
"button.attributes.add.another": "Přidat další pole",
|
||||
"button.component.add": "Přidat komponent",
|
||||
"button.component.create": "Vytvorit nový komponent",
|
||||
"button.model.create": "Vytvořit nový Typ obsahu",
|
||||
"components.componentSelect.no-component-available": "Už jste přidali všechny komponenty",
|
||||
"components.componentSelect.no-component-available.with-search": "Nenašel se žádný komponent splňující výraz",
|
||||
"components.componentSelect.value-component": "Označené komponenty: {number} (zadejte hledaný text)",
|
||||
"components.componentSelect.value-components": "Označené komponenty: {number}",
|
||||
"component.repeatable": "(opakující)",
|
||||
"configurations": "nastavení",
|
||||
"contentType.UID.description": "UID se používa pro vygenerovanie API URL adres a databázových tabulek",
|
||||
"contentType.collectionName.description": "Vhodné když se názvy Typu obsahu a tabulky liší",
|
||||
"contentType.collectionName.label": "Interní název",
|
||||
"contentType.displayName.label": "Název",
|
||||
"error.contentTypeName.reserved-name": "Tento název je vyhrazený a nemůže být použit",
|
||||
"error.validation.minSupMax": "Nemůže být nadřazený",
|
||||
"form.attribute.component.option.add": "Přidat komponent",
|
||||
"form.attribute.component.option.create": "Vytvořit nový komponent",
|
||||
"form.attribute.component.option.create.description": "Komponent je dostupný mezi všemi typy a komponenty.",
|
||||
"form.attribute.component.option.repeatable": "Znovu použitelný komponent",
|
||||
"form.attribute.component.option.repeatable.description": "Nejlepší pro několikanásobné instance (pole) hodnot, meta tagy, apod...",
|
||||
"form.attribute.component.option.reuse-existing": "Použít existující komponent",
|
||||
"form.attribute.component.option.reuse-existing.description": "Používejte už vytvořené komponenty pro uchování konzistentních dat mezi Typy obsahu.",
|
||||
"form.attribute.component.option.single": "Jednoduchý komponent",
|
||||
"form.attribute.component.option.single.description": "Vhodné pro seskupení políček, např. celá adresa",
|
||||
"form.attribute.item.customColumnName": "Vlastné názvy stĺpcov",
|
||||
"form.attribute.item.customColumnName.description": "Umožňuje přejmenovat databázový sloupec pro potřeby API",
|
||||
"form.attribute.item.date.type.date": "datum",
|
||||
"form.attribute.item.date.type.datetime": "datum a čas",
|
||||
"form.attribute.item.date.type.time": "čas",
|
||||
"form.attribute.item.defineRelation.fieldName": "Název pole",
|
||||
"form.attribute.item.enumeration.graphql": "Název pole pro GraphQL",
|
||||
"form.attribute.item.enumeration.graphql.description": "Umožňuje přepsat přednastavené názvy názvy pro GraphQL",
|
||||
"form.attribute.item.enumeration.placeholder": "Např.:\nráno\nden\nvečer",
|
||||
"form.attribute.item.enumeration.rules": "Hodnoty (jedna na řádek)",
|
||||
"form.attribute.item.maximum": "Maximální hodnota",
|
||||
"form.attribute.item.maximumLength": "Maximální délka",
|
||||
"form.attribute.item.minimum": "Minimální hodnota",
|
||||
"form.attribute.item.minimumLength": "Minimální délka",
|
||||
"form.attribute.item.number.type": "Číselný formát",
|
||||
"form.attribute.item.number.type.biginteger": "velké číslo (např.: 123456789)",
|
||||
"form.attribute.item.number.type.decimal": "desetinné číslo (např.: 2.22)",
|
||||
"form.attribute.item.number.type.float": "desetinné číslo (např.: 3.33333333)",
|
||||
"form.attribute.item.number.type.integer": "celé číslo (např.: 10)",
|
||||
"form.attribute.item.requiredField": "Povinné pole",
|
||||
"form.attribute.item.requiredField.description": "Nedovolí vytvořit záznam když toto pole zůstane prázdne",
|
||||
"form.attribute.item.settings.name": "Nastavení",
|
||||
"form.attribute.item.privateField": "Skryté pole",
|
||||
"form.attribute.item.privateField.description": "Toto pole se nebude zobrazovat v API",
|
||||
"form.attribute.item.uniqueField": "Unikátní pole",
|
||||
"form.attribute.item.uniqueField.description": "Nedovolí vytvořit záznam když už existuje jiný záznam se stejnou hodnotou",
|
||||
"form.attribute.media.option.multiple": "Více souborů",
|
||||
"form.attribute.media.option.multiple.description": "Vhodné pro galerii, seznam souborů na stáhnutí",
|
||||
"form.attribute.media.option.single": "Jeden soubor",
|
||||
"form.attribute.media.option.single.description": "Vhodné pro profilovou fotku nebo hlavní obrázek",
|
||||
"form.attribute.settings.default": "Předvolená hodnota",
|
||||
"form.attribute.text.option.long-text": "Dlouhý text",
|
||||
"form.attribute.text.option.long-text.description": "Vhodné pro delší popisy. Přesné vyhledávání je vypnuté.",
|
||||
"form.attribute.text.option.short-text": "Krátky text",
|
||||
"form.attribute.text.option.short-text.description": "Vhodné pro nadpisy, názvy, URL adresy. Přesné vyhledávání je zapnuté.",
|
||||
"form.button.add-components-to-dynamiczone": "Přidat komponenty do zóny",
|
||||
"form.button.add-field": "Přidat další pole",
|
||||
"form.button.add-first-field-to-created-component": "Přidat první pole do komponentu",
|
||||
"form.button.add.field.to.component": "Přidat další pole do komponentu",
|
||||
"form.button.add.field.to.contentType": "Přidat další pole do Typu obsahu",
|
||||
"form.button.cancel": "Zrušit",
|
||||
"form.button.configure-component": "Nastavit komponent",
|
||||
"form.button.configure-view": "Upravit vzhled",
|
||||
"form.button.continue": "Pokračovat",
|
||||
"form.button.delete": "Odstránit",
|
||||
"form.button.finish": "Dokončit",
|
||||
"form.button.save": "Uložit",
|
||||
"form.button.select-component": "Vybrat komponent",
|
||||
"from": "od",
|
||||
|
||||
"injected-components.content-manager.edit-settings-view.link.content-types": "Upravit Typ obsahu",
|
||||
"injected-components.content-manager.edit-settings-view.link.components": "Upravit komponent",
|
||||
"menu.section.components.name.plural": "Komponenty",
|
||||
"menu.section.components.name.singular": "Komponent",
|
||||
"menu.section.models.name.plural": "Typy obsahu",
|
||||
"menu.section.models.name.singular": "Typ obsahu",
|
||||
"modalForm.attribute.form.base.name": "Jméno",
|
||||
"modalForm.attribute.form.base.name.description": "Mezery v názvu pole nejsou povoleny",
|
||||
"modalForm.attribute.text.type-selection": "Typ",
|
||||
"modalForm.attributes.select-component": "Vyberte komponent",
|
||||
"modalForm.attributes.select-components": "Vyberte komponenty",
|
||||
"modalForm.component.header-create": "Vytvorte komponent",
|
||||
"modalForm.components.create-component.category.label": "Vyberte kategorii nebo zadejte název pro vytvoření nové",
|
||||
"modalForm.components.icon.label": "Ikona",
|
||||
"modalForm.contentType.header-create": "Vytvořit Typ obsahu",
|
||||
"modalForm.editCategory.base.name.description": "Mezery v názvu kategorie nejsou povoleny",
|
||||
"modalForm.header-edit": "Upravit {name}",
|
||||
"modalForm.header.categories": "Kategorie",
|
||||
"modalForm.sub-header.addComponentToDynamicZone": "Přidat nový komponent do dynamické zóny",
|
||||
"modalForm.sub-header.attribute.create": "Přidat nové pole {type}",
|
||||
"modalForm.sub-header.attribute.create.step": "Přidat nový komponent ({step}/2)",
|
||||
"modalForm.sub-header.attribute.edit": "Upravit {name}",
|
||||
"modalForm.sub-header.chooseAttribute.component": "Vyberte typ pole pro komponent",
|
||||
"modalForm.sub-header.chooseAttribute.contentType": "Vyberte typ pole pro Typ obsahu",
|
||||
"modelPage.attribute.relationWith": "Propojení s",
|
||||
"modelPage.contentHeader.emptyDescription.description": "žádný popis",
|
||||
"notification.info.creating.notSaved": "Uložte změny před vytvořením nového Typu obsahu nebo komponentu",
|
||||
"plugin.description.long": "Navrhněte strukturu webu jednoduše. Vytvořte nová pole a propojení během pár sekund. Soubory se automaticky vytvoří a upraví v rámci projektu.",
|
||||
"plugin.description.short": "Navrhněte strukturu webu jednoduše.",
|
||||
"popUpForm.navContainer.advanced": "Pokročilá nastavení",
|
||||
"popUpForm.navContainer.base": "Základní nastavení",
|
||||
"popUpWarning.bodyMessage.cancel-modifications": "Jste si jisti, že chcete zrušit úpravy?",
|
||||
"popUpWarning.bodyMessage.cancel-modifications.with-components": "Jste si jisti, že chcete zrušit úpravy? Některé komponenty byly vytvořeny nebo upraveny...",
|
||||
"popUpWarning.bodyMessage.category.delete": "Jste si jisti, že chcete odstranit tuto kategorii? Všechny komponentu budou rovněž odstraněny.",
|
||||
"popUpWarning.bodyMessage.component.delete": "Jste si jisti, že chcete odstranit tento komponent?",
|
||||
"popUpWarning.bodyMessage.contentType.delete": "Jste si jisti, že chcete odstranit tento Typ obsahu?",
|
||||
"prompt.unsaved": "Jste si jisti, že chcete odejít? Všechny úpravy budou ztraceny.",
|
||||
"relation.attributeName.placeholder": "Např: autor, kategorie, tag",
|
||||
"relation.manyToMany": "má víc a patří všem",
|
||||
"relation.manyToOne": "má víc",
|
||||
"relation.manyWay": "má víc",
|
||||
"relation.oneToMany": "patří více",
|
||||
"relation.oneToOne": "má jeden a patří jednomu",
|
||||
"relation.oneWay": "má jeden",
|
||||
"table.attributes.title.plural": "Pole: {number}",
|
||||
"table.attributes.title.singular": "Pole: {number}"
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
import ar from './ar.json';
|
||||
import cs from './cs.json';
|
||||
import de from './de.json';
|
||||
import en from './en.json';
|
||||
import es from './es.json';
|
||||
@ -18,6 +19,7 @@ import sk from './sk.json';
|
||||
|
||||
const trads = {
|
||||
ar,
|
||||
cs,
|
||||
de,
|
||||
en,
|
||||
es,
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
const getAttributeDisplayedType = type => {
|
||||
let displayedType;
|
||||
|
||||
switch (type) {
|
||||
case 'date':
|
||||
case 'datetime':
|
||||
case 'time':
|
||||
displayedType = 'date';
|
||||
break;
|
||||
case 'integer':
|
||||
case 'biginteger':
|
||||
case 'decimal':
|
||||
case 'float':
|
||||
displayedType = 'number';
|
||||
break;
|
||||
case 'string':
|
||||
case 'text':
|
||||
displayedType = 'text';
|
||||
break;
|
||||
case '':
|
||||
displayedType = 'relation';
|
||||
break;
|
||||
default:
|
||||
displayedType = type;
|
||||
}
|
||||
|
||||
return displayedType;
|
||||
};
|
||||
|
||||
export default getAttributeDisplayedType;
|
||||
@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const validateComponentCategory = require('./validation/component-category');
|
||||
const componentCategoryService = require('../services/ComponentCategories');
|
||||
|
||||
module.exports = {
|
||||
async editCategory(ctx) {
|
||||
@ -17,17 +16,24 @@ module.exports = {
|
||||
|
||||
strapi.reload.isWatching = false;
|
||||
|
||||
const componentCategoryService =
|
||||
strapi.plugins['content-type-builder'].services.componentcategories;
|
||||
|
||||
const newName = await componentCategoryService.editCategory(name, body);
|
||||
|
||||
setImmediate(() => strapi.reload());
|
||||
|
||||
ctx.send({ name: newName });
|
||||
},
|
||||
|
||||
async deleteCategory(ctx) {
|
||||
const { name } = ctx.params;
|
||||
|
||||
strapi.reload.isWatching = false;
|
||||
|
||||
const componentCategoryService =
|
||||
strapi.plugins['content-type-builder'].services.componentcategories;
|
||||
|
||||
await componentCategoryService.deleteCategory(name);
|
||||
|
||||
setImmediate(() => strapi.reload());
|
||||
|
||||
@ -6,7 +6,6 @@ const {
|
||||
validateComponentInput,
|
||||
validateUpdateComponentInput,
|
||||
} = require('./validation/component');
|
||||
const componentService = require('../services/Components');
|
||||
|
||||
/**
|
||||
* Components controller
|
||||
@ -19,6 +18,9 @@ module.exports = {
|
||||
* @param {Object} ctx - koa context
|
||||
*/
|
||||
async getComponents(ctx) {
|
||||
const componentService =
|
||||
strapi.plugins['content-type-builder'].services.components;
|
||||
|
||||
const data = Object.keys(strapi.components).map(uid => {
|
||||
return componentService.formatComponent(strapi.components[uid]);
|
||||
});
|
||||
@ -40,6 +42,9 @@ module.exports = {
|
||||
return ctx.send({ error: 'component.notFound' }, 404);
|
||||
}
|
||||
|
||||
const componentService =
|
||||
strapi.plugins['content-type-builder'].services.components;
|
||||
|
||||
ctx.send({ data: componentService.formatComponent(component) });
|
||||
},
|
||||
|
||||
@ -60,6 +65,9 @@ module.exports = {
|
||||
try {
|
||||
strapi.reload.isWatching = false;
|
||||
|
||||
const componentService =
|
||||
strapi.plugins['content-type-builder'].services.components;
|
||||
|
||||
const component = await componentService.createComponent({
|
||||
component: body.component,
|
||||
components: body.components,
|
||||
@ -96,6 +104,9 @@ module.exports = {
|
||||
try {
|
||||
strapi.reload.isWatching = false;
|
||||
|
||||
const componentService =
|
||||
strapi.plugins['content-type-builder'].services.components;
|
||||
|
||||
const component = await componentService.editComponent(uid, {
|
||||
component: body.component,
|
||||
components: body.components,
|
||||
@ -125,6 +136,9 @@ module.exports = {
|
||||
try {
|
||||
strapi.reload.isWatching = false;
|
||||
|
||||
const componentService =
|
||||
strapi.plugins['content-type-builder'].services.components;
|
||||
|
||||
const component = await componentService.deleteComponent(uid);
|
||||
|
||||
setImmediate(() => strapi.reload());
|
||||
|
||||
@ -7,10 +7,11 @@ const {
|
||||
validateUpdateContentTypeInput,
|
||||
} = require('./validation/content-type');
|
||||
|
||||
const contentTypeService = require('../services/ContentTypes');
|
||||
|
||||
module.exports = {
|
||||
getContentTypes(ctx) {
|
||||
const contentTypeService =
|
||||
strapi.plugins['content-type-builder'].services.contenttypes;
|
||||
|
||||
const contentTypes = Object.keys(strapi.contentTypes)
|
||||
.filter(uid => {
|
||||
if (uid.startsWith('strapi::')) return false;
|
||||
@ -36,6 +37,9 @@ module.exports = {
|
||||
return ctx.send({ error: 'contentType.notFound' }, 404);
|
||||
}
|
||||
|
||||
const contentTypeService =
|
||||
strapi.plugins['content-type-builder'].services.contenttypes;
|
||||
|
||||
ctx.send({ data: contentTypeService.formatContentType(contentType) });
|
||||
},
|
||||
|
||||
@ -51,6 +55,9 @@ module.exports = {
|
||||
try {
|
||||
strapi.reload.isWatching = false;
|
||||
|
||||
const contentTypeService =
|
||||
strapi.plugins['content-type-builder'].services.contenttypes;
|
||||
|
||||
const component = await contentTypeService.createContentType({
|
||||
contentType: body.contentType,
|
||||
components: body.components,
|
||||
@ -89,6 +96,9 @@ module.exports = {
|
||||
try {
|
||||
strapi.reload.isWatching = false;
|
||||
|
||||
const contentTypeService =
|
||||
strapi.plugins['content-type-builder'].services.contenttypes;
|
||||
|
||||
const component = await contentTypeService.editContentType(uid, {
|
||||
contentType: body.contentType,
|
||||
components: body.components,
|
||||
@ -113,6 +123,9 @@ module.exports = {
|
||||
try {
|
||||
strapi.reload.isWatching = false;
|
||||
|
||||
const contentTypeService =
|
||||
strapi.plugins['content-type-builder'].services.contenttypes;
|
||||
|
||||
const component = await contentTypeService.deleteContentType(uid);
|
||||
|
||||
setImmediate(() => strapi.reload());
|
||||
|
||||
@ -127,6 +127,8 @@ const getTypeShape = (attribute, { modelType } = {}) => {
|
||||
max: yup.number(),
|
||||
};
|
||||
}
|
||||
case 'time':
|
||||
case 'datetime':
|
||||
case 'date': {
|
||||
return {
|
||||
default: yup.string(),
|
||||
|
||||
@ -31,6 +31,8 @@ module.exports = function createComponentBuilder() {
|
||||
const targetCT = this.contentTypes.get(uid);
|
||||
const targetAttribute = targetCT.getAttribute(attribute.via);
|
||||
|
||||
if (!targetAttribute) return;
|
||||
|
||||
// do not delete polymorphic relations
|
||||
if (targetAttribute.collection === '*' || targetAttribute.model === '*') {
|
||||
return;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -19,13 +19,15 @@
|
||||
"ListHeader.type": "Typ",
|
||||
"ListHeader.updated": "Aktualizováno",
|
||||
"PluginInputFile.link": "prohlédnout",
|
||||
"PluginInputFile.loading": "Vaše soubory jsou právě nahrávány...",
|
||||
"PluginInputFile.text": "Přesuňte zde kurzorem vaše soubory do nebo {link} ze souboru k nahrání",
|
||||
"PluginInputFile.loading": "Soubory se nahrávají...",
|
||||
"PluginInputFile.text": "Přesuňte zde soubory kurzorem nebo {link} soubory v počítači",
|
||||
"Upload.status.empty": "Soubory jsou prázdné",
|
||||
"Upload.status.disabled": "Nahrávání souborů je zakázáno",
|
||||
"Upload.status.sizeLimit": "{file} soubor je větší než maximální povolená velikost!",
|
||||
"notification.config.success": "Nastavení bylo uloženo",
|
||||
"notification.delete.success": "Soubor byl odstraněn",
|
||||
"notification.dropFile.success": "Váš soubor byl nahrán",
|
||||
"notification.dropFiles.success": "{number} soubory byly nahrány"
|
||||
"notification.dropFiles.success": "soubory byly nahrány ({number})",
|
||||
"plugin.description.long": "Správce multimediálních souborů.",
|
||||
"plugin.description.short": "Správce multimediálních souborů."
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
"EditForm.inputSelect.label.role": "Výchozí role pro autentifikovaného uživatele",
|
||||
"EditForm.inputSelect.subscriptions.description": "Limitovat počet odběrů na IP adresu na hodinu.",
|
||||
"EditForm.inputSelect.subscriptions.label": "Spravovat kvóty na odběry",
|
||||
"EditForm.inputToggle.description.email": "Zabránit uživateli vytvářet různé účty se stejným meailem a jinými poskytovateli autentifikace.",
|
||||
"EditForm.inputToggle.description.email": "Zabránit uživateli vytvářet různé účty se stejným e-mailem a jinými poskytovateli autentifikace.",
|
||||
"EditForm.inputToggle.description.email-confirmation": "Pokud je tato funkce povolena (ON), nově registrovaní uživatelé dostanou potvrzující e-mail.",
|
||||
"EditForm.inputToggle.description.email-confirmation-redirection": "Po potvrzení e-mailu, zvolte kam budete přesměrováni.",
|
||||
"EditForm.inputToggle.description.email-reset-password": "Adresa stránky obnovení hesla vaší aplikace",
|
||||
@ -37,7 +37,7 @@
|
||||
"Email.template.reset_password": "Obnovit heslo",
|
||||
"Email.template.success_register": "Registrace proběhla úspěšně",
|
||||
"HeaderNav.link.advancedSettings": "Pokročilá nastavení",
|
||||
"HeaderNav.link.emailTemplates": "E-mail templates",
|
||||
"HeaderNav.link.emailTemplates": "E-mailové šablony",
|
||||
"HeaderNav.link.providers": "Poskytovatelé",
|
||||
"HeaderNav.link.roles": "Role & Práva",
|
||||
"HomePage.header.description": "Definujte role a práva vašim uživatelům.",
|
||||
@ -54,7 +54,7 @@
|
||||
"List.title.roles.plural": "{number} role jsou k dispozici",
|
||||
"List.title.roles.singular": "{number} role je k dispozici",
|
||||
"Plugin.permissions.application.description": "Definujte všechy povolené akce na vašem projektu.",
|
||||
"Plugin.permissions.plugins.description": "Definovat všechny akce pro zásuvný modul {name}.",
|
||||
"Plugin.permissions.plugins.description": "Nastavit všechny akce pro zásuvný modul {name}.",
|
||||
"Plugins.header.description": "Pouze akce spojené s adresou jsou vypsány níže.",
|
||||
"Plugins.header.title": "Povolení",
|
||||
"Policies.InputSelect.empty": "Žádné",
|
||||
@ -78,21 +78,22 @@
|
||||
"PopUpForm.Email.validation_email.options.message.placeholder": "<p>Prosím klikněte na tento odkaz pro ověření vašeho účtu</p>",
|
||||
"PopUpForm.Email.validation_email.options.object.placeholder": "Prosím potvrďte e-mailovou adresu pr %APP_NAME%",
|
||||
"PopUpForm.Providers.callback.placeholder": "TEXT",
|
||||
"PopUpForm.Providers.discord.providerConfig.redirectURL": "Adresa pro přesměrování k přidání do vaší Discord konfigurace",
|
||||
"PopUpForm.Providers.discord.providerConfig.redirectURL": "Adresa pro přesměrování, kterou přidejte do nastavení aplikace Discord",
|
||||
"PopUpForm.Providers.enabled.description": "If disabled, users won't be able to use this provider.",
|
||||
"PopUpForm.Providers.enabled.label": "Povolit",
|
||||
"PopUpForm.Providers.facebook.providerConfig.redirectURL": "Adresa pro přesměrování k přidání do vaší Facebook konfigurace",
|
||||
"PopUpForm.Providers.github.providerConfig.redirectURL": "Adresa pro přesměrování k přidání do vaší GitHub konfigurace",
|
||||
"PopUpForm.Providers.google.providerConfig.redirectURL": "Adresa pro přesměrování k přidání do vaší Google konfigurace",
|
||||
"PopUpForm.Providers.instagram.providerConfig.redirectURL": "Adresa pro přesměrování k přidání do vaší Instagram konfigurace",
|
||||
"PopUpForm.Providers.facebook.providerConfig.redirectURL": "Adresa pro přesměrování, kterou přidejte do nastavení aplikace Facebook",
|
||||
"PopUpForm.Providers.github.providerConfig.redirectURL": "Adresa pro přesměrování, kterou přidejte do nastavení aplikace GitHub",
|
||||
"PopUpForm.Providers.google.providerConfig.redirectURL": "Adresa pro přesměrování, kterou přidejte do nastavení aplikace Google",
|
||||
"PopUpForm.Providers.instagram.providerConfig.redirectURL": "Adresa pro přesměrování, kterou přidejte do nastavení aplikace Instagram",
|
||||
"PopUpForm.Providers.vk.providerConfig.redirectURL": "Adresa pro přesměrování, kterou přidejte do nastavení aplikace VK",
|
||||
"PopUpForm.Providers.key.label": "Client ID",
|
||||
"PopUpForm.Providers.key.placeholder": "TEXT",
|
||||
"PopUpForm.Providers.linkedin2.providerConfig.redirectURL": "Adresa pro přesměrování k přidání do vaší Linkedin konfigurace",
|
||||
"PopUpForm.Providers.microsoft.providerConfig.redirectURL": "Adresa pro přesměrování k přidání do vaší Microsoft konfigurace",
|
||||
"PopUpForm.Providers.linkedin2.providerConfig.redirectURL": "Adresa pro přesměrování, kterou přidejte do nastavení aplikace Linkedin",
|
||||
"PopUpForm.Providers.microsoft.providerConfig.redirectURL": "Adresa pro přesměrování, kterou přidejte do nastavení aplikace Microsoft",
|
||||
"PopUpForm.Providers.redirectURL.front-end.label": "Adresa pro přesměrování na vaši front-end aplikaci",
|
||||
"PopUpForm.Providers.secret.label": "Client Secret",
|
||||
"PopUpForm.Providers.secret.placeholder": "TEXT",
|
||||
"PopUpForm.Providers.twitter.providerConfig.redirectURL": "Adresa pro přesměrování k přidání do vaší Twitter konfigurace",
|
||||
"PopUpForm.Providers.twitter.providerConfig.redirectURL": "Adresa pro přesměrování, kterou přidejte do nastavení aplikace Twitter",
|
||||
"PopUpForm.button.cancel": "Zrušit",
|
||||
"PopUpForm.button.save": "Uložit",
|
||||
"PopUpForm.header.add.providers": "Přidat nového poskytovatele",
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
Copyright (c) 2017, Vandium Software Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015-2019 Strapi Solutions.
|
||||
Copyright (c) 2015-2020 Strapi Solutions.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user