From 6f8c98728b3a040a8bea5cc283a236824f16c3fd Mon Sep 17 00:00:00 2001 From: Martin Ficzel Date: Fri, 6 Jan 2023 17:36:22 +0100 Subject: [PATCH 1/5] Feature: Adjust rendering of backend module from fluid to fusion --- Classes/Controller/ModuleController.php | 87 +++++----- Configuration/Views.yaml | 6 + .../Backend/Fragments/LanguageSelector.fusion | 34 ++++ Resources/Private/Fusion/Backend/Root.fusion | 12 ++ .../Fusion/Backend/Views/Taxonomy.Edit.fusion | 46 ++++++ .../Fusion/Backend/Views/Taxonomy.List.fusion | 156 ++++++++++++++++++ .../Fusion/Backend/Views/Taxonomy.New.fusion | 37 +++++ .../Backend/Views/Vocabulary.Edit.fusion | 47 ++++++ .../Backend/Views/Vocabulary.List.fusion | 103 ++++++++++++ .../Backend/Views/Vocabulary.New.fusion | 36 ++++ .../Private/Layouts/BackendSubModule.html | 11 -- Resources/Private/Partials/FlashMessages.html | 10 -- .../Private/Partials/LanguageSelection.html | 17 -- .../Private/Partials/TaxonRecursive.html | 76 --------- .../Templates/Module/EditTaxonomy.html | 56 ------- .../Templates/Module/EditVocabulary.html | 55 ------ Resources/Private/Templates/Module/Index.html | 109 ------------ .../Private/Templates/Module/NewTaxonomy.html | 23 --- .../Templates/Module/NewVocabulary.html | 23 --- .../Private/Templates/Module/Vocabulary.html | 60 ------- composer.json | 5 +- 21 files changed, 526 insertions(+), 483 deletions(-) create mode 100644 Configuration/Views.yaml create mode 100644 Resources/Private/Fusion/Backend/Fragments/LanguageSelector.fusion create mode 100644 Resources/Private/Fusion/Backend/Root.fusion create mode 100644 Resources/Private/Fusion/Backend/Views/Taxonomy.Edit.fusion create mode 100644 Resources/Private/Fusion/Backend/Views/Taxonomy.List.fusion create mode 100644 Resources/Private/Fusion/Backend/Views/Taxonomy.New.fusion create mode 100644 Resources/Private/Fusion/Backend/Views/Vocabulary.Edit.fusion create mode 100644 Resources/Private/Fusion/Backend/Views/Vocabulary.List.fusion create mode 100644 Resources/Private/Fusion/Backend/Views/Vocabulary.New.fusion delete mode 100644 Resources/Private/Layouts/BackendSubModule.html delete mode 100644 Resources/Private/Partials/FlashMessages.html delete mode 100644 Resources/Private/Partials/LanguageSelection.html delete mode 100644 Resources/Private/Partials/TaxonRecursive.html delete mode 100644 Resources/Private/Templates/Module/EditTaxonomy.html delete mode 100644 Resources/Private/Templates/Module/EditVocabulary.html delete mode 100644 Resources/Private/Templates/Module/Index.html delete mode 100644 Resources/Private/Templates/Module/NewTaxonomy.html delete mode 100644 Resources/Private/Templates/Module/NewVocabulary.html delete mode 100644 Resources/Private/Templates/Module/Vocabulary.html diff --git a/Classes/Controller/ModuleController.php b/Classes/Controller/ModuleController.php index d7f87cf..45026dc 100644 --- a/Classes/Controller/ModuleController.php +++ b/Classes/Controller/ModuleController.php @@ -150,6 +150,7 @@ public function changeContextAction($targetAction, $targetProperty, NodeInterfac $newContextProperties['targetDimensions'][$dimensionName] = $presetName; } $modifiedContext = $this->contextFactory->create(array_merge($contextProperties, $newContextProperties)); + $nodeInModifiedContext = $modifiedContext->getNodeByIdentifier($contextNode->getIdentifier()); $this->redirect($targetAction, null, null, [$targetProperty => $nodeInModifiedContext]); @@ -277,24 +278,27 @@ public function newVocabularyAction(NodeInterface $taxonomyRoot) * Create a new vocabulary * * @param NodeInterface $taxonomyRoot - * @param string $title - * @param string $description + * @param array $properties * @return void */ - public function createVocabularyAction(NodeInterface $taxonomyRoot, $title, $description = '') + public function createVocabularyAction(NodeInterface $taxonomyRoot, array $properties) { $vocabularyNodeType = $this->nodeTypeManager->getNodeType($this->taxonomyService->getVocabularyNodeType()); + $vocabularyProperties = $vocabularyNodeType->getProperties(); $nodeTemplate = new NodeTemplate(); $nodeTemplate->setNodeType($vocabularyNodeType); - $nodeTemplate->setName(CrUtitlity::renderValidNodeName($title)); - $nodeTemplate->setProperty('title', $title); - $nodeTemplate->setProperty('description', $description); + $nodeTemplate->setName(CrUtitlity::renderValidNodeName($properties['title'])); + foreach($properties as $name => $value) { + if (array_key_exists($name, $vocabularyProperties)) { + $nodeTemplate->setProperty($name, $value); + } + } $vocabulary = $taxonomyRoot->createNodeFromTemplate($nodeTemplate); $this->addFlashMessage( - sprintf('Created vocabulary %s at path %s', $title, $vocabulary->getPath()) + sprintf('Created vocabulary %s at path %s', $properties['title'], $vocabulary->getLabel()) ); $this->redirect('index', null, null, ['root' => $taxonomyRoot]); } @@ -317,26 +321,24 @@ public function editVocabularyAction(NodeInterface $vocabulary) * Apply changes to the given vocabulary * * @param NodeInterface $vocabulary - * @param string $title - * @param string $description + * @param array $properties * @return void */ - public function updateVocabularyAction(NodeInterface $vocabulary, $title, $description = '') + public function updateVocabularyAction(NodeInterface $vocabulary, array $properties) { $taxonomyRoot = $this->taxonomyService->getRoot($vocabulary->getContext()); - $previousTitle = $vocabulary->getProperty('title'); - $previousDescription = $vocabulary->getProperty('description'); - - if ($previousTitle !== $title) { - $vocabulary->setProperty('title', $title); - } - - if ($previousDescription !== $description) { - $vocabulary->setProperty('description', $description); + $vocabularyProperties = $vocabulary->getNodeType()->getProperties(); + foreach($properties as $name => $value) { + if (array_key_exists($name, $vocabularyProperties)) { + $previous = $vocabulary->getProperty($name); + if ($previous !== $value) { + $vocabulary->setProperty($name, $value); + } + } } $this->addFlashMessage( - sprintf('Updated vocabulary %s', $title) + sprintf('Updated vocabulary %s', $vocabulary->getLabel()) ); $this->redirect('index', null, null, ['root' => $taxonomyRoot]); } @@ -381,22 +383,28 @@ public function newTaxonomyAction(NodeInterface $parent) * Create a new taxonomy * * @param NodeInterface $parent - * @param string $title - * @param string $description + * @param array $properties * @return void */ - public function createTaxonomyAction(NodeInterface $parent, $title, $description = '') + public function createTaxonomyAction(NodeInterface $parent, array $properties) { + $taxonomyNodeType = $this->nodeTypeManager->getNodeType($this->taxonomyService->getTaxonomyNodeType()); + $taxomonyProperties = $taxonomyNodeType->getProperties(); + $nodeTemplate = new NodeTemplate(); - $nodeTemplate->setNodeType($this->nodeTypeManager->getNodeType($this->taxonomyService->getTaxonomyNodeType())); - $nodeTemplate->setName(CrUtitlity::renderValidNodeName($title)); - $nodeTemplate->setProperty('title', $title); - $nodeTemplate->setProperty('description', $description); + $nodeTemplate->setNodeType($taxonomyNodeType); + $nodeTemplate->setName(CrUtitlity::renderValidNodeName($properties['title'])); + + foreach($properties as $name => $value) { + if (array_key_exists($name, $taxomonyProperties)) { + $nodeTemplate->setProperty($name, $value); + } + } $taxonomy = $parent->createNodeFromTemplate($nodeTemplate); $this->addFlashMessage( - sprintf('Created taxonomy %s at path %s', $title, $taxonomy->getPath()) + sprintf('Created taxonomy %s at path %s', $taxonomy->getLabel(), $taxonomy->getPath()) ); $flowQuery = new FlowQuery([$taxonomy]); @@ -430,28 +438,25 @@ public function editTaxonomyAction(NodeInterface $taxonomy) $this->view->assign('taxonomy', $taxonomy); $this->view->assign('defaultTaxonomy', $this->getNodeInDefaultDimensions($taxonomy)); - } /** * Apply changes to the given taxonomy * * @param NodeInterface $taxonomy - * @param string $title - * @param string $description + * @param array $properties * @return void */ - public function updateTaxonomyAction(NodeInterface $taxonomy, $title, $description = '') + public function updateTaxonomyAction(NodeInterface $taxonomy, array $properties) { - $previousTitle = $taxonomy->getProperty('title'); - $previousDescription = $taxonomy->getProperty('description'); - - if ($previousTitle !== $title) { - $taxonomy->setProperty('title', $title); - } - - if ($previousDescription !== $description) { - $taxonomy->setProperty('description', $description); + $taxonomyProperties = $taxonomy->getNodeType()->getProperties(); + foreach($properties as $name => $value) { + if (array_key_exists($name, $taxonomyProperties)) { + $previous = $taxonomy->getProperty($name); + if ($previous !== $value) { + $taxonomy->setProperty($name, $value); + } + } } $this->addFlashMessage( diff --git a/Configuration/Views.yaml b/Configuration/Views.yaml new file mode 100644 index 0000000..eada44b --- /dev/null +++ b/Configuration/Views.yaml @@ -0,0 +1,6 @@ +- + requestFilter: 'isPackage("Sitegeist.Taxonomy") && isController("Module")' + viewObjectName: 'Neos\Fusion\View\FusionView' + options: + fusionPathPatterns: + - 'resource://Sitegeist.Taxonomy/Private/Fusion/Backend' diff --git a/Resources/Private/Fusion/Backend/Fragments/LanguageSelector.fusion b/Resources/Private/Fusion/Backend/Fragments/LanguageSelector.fusion new file mode 100644 index 0000000..11016e2 --- /dev/null +++ b/Resources/Private/Fusion/Backend/Fragments/LanguageSelector.fusion @@ -0,0 +1,34 @@ +prototype(Sitegeist.Taxonomy:Views.Fragments.LanguageSelector) < prototype(Neos.Fusion:Component) { + + targetAction = null + targetProperty = null + contentDimensionOptions = null + contextNode = null + + renderer = afx` + + + + + + + {iterator.isFirst ? '' : ' '} + + + {presetName} + + + + + + + ` +} diff --git a/Resources/Private/Fusion/Backend/Root.fusion b/Resources/Private/Fusion/Backend/Root.fusion new file mode 100644 index 0000000..61c6471 --- /dev/null +++ b/Resources/Private/Fusion/Backend/Root.fusion @@ -0,0 +1,12 @@ +include: resource://Neos.Fusion/Private/Fusion/Root.fusion +include: resource://Neos.Fusion.Form/Private/Fusion/Root.fusion +include: **/*.fusion + + +Sitegeist.Taxonomy.ModuleController.index = Sitegeist.Taxonomy:Views.Module.Vocabulary.List +Sitegeist.Taxonomy.ModuleController.newVocabulary = Sitegeist.Taxonomy:Views.Module.Vocabulary.New +Sitegeist.Taxonomy.ModuleController.editVocabulary = Sitegeist.Taxonomy:Views.Module.Vocabulary.Edit + +Sitegeist.Taxonomy.ModuleController.vocabulary = Sitegeist.Taxonomy:Views.Module.Taxonomy.List +Sitegeist.Taxonomy.ModuleController.newTaxonomy = Sitegeist.Taxonomy:Views.Module.Taxonomy.New +Sitegeist.Taxonomy.ModuleController.editTaxonomy = Sitegeist.Taxonomy:Views.Module.Taxonomy.Edit diff --git a/Resources/Private/Fusion/Backend/Views/Taxonomy.Edit.fusion b/Resources/Private/Fusion/Backend/Views/Taxonomy.Edit.fusion new file mode 100644 index 0000000..8b7fb21 --- /dev/null +++ b/Resources/Private/Fusion/Backend/Views/Taxonomy.Edit.fusion @@ -0,0 +1,46 @@ +prototype(Sitegeist.Taxonomy:Views.Module.Taxonomy.Edit) < prototype(Neos.Fusion:Component) { + + i18nMain = ${Translation.value('').package("Sitegeist.Taxonomy").source('Main')} + i18nVocabulary = ${Translation.value('').package("Sitegeist.Taxonomy").source('NodeTypes/Vocabulary')} + i18nTaxonomy = ${Translation.value('').package("Sitegeist.Taxonomy").source('NodeTypes/Taxonomy')} + + renderer = afx` + {props.i18nMain.id('taxon')}: {taxonomy.properties.title} + {props.i18nMain.id('generic.default')}: {defaultTaxonomy.properties.title} + + + + +
+
+ + +
+ +
+ + +
+ +
+ + {props.i18nMain.id('generic.cancel')} + +   + {props.i18nMain.id('generic.save') + ''} +
+
+
+ ` + +} diff --git a/Resources/Private/Fusion/Backend/Views/Taxonomy.List.fusion b/Resources/Private/Fusion/Backend/Views/Taxonomy.List.fusion new file mode 100644 index 0000000..eab4c90 --- /dev/null +++ b/Resources/Private/Fusion/Backend/Views/Taxonomy.List.fusion @@ -0,0 +1,156 @@ +prototype(Sitegeist.Taxonomy:Views.Module.Taxonomy.List) < prototype(Neos.Fusion:Component) { + + i18n = ${Translation.value('').package("Sitegeist.Taxonomy").source('Main')} + i18nVocabulary = ${Translation.value('').package("Sitegeist.Taxonomy").source('NodeTypes/Vocabulary')} + i18nTaxonomy = ${Translation.value('').package("Sitegeist.Taxonomy").source('NodeTypes/Taxonomy')} + + renderer = afx` +
+ + {props.i18n.id('vocabulary')} {vocabulary.properties.title} + ({defaultVocabulary.properties.title}) +
+ +
+
+
+ +

+ {vocabulary.properties.description} +

+ +

+ {props.i18n.id('vocabulary.empty')} +

+ + + + + + + + + + + + + + +
+ {props.i18nTaxonomy.id('properties.title')} + + {defaultVocabulary ? 'Default' : ''} +
+ +
+ + {props.i18n.id('generic.back')} + +   + + {props.i18n.id('taxon.create')} + +
+ ` +} + + +prototype(Sitegeist.Taxonomy:Views.Module.Taxonomy.List.Item) < prototype(Neos.Fusion:Component) { + taxon = null + + renderer = afx` + + + +       + + +   + {props.taxon.node.properties.title} + + + {props.taxon.defaultNode ? props.taxon.defaultNode.properties.title : ''} + + + {props.taxon.node.properties.description} + + +
+ + + + + + +   + + + + + +   + +
+
+
+
+ +
Do you really want to delete the taxonomy "{taxon.node.properties.title}"? This action cannot be undone.
+
+ +
+
+
+
+ +
+ +
+ +
+ + + + + + + + ` +} diff --git a/Resources/Private/Fusion/Backend/Views/Taxonomy.New.fusion b/Resources/Private/Fusion/Backend/Views/Taxonomy.New.fusion new file mode 100644 index 0000000..cc95703 --- /dev/null +++ b/Resources/Private/Fusion/Backend/Views/Taxonomy.New.fusion @@ -0,0 +1,37 @@ +prototype(Sitegeist.Taxonomy:Views.Module.Taxonomy.New) < prototype(Neos.Fusion:Component) { + + i18nMain = ${Translation.value('').package("Sitegeist.Taxonomy").source('Main')} + i18nTaxonomy = ${Translation.value('').package("Sitegeist.Taxonomy").source('NodeTypes/Taxonomy')} + + renderer = afx` + {props.i18nMain.id('taxon.createBelow')} "{parent.properties.title}" + + + +
+ +
+ + +
+ +
+ + +
+ +
+ + {props.i18nMain.id('generic.cancel')} + +   + {props.i18nMain.id('taxon.create') + ''} +
+
+
+ ` +} diff --git a/Resources/Private/Fusion/Backend/Views/Vocabulary.Edit.fusion b/Resources/Private/Fusion/Backend/Views/Vocabulary.Edit.fusion new file mode 100644 index 0000000..3089e67 --- /dev/null +++ b/Resources/Private/Fusion/Backend/Views/Vocabulary.Edit.fusion @@ -0,0 +1,47 @@ +prototype(Sitegeist.Taxonomy:Views.Module.Vocabulary.Edit) < prototype(Neos.Fusion:Component) { + + i18nMain = ${Translation.value('').package("Sitegeist.Taxonomy").source('Main')} + i18nVocabulary = ${Translation.value('').package("Sitegeist.Taxonomy").source('NodeTypes/Vocabulary')} + + renderer = afx` +
+ {props.i18nMain.id('vocabulary')}: {vocabulary.properties.title} + {props.i18nMain.id('generic.default')}: {defaultVocabulary.properties.title} +
+ + + + +
+
+ + +
+ +
+ + +
+ +
+ + {props.i18nMain.id('generic.cancel')} + +   + {props.i18nMain.id('generic.save') + ''} +
+
+
+ ` + +} diff --git a/Resources/Private/Fusion/Backend/Views/Vocabulary.List.fusion b/Resources/Private/Fusion/Backend/Views/Vocabulary.List.fusion new file mode 100644 index 0000000..fcd97bc --- /dev/null +++ b/Resources/Private/Fusion/Backend/Views/Vocabulary.List.fusion @@ -0,0 +1,103 @@ +prototype(Sitegeist.Taxonomy:Views.Module.Vocabulary.List) < prototype(Neos.Fusion:Component) { + + i18n = ${Translation.value('').package("Sitegeist.Taxonomy").source('Main')} + + renderer = afx` + +
+ + {props.i18n.id('vocabularies')} +
+ +
+
+
+ +

+ +

+ {props.i18n.id('noVocabularies')} +

+ +
+
+ +
+
+
+ +

+ + {vocabulary.node.properties.title} ({vocabulary.defaultNode.properties.title}) + +

+
+ +
+

{vocabulary.node.properties.description}

+
+ + +
+
+ {((iterator.cycle % 4) && (!iterator.isLast)) ? '' : '
'} + +
+
+ +
+ + {props.i18n.id('vocabulary.create')} + +
+ ` +} diff --git a/Resources/Private/Fusion/Backend/Views/Vocabulary.New.fusion b/Resources/Private/Fusion/Backend/Views/Vocabulary.New.fusion new file mode 100644 index 0000000..a5811c4 --- /dev/null +++ b/Resources/Private/Fusion/Backend/Views/Vocabulary.New.fusion @@ -0,0 +1,36 @@ +prototype(Sitegeist.Taxonomy:Views.Module.Vocabulary.New) < prototype(Neos.Fusion:Component) { + + i18nMain = ${Translation.value('').package("Sitegeist.Taxonomy").source('Main')} + i18nVocabulary = ${Translation.value('').package("Sitegeist.Taxonomy").source('NodeTypes/Vocabulary')} + + renderer = afx` + {props.i18nMain.id('vocabulary.create')} + + + +
+
+ + +
+ +
+ + +
+ +
+ + {props.i18nMain.id('generic.cancel')} + +   + {props.i18nMain.id('vocabulary.create') + ''} +
+
+
+ ` +} diff --git a/Resources/Private/Layouts/BackendSubModule.html b/Resources/Private/Layouts/BackendSubModule.html deleted file mode 100644 index 26da6d1..0000000 --- a/Resources/Private/Layouts/BackendSubModule.html +++ /dev/null @@ -1,11 +0,0 @@ -
- - -
- -
- - - - -
diff --git a/Resources/Private/Partials/FlashMessages.html b/Resources/Private/Partials/FlashMessages.html deleted file mode 100644 index 535e571..0000000 --- a/Resources/Private/Partials/FlashMessages.html +++ /dev/null @@ -1,10 +0,0 @@ -{namespace neos=Neos\Neos\ViewHelpers} - - -
    - -
  • {neos:backend.translate(id: 'flashMessage.{flashMessage.code}', arguments: flashMessage.arguments, value: flashMessage)}
  • -
    -
-
-
\ No newline at end of file diff --git a/Resources/Private/Partials/LanguageSelection.html b/Resources/Private/Partials/LanguageSelection.html deleted file mode 100644 index 6f68381..0000000 --- a/Resources/Private/Partials/LanguageSelection.html +++ /dev/null @@ -1,17 +0,0 @@ -{namespace neos=Neos\Neos\ViewHelpers} -{namespace taxonomy=Sitegeist\Taxonomy\ViewHelpers} - - - - - - - - - - - - - - - diff --git a/Resources/Private/Partials/TaxonRecursive.html b/Resources/Private/Partials/TaxonRecursive.html deleted file mode 100644 index 29de0cf..0000000 --- a/Resources/Private/Partials/TaxonRecursive.html +++ /dev/null @@ -1,76 +0,0 @@ -{namespace neos=Neos\Neos\ViewHelpers} - - - - -       - - - - - - - - - - -   - {taxon.node.properties.title} - - - {taxon.defaultNode.properties.title} - - - {taxon.node.properties.description} - - -
- - - - - - - - - - - - - - - - - -
-
-
-
- -
Do you really want to delete the taxonomy "{taxon.node.properties.title}"? This action cannot be undone.
-
- -
-
-
-
- -
- -
- -
- - - - - - - diff --git a/Resources/Private/Templates/Module/EditTaxonomy.html b/Resources/Private/Templates/Module/EditTaxonomy.html deleted file mode 100644 index 7f94a64..0000000 --- a/Resources/Private/Templates/Module/EditTaxonomy.html +++ /dev/null @@ -1,56 +0,0 @@ -{namespace neos=Neos\Neos\ViewHelpers} - - - - -
-
- {f:translate(id: 'taxon')}: {taxonomy.properties.title} -
- -
- {f:translate(id: 'generic.default')}: {defaultTaxonomy.properties.title} -
-
-
- - -
- - - - -
-
-
- -
-
- -
- -
-
-
- - - -
-
-
- -
-
- -
- -
-
-
- - {f:translate(id: 'generic.cancel')} - - -
-
-
diff --git a/Resources/Private/Templates/Module/EditVocabulary.html b/Resources/Private/Templates/Module/EditVocabulary.html deleted file mode 100644 index 8d1c1a3..0000000 --- a/Resources/Private/Templates/Module/EditVocabulary.html +++ /dev/null @@ -1,55 +0,0 @@ -{namespace neos=Neos\Neos\ViewHelpers} - - - -
-
- {f:translate(id: 'vocabulary')}: {vocabulary.properties.title} -
- -
- {f:translate(id: 'generic.default')}: {defaultVocabulary.properties.title} -
-
-
- - -
- - - - -
-
-
- -
-
- -
- -
-
-
- - - -
-
-
- -
-
- -
- -
-
-
- - {f:translate(id: 'generic.cancel')} - - -
-
-
diff --git a/Resources/Private/Templates/Module/Index.html b/Resources/Private/Templates/Module/Index.html deleted file mode 100644 index cd99d81..0000000 --- a/Resources/Private/Templates/Module/Index.html +++ /dev/null @@ -1,109 +0,0 @@ -{namespace neos=Neos\Neos\ViewHelpers} - - - - - -
- - {f:translate(id: 'vocabularies')} -
- -
-
-
- -

- - - -
-
- -
-
-
- -

- - {vocabulary.node.properties.title} ({vocabulary.defaultNode.properties.title}) - -

-
- -
-

{vocabulary.node.properties.description}

-
- - -
-
- - - - -
- - - - - -
-
-
- -

- {f:translate(id: 'noVocabularies')} -

-
-
- - - -
- - - {f:translate(id: 'vocabulary.create')} - - -
- -
- -
diff --git a/Resources/Private/Templates/Module/NewTaxonomy.html b/Resources/Private/Templates/Module/NewTaxonomy.html deleted file mode 100644 index 52e2e35..0000000 --- a/Resources/Private/Templates/Module/NewTaxonomy.html +++ /dev/null @@ -1,23 +0,0 @@ -{namespace neos=Neos\Neos\ViewHelpers} - - - - -
- {f:translate(id: 'taxon.createBelow')} "{parent.properties.title}" - - -
- - -
-
- - -
- - {f:translate(id: 'generic.cancel')} - -
-
-
diff --git a/Resources/Private/Templates/Module/NewVocabulary.html b/Resources/Private/Templates/Module/NewVocabulary.html deleted file mode 100644 index b5f2583..0000000 --- a/Resources/Private/Templates/Module/NewVocabulary.html +++ /dev/null @@ -1,23 +0,0 @@ -{namespace neos=Neos\Neos\ViewHelpers} - - - - -
- {f:translate(id: 'vocabulary.create')} - - -
- - -
-
- - -
- - {f:translate(id: 'generic.cancel')} - -
-
-
diff --git a/Resources/Private/Templates/Module/Vocabulary.html b/Resources/Private/Templates/Module/Vocabulary.html deleted file mode 100644 index 5660b30..0000000 --- a/Resources/Private/Templates/Module/Vocabulary.html +++ /dev/null @@ -1,60 +0,0 @@ -{namespace neos=Neos\Neos\ViewHelpers} - - - -
- - {f:translate(id: 'vocabulary')} {vocabulary.properties.title} - ({defaultVocabulary.properties.title}) -
- -
-
-
- -

- {vocabulary.properties.description} -

- - - - - - - - - - - - - - - - -
- {f:translate(id: 'properties.title', source:'NodeTypes/Taxonomy')} - - Default -
-
- -

- {f:translate(id: 'vocabulary.empty')} -

-
-
- - - -
- - {f:translate(id: 'generic.back')} - - - {f:translate(id: 'taxon.create')} - -
- -
- -
diff --git a/composer.json b/composer.json index c945bdc..ae68451 100644 --- a/composer.json +++ b/composer.json @@ -4,8 +4,9 @@ "name": "sitegeist/taxonomy", "license": "GPL-3.0+", "require": { - "neos/neos": "^4.3 || ^5.0 || ^7.0 || ^8.0 || dev-master", - "neos/neos-ui": "^4.0 || ^5.0 || ^7.0 || ^8.0 || dev-master", + "neos/neos": "^7.1 || ^8.0 || dev-master", + "neos/neos-ui": "^7.1 || ^8.0 || dev-master", + "neos/fusion-form": ">2.1", "neos/content-repository": "*" }, "autoload": { From 9f6118491a08e0e6dc328d583fc0f906163b5cbf Mon Sep 17 00:00:00 2001 From: Martin Ficzel Date: Fri, 13 Jan 2023 15:40:57 +0100 Subject: [PATCH 2/5] Apply suggestions from code review Co-authored-by: Jon Uhlmann --- Resources/Private/Fusion/Backend/Views/Taxonomy.List.fusion | 2 +- Resources/Private/Fusion/Backend/Views/Vocabulary.List.fusion | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Resources/Private/Fusion/Backend/Views/Taxonomy.List.fusion b/Resources/Private/Fusion/Backend/Views/Taxonomy.List.fusion index eab4c90..30de808 100644 --- a/Resources/Private/Fusion/Backend/Views/Taxonomy.List.fusion +++ b/Resources/Private/Fusion/Backend/Views/Taxonomy.List.fusion @@ -131,7 +131,7 @@ prototype(Sitegeist.Taxonomy:Views.Module.Taxonomy.List.Item) < prototype(Neos.F diff --git a/Resources/Private/Fusion/Backend/Views/Vocabulary.List.fusion b/Resources/Private/Fusion/Backend/Views/Vocabulary.List.fusion index fcd97bc..67db5e1 100644 --- a/Resources/Private/Fusion/Backend/Views/Vocabulary.List.fusion +++ b/Resources/Private/Fusion/Backend/Views/Vocabulary.List.fusion @@ -69,7 +69,7 @@ prototype(Sitegeist.Taxonomy:Views.Module.Vocabulary.List) < prototype(Neos.Fusi + + +
+
+
+
+ +
Do you really want to delete the vocabulary "{vocabulary.node.properties.title}"? This action cannot be undone.
+
+ +
+
+
+
+
{((iterator.cycle % 4) && (!iterator.isLast)) ? '' : '
'} diff --git a/composer.json b/composer.json index ae68451..02f58a3 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "require": { "neos/neos": "^7.1 || ^8.0 || dev-master", "neos/neos-ui": "^7.1 || ^8.0 || dev-master", - "neos/fusion-form": ">2.1", + "neos/fusion-form": ">=2.1.0", "neos/content-repository": "*" }, "autoload": { From b7f65971e305811c924fd1d8582075893e1ce3c2 Mon Sep 17 00:00:00 2001 From: Martin Ficzel Date: Fri, 13 Jan 2023 16:48:38 +0100 Subject: [PATCH 4/5] TASK: Extract forms and add basic extensibility Packages can add additional fields to the forms of taxonomies and vocabularies. To do this the following steps are required. 1. Extend the NodeTypes `Sitegeist.Taxonomy:Taxonomy` or `Sitegeist.Taxonomy:Vocabulary` in your package. 2. Add a Views.yaml to your package and configure additional Fusion pathes to be loaded. 3. In the fusion code define each field as prototype that accepts the props `taxon` & `defaultTaxon` resp. `vocabulary` & `defaultVocabulary`. 4. Register those prototypes by adding them to the property `additionalFieldPrototypeNames` of the prototype `Sitegeist.Taxonomy:Form.Taxonomy` or `Sitegeist.Taxonomy:Form.Vocabulary` --- Classes/Controller/ModuleController.php | 19 ++++++ Configuration/Settings.yaml | 4 ++ Configuration/Views.yaml | 6 -- README.md | 15 +++-- .../Fusion/Backend/Form/Taxonomy.fusion | 67 +++++++++++++++++++ .../Fusion/Backend/Form/Vocabulary.fusion | 64 ++++++++++++++++++ .../Fusion/Backend/Views/Taxonomy.Edit.fusion | 40 ++--------- .../Fusion/Backend/Views/Taxonomy.New.fusion | 33 ++------- .../Backend/Views/Vocabulary.Edit.fusion | 40 ++--------- .../Backend/Views/Vocabulary.New.fusion | 31 ++------- 10 files changed, 186 insertions(+), 133 deletions(-) delete mode 100644 Configuration/Views.yaml create mode 100644 Resources/Private/Fusion/Backend/Form/Taxonomy.fusion create mode 100644 Resources/Private/Fusion/Backend/Form/Vocabulary.fusion diff --git a/Classes/Controller/ModuleController.php b/Classes/Controller/ModuleController.php index 45026dc..1aedf10 100644 --- a/Classes/Controller/ModuleController.php +++ b/Classes/Controller/ModuleController.php @@ -17,6 +17,7 @@ use Neos\Flow\Annotations as Flow; use Neos\Flow\Mvc\View\ViewInterface; use Neos\Flow\Mvc\Controller\ActionController; +use Neos\Fusion\View\FusionView; use Sitegeist\Taxonomy\Service\DimensionService; use Sitegeist\Taxonomy\Service\TaxonomyService; use Neos\ContentRepository\Domain\Service\ContextFactoryInterface; @@ -35,6 +36,15 @@ */ class ModuleController extends ActionController { + /** + * @var string + */ + protected $defaultViewObjectName = FusionView::class; + + /** + * @var FusionView + */ + protected $view; /** * @Flow\Inject @@ -60,6 +70,12 @@ class ModuleController extends ActionController */ protected $persistenceManager; + /** + * @var array + * @Flow\InjectConfiguration(path="backendModule.fusionPathPatterns") + */ + protected $fusionPathPatterns; + /** * @var string * @Flow\InjectConfiguration(package="Neos.ContentRepository", path="contentDimensions") @@ -91,6 +107,7 @@ class ModuleController extends ActionController */ public function initializeView(ViewInterface $view) { + $this->view->setFusionPathPatterns($this->fusionPathPatterns); $this->view->assign('contentDimensionOptions', $this->getContentDimensionOptions()); } @@ -496,4 +513,6 @@ public function deleteTaxonomyAction(NodeInterface $taxonomy) $this->redirect('vocabulary', null, null, ['vocabulary' => $vocabulary]); } + + } diff --git a/Configuration/Settings.yaml b/Configuration/Settings.yaml index b9c2215..77499b9 100644 --- a/Configuration/Settings.yaml +++ b/Configuration/Settings.yaml @@ -1,5 +1,9 @@ Sitegeist: Taxonomy: + backendModule: + fusionPathPatterns: + Sitegeist.Taxonomy: 'resource://Sitegeist.Taxonomy/Private/Fusion/Backend' + contentRepository: rootNodeName: 'taxonomies' rootNodeType: 'Sitegeist.Taxonomy:Root' diff --git a/Configuration/Views.yaml b/Configuration/Views.yaml deleted file mode 100644 index eada44b..0000000 --- a/Configuration/Views.yaml +++ /dev/null @@ -1,6 +0,0 @@ -- - requestFilter: 'isPackage("Sitegeist.Taxonomy") && isController("Module")' - viewObjectName: 'Neos\Fusion\View\FusionView' - options: - fusionPathPatterns: - - 'resource://Sitegeist.Taxonomy/Private/Fusion/Backend' diff --git a/README.md b/README.md index b958da0..6ea74bb 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,10 @@ multiple sites and the taxonomy documents can be defined without interfering wit It also provides a separate backend module for managing vocabularies and taxonomies. +## Installation + +Sitegeist.Taxonomy is available via packagist `composer require sitegeist/taxonomy`. +We use semantic-versioning, so every breaking change will increase the major version number. ## Storing vocabularies and taxonomies in the ContentRepository @@ -113,12 +117,15 @@ of taxonomies: Reading and referencing taxonomies from other nodes is currently not limited. -## Installation +## Extensibility -Sitegeist.Taxonomy is available via packagist. `"sitegeist/taxonomy" : "^1.0"` to the require section of the composer.json -or run `composer require sitegeist/taxonomy`. +Packages can add additional fields to the forms of taxonomies and vocabularies. To do this +the following steps are required. -We use semantic-versioning, so every breaking change will increase the major version number. +1. Extend the NodeTypes `Sitegeist.Taxonomy:Taxonomy` or `Sitegeist.Taxonomy:Vocabulary` in your package. +2. Add tha path to your additional `Root.fusion` to the Setting in path `Sitegeist.Taxonomy.backendModule.fusionPathPatterns`. +3. In the fusion code define each field as prototype that accepts the props `taxon` & `defaultTaxon` resp. `vocabulary` & `defaultVocabulary`. +4. Register those prototypesNames by adding them to the property `additionalFieldPrototypeNames` of the prototype `Sitegeist.Taxonomy:Form.Taxonomy` or `Sitegeist.Taxonomy:Form.Vocabulary` ## Contribution diff --git a/Resources/Private/Fusion/Backend/Form/Taxonomy.fusion b/Resources/Private/Fusion/Backend/Form/Taxonomy.fusion new file mode 100644 index 0000000..4664ec4 --- /dev/null +++ b/Resources/Private/Fusion/Backend/Form/Taxonomy.fusion @@ -0,0 +1,67 @@ +prototype(Sitegeist.Taxonomy:Form.Taxonomy) < prototype(Neos.Fusion:Component) { + + i18nMain = ${Translation.value('').package("Sitegeist.Taxonomy").source('Main')} + i18nVocabulary = ${Translation.value('').package("Sitegeist.Taxonomy").source('NodeTypes/Vocabulary')} + i18nTaxonomy = ${Translation.value('').package("Sitegeist.Taxonomy").source('NodeTypes/Taxonomy')} + + targetAction = null + taxonomy = null + defaultTaxonomy = null + parent = null + vocabulary = null + + additionalFieldPrototypeNames = Neos.Fusion:DataStructure + + renderer = afx` + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ +
+
+
+ +
+ + {props.i18nMain.id('generic.cancel')} + +   + {props.i18nMain.id('generic.save') + ''} +
+
+
+ ` + +} diff --git a/Resources/Private/Fusion/Backend/Form/Vocabulary.fusion b/Resources/Private/Fusion/Backend/Form/Vocabulary.fusion new file mode 100644 index 0000000..605fae8 --- /dev/null +++ b/Resources/Private/Fusion/Backend/Form/Vocabulary.fusion @@ -0,0 +1,64 @@ +prototype(Sitegeist.Taxonomy:Form.Vocabulary) < prototype(Neos.Fusion:Component) { + + i18nMain = ${Translation.value('').package("Sitegeist.Taxonomy").source('Main')} + i18nVocabulary = ${Translation.value('').package("Sitegeist.Taxonomy").source('NodeTypes/Vocabulary')} + + targetAction = null + vocabulary = null + defaultVocabulary = null + taxonomyRoot = null + + additionalFieldPrototypeNames = Neos.Fusion:DataStructure + + renderer = afx` + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ +
+
+
+ +
+ + {props.i18nMain.id('generic.cancel')} + +   + {props.i18nMain.id('generic.save') + ''} +
+
+
+ ` + +} diff --git a/Resources/Private/Fusion/Backend/Views/Taxonomy.Edit.fusion b/Resources/Private/Fusion/Backend/Views/Taxonomy.Edit.fusion index 8b7fb21..56f1ae3 100644 --- a/Resources/Private/Fusion/Backend/Views/Taxonomy.Edit.fusion +++ b/Resources/Private/Fusion/Backend/Views/Taxonomy.Edit.fusion @@ -7,40 +7,12 @@ prototype(Sitegeist.Taxonomy:Views.Module.Taxonomy.Edit) < prototype(Neos.Fusion renderer = afx` {props.i18nMain.id('taxon')}: {taxonomy.properties.title} {props.i18nMain.id('generic.default')}: {defaultTaxonomy.properties.title} - - - - -
-
- - -
- -
- - -
- -
- - {props.i18nMain.id('generic.cancel')} - -   - {props.i18nMain.id('generic.save') + ''} -
-
-
+ ` } diff --git a/Resources/Private/Fusion/Backend/Views/Taxonomy.New.fusion b/Resources/Private/Fusion/Backend/Views/Taxonomy.New.fusion index cc95703..6f6fea6 100644 --- a/Resources/Private/Fusion/Backend/Views/Taxonomy.New.fusion +++ b/Resources/Private/Fusion/Backend/Views/Taxonomy.New.fusion @@ -5,33 +5,10 @@ prototype(Sitegeist.Taxonomy:Views.Module.Taxonomy.New) < prototype(Neos.Fusion: renderer = afx` {props.i18nMain.id('taxon.createBelow')} "{parent.properties.title}" - - - -
- -
- - -
- -
- - -
- -
- - {props.i18nMain.id('generic.cancel')} - -   - {props.i18nMain.id('taxon.create') + ''} -
-
-
+ ` } diff --git a/Resources/Private/Fusion/Backend/Views/Vocabulary.Edit.fusion b/Resources/Private/Fusion/Backend/Views/Vocabulary.Edit.fusion index 3089e67..e31edec 100644 --- a/Resources/Private/Fusion/Backend/Views/Vocabulary.Edit.fusion +++ b/Resources/Private/Fusion/Backend/Views/Vocabulary.Edit.fusion @@ -8,40 +8,12 @@ prototype(Sitegeist.Taxonomy:Views.Module.Vocabulary.Edit) < prototype(Neos.Fusi {props.i18nMain.id('vocabulary')}: {vocabulary.properties.title} {props.i18nMain.id('generic.default')}: {defaultVocabulary.properties.title}
- - - - -
-
- - -
- -
- - -
- -
- - {props.i18nMain.id('generic.cancel')} - -   - {props.i18nMain.id('generic.save') + ''} -
-
-
+ ` } diff --git a/Resources/Private/Fusion/Backend/Views/Vocabulary.New.fusion b/Resources/Private/Fusion/Backend/Views/Vocabulary.New.fusion index a5811c4..d347ef6 100644 --- a/Resources/Private/Fusion/Backend/Views/Vocabulary.New.fusion +++ b/Resources/Private/Fusion/Backend/Views/Vocabulary.New.fusion @@ -5,32 +5,9 @@ prototype(Sitegeist.Taxonomy:Views.Module.Vocabulary.New) < prototype(Neos.Fusio renderer = afx` {props.i18nMain.id('vocabulary.create')} - - - -
-
- - -
- -
- - -
- -
- - {props.i18nMain.id('generic.cancel')} - -   - {props.i18nMain.id('vocabulary.create') + ''} -
-
-
+ ` } From 15725b73327ffeb4c2db3fa6969e02b5bc22a496 Mon Sep 17 00:00:00 2001 From: Martin Ficzel Date: Mon, 16 Jan 2023 09:42:19 +0100 Subject: [PATCH 5/5] TASK: Configure addtitional form prototypes via settings --- Classes/Controller/ModuleController.php | 10 +++++++--- Configuration/Settings.yaml | 8 ++++++-- README.md | 7 ++++--- Resources/Private/Fusion/Backend/Form/Taxonomy.fusion | 2 +- .../Private/Fusion/Backend/Form/Vocabulary.fusion | 2 +- 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/Classes/Controller/ModuleController.php b/Classes/Controller/ModuleController.php index 1aedf10..cbaa8bb 100644 --- a/Classes/Controller/ModuleController.php +++ b/Classes/Controller/ModuleController.php @@ -72,9 +72,9 @@ class ModuleController extends ActionController /** * @var array - * @Flow\InjectConfiguration(path="backendModule.fusionPathPatterns") + * @Flow\InjectConfiguration(path="backendModule.additionalFusionIncludePathes") */ - protected $fusionPathPatterns; + protected $additionalFusionIncludePathes; /** * @var string @@ -107,7 +107,11 @@ class ModuleController extends ActionController */ public function initializeView(ViewInterface $view) { - $this->view->setFusionPathPatterns($this->fusionPathPatterns); + $fusionPathes = ['resource://Sitegeist.Taxonomy/Private/Fusion/Backend']; + if ($this->additionalFusionIncludePathes && is_array($this->additionalFusionIncludePathes)) { + $fusionPathes = Arrays::arrayMergeRecursiveOverrule($fusionPathes, $this->additionalFusionIncludePathes); + } + $this->view->setFusionPathPatterns($fusionPathes); $this->view->assign('contentDimensionOptions', $this->getContentDimensionOptions()); } diff --git a/Configuration/Settings.yaml b/Configuration/Settings.yaml index 77499b9..f54f8ac 100644 --- a/Configuration/Settings.yaml +++ b/Configuration/Settings.yaml @@ -1,8 +1,12 @@ Sitegeist: Taxonomy: backendModule: - fusionPathPatterns: - Sitegeist.Taxonomy: 'resource://Sitegeist.Taxonomy/Private/Fusion/Backend' + # fusion files or folders that are to be included in the backend module + additionalFusionIncludePathes: [] + # names of additional prototypes to be rendered in vocabulary forms + additionalVocabularyFieldPrototypes: [] + # names of additional prototypes to be rendered in taxonomy forms + additionalTaxonomyFieldPrototypes: [] contentRepository: rootNodeName: 'taxonomies' diff --git a/README.md b/README.md index 6ea74bb..12c5ba4 100644 --- a/README.md +++ b/README.md @@ -123,9 +123,10 @@ Packages can add additional fields to the forms of taxonomies and vocabularies. the following steps are required. 1. Extend the NodeTypes `Sitegeist.Taxonomy:Taxonomy` or `Sitegeist.Taxonomy:Vocabulary` in your package. -2. Add tha path to your additional `Root.fusion` to the Setting in path `Sitegeist.Taxonomy.backendModule.fusionPathPatterns`. -3. In the fusion code define each field as prototype that accepts the props `taxon` & `defaultTaxon` resp. `vocabulary` & `defaultVocabulary`. -4. Register those prototypesNames by adding them to the property `additionalFieldPrototypeNames` of the prototype `Sitegeist.Taxonomy:Form.Taxonomy` or `Sitegeist.Taxonomy:Form.Vocabulary` +2. Add tha path to your additional `Root.fusion` to the Setting in path `Sitegeist.Taxonomy.backendModule.additionalFusionIncludePathes`. +3. In the fusion code define each field as prototype that accepts the props `name` plus `taxon` & `defaultTaxon` resp. `vocabulary` & `defaultVocabulary`. +4. Register addtional prototypesNames by adding them to the Settings `Sitegeist.Taxonomy.backendModule.additionalVocabularyFieldPrototypes` or + `Sitegeist.Taxonomy.backendModule.additionalTaxonomyFieldPrototypes` ## Contribution diff --git a/Resources/Private/Fusion/Backend/Form/Taxonomy.fusion b/Resources/Private/Fusion/Backend/Form/Taxonomy.fusion index 4664ec4..1e53440 100644 --- a/Resources/Private/Fusion/Backend/Form/Taxonomy.fusion +++ b/Resources/Private/Fusion/Backend/Form/Taxonomy.fusion @@ -10,7 +10,7 @@ prototype(Sitegeist.Taxonomy:Form.Taxonomy) < prototype(Neos.Fusion:Component) { parent = null vocabulary = null - additionalFieldPrototypeNames = Neos.Fusion:DataStructure + additionalFieldPrototypeNames = ${Configuration.setting('Sitegeist.Taxonomy.backendModule.additionalTaxonomyFieldPrototypes')} renderer = afx` diff --git a/Resources/Private/Fusion/Backend/Form/Vocabulary.fusion b/Resources/Private/Fusion/Backend/Form/Vocabulary.fusion index 605fae8..07b7b0a 100644 --- a/Resources/Private/Fusion/Backend/Form/Vocabulary.fusion +++ b/Resources/Private/Fusion/Backend/Form/Vocabulary.fusion @@ -8,7 +8,7 @@ prototype(Sitegeist.Taxonomy:Form.Vocabulary) < prototype(Neos.Fusion:Component) defaultVocabulary = null taxonomyRoot = null - additionalFieldPrototypeNames = Neos.Fusion:DataStructure + additionalFieldPrototypeNames = ${Configuration.setting('Sitegeist.Taxonomy.backendModule.additionalVocabularyFieldPrototypes')} renderer = afx`