From 38f48a62ea1d995e5885c0353ccab5fbebacfa42 Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Tue, 9 Jul 2024 13:09:30 -0400 Subject: [PATCH 01/47] Begin implementing resource stub --- application/config/module.config.php | 1 + .../src/Controller/Admin/ItemController.php | 2 + application/src/Form/ResourceStubForm.php | 87 +++++++++++++++++++ .../Service/Form/ResourceStubFormFactory.php | 17 ++++ .../omeka/admin/item/sidebar-select.phtml | 29 ++++++- 5 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 application/src/Form/ResourceStubForm.php create mode 100644 application/src/Service/Form/ResourceStubFormFactory.php diff --git a/application/config/module.config.php b/application/config/module.config.php index db1deac12..516f18e92 100644 --- a/application/config/module.config.php +++ b/application/config/module.config.php @@ -520,6 +520,7 @@ ], 'factories' => [ 'Omeka\Form\ResourceForm' => Service\Form\ResourceFormFactory::class, + 'Omeka\Form\ResourceStubForm' => Service\Form\ResourceStubFormFactory::class, 'Omeka\Form\VocabularyForm' => Service\Form\VocabularyFormFactory::class, 'Omeka\Form\ResourceBatchUpdateForm' => Service\Form\ResourceBatchUpdateFormFactory::class, 'Omeka\Form\UserForm' => Service\Form\UserFormFactory::class, diff --git a/application/src/Controller/Admin/ItemController.php b/application/src/Controller/Admin/ItemController.php index 440924fc2..8a3fc9757 100644 --- a/application/src/Controller/Admin/ItemController.php +++ b/application/src/Controller/Admin/ItemController.php @@ -3,6 +3,7 @@ use Omeka\Form\ConfirmForm; use Omeka\Form\ResourceForm; +use Omeka\Form\ResourceStubForm; use Omeka\Form\ResourceBatchUpdateForm; use Omeka\Media\Ingester\Manager; use Omeka\Stdlib\Message; @@ -103,6 +104,7 @@ public function sidebarSelectAction() $view->setVariable('itemSetId', $this->params()->fromQuery('item_set_id')); $view->setVariable('id', $this->params()->fromQuery('id')); $view->setVariable('showDetails', true); + $view->setVariable('resourceStubForm', $this->getForm(ResourceStubForm::class)); $view->setTerminal(true); return $view; } diff --git a/application/src/Form/ResourceStubForm.php b/application/src/Form/ResourceStubForm.php new file mode 100644 index 000000000..6c2f5321f --- /dev/null +++ b/application/src/Form/ResourceStubForm.php @@ -0,0 +1,87 @@ +getUrlHelper(); + + $this->add([ + 'type' => ResourceSelect::class, + 'name' => 'resource_template', + 'options' => [ + 'label' => 'Resource template', // @translate + 'empty_option' => '', + 'resource_value_options' => [ + 'resource' => 'resource_templates', + 'query' => [ + 'sort_by' => 'label', + ], + 'option_text_callback' => function ($resourceTemplate) { + return $resourceTemplate->label(); + }, + ], + ], + 'attributes' => [ + 'id' => 'resource-stub-resource-template-select', + 'class' => 'chosen-select', + 'data-placeholder' => 'Select a template', // @translate + 'data-api-base-url' => $urlHelper('api/default', ['resource' => 'resource_templates']), + ], + ]); + $this->add([ + 'type' => ResourceClassSelect::class, + 'name' => 'resource_class', + 'options' => [ + 'label' => 'Class', // @translate + 'empty_option' => '', + ], + 'attributes' => [ + 'id' => 'resource-stub-resource-class-select', + 'class' => 'chosen-select', + 'data-placeholder' => 'Select a class', // @translate + ], + ]); + $this->add([ + 'type' => 'textarea', + 'name' => 'title', + 'options' => [ + 'label' => 'Title', // @translate + ], + 'attributes' => [ + 'id' => 'resource-stub-title-textarea', + ], + ]); + $this->add([ + 'type' => 'textarea', + 'name' => 'description', + 'options' => [ + 'label' => 'Description', // @translate + ], + 'attributes' => [ + 'id' => 'resource-stub-description-textarea', + ], + ]); + } + + public function setUrlHelper(Url $urlHelper) + { + $this->urlHelper = $urlHelper; + } + + public function getUrlHelper() + { + return $this->urlHelper; + } +} diff --git a/application/src/Service/Form/ResourceStubFormFactory.php b/application/src/Service/Form/ResourceStubFormFactory.php new file mode 100644 index 000000000..4659e06a5 --- /dev/null +++ b/application/src/Service/Form/ResourceStubFormFactory.php @@ -0,0 +1,17 @@ +setUrlHelper($services->get('ViewHelperManager')->get('Url')); + $form->setEventManager($services->get('EventManager')); + return $form; + } +} diff --git a/application/view/omeka/admin/item/sidebar-select.phtml b/application/view/omeka/admin/item/sidebar-select.phtml index 2b2fe216b..fa8d4ea95 100644 --- a/application/view/omeka/admin/item/sidebar-select.phtml +++ b/application/view/omeka/admin/item/sidebar-select.phtml @@ -6,9 +6,15 @@ $itemsFound = count($items) > 0; $expanded = $resourceClassId || $itemSetId || $id; ?> +sectionNav([ + 'existing-resource-section' => $translate('Existing item'), + 'new-resource-section' => $translate('New item'), +]); ?> + +
+

-
+ +
+ +
+ formCollection($resourceStubForm, false); ?> + +
+ + From e9c5850b71ca774a8faa5899cfe77a4e9a90fdcf Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Tue, 9 Jul 2024 13:29:25 -0400 Subject: [PATCH 02/47] Continue dev --- .../omeka/admin/item/sidebar-select.phtml | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/application/view/omeka/admin/item/sidebar-select.phtml b/application/view/omeka/admin/item/sidebar-select.phtml index fa8d4ea95..869f8c19c 100644 --- a/application/view/omeka/admin/item/sidebar-select.phtml +++ b/application/view/omeka/admin/item/sidebar-select.phtml @@ -7,11 +7,11 @@ $expanded = $resourceClassId || $itemSetId || $id; ?> sectionNav([ - 'existing-resource-section' => $translate('Existing item'), - 'new-resource-section' => $translate('New item'), + 'resource-section' => $translate('Existing item'), + 'resource-stub-section' => $translate('New item'), ]); ?> -
+

@@ -113,21 +113,31 @@ $expanded = $resourceClassId || $itemSetId || $id;
-
+
formCollection($resourceStubForm, false); ?> - +
From e7db625bd3e9a4ead34f7c87e24859707910414d Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Wed, 10 Jul 2024 18:07:34 -0400 Subject: [PATCH 03/47] Continue dev --- application/config/module.config.php | 2 +- .../src/Controller/Admin/ItemController.php | 4 +- ...{ResourceStubForm.php => ItemStubForm.php} | 50 ++++++++----- ...ormFactory.php => ItemStubFormFactory.php} | 8 +-- .../omeka/admin/item/sidebar-select.phtml | 71 ++++++++++++++----- 5 files changed, 92 insertions(+), 43 deletions(-) rename application/src/Form/{ResourceStubForm.php => ItemStubForm.php} (53%) rename application/src/Service/Form/{ResourceStubFormFactory.php => ItemStubFormFactory.php} (61%) diff --git a/application/config/module.config.php b/application/config/module.config.php index 516f18e92..88c5ee6f9 100644 --- a/application/config/module.config.php +++ b/application/config/module.config.php @@ -520,7 +520,7 @@ ], 'factories' => [ 'Omeka\Form\ResourceForm' => Service\Form\ResourceFormFactory::class, - 'Omeka\Form\ResourceStubForm' => Service\Form\ResourceStubFormFactory::class, + 'Omeka\Form\ItemStubForm' => Service\Form\ItemStubFormFactory::class, 'Omeka\Form\VocabularyForm' => Service\Form\VocabularyFormFactory::class, 'Omeka\Form\ResourceBatchUpdateForm' => Service\Form\ResourceBatchUpdateFormFactory::class, 'Omeka\Form\UserForm' => Service\Form\UserFormFactory::class, diff --git a/application/src/Controller/Admin/ItemController.php b/application/src/Controller/Admin/ItemController.php index 8a3fc9757..6b041f017 100644 --- a/application/src/Controller/Admin/ItemController.php +++ b/application/src/Controller/Admin/ItemController.php @@ -2,8 +2,8 @@ namespace Omeka\Controller\Admin; use Omeka\Form\ConfirmForm; +use Omeka\Form\ItemStubForm; use Omeka\Form\ResourceForm; -use Omeka\Form\ResourceStubForm; use Omeka\Form\ResourceBatchUpdateForm; use Omeka\Media\Ingester\Manager; use Omeka\Stdlib\Message; @@ -104,7 +104,7 @@ public function sidebarSelectAction() $view->setVariable('itemSetId', $this->params()->fromQuery('item_set_id')); $view->setVariable('id', $this->params()->fromQuery('id')); $view->setVariable('showDetails', true); - $view->setVariable('resourceStubForm', $this->getForm(ResourceStubForm::class)); + $view->setVariable('itemStubForm', $this->getForm(ItemStubForm::class)); $view->setTerminal(true); return $view; } diff --git a/application/src/Form/ResourceStubForm.php b/application/src/Form/ItemStubForm.php similarity index 53% rename from application/src/Form/ResourceStubForm.php rename to application/src/Form/ItemStubForm.php index 6c2f5321f..d1ea04d63 100644 --- a/application/src/Form/ResourceStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -1,24 +1,32 @@ getUrlHelper(); + $urlHelper = $this->viewHelperManager->get('url'); + $apiHelper = $this->viewHelperManager->get('api'); + + $titleProperty = $apiHelper->searchOne('properties', ['term' => 'dcterms:title'])->getContent(); + $descriptionProperty = $apiHelper->searchOne('properties', ['term' => 'dcterms:description'])->getContent(); + + $this->setAttribute('id', 'item-stub-form'); + $this->setAttribute('data-url', $urlHelper('admin/default', ['controller' => 'item', 'action' => 'add-resource-stub'])); $this->add([ - 'type' => ResourceSelect::class, + 'type' => OmekaElement\ResourceSelect::class, 'name' => 'resource_template', 'options' => [ 'label' => 'Resource template', // @translate @@ -34,21 +42,20 @@ public function init() ], ], 'attributes' => [ - 'id' => 'resource-stub-resource-template-select', + 'id' => 'item-stub-resource-template', 'class' => 'chosen-select', 'data-placeholder' => 'Select a template', // @translate - 'data-api-base-url' => $urlHelper('api/default', ['resource' => 'resource_templates']), ], ]); $this->add([ - 'type' => ResourceClassSelect::class, + 'type' => OmekaElement\ResourceClassSelect::class, 'name' => 'resource_class', 'options' => [ 'label' => 'Class', // @translate 'empty_option' => '', ], 'attributes' => [ - 'id' => 'resource-stub-resource-class-select', + 'id' => 'item-stub-resource-class', 'class' => 'chosen-select', 'data-placeholder' => 'Select a class', // @translate ], @@ -60,7 +67,7 @@ public function init() 'label' => 'Title', // @translate ], 'attributes' => [ - 'id' => 'resource-stub-title-textarea', + 'data-property-term' => $titleProperty->term(), ], ]); $this->add([ @@ -70,18 +77,25 @@ public function init() 'label' => 'Description', // @translate ], 'attributes' => [ - 'id' => 'resource-stub-description-textarea', + 'data-property-term' => $descriptionProperty->term(), + ], + ]); + $this->add([ + 'type' => 'submit', + 'name' => 'submit', + 'attributes' => [ + 'id' => 'item-stub-submit', + 'value' => 'Add and select item', // @translate ], ]); - } - public function setUrlHelper(Url $urlHelper) - { - $this->urlHelper = $urlHelper; + // Allow modules to add elements to the item stub form. + $addEvent = new Event('form.add_elements', $this); + $this->getEventManager()->triggerEvent($addEvent); } - public function getUrlHelper() + public function setViewHelperManager($viewHelperManager) { - return $this->urlHelper; + $this->viewHelperManager = $viewHelperManager; } } diff --git a/application/src/Service/Form/ResourceStubFormFactory.php b/application/src/Service/Form/ItemStubFormFactory.php similarity index 61% rename from application/src/Service/Form/ResourceStubFormFactory.php rename to application/src/Service/Form/ItemStubFormFactory.php index 4659e06a5..5dd18b1e8 100644 --- a/application/src/Service/Form/ResourceStubFormFactory.php +++ b/application/src/Service/Form/ItemStubFormFactory.php @@ -1,16 +1,16 @@ setUrlHelper($services->get('ViewHelperManager')->get('Url')); + $form = new ItemStubForm; + $form->setViewHelperManager($services->get('ViewHelperManager')); $form->setEventManager($services->get('EventManager')); return $form; } diff --git a/application/view/omeka/admin/item/sidebar-select.phtml b/application/view/omeka/admin/item/sidebar-select.phtml index 869f8c19c..587886ca5 100644 --- a/application/view/omeka/admin/item/sidebar-select.phtml +++ b/application/view/omeka/admin/item/sidebar-select.phtml @@ -7,11 +7,11 @@ $expanded = $resourceClassId || $itemSetId || $id; ?> sectionNav([ - 'resource-section' => $translate('Existing item'), - 'resource-stub-section' => $translate('New item'), + 'item-section' => $translate('Existing item'), + 'item-stub-section' => $translate('New item'), ]); ?> -
+

@@ -113,30 +113,65 @@ $expanded = $resourceClassId || $itemSetId || $id;
-
- formCollection($resourceStubForm, false); ?> - +
+ form($itemStubForm, false); ?>
From 6950b81aeb196c0de4a57d11fc8302d837af8c2d Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Thu, 11 Jul 2024 14:57:12 -0400 Subject: [PATCH 05/47] Continue dev --- application/asset/js/resource-form.js | 5 ++--- application/src/Controller/Admin/ItemController.php | 3 ++- application/src/Form/ItemStubForm.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index e55b10047..25afe8a66 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -436,9 +436,8 @@ }); $.post(itemStubForm.data('url'), itemData, function(data) { const selectedResource = $('.selecting-resource').find('.selected-resource'); - const img = $('', {src: data['thumbnail_display_urls']['square']}); - const a = $('', {href: data['admin_url']}).text(data['o:title']); - selectedResource.find('.o-title').addClass('items').empty().append(img, a); + const a = $('', {href: data['admin_url']}).text(data['display_title']); + selectedResource.find('.o-title').removeClass().addClass('o-title items').html(a); selectedResource.find('.value').val(data['o:id']); }); }); diff --git a/application/src/Controller/Admin/ItemController.php b/application/src/Controller/Admin/ItemController.php index 389e86e19..c02ccfbbc 100644 --- a/application/src/Controller/Admin/ItemController.php +++ b/application/src/Controller/Admin/ItemController.php @@ -238,7 +238,7 @@ public function addAction() return $view; } - public function addResourceStubAction() + public function addItemStubAction() { $request = $this->getRequest(); $response = $this->getResponse(); @@ -249,6 +249,7 @@ public function addResourceStubAction() $item = $this->api()->create('items', $itemData)->getContent(); $itemJson = json_decode(json_encode($item), true); $itemJson['admin_url'] = $this->url()->fromRoute('admin/id', ['action' => 'show', 'id' => $item->id()], true); + $itemJson['display_title'] = $item->displayTitle(); $response->getHeaders()->addHeaders(['Content-Type' => 'application/ld+json']); $response->setContent(json_encode($itemJson)); return $response; diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index d1ea04d63..d2c63c577 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -23,7 +23,7 @@ public function init() $descriptionProperty = $apiHelper->searchOne('properties', ['term' => 'dcterms:description'])->getContent(); $this->setAttribute('id', 'item-stub-form'); - $this->setAttribute('data-url', $urlHelper('admin/default', ['controller' => 'item', 'action' => 'add-resource-stub'])); + $this->setAttribute('data-url', $urlHelper('admin/default', ['controller' => 'item', 'action' => 'add-item-stub'])); $this->add([ 'type' => OmekaElement\ResourceSelect::class, From 0d8995e77223efe399599be4f8c9ea36198a392d Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Fri, 12 Jul 2024 16:57:34 -0400 Subject: [PATCH 06/47] Continue dev --- application/asset/js/resource-form.js | 10 ++++-- .../src/Controller/Admin/ItemController.php | 9 ++++- application/src/Form/ItemStubForm.php | 33 +++++++++++++++---- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index 25afe8a66..84a6d5cb8 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -417,6 +417,7 @@ const resourceTemplate = $('#item-stub-resource-template'); const resourceClass = $('#item-stub-resource-class'); const itemData = {}; + if (resourceTemplate.val()) { itemData['o:resource_template'] = {'o:id': resourceTemplate.val()}; } @@ -427,18 +428,23 @@ const propertyValue = $(this); if (propertyValue.val()) { const propertyTerm = propertyValue.data('propertyTerm'); - itemData[propertyTerm] = [{ + if (!itemData.hasOwnProperty(propertyTerm)) { + itemData[propertyTerm] = []; + } + itemData[propertyTerm].push({ 'type': 'literal', 'property_id': 'auto', '@value': propertyValue.val() - }]; + }); } }); + itemData['csrf'] = itemStubForm.find('input[name="csrf"]').val(); $.post(itemStubForm.data('url'), itemData, function(data) { const selectedResource = $('.selecting-resource').find('.selected-resource'); const a = $('', {href: data['admin_url']}).text(data['display_title']); selectedResource.find('.o-title').removeClass().addClass('o-title items').html(a); selectedResource.find('.value').val(data['o:id']); + Omeka.closeSidebar($('#select-resource')); }); }); $(document).on('change', '#item-stub-resource-template', function(e) { diff --git a/application/src/Controller/Admin/ItemController.php b/application/src/Controller/Admin/ItemController.php index c02ccfbbc..0c8f70354 100644 --- a/application/src/Controller/Admin/ItemController.php +++ b/application/src/Controller/Admin/ItemController.php @@ -243,9 +243,16 @@ public function addItemStubAction() $request = $this->getRequest(); $response = $this->getResponse(); if (!$request->isPost()) { - return $this->redirect()->toRoute(null, ['action' => 'browse'], true); + $response->setStatusCode(500); + return $response; } $itemData = $this->params()->fromPost(); + $form = $this->getForm(ItemStubForm::class); + $form->setData($itemData); + if (!$form->isValid()) { + $response->setStatusCode(500); + return $response; + } $item = $this->api()->create('items', $itemData)->getContent(); $itemJson = json_decode(json_encode($item), true); $itemJson['admin_url'] = $this->url()->fromRoute('admin/id', ['action' => 'show', 'id' => $item->id()], true); diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index d2c63c577..8239b5dc5 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -14,14 +14,13 @@ class ItemStubForm extends Form protected $viewHelperManager; + protected $valueIndex = []; + public function init() { $urlHelper = $this->viewHelperManager->get('url'); $apiHelper = $this->viewHelperManager->get('api'); - $titleProperty = $apiHelper->searchOne('properties', ['term' => 'dcterms:title'])->getContent(); - $descriptionProperty = $apiHelper->searchOne('properties', ['term' => 'dcterms:description'])->getContent(); - $this->setAttribute('id', 'item-stub-form'); $this->setAttribute('data-url', $urlHelper('admin/default', ['controller' => 'item', 'action' => 'add-item-stub'])); @@ -47,6 +46,7 @@ public function init() 'data-placeholder' => 'Select a template', // @translate ], ]); + $this->add([ 'type' => OmekaElement\ResourceClassSelect::class, 'name' => 'resource_class', @@ -60,6 +60,7 @@ public function init() 'data-placeholder' => 'Select a class', // @translate ], ]); + $this->add([ 'type' => 'textarea', 'name' => 'title', @@ -67,9 +68,11 @@ public function init() 'label' => 'Title', // @translate ], 'attributes' => [ - 'data-property-term' => $titleProperty->term(), + 'id' => 'item-stub-title', + 'data-property-term' => 'dcterms:title', ], ]); + $this->add([ 'type' => 'textarea', 'name' => 'description', @@ -77,9 +80,11 @@ public function init() 'label' => 'Description', // @translate ], 'attributes' => [ - 'data-property-term' => $descriptionProperty->term(), + 'id' => 'item-stub-description', + 'data-property-term' => 'dcterms:description', ], ]); + $this->add([ 'type' => 'submit', 'name' => 'submit', @@ -89,9 +94,25 @@ public function init() ], ]); - // Allow modules to add elements to the item stub form. + // Allow modules to modify this form. $addEvent = new Event('form.add_elements', $this); $this->getEventManager()->triggerEvent($addEvent); + + $inputFilter = $this->getInputFilter(); + $inputFilter->add([ + 'name' => 'resource_template', + 'required' => false, + 'allow_empty' => true, + ]); + $inputFilter->add([ + 'name' => 'resource_class', + 'required' => false, + 'allow_empty' => true, + ]); + + // Allow modules to modify this form's input filters. + $filterEvent = new Event('form.add_input_filters', $this, ['inputFilter' => $inputFilter]); + $this->getEventManager()->triggerEvent($filterEvent); } public function setViewHelperManager($viewHelperManager) From 057d34557357f00a7db19e534eb51c8a4e28f0f4 Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Fri, 12 Jul 2024 22:13:14 -0400 Subject: [PATCH 07/47] Continue dev --- application/asset/js/resource-form.js | 2 +- application/src/Form/ItemStubForm.php | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index 84a6d5cb8..7a28d3c2b 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -417,7 +417,6 @@ const resourceTemplate = $('#item-stub-resource-template'); const resourceClass = $('#item-stub-resource-class'); const itemData = {}; - if (resourceTemplate.val()) { itemData['o:resource_template'] = {'o:id': resourceTemplate.val()}; } @@ -441,6 +440,7 @@ itemData['csrf'] = itemStubForm.find('input[name="csrf"]').val(); $.post(itemStubForm.data('url'), itemData, function(data) { const selectedResource = $('.selecting-resource').find('.selected-resource'); + selectedResource.prev('span.default').hide(); const a = $('', {href: data['admin_url']}).text(data['display_title']); selectedResource.find('.o-title').removeClass().addClass('o-title items').html(a); selectedResource.find('.value').val(data['o:id']); diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index 8239b5dc5..1517a51a3 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -94,7 +94,9 @@ public function init() ], ]); - // Allow modules to modify this form. + // Allow modules to modify this form. Modules can add value elements by + // setting a "data-property-term" attribute with the property's term + // (e.g. dcterms:creator). $addEvent = new Event('form.add_elements', $this); $this->getEventManager()->triggerEvent($addEvent); From 99f0eda96728a7aa9fe41261040daf8cd73c189b Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Sun, 14 Jul 2024 21:01:59 -0400 Subject: [PATCH 08/47] Continue dev --- application/asset/js/resource-form.js | 40 +++++++++---- application/src/Form/ItemStubForm.php | 57 ++++++++++++++----- .../src/Service/Form/ItemStubFormFactory.php | 3 +- 3 files changed, 75 insertions(+), 25 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index 7a28d3c2b..53c1e092c 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -423,22 +423,23 @@ if (resourceClass.val()) { itemData['o:resource_class'] = {'o:id': resourceClass.val()}; } - itemStubForm.find('[data-property-term]').each(function() { + itemStubForm.find('[data-property-id]').each(function() { const propertyValue = $(this); if (propertyValue.val()) { - const propertyTerm = propertyValue.data('propertyTerm'); - if (!itemData.hasOwnProperty(propertyTerm)) { - itemData[propertyTerm] = []; + const propertyId = propertyValue.data('propertyId'); + const type = propertyValue.data('type'); + if (!itemData.hasOwnProperty(propertyId)) { + itemData[propertyId] = []; } - itemData[propertyTerm].push({ - 'type': 'literal', - 'property_id': 'auto', + itemData[propertyId].push({ + 'property_id': propertyId, + 'type': type, '@value': propertyValue.val() }); } }); itemData['csrf'] = itemStubForm.find('input[name="csrf"]').val(); - $.post(itemStubForm.data('url'), itemData, function(data) { + $.post(itemStubForm.data('submitUrl'), itemData, function(data) { const selectedResource = $('.selecting-resource').find('.selected-resource'); selectedResource.prev('span.default').hide(); const a = $('', {href: data['admin_url']}).text(data['display_title']); @@ -448,9 +449,26 @@ }); }); $(document).on('change', '#item-stub-resource-template', function(e) { - console.log('#item-stub-resource-template'); - // @todo: get resource template from the API (via data attribute) - // @todo: change resource class, title property, description property accordingly + const itemStubForm = $('#item-stub-form'); + const resourceTemplate = $('#item-stub-resource-template'); + const resourceClass = $('#item-stub-resource-class'); + const title = $('#item-stub-title'); + const description = $('#item-stub-description'); + const resourceTemplateUrl = itemStubForm.data('templateUrl') + '/' + resourceTemplate.val(); + $.get(resourceTemplateUrl, function(data) { + const templateResourceClass = data['o:resource_class']; + const templateTitleProperty = data['o:title_property']; + const templateDescriptionProperty = data['o:description_property']; + if (templateResourceClass) { + resourceClass.val(templateResourceClass['o:id']); + resourceClass.trigger('chosen:updated'); + } + if (templateTitleProperty) { + // @todo: get property data from API (for label in particular) + title.data('property-id', templateTitleProperty['o:id']); + // @todo: get and set alt label, if any + } + }); }); initPage(); diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index 1517a51a3..66c5d2089 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -12,17 +12,21 @@ class ItemStubForm extends Form { use EventManagerAwareTrait; - protected $viewHelperManager; + protected $apiManager; - protected $valueIndex = []; + protected $urlHelper; public function init() { - $urlHelper = $this->viewHelperManager->get('url'); - $apiHelper = $this->viewHelperManager->get('api'); - $this->setAttribute('id', 'item-stub-form'); - $this->setAttribute('data-url', $urlHelper('admin/default', ['controller' => 'item', 'action' => 'add-item-stub'])); + $this->setAttribute('data-submit-url', $this->getUrlHelper()( + 'admin/default', + ['controller' => 'item', 'action' => 'add-item-stub'] + )); + $this->setAttribute('data-template-url', $this->getUrlHelper()( + 'api/default', + ['resource' => 'resource_templates'] + )); $this->add([ 'type' => OmekaElement\ResourceSelect::class, @@ -61,6 +65,10 @@ public function init() ], ]); + $property = $this->getApiManager()->search( + 'properties', + ['term' => 'dcterms:title'] + )->getContent()[0]; $this->add([ 'type' => 'textarea', 'name' => 'title', @@ -69,10 +77,17 @@ public function init() ], 'attributes' => [ 'id' => 'item-stub-title', - 'data-property-term' => 'dcterms:title', + 'data-property-id' => $property->id(), + 'data-type' => 'literal', + 'data-property-id-original' => $property->id(), + 'data-property-label-original' => 'Title', // @translate ], ]); + $property = $this->getApiManager()->search( + 'properties', + ['term' => 'dcterms:description'] + )->getContent()[0]; $this->add([ 'type' => 'textarea', 'name' => 'description', @@ -81,7 +96,10 @@ public function init() ], 'attributes' => [ 'id' => 'item-stub-description', - 'data-property-term' => 'dcterms:description', + 'data-property-id' => $property->id(), + 'data-type' => 'literal', + 'data-property-id-original' => $property->id(), + 'data-property-label-original' => 'Description', // @translate ], ]); @@ -94,9 +112,7 @@ public function init() ], ]); - // Allow modules to modify this form. Modules can add value elements by - // setting a "data-property-term" attribute with the property's term - // (e.g. dcterms:creator). + // Allow modules to modify this form. $addEvent = new Event('form.add_elements', $this); $this->getEventManager()->triggerEvent($addEvent); @@ -117,8 +133,23 @@ public function init() $this->getEventManager()->triggerEvent($filterEvent); } - public function setViewHelperManager($viewHelperManager) + public function setApiManager(ApiManager $apiManager) + { + $this->apiManager = $apiManager; + } + + public function getApiManager() + { + return $this->apiManager; + } + + public function setUrlHelper(Url $urlHelper) + { + $this->urlHelper = $urlHelper; + } + + public function getUrlHelper() { - $this->viewHelperManager = $viewHelperManager; + return $this->urlHelper; } } diff --git a/application/src/Service/Form/ItemStubFormFactory.php b/application/src/Service/Form/ItemStubFormFactory.php index 5dd18b1e8..63825b657 100644 --- a/application/src/Service/Form/ItemStubFormFactory.php +++ b/application/src/Service/Form/ItemStubFormFactory.php @@ -10,7 +10,8 @@ class ItemStubFormFactory implements FactoryInterface public function __invoke(ContainerInterface $services, $requestedName, array $options = null) { $form = new ItemStubForm; - $form->setViewHelperManager($services->get('ViewHelperManager')); + $form->setApiManager($services->get('Omeka\ApiManager')); + $form->setUrlHelper($services->get('ViewHelperManager')->get('Url')); $form->setEventManager($services->get('EventManager')); return $form; } From 664ac712ae5969557c0a451d599db1d7e91219d2 Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Mon, 15 Jul 2024 13:23:51 -0400 Subject: [PATCH 09/47] Continue dev --- application/asset/js/resource-form.js | 51 ++++++++++++++++--- application/src/Form/ItemStubForm.php | 39 ++++++++------ .../src/Service/Form/ItemStubFormFactory.php | 2 +- 3 files changed, 67 insertions(+), 25 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index 53c1e092c..eb6774306 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -448,25 +448,60 @@ Omeka.closeSidebar($('#select-resource')); }); }); + // Item stub form: handle resource template change. $(document).on('change', '#item-stub-resource-template', function(e) { const itemStubForm = $('#item-stub-form'); const resourceTemplate = $('#item-stub-resource-template'); const resourceClass = $('#item-stub-resource-class'); const title = $('#item-stub-title'); const description = $('#item-stub-description'); - const resourceTemplateUrl = itemStubForm.data('templateUrl') + '/' + resourceTemplate.val(); - $.get(resourceTemplateUrl, function(data) { - const templateResourceClass = data['o:resource_class']; - const templateTitleProperty = data['o:title_property']; - const templateDescriptionProperty = data['o:description_property']; + const resourceTemplateUrl = itemStubForm.data('resourceTemplateUrl') + '/' + resourceTemplate.val(); + $.get(resourceTemplateUrl, function(resourceTemplateData) { + const templateResourceClass = resourceTemplateData['o:resource_class']; + const templateTitleProperty = resourceTemplateData['o:title_property']; + const templateDescriptionProperty = resourceTemplateData['o:description_property']; if (templateResourceClass) { + // Set the template-defined class. resourceClass.val(templateResourceClass['o:id']); resourceClass.trigger('chosen:updated'); } if (templateTitleProperty) { - // @todo: get property data from API (for label in particular) - title.data('property-id', templateTitleProperty['o:id']); - // @todo: get and set alt label, if any + // Set the title defined by the template (including alt label). + const propertyUrl = itemStubForm.data('propertyUrl') + '/' + templateTitleProperty['o:id']; + $.get(propertyUrl, function(propertyData) { + let propertyLabel = propertyData['o:label']; + $.each(resourceTemplateData['o:resource_template_property'], function(key, value) { + if (value['o:property']['o:id'] === templateTitleProperty['o:id']) { + if (value['o:alternate_label']) propertyLabel = value['o:alternate_label']; + return false; + } + }); + title.data('propertyId', templateTitleProperty['o:id']); + title.closest('.field').find('[for="item-stub-title"]').text(propertyLabel); + }); + } else { + // Set the default title. + title.data('propertyId', title.data('propertyIdDefault')); + title.closest('.field').find('[for="item-stub-title"]').text(title.data('propertyLabelDefault')); + } + if (templateDescriptionProperty) { + // Set the description defined by the template (including alt label). + const propertyUrl = itemStubForm.data('propertyUrl') + '/' + templateDescriptionProperty['o:id']; + $.get(propertyUrl, function(propertyData) { + let propertyLabel = propertyData['o:label']; + $.each(resourceTemplateData['o:resource_template_property'], function(key, value) { + if (value['o:property']['o:id'] === templateDescriptionProperty['o:id']) { + if (value['o:alternate_label']) propertyLabel = value['o:alternate_label']; + return false; + } + }); + description.data('propertyId', templateDescriptionProperty['o:id']); + description.closest('.field').find('[for="item-stub-description"]').text(propertyLabel); + }); + } else { + // Set the default description. + description.data('propertyId', description.data('propertyIdDefault')); + description.closest('.field').find('[for="item-stub-description"]').text(description.data('propertyLabelDefault')); } }); }); diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index 66c5d2089..6080d540e 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -4,7 +4,7 @@ use Laminas\EventManager\Event; use Laminas\EventManager\EventManagerAwareTrait; use Laminas\Form\Form; -use Laminas\View\Helper\Url; +use Laminas\View\HelperPluginManager; use Omeka\Api\Manager as ApiManager; use Omeka\Form\Element as OmekaElement; @@ -14,19 +14,26 @@ class ItemStubForm extends Form protected $apiManager; - protected $urlHelper; + protected $viewHelperManager; public function init() { + $urlHelper = $this->getViewHelperManager()->get('url'); + $apiHelper = $this->getViewHelperManager()->get('api'); + $this->setAttribute('id', 'item-stub-form'); - $this->setAttribute('data-submit-url', $this->getUrlHelper()( + $this->setAttribute('data-submit-url', $urlHelper( 'admin/default', ['controller' => 'item', 'action' => 'add-item-stub'] )); - $this->setAttribute('data-template-url', $this->getUrlHelper()( + $this->setAttribute('data-resource-template-url', $urlHelper( 'api/default', ['resource' => 'resource_templates'] )); + $this->setAttribute('data-property-url', $urlHelper( + 'api/default', + ['resource' => 'properties'] + )); $this->add([ 'type' => OmekaElement\ResourceSelect::class, @@ -65,10 +72,10 @@ public function init() ], ]); - $property = $this->getApiManager()->search( + $property = $apiHelper->searchOne( 'properties', ['term' => 'dcterms:title'] - )->getContent()[0]; + )->getContent(); $this->add([ 'type' => 'textarea', 'name' => 'title', @@ -79,15 +86,15 @@ public function init() 'id' => 'item-stub-title', 'data-property-id' => $property->id(), 'data-type' => 'literal', - 'data-property-id-original' => $property->id(), - 'data-property-label-original' => 'Title', // @translate + 'data-property-id-default' => $property->id(), + 'data-property-label-default' => 'Title', // @translate ], ]); - $property = $this->getApiManager()->search( + $property = $apiHelper->searchOne( 'properties', ['term' => 'dcterms:description'] - )->getContent()[0]; + )->getContent(); $this->add([ 'type' => 'textarea', 'name' => 'description', @@ -98,8 +105,8 @@ public function init() 'id' => 'item-stub-description', 'data-property-id' => $property->id(), 'data-type' => 'literal', - 'data-property-id-original' => $property->id(), - 'data-property-label-original' => 'Description', // @translate + 'data-property-id-default' => $property->id(), + 'data-property-label-default' => 'Description', // @translate ], ]); @@ -143,13 +150,13 @@ public function getApiManager() return $this->apiManager; } - public function setUrlHelper(Url $urlHelper) + public function setViewHelperManager(HelperPluginManager $viewHelperManager) { - $this->urlHelper = $urlHelper; + $this->viewHelperManager = $viewHelperManager; } - public function getUrlHelper() + public function getViewHelperManager() { - return $this->urlHelper; + return $this->viewHelperManager; } } diff --git a/application/src/Service/Form/ItemStubFormFactory.php b/application/src/Service/Form/ItemStubFormFactory.php index 63825b657..6b573c3f7 100644 --- a/application/src/Service/Form/ItemStubFormFactory.php +++ b/application/src/Service/Form/ItemStubFormFactory.php @@ -11,7 +11,7 @@ public function __invoke(ContainerInterface $services, $requestedName, array $op { $form = new ItemStubForm; $form->setApiManager($services->get('Omeka\ApiManager')); - $form->setUrlHelper($services->get('ViewHelperManager')->get('Url')); + $form->setViewHelperManager($services->get('ViewHelperManager')); $form->setEventManager($services->get('EventManager')); return $form; } From 0da03d1f1e9efeecbef6d8379d81f1720bd75e94 Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Tue, 16 Jul 2024 13:04:01 -0400 Subject: [PATCH 10/47] Continue dev --- application/asset/js/resource-form.js | 2 +- application/src/Form/ItemStubForm.php | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index eb6774306..a1270671a 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -402,7 +402,7 @@ $(this).closest('.section-nav').find('li').toggleClass('active'); $('#item-section').hide(); $('#item-stub-section').show(); - $('.chosen-select').chosen(); + $('.chosen-select').chosen({allow_single_deselect: true}); }); // Item stub form: handle "Existing item" nav click. $(document).on('click', '#item-section-label', function(e) { diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index 6080d540e..82c257519 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -18,19 +18,20 @@ class ItemStubForm extends Form public function init() { - $urlHelper = $this->getViewHelperManager()->get('url'); - $apiHelper = $this->getViewHelperManager()->get('api'); + $url = $this->getViewHelperManager()->get('url'); + $translate = $this->getViewHelperManager()->get('translate'); + $api = $this->getViewHelperManager()->get('api'); $this->setAttribute('id', 'item-stub-form'); - $this->setAttribute('data-submit-url', $urlHelper( + $this->setAttribute('data-submit-url', $url( 'admin/default', ['controller' => 'item', 'action' => 'add-item-stub'] )); - $this->setAttribute('data-resource-template-url', $urlHelper( + $this->setAttribute('data-resource-template-url', $url( 'api/default', ['resource' => 'resource_templates'] )); - $this->setAttribute('data-property-url', $urlHelper( + $this->setAttribute('data-property-url', $url( 'api/default', ['resource' => 'properties'] )); @@ -72,7 +73,7 @@ public function init() ], ]); - $property = $apiHelper->searchOne( + $property = $api->searchOne( 'properties', ['term' => 'dcterms:title'] )->getContent(); @@ -87,11 +88,11 @@ public function init() 'data-property-id' => $property->id(), 'data-type' => 'literal', 'data-property-id-default' => $property->id(), - 'data-property-label-default' => 'Title', // @translate + 'data-property-label-default' => $translate('Title'), ], ]); - $property = $apiHelper->searchOne( + $property = $api->searchOne( 'properties', ['term' => 'dcterms:description'] )->getContent(); @@ -106,7 +107,7 @@ public function init() 'data-property-id' => $property->id(), 'data-type' => 'literal', 'data-property-id-default' => $property->id(), - 'data-property-label-default' => 'Description', // @translate + 'data-property-label-default' => $translate('Description'), ], ]); From f4b4f28cc7f6e3cbece2f55e4d6b1e73f5b5fbfd Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Tue, 16 Jul 2024 13:44:01 -0400 Subject: [PATCH 11/47] Continue dev --- application/asset/js/resource-form.js | 2 +- application/src/Form/ItemStubForm.php | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index a1270671a..2d361c1e4 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -427,7 +427,7 @@ const propertyValue = $(this); if (propertyValue.val()) { const propertyId = propertyValue.data('propertyId'); - const type = propertyValue.data('type'); + const type = propertyValue.data('type') ?? 'literal'; if (!itemData.hasOwnProperty(propertyId)) { itemData[propertyId] = []; } diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index 82c257519..a285f62e4 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -86,7 +86,6 @@ public function init() 'attributes' => [ 'id' => 'item-stub-title', 'data-property-id' => $property->id(), - 'data-type' => 'literal', 'data-property-id-default' => $property->id(), 'data-property-label-default' => $translate('Title'), ], @@ -105,7 +104,6 @@ public function init() 'attributes' => [ 'id' => 'item-stub-description', 'data-property-id' => $property->id(), - 'data-type' => 'literal', 'data-property-id-default' => $property->id(), 'data-property-label-default' => $translate('Description'), ], @@ -120,7 +118,10 @@ public function init() ], ]); - // Allow modules to modify this form. + // Allow modules to modify this form. Modules may add value elements by + // adding a "data-property-id" attribute to the element, set to the + // property ID. They may also add a "data-type" attribute to the element + // to set a data type that is not "literal". $addEvent = new Event('form.add_elements', $this); $this->getEventManager()->triggerEvent($addEvent); From 3e73aad839653e314a5cc5a60a867a74aaf5c33d Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Thu, 18 Jul 2024 16:04:32 -0400 Subject: [PATCH 12/47] Begin converting to template-based item stub form --- application/asset/js/resource-form.js | 9 +++ .../src/Controller/Admin/ItemController.php | 22 +++++++ application/src/Form/ItemStubForm.php | 62 +++++-------------- .../item/get-item-stub-property-values.phtml | 5 ++ .../omeka/admin/item/sidebar-select.phtml | 2 +- 5 files changed, 53 insertions(+), 47 deletions(-) create mode 100644 application/view/omeka/admin/item/get-item-stub-property-values.phtml diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index 2d361c1e4..8b9c21a74 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -397,6 +397,15 @@ $('#values-json').val(JSON.stringify(collectValues())); }); + /** ITEM STUB */ + + $('#select-resource').on('o:sidebar-content-loaded', function(e) { + const itemStubForm = $('#item-stub-form'); + $.post(itemStubForm.data('getItemStubPropertyValuesUrl'), function(data) { + console.log(data); + }); + }); + // Item stub form: handle "New item" nav click. $(document).on('click', '#item-stub-section-label', function(e) { $(this).closest('.section-nav').find('li').toggleClass('active'); diff --git a/application/src/Controller/Admin/ItemController.php b/application/src/Controller/Admin/ItemController.php index 0c8f70354..05fabd90c 100644 --- a/application/src/Controller/Admin/ItemController.php +++ b/application/src/Controller/Admin/ItemController.php @@ -238,6 +238,28 @@ public function addAction() return $view; } + public function getItemStubPropertyValuesAction() + { + $request = $this->getRequest(); + $response = $this->getResponse(); + if (!$request->isPost()) { + $response->setStatusCode(500); + return $response; + } + $postData = $this->params()->fromPost(); + $resourceTemplateId = $postData['resource_template_id'] ?? 0; + try { + $resourceTemplate = $this->api()->read('resource_templates', $resourceTemplateId)->getContent(); + } catch (\Omeka\Api\Exception\NotFoundException $e) { + $resourceTemplate = null; + } + + $view = new ViewModel; + $view->setTerminal(true); + $view->setVariable('resourceTemplate', $resourceTemplate); + return $view; + } + public function addItemStubAction() { $request = $this->getRequest(); diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index a285f62e4..4f303bb6e 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -27,16 +27,20 @@ public function init() 'admin/default', ['controller' => 'item', 'action' => 'add-item-stub'] )); - $this->setAttribute('data-resource-template-url', $url( - 'api/default', - ['resource' => 'resource_templates'] - )); - $this->setAttribute('data-property-url', $url( - 'api/default', - ['resource' => 'properties'] + $this->setAttribute('data-get-item-stub-property-values-url', $url( + 'admin/default', + ['controller' => 'item', 'action' => 'get-item-stub-property-values'] )); $this->add([ + 'type' => 'fieldset', + 'name' => 'fieldset-main', + 'attributes' => [ + 'id' => 'item-stub-fieldset-main' + ], + ]); + $fieldsetMain = $this->get('fieldset-main'); + $fieldsetMain->add([ 'type' => OmekaElement\ResourceSelect::class, 'name' => 'resource_template', 'options' => [ @@ -58,8 +62,7 @@ public function init() 'data-placeholder' => 'Select a template', // @translate ], ]); - - $this->add([ + $fieldsetMain->add([ 'type' => OmekaElement\ResourceClassSelect::class, 'name' => 'resource_class', 'options' => [ @@ -72,43 +75,13 @@ public function init() 'data-placeholder' => 'Select a class', // @translate ], ]); - - $property = $api->searchOne( - 'properties', - ['term' => 'dcterms:title'] - )->getContent(); - $this->add([ - 'type' => 'textarea', - 'name' => 'title', - 'options' => [ - 'label' => 'Title', // @translate - ], - 'attributes' => [ - 'id' => 'item-stub-title', - 'data-property-id' => $property->id(), - 'data-property-id-default' => $property->id(), - 'data-property-label-default' => $translate('Title'), - ], - ]); - - $property = $api->searchOne( - 'properties', - ['term' => 'dcterms:description'] - )->getContent(); $this->add([ - 'type' => 'textarea', - 'name' => 'description', - 'options' => [ - 'label' => 'Description', // @translate - ], + 'type' => 'fieldset', + 'name' => 'fieldset-property-values', 'attributes' => [ - 'id' => 'item-stub-description', - 'data-property-id' => $property->id(), - 'data-property-id-default' => $property->id(), - 'data-property-label-default' => $translate('Description'), + 'id' => 'item-stub-property-values' ], ]); - $this->add([ 'type' => 'submit', 'name' => 'submit', @@ -118,10 +91,7 @@ public function init() ], ]); - // Allow modules to modify this form. Modules may add value elements by - // adding a "data-property-id" attribute to the element, set to the - // property ID. They may also add a "data-type" attribute to the element - // to set a data type that is not "literal". + // Allow modules to modify this form. $addEvent = new Event('form.add_elements', $this); $this->getEventManager()->triggerEvent($addEvent); diff --git a/application/view/omeka/admin/item/get-item-stub-property-values.phtml b/application/view/omeka/admin/item/get-item-stub-property-values.phtml new file mode 100644 index 000000000..05ea31742 --- /dev/null +++ b/application/view/omeka/admin/item/get-item-stub-property-values.phtml @@ -0,0 +1,5 @@ + + + + + diff --git a/application/view/omeka/admin/item/sidebar-select.phtml b/application/view/omeka/admin/item/sidebar-select.phtml index b9e21934f..d5c71bd65 100644 --- a/application/view/omeka/admin/item/sidebar-select.phtml +++ b/application/view/omeka/admin/item/sidebar-select.phtml @@ -114,5 +114,5 @@ $expanded = $resourceClassId || $itemSetId || $id;
- form($itemStubForm, false); ?> + form($itemStubForm); ?>
From 7aa38a852531c2ce7b86c5d32049a49fefc4170e Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Fri, 19 Jul 2024 18:54:06 -0400 Subject: [PATCH 13/47] Continue dev --- application/asset/js/resource-form.js | 82 ++++--------------- .../src/Controller/Admin/ItemController.php | 2 +- application/src/Form/ItemStubForm.php | 8 +- application/src/View/Helper/DataType.php | 44 ++++++++++ .../common/value-annotation-wrapper.phtml | 4 +- .../admin/item/get-item-stub-fieldset.phtml | 1 + .../item/get-item-stub-property-values.phtml | 5 -- 7 files changed, 69 insertions(+), 77 deletions(-) create mode 100644 application/view/omeka/admin/item/get-item-stub-fieldset.phtml delete mode 100644 application/view/omeka/admin/item/get-item-stub-property-values.phtml diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index 8b9c21a74..da26d0482 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -397,29 +397,28 @@ $('#values-json').val(JSON.stringify(collectValues())); }); - /** ITEM STUB */ + /** ITEM STUB FORM */ $('#select-resource').on('o:sidebar-content-loaded', function(e) { const itemStubForm = $('#item-stub-form'); - $.post(itemStubForm.data('getItemStubPropertyValuesUrl'), function(data) { - console.log(data); + $.post(itemStubForm.data('getItemStubFieldsetUrl'), function(data) { + $('#item-stub-property-values').html(data); }); }); - - // Item stub form: handle "New item" nav click. + // Handle "New item" nav click. $(document).on('click', '#item-stub-section-label', function(e) { $(this).closest('.section-nav').find('li').toggleClass('active'); $('#item-section').hide(); $('#item-stub-section').show(); $('.chosen-select').chosen({allow_single_deselect: true}); }); - // Item stub form: handle "Existing item" nav click. + // Handle "Existing item" nav click. $(document).on('click', '#item-section-label', function(e) { $(this).closest('.section-nav').find('li').toggleClass('active'); $('#item-section').show(); $('#item-stub-section').hide(); }); - // Item stub form: handle item stub form submission. + // Handle item stub form submission. $(document).on('click', '#item-stub-submit', function(e) { e.preventDefault(); const itemStubForm = $('#item-stub-form'); @@ -432,21 +431,7 @@ if (resourceClass.val()) { itemData['o:resource_class'] = {'o:id': resourceClass.val()}; } - itemStubForm.find('[data-property-id]').each(function() { - const propertyValue = $(this); - if (propertyValue.val()) { - const propertyId = propertyValue.data('propertyId'); - const type = propertyValue.data('type') ?? 'literal'; - if (!itemData.hasOwnProperty(propertyId)) { - itemData[propertyId] = []; - } - itemData[propertyId].push({ - 'property_id': propertyId, - 'type': type, - '@value': propertyValue.val() - }); - } - }); + // @todo: Build the item data object. itemData['csrf'] = itemStubForm.find('input[name="csrf"]').val(); $.post(itemStubForm.data('submitUrl'), itemData, function(data) { const selectedResource = $('.selecting-resource').find('.selected-resource'); @@ -457,64 +442,27 @@ Omeka.closeSidebar($('#select-resource')); }); }); - // Item stub form: handle resource template change. + // Handle resource template change. $(document).on('change', '#item-stub-resource-template', function(e) { const itemStubForm = $('#item-stub-form'); const resourceTemplate = $('#item-stub-resource-template'); const resourceClass = $('#item-stub-resource-class'); - const title = $('#item-stub-title'); - const description = $('#item-stub-description'); const resourceTemplateUrl = itemStubForm.data('resourceTemplateUrl') + '/' + resourceTemplate.val(); - $.get(resourceTemplateUrl, function(resourceTemplateData) { - const templateResourceClass = resourceTemplateData['o:resource_class']; - const templateTitleProperty = resourceTemplateData['o:title_property']; - const templateDescriptionProperty = resourceTemplateData['o:description_property']; + $.get(resourceTemplateUrl, function(data) { + const templateResourceClass = data['o:resource_class']; if (templateResourceClass) { // Set the template-defined class. resourceClass.val(templateResourceClass['o:id']); resourceClass.trigger('chosen:updated'); } - if (templateTitleProperty) { - // Set the title defined by the template (including alt label). - const propertyUrl = itemStubForm.data('propertyUrl') + '/' + templateTitleProperty['o:id']; - $.get(propertyUrl, function(propertyData) { - let propertyLabel = propertyData['o:label']; - $.each(resourceTemplateData['o:resource_template_property'], function(key, value) { - if (value['o:property']['o:id'] === templateTitleProperty['o:id']) { - if (value['o:alternate_label']) propertyLabel = value['o:alternate_label']; - return false; - } - }); - title.data('propertyId', templateTitleProperty['o:id']); - title.closest('.field').find('[for="item-stub-title"]').text(propertyLabel); - }); - } else { - // Set the default title. - title.data('propertyId', title.data('propertyIdDefault')); - title.closest('.field').find('[for="item-stub-title"]').text(title.data('propertyLabelDefault')); - } - if (templateDescriptionProperty) { - // Set the description defined by the template (including alt label). - const propertyUrl = itemStubForm.data('propertyUrl') + '/' + templateDescriptionProperty['o:id']; - $.get(propertyUrl, function(propertyData) { - let propertyLabel = propertyData['o:label']; - $.each(resourceTemplateData['o:resource_template_property'], function(key, value) { - if (value['o:property']['o:id'] === templateDescriptionProperty['o:id']) { - if (value['o:alternate_label']) propertyLabel = value['o:alternate_label']; - return false; - } - }); - description.data('propertyId', templateDescriptionProperty['o:id']); - description.closest('.field').find('[for="item-stub-description"]').text(propertyLabel); - }); - } else { - // Set the default description. - description.data('propertyId', description.data('propertyIdDefault')); - description.closest('.field').find('[for="item-stub-description"]').text(description.data('propertyLabelDefault')); - } + }); + $.post(itemStubForm.data('getItemStubFieldsetUrl'), {resource_template_id: resourceTemplate.val()}, function(data) { + $('#item-stub-property-values').html(data); }); }); + /** END ITEM STUB FORM */ + initPage(); }); diff --git a/application/src/Controller/Admin/ItemController.php b/application/src/Controller/Admin/ItemController.php index 05fabd90c..bea7a09bc 100644 --- a/application/src/Controller/Admin/ItemController.php +++ b/application/src/Controller/Admin/ItemController.php @@ -238,7 +238,7 @@ public function addAction() return $view; } - public function getItemStubPropertyValuesAction() + public function getItemStubFieldsetAction() { $request = $this->getRequest(); $response = $this->getResponse(); diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index 4f303bb6e..178eee0f8 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -27,9 +27,13 @@ public function init() 'admin/default', ['controller' => 'item', 'action' => 'add-item-stub'] )); - $this->setAttribute('data-get-item-stub-property-values-url', $url( + $this->setAttribute('data-get-item-stub-fieldset-url', $url( 'admin/default', - ['controller' => 'item', 'action' => 'get-item-stub-property-values'] + ['controller' => 'item', 'action' => 'get-item-stub-fieldset'] + )); + $this->setAttribute('data-resource-template-url', $url( + 'api/default', + ['resource' => 'resource_templates'] )); $this->add([ diff --git a/application/src/View/Helper/DataType.php b/application/src/View/Helper/DataType.php index cd2a9bad7..5e25e722d 100644 --- a/application/src/View/Helper/DataType.php +++ b/application/src/View/Helper/DataType.php @@ -179,4 +179,48 @@ public function getValueAnnotationTemplates() } return $templates; } + + public function getItemStubFieldset($resourceTemplate = null) + { + $view = $this->getView(); + $form = []; + if ($resourceTemplate) { + // Build the form defined by the resource template. + foreach ($resourceTemplate->resourceTemplateProperties() as $rtProperty) { + $dataTypeNames = $rtProperty->dataTypes(); + if ($dataTypeNames) { + $dataTypeName = $dataTypeNames[0]; + if (in_array($dataTypeName, ['resource', 'resource:item', 'resource:itemset', 'resource:media', ])) { + // Set "resource" data types to "literal". + $dataTypeName = 'literal'; + } + $dataType = $this->manager->get($dataTypeName); + if (!($dataType instanceof ValueAnnotatingInterface)) { + // Set non-supported data types to "literal". + $dataType = $this->manager->get('literal'); + } + } else { + $dataType = $this->manager->get('literal'); + } + $property = $rtProperty->property(); + $form[] = $view->partial('common/value-annotation-wrapper', [ + 'dataType' => $dataType, + 'propertyId' => $property->id(), + 'propertyLabel' => $rtProperty->alternateLabel() ?? $property->label(), + ]); + } + } else { + // Build the default form. + $dataType = $this->manager->get('literal'); + foreach (['dcterms:title', 'dcterms:description'] as $propertyTerm) { + $property = $view->api()->searchOne('properties', ['term' => $propertyTerm])->getContent(); + $form[] = $view->partial('common/value-annotation-wrapper', [ + 'dataType' => $dataType, + 'propertyId' => $property->id(), + 'propertyLabel' => $property->label(), + ]); + } + } + return implode('', $form); + } } diff --git a/application/view/common/value-annotation-wrapper.phtml b/application/view/common/value-annotation-wrapper.phtml index e5b1dbf8a..2628db41c 100644 --- a/application/view/common/value-annotation-wrapper.phtml +++ b/application/view/common/value-annotation-wrapper.phtml @@ -2,7 +2,7 @@ $dataTypeName = (strpos('resource', $dataType->getName()) !== false) ? 'resource' : $dataType->getName(); ?>
-

+

valueAnnotationForm($this); ?>
diff --git a/application/view/omeka/admin/item/get-item-stub-fieldset.phtml b/application/view/omeka/admin/item/get-item-stub-fieldset.phtml new file mode 100644 index 000000000..1b1d423e0 --- /dev/null +++ b/application/view/omeka/admin/item/get-item-stub-fieldset.phtml @@ -0,0 +1 @@ +dataType()->getItemStubFieldset($resourceTemplate); ?> diff --git a/application/view/omeka/admin/item/get-item-stub-property-values.phtml b/application/view/omeka/admin/item/get-item-stub-property-values.phtml deleted file mode 100644 index 05ea31742..000000000 --- a/application/view/omeka/admin/item/get-item-stub-property-values.phtml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - From d71c1c2c5077dce4def9e0b797a4d48266167e24 Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Fri, 19 Jul 2024 22:41:00 -0400 Subject: [PATCH 14/47] Continue dev --- application/asset/js/resource-form.js | 27 ++++++++---- .../src/Controller/Admin/ItemController.php | 22 ---------- application/src/Form/ItemStubForm.php | 4 -- application/src/View/Helper/DataType.php | 44 ------------------- .../admin/item/get-item-stub-fieldset.phtml | 1 - 5 files changed, 18 insertions(+), 80 deletions(-) delete mode 100644 application/view/omeka/admin/item/get-item-stub-fieldset.phtml diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index da26d0482..7da0ad925 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -401,9 +401,7 @@ $('#select-resource').on('o:sidebar-content-loaded', function(e) { const itemStubForm = $('#item-stub-form'); - $.post(itemStubForm.data('getItemStubFieldsetUrl'), function(data) { - $('#item-stub-property-values').html(data); - }); + // @todo: Set the default property values (title and description) }); // Handle "New item" nav click. $(document).on('click', '#item-stub-section-label', function(e) { @@ -447,17 +445,28 @@ const itemStubForm = $('#item-stub-form'); const resourceTemplate = $('#item-stub-resource-template'); const resourceClass = $('#item-stub-resource-class'); + const propertyValues = $('#item-stub-property-values'); const resourceTemplateUrl = itemStubForm.data('resourceTemplateUrl') + '/' + resourceTemplate.val(); - $.get(resourceTemplateUrl, function(data) { - const templateResourceClass = data['o:resource_class']; + $.get(resourceTemplateUrl, function(rtData) { + const templateResourceClass = rtData['o:resource_class']; + // Set the template-defined class. if (templateResourceClass) { - // Set the template-defined class. resourceClass.val(templateResourceClass['o:id']); resourceClass.trigger('chosen:updated'); } - }); - $.post(itemStubForm.data('getItemStubFieldsetUrl'), {resource_template_id: resourceTemplate.val()}, function(data) { - $('#item-stub-property-values').html(data); + // Set the proprerty values. + propertyValues.empty(); + $.each(rtData['o:resource_template_property'], function(index, rtProperty) { + let dataTypeName = rtProperty['o:data_type'][0]; + // // Set non-supported and "resource" data types to "literal". + if (dataTypeName === undefined || !(dataTypeName in vaTemplates) || ['resource', 'resource:item', 'resource:itemset', 'resource:media'].includes(dataTypeName)) { + dataTypeName = 'literal'; + } + const valueAnnotation = $($.parseHTML(vaTemplates[dataTypeName])); + // @todo: Hydrate the markup + $(document).trigger('o:prepare-value-annotation', [dataTypeName, valueAnnotation]); + propertyValues.append(valueAnnotation); + }); }); }); diff --git a/application/src/Controller/Admin/ItemController.php b/application/src/Controller/Admin/ItemController.php index bea7a09bc..0c8f70354 100644 --- a/application/src/Controller/Admin/ItemController.php +++ b/application/src/Controller/Admin/ItemController.php @@ -238,28 +238,6 @@ public function addAction() return $view; } - public function getItemStubFieldsetAction() - { - $request = $this->getRequest(); - $response = $this->getResponse(); - if (!$request->isPost()) { - $response->setStatusCode(500); - return $response; - } - $postData = $this->params()->fromPost(); - $resourceTemplateId = $postData['resource_template_id'] ?? 0; - try { - $resourceTemplate = $this->api()->read('resource_templates', $resourceTemplateId)->getContent(); - } catch (\Omeka\Api\Exception\NotFoundException $e) { - $resourceTemplate = null; - } - - $view = new ViewModel; - $view->setTerminal(true); - $view->setVariable('resourceTemplate', $resourceTemplate); - return $view; - } - public function addItemStubAction() { $request = $this->getRequest(); diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index 178eee0f8..da21b6705 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -27,10 +27,6 @@ public function init() 'admin/default', ['controller' => 'item', 'action' => 'add-item-stub'] )); - $this->setAttribute('data-get-item-stub-fieldset-url', $url( - 'admin/default', - ['controller' => 'item', 'action' => 'get-item-stub-fieldset'] - )); $this->setAttribute('data-resource-template-url', $url( 'api/default', ['resource' => 'resource_templates'] diff --git a/application/src/View/Helper/DataType.php b/application/src/View/Helper/DataType.php index 5e25e722d..cd2a9bad7 100644 --- a/application/src/View/Helper/DataType.php +++ b/application/src/View/Helper/DataType.php @@ -179,48 +179,4 @@ public function getValueAnnotationTemplates() } return $templates; } - - public function getItemStubFieldset($resourceTemplate = null) - { - $view = $this->getView(); - $form = []; - if ($resourceTemplate) { - // Build the form defined by the resource template. - foreach ($resourceTemplate->resourceTemplateProperties() as $rtProperty) { - $dataTypeNames = $rtProperty->dataTypes(); - if ($dataTypeNames) { - $dataTypeName = $dataTypeNames[0]; - if (in_array($dataTypeName, ['resource', 'resource:item', 'resource:itemset', 'resource:media', ])) { - // Set "resource" data types to "literal". - $dataTypeName = 'literal'; - } - $dataType = $this->manager->get($dataTypeName); - if (!($dataType instanceof ValueAnnotatingInterface)) { - // Set non-supported data types to "literal". - $dataType = $this->manager->get('literal'); - } - } else { - $dataType = $this->manager->get('literal'); - } - $property = $rtProperty->property(); - $form[] = $view->partial('common/value-annotation-wrapper', [ - 'dataType' => $dataType, - 'propertyId' => $property->id(), - 'propertyLabel' => $rtProperty->alternateLabel() ?? $property->label(), - ]); - } - } else { - // Build the default form. - $dataType = $this->manager->get('literal'); - foreach (['dcterms:title', 'dcterms:description'] as $propertyTerm) { - $property = $view->api()->searchOne('properties', ['term' => $propertyTerm])->getContent(); - $form[] = $view->partial('common/value-annotation-wrapper', [ - 'dataType' => $dataType, - 'propertyId' => $property->id(), - 'propertyLabel' => $property->label(), - ]); - } - } - return implode('', $form); - } } diff --git a/application/view/omeka/admin/item/get-item-stub-fieldset.phtml b/application/view/omeka/admin/item/get-item-stub-fieldset.phtml deleted file mode 100644 index 1b1d423e0..000000000 --- a/application/view/omeka/admin/item/get-item-stub-fieldset.phtml +++ /dev/null @@ -1 +0,0 @@ -dataType()->getItemStubFieldset($resourceTemplate); ?> From 6423db505afffa1019b403c5fe6a5b27103ea1bd Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Tue, 9 Jul 2024 13:09:30 -0400 Subject: [PATCH 15/47] Begin implementing resource stub --- application/config/module.config.php | 1 + .../src/Controller/Admin/ItemController.php | 2 + application/src/Form/ResourceStubForm.php | 87 +++++++++++++++++++ .../Service/Form/ResourceStubFormFactory.php | 17 ++++ .../omeka/admin/item/sidebar-select.phtml | 29 ++++++- 5 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 application/src/Form/ResourceStubForm.php create mode 100644 application/src/Service/Form/ResourceStubFormFactory.php diff --git a/application/config/module.config.php b/application/config/module.config.php index db1deac12..516f18e92 100644 --- a/application/config/module.config.php +++ b/application/config/module.config.php @@ -520,6 +520,7 @@ ], 'factories' => [ 'Omeka\Form\ResourceForm' => Service\Form\ResourceFormFactory::class, + 'Omeka\Form\ResourceStubForm' => Service\Form\ResourceStubFormFactory::class, 'Omeka\Form\VocabularyForm' => Service\Form\VocabularyFormFactory::class, 'Omeka\Form\ResourceBatchUpdateForm' => Service\Form\ResourceBatchUpdateFormFactory::class, 'Omeka\Form\UserForm' => Service\Form\UserFormFactory::class, diff --git a/application/src/Controller/Admin/ItemController.php b/application/src/Controller/Admin/ItemController.php index 440924fc2..8a3fc9757 100644 --- a/application/src/Controller/Admin/ItemController.php +++ b/application/src/Controller/Admin/ItemController.php @@ -3,6 +3,7 @@ use Omeka\Form\ConfirmForm; use Omeka\Form\ResourceForm; +use Omeka\Form\ResourceStubForm; use Omeka\Form\ResourceBatchUpdateForm; use Omeka\Media\Ingester\Manager; use Omeka\Stdlib\Message; @@ -103,6 +104,7 @@ public function sidebarSelectAction() $view->setVariable('itemSetId', $this->params()->fromQuery('item_set_id')); $view->setVariable('id', $this->params()->fromQuery('id')); $view->setVariable('showDetails', true); + $view->setVariable('resourceStubForm', $this->getForm(ResourceStubForm::class)); $view->setTerminal(true); return $view; } diff --git a/application/src/Form/ResourceStubForm.php b/application/src/Form/ResourceStubForm.php new file mode 100644 index 000000000..6c2f5321f --- /dev/null +++ b/application/src/Form/ResourceStubForm.php @@ -0,0 +1,87 @@ +getUrlHelper(); + + $this->add([ + 'type' => ResourceSelect::class, + 'name' => 'resource_template', + 'options' => [ + 'label' => 'Resource template', // @translate + 'empty_option' => '', + 'resource_value_options' => [ + 'resource' => 'resource_templates', + 'query' => [ + 'sort_by' => 'label', + ], + 'option_text_callback' => function ($resourceTemplate) { + return $resourceTemplate->label(); + }, + ], + ], + 'attributes' => [ + 'id' => 'resource-stub-resource-template-select', + 'class' => 'chosen-select', + 'data-placeholder' => 'Select a template', // @translate + 'data-api-base-url' => $urlHelper('api/default', ['resource' => 'resource_templates']), + ], + ]); + $this->add([ + 'type' => ResourceClassSelect::class, + 'name' => 'resource_class', + 'options' => [ + 'label' => 'Class', // @translate + 'empty_option' => '', + ], + 'attributes' => [ + 'id' => 'resource-stub-resource-class-select', + 'class' => 'chosen-select', + 'data-placeholder' => 'Select a class', // @translate + ], + ]); + $this->add([ + 'type' => 'textarea', + 'name' => 'title', + 'options' => [ + 'label' => 'Title', // @translate + ], + 'attributes' => [ + 'id' => 'resource-stub-title-textarea', + ], + ]); + $this->add([ + 'type' => 'textarea', + 'name' => 'description', + 'options' => [ + 'label' => 'Description', // @translate + ], + 'attributes' => [ + 'id' => 'resource-stub-description-textarea', + ], + ]); + } + + public function setUrlHelper(Url $urlHelper) + { + $this->urlHelper = $urlHelper; + } + + public function getUrlHelper() + { + return $this->urlHelper; + } +} diff --git a/application/src/Service/Form/ResourceStubFormFactory.php b/application/src/Service/Form/ResourceStubFormFactory.php new file mode 100644 index 000000000..4659e06a5 --- /dev/null +++ b/application/src/Service/Form/ResourceStubFormFactory.php @@ -0,0 +1,17 @@ +setUrlHelper($services->get('ViewHelperManager')->get('Url')); + $form->setEventManager($services->get('EventManager')); + return $form; + } +} diff --git a/application/view/omeka/admin/item/sidebar-select.phtml b/application/view/omeka/admin/item/sidebar-select.phtml index 2b2fe216b..fa8d4ea95 100644 --- a/application/view/omeka/admin/item/sidebar-select.phtml +++ b/application/view/omeka/admin/item/sidebar-select.phtml @@ -6,9 +6,15 @@ $itemsFound = count($items) > 0; $expanded = $resourceClassId || $itemSetId || $id; ?> +sectionNav([ + 'existing-resource-section' => $translate('Existing item'), + 'new-resource-section' => $translate('New item'), +]); ?> + +
+

-
+ +
+ +
+ formCollection($resourceStubForm, false); ?> + +
+ + From e8271803bb69d2ff715041ab8e9d10acc915a092 Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Tue, 9 Jul 2024 13:29:25 -0400 Subject: [PATCH 16/47] Continue dev --- .../omeka/admin/item/sidebar-select.phtml | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/application/view/omeka/admin/item/sidebar-select.phtml b/application/view/omeka/admin/item/sidebar-select.phtml index fa8d4ea95..869f8c19c 100644 --- a/application/view/omeka/admin/item/sidebar-select.phtml +++ b/application/view/omeka/admin/item/sidebar-select.phtml @@ -7,11 +7,11 @@ $expanded = $resourceClassId || $itemSetId || $id; ?> sectionNav([ - 'existing-resource-section' => $translate('Existing item'), - 'new-resource-section' => $translate('New item'), + 'resource-section' => $translate('Existing item'), + 'resource-stub-section' => $translate('New item'), ]); ?> -
+

@@ -113,21 +113,31 @@ $expanded = $resourceClassId || $itemSetId || $id;
-
+
formCollection($resourceStubForm, false); ?> - +
From 3d9655c2d38f418f679af27847e048017edfc0cc Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Wed, 10 Jul 2024 18:07:34 -0400 Subject: [PATCH 17/47] Continue dev --- application/config/module.config.php | 2 +- .../src/Controller/Admin/ItemController.php | 4 +- ...{ResourceStubForm.php => ItemStubForm.php} | 50 ++++++++----- ...ormFactory.php => ItemStubFormFactory.php} | 8 +-- .../omeka/admin/item/sidebar-select.phtml | 71 ++++++++++++++----- 5 files changed, 92 insertions(+), 43 deletions(-) rename application/src/Form/{ResourceStubForm.php => ItemStubForm.php} (53%) rename application/src/Service/Form/{ResourceStubFormFactory.php => ItemStubFormFactory.php} (61%) diff --git a/application/config/module.config.php b/application/config/module.config.php index 516f18e92..88c5ee6f9 100644 --- a/application/config/module.config.php +++ b/application/config/module.config.php @@ -520,7 +520,7 @@ ], 'factories' => [ 'Omeka\Form\ResourceForm' => Service\Form\ResourceFormFactory::class, - 'Omeka\Form\ResourceStubForm' => Service\Form\ResourceStubFormFactory::class, + 'Omeka\Form\ItemStubForm' => Service\Form\ItemStubFormFactory::class, 'Omeka\Form\VocabularyForm' => Service\Form\VocabularyFormFactory::class, 'Omeka\Form\ResourceBatchUpdateForm' => Service\Form\ResourceBatchUpdateFormFactory::class, 'Omeka\Form\UserForm' => Service\Form\UserFormFactory::class, diff --git a/application/src/Controller/Admin/ItemController.php b/application/src/Controller/Admin/ItemController.php index 8a3fc9757..6b041f017 100644 --- a/application/src/Controller/Admin/ItemController.php +++ b/application/src/Controller/Admin/ItemController.php @@ -2,8 +2,8 @@ namespace Omeka\Controller\Admin; use Omeka\Form\ConfirmForm; +use Omeka\Form\ItemStubForm; use Omeka\Form\ResourceForm; -use Omeka\Form\ResourceStubForm; use Omeka\Form\ResourceBatchUpdateForm; use Omeka\Media\Ingester\Manager; use Omeka\Stdlib\Message; @@ -104,7 +104,7 @@ public function sidebarSelectAction() $view->setVariable('itemSetId', $this->params()->fromQuery('item_set_id')); $view->setVariable('id', $this->params()->fromQuery('id')); $view->setVariable('showDetails', true); - $view->setVariable('resourceStubForm', $this->getForm(ResourceStubForm::class)); + $view->setVariable('itemStubForm', $this->getForm(ItemStubForm::class)); $view->setTerminal(true); return $view; } diff --git a/application/src/Form/ResourceStubForm.php b/application/src/Form/ItemStubForm.php similarity index 53% rename from application/src/Form/ResourceStubForm.php rename to application/src/Form/ItemStubForm.php index 6c2f5321f..d1ea04d63 100644 --- a/application/src/Form/ResourceStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -1,24 +1,32 @@ getUrlHelper(); + $urlHelper = $this->viewHelperManager->get('url'); + $apiHelper = $this->viewHelperManager->get('api'); + + $titleProperty = $apiHelper->searchOne('properties', ['term' => 'dcterms:title'])->getContent(); + $descriptionProperty = $apiHelper->searchOne('properties', ['term' => 'dcterms:description'])->getContent(); + + $this->setAttribute('id', 'item-stub-form'); + $this->setAttribute('data-url', $urlHelper('admin/default', ['controller' => 'item', 'action' => 'add-resource-stub'])); $this->add([ - 'type' => ResourceSelect::class, + 'type' => OmekaElement\ResourceSelect::class, 'name' => 'resource_template', 'options' => [ 'label' => 'Resource template', // @translate @@ -34,21 +42,20 @@ public function init() ], ], 'attributes' => [ - 'id' => 'resource-stub-resource-template-select', + 'id' => 'item-stub-resource-template', 'class' => 'chosen-select', 'data-placeholder' => 'Select a template', // @translate - 'data-api-base-url' => $urlHelper('api/default', ['resource' => 'resource_templates']), ], ]); $this->add([ - 'type' => ResourceClassSelect::class, + 'type' => OmekaElement\ResourceClassSelect::class, 'name' => 'resource_class', 'options' => [ 'label' => 'Class', // @translate 'empty_option' => '', ], 'attributes' => [ - 'id' => 'resource-stub-resource-class-select', + 'id' => 'item-stub-resource-class', 'class' => 'chosen-select', 'data-placeholder' => 'Select a class', // @translate ], @@ -60,7 +67,7 @@ public function init() 'label' => 'Title', // @translate ], 'attributes' => [ - 'id' => 'resource-stub-title-textarea', + 'data-property-term' => $titleProperty->term(), ], ]); $this->add([ @@ -70,18 +77,25 @@ public function init() 'label' => 'Description', // @translate ], 'attributes' => [ - 'id' => 'resource-stub-description-textarea', + 'data-property-term' => $descriptionProperty->term(), + ], + ]); + $this->add([ + 'type' => 'submit', + 'name' => 'submit', + 'attributes' => [ + 'id' => 'item-stub-submit', + 'value' => 'Add and select item', // @translate ], ]); - } - public function setUrlHelper(Url $urlHelper) - { - $this->urlHelper = $urlHelper; + // Allow modules to add elements to the item stub form. + $addEvent = new Event('form.add_elements', $this); + $this->getEventManager()->triggerEvent($addEvent); } - public function getUrlHelper() + public function setViewHelperManager($viewHelperManager) { - return $this->urlHelper; + $this->viewHelperManager = $viewHelperManager; } } diff --git a/application/src/Service/Form/ResourceStubFormFactory.php b/application/src/Service/Form/ItemStubFormFactory.php similarity index 61% rename from application/src/Service/Form/ResourceStubFormFactory.php rename to application/src/Service/Form/ItemStubFormFactory.php index 4659e06a5..5dd18b1e8 100644 --- a/application/src/Service/Form/ResourceStubFormFactory.php +++ b/application/src/Service/Form/ItemStubFormFactory.php @@ -1,16 +1,16 @@ setUrlHelper($services->get('ViewHelperManager')->get('Url')); + $form = new ItemStubForm; + $form->setViewHelperManager($services->get('ViewHelperManager')); $form->setEventManager($services->get('EventManager')); return $form; } diff --git a/application/view/omeka/admin/item/sidebar-select.phtml b/application/view/omeka/admin/item/sidebar-select.phtml index 869f8c19c..587886ca5 100644 --- a/application/view/omeka/admin/item/sidebar-select.phtml +++ b/application/view/omeka/admin/item/sidebar-select.phtml @@ -7,11 +7,11 @@ $expanded = $resourceClassId || $itemSetId || $id; ?> sectionNav([ - 'resource-section' => $translate('Existing item'), - 'resource-stub-section' => $translate('New item'), + 'item-section' => $translate('Existing item'), + 'item-stub-section' => $translate('New item'), ]); ?> -
+

@@ -113,30 +113,65 @@ $expanded = $resourceClassId || $itemSetId || $id;
-
- formCollection($resourceStubForm, false); ?> - +
+ form($itemStubForm, false); ?>
From 6ae3386cd2ba2537be0456640aa862044cfd766e Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Thu, 11 Jul 2024 14:57:12 -0400 Subject: [PATCH 19/47] Continue dev --- application/asset/js/resource-form.js | 5 ++--- application/src/Controller/Admin/ItemController.php | 3 ++- application/src/Form/ItemStubForm.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index e55b10047..25afe8a66 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -436,9 +436,8 @@ }); $.post(itemStubForm.data('url'), itemData, function(data) { const selectedResource = $('.selecting-resource').find('.selected-resource'); - const img = $('', {src: data['thumbnail_display_urls']['square']}); - const a = $('', {href: data['admin_url']}).text(data['o:title']); - selectedResource.find('.o-title').addClass('items').empty().append(img, a); + const a = $('', {href: data['admin_url']}).text(data['display_title']); + selectedResource.find('.o-title').removeClass().addClass('o-title items').html(a); selectedResource.find('.value').val(data['o:id']); }); }); diff --git a/application/src/Controller/Admin/ItemController.php b/application/src/Controller/Admin/ItemController.php index 389e86e19..c02ccfbbc 100644 --- a/application/src/Controller/Admin/ItemController.php +++ b/application/src/Controller/Admin/ItemController.php @@ -238,7 +238,7 @@ public function addAction() return $view; } - public function addResourceStubAction() + public function addItemStubAction() { $request = $this->getRequest(); $response = $this->getResponse(); @@ -249,6 +249,7 @@ public function addResourceStubAction() $item = $this->api()->create('items', $itemData)->getContent(); $itemJson = json_decode(json_encode($item), true); $itemJson['admin_url'] = $this->url()->fromRoute('admin/id', ['action' => 'show', 'id' => $item->id()], true); + $itemJson['display_title'] = $item->displayTitle(); $response->getHeaders()->addHeaders(['Content-Type' => 'application/ld+json']); $response->setContent(json_encode($itemJson)); return $response; diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index d1ea04d63..d2c63c577 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -23,7 +23,7 @@ public function init() $descriptionProperty = $apiHelper->searchOne('properties', ['term' => 'dcterms:description'])->getContent(); $this->setAttribute('id', 'item-stub-form'); - $this->setAttribute('data-url', $urlHelper('admin/default', ['controller' => 'item', 'action' => 'add-resource-stub'])); + $this->setAttribute('data-url', $urlHelper('admin/default', ['controller' => 'item', 'action' => 'add-item-stub'])); $this->add([ 'type' => OmekaElement\ResourceSelect::class, From 15f10f54ff48425758b0550205f99233b110c59d Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Fri, 12 Jul 2024 16:57:34 -0400 Subject: [PATCH 20/47] Continue dev --- application/asset/js/resource-form.js | 10 ++++-- .../src/Controller/Admin/ItemController.php | 9 ++++- application/src/Form/ItemStubForm.php | 33 +++++++++++++++---- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index 25afe8a66..84a6d5cb8 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -417,6 +417,7 @@ const resourceTemplate = $('#item-stub-resource-template'); const resourceClass = $('#item-stub-resource-class'); const itemData = {}; + if (resourceTemplate.val()) { itemData['o:resource_template'] = {'o:id': resourceTemplate.val()}; } @@ -427,18 +428,23 @@ const propertyValue = $(this); if (propertyValue.val()) { const propertyTerm = propertyValue.data('propertyTerm'); - itemData[propertyTerm] = [{ + if (!itemData.hasOwnProperty(propertyTerm)) { + itemData[propertyTerm] = []; + } + itemData[propertyTerm].push({ 'type': 'literal', 'property_id': 'auto', '@value': propertyValue.val() - }]; + }); } }); + itemData['csrf'] = itemStubForm.find('input[name="csrf"]').val(); $.post(itemStubForm.data('url'), itemData, function(data) { const selectedResource = $('.selecting-resource').find('.selected-resource'); const a = $('', {href: data['admin_url']}).text(data['display_title']); selectedResource.find('.o-title').removeClass().addClass('o-title items').html(a); selectedResource.find('.value').val(data['o:id']); + Omeka.closeSidebar($('#select-resource')); }); }); $(document).on('change', '#item-stub-resource-template', function(e) { diff --git a/application/src/Controller/Admin/ItemController.php b/application/src/Controller/Admin/ItemController.php index c02ccfbbc..0c8f70354 100644 --- a/application/src/Controller/Admin/ItemController.php +++ b/application/src/Controller/Admin/ItemController.php @@ -243,9 +243,16 @@ public function addItemStubAction() $request = $this->getRequest(); $response = $this->getResponse(); if (!$request->isPost()) { - return $this->redirect()->toRoute(null, ['action' => 'browse'], true); + $response->setStatusCode(500); + return $response; } $itemData = $this->params()->fromPost(); + $form = $this->getForm(ItemStubForm::class); + $form->setData($itemData); + if (!$form->isValid()) { + $response->setStatusCode(500); + return $response; + } $item = $this->api()->create('items', $itemData)->getContent(); $itemJson = json_decode(json_encode($item), true); $itemJson['admin_url'] = $this->url()->fromRoute('admin/id', ['action' => 'show', 'id' => $item->id()], true); diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index d2c63c577..8239b5dc5 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -14,14 +14,13 @@ class ItemStubForm extends Form protected $viewHelperManager; + protected $valueIndex = []; + public function init() { $urlHelper = $this->viewHelperManager->get('url'); $apiHelper = $this->viewHelperManager->get('api'); - $titleProperty = $apiHelper->searchOne('properties', ['term' => 'dcterms:title'])->getContent(); - $descriptionProperty = $apiHelper->searchOne('properties', ['term' => 'dcterms:description'])->getContent(); - $this->setAttribute('id', 'item-stub-form'); $this->setAttribute('data-url', $urlHelper('admin/default', ['controller' => 'item', 'action' => 'add-item-stub'])); @@ -47,6 +46,7 @@ public function init() 'data-placeholder' => 'Select a template', // @translate ], ]); + $this->add([ 'type' => OmekaElement\ResourceClassSelect::class, 'name' => 'resource_class', @@ -60,6 +60,7 @@ public function init() 'data-placeholder' => 'Select a class', // @translate ], ]); + $this->add([ 'type' => 'textarea', 'name' => 'title', @@ -67,9 +68,11 @@ public function init() 'label' => 'Title', // @translate ], 'attributes' => [ - 'data-property-term' => $titleProperty->term(), + 'id' => 'item-stub-title', + 'data-property-term' => 'dcterms:title', ], ]); + $this->add([ 'type' => 'textarea', 'name' => 'description', @@ -77,9 +80,11 @@ public function init() 'label' => 'Description', // @translate ], 'attributes' => [ - 'data-property-term' => $descriptionProperty->term(), + 'id' => 'item-stub-description', + 'data-property-term' => 'dcterms:description', ], ]); + $this->add([ 'type' => 'submit', 'name' => 'submit', @@ -89,9 +94,25 @@ public function init() ], ]); - // Allow modules to add elements to the item stub form. + // Allow modules to modify this form. $addEvent = new Event('form.add_elements', $this); $this->getEventManager()->triggerEvent($addEvent); + + $inputFilter = $this->getInputFilter(); + $inputFilter->add([ + 'name' => 'resource_template', + 'required' => false, + 'allow_empty' => true, + ]); + $inputFilter->add([ + 'name' => 'resource_class', + 'required' => false, + 'allow_empty' => true, + ]); + + // Allow modules to modify this form's input filters. + $filterEvent = new Event('form.add_input_filters', $this, ['inputFilter' => $inputFilter]); + $this->getEventManager()->triggerEvent($filterEvent); } public function setViewHelperManager($viewHelperManager) From 79109abacab9cc84b6926c6385a38e2e5a3e3adf Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Fri, 12 Jul 2024 22:13:14 -0400 Subject: [PATCH 21/47] Continue dev --- application/asset/js/resource-form.js | 2 +- application/src/Form/ItemStubForm.php | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index 84a6d5cb8..7a28d3c2b 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -417,7 +417,6 @@ const resourceTemplate = $('#item-stub-resource-template'); const resourceClass = $('#item-stub-resource-class'); const itemData = {}; - if (resourceTemplate.val()) { itemData['o:resource_template'] = {'o:id': resourceTemplate.val()}; } @@ -441,6 +440,7 @@ itemData['csrf'] = itemStubForm.find('input[name="csrf"]').val(); $.post(itemStubForm.data('url'), itemData, function(data) { const selectedResource = $('.selecting-resource').find('.selected-resource'); + selectedResource.prev('span.default').hide(); const a = $('', {href: data['admin_url']}).text(data['display_title']); selectedResource.find('.o-title').removeClass().addClass('o-title items').html(a); selectedResource.find('.value').val(data['o:id']); diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index 8239b5dc5..1517a51a3 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -94,7 +94,9 @@ public function init() ], ]); - // Allow modules to modify this form. + // Allow modules to modify this form. Modules can add value elements by + // setting a "data-property-term" attribute with the property's term + // (e.g. dcterms:creator). $addEvent = new Event('form.add_elements', $this); $this->getEventManager()->triggerEvent($addEvent); From 4167a551539ecfe2599d51cd6a7ab90c61542528 Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Sun, 14 Jul 2024 21:01:59 -0400 Subject: [PATCH 22/47] Continue dev --- application/asset/js/resource-form.js | 40 +++++++++---- application/src/Form/ItemStubForm.php | 57 ++++++++++++++----- .../src/Service/Form/ItemStubFormFactory.php | 3 +- 3 files changed, 75 insertions(+), 25 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index 7a28d3c2b..53c1e092c 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -423,22 +423,23 @@ if (resourceClass.val()) { itemData['o:resource_class'] = {'o:id': resourceClass.val()}; } - itemStubForm.find('[data-property-term]').each(function() { + itemStubForm.find('[data-property-id]').each(function() { const propertyValue = $(this); if (propertyValue.val()) { - const propertyTerm = propertyValue.data('propertyTerm'); - if (!itemData.hasOwnProperty(propertyTerm)) { - itemData[propertyTerm] = []; + const propertyId = propertyValue.data('propertyId'); + const type = propertyValue.data('type'); + if (!itemData.hasOwnProperty(propertyId)) { + itemData[propertyId] = []; } - itemData[propertyTerm].push({ - 'type': 'literal', - 'property_id': 'auto', + itemData[propertyId].push({ + 'property_id': propertyId, + 'type': type, '@value': propertyValue.val() }); } }); itemData['csrf'] = itemStubForm.find('input[name="csrf"]').val(); - $.post(itemStubForm.data('url'), itemData, function(data) { + $.post(itemStubForm.data('submitUrl'), itemData, function(data) { const selectedResource = $('.selecting-resource').find('.selected-resource'); selectedResource.prev('span.default').hide(); const a = $('', {href: data['admin_url']}).text(data['display_title']); @@ -448,9 +449,26 @@ }); }); $(document).on('change', '#item-stub-resource-template', function(e) { - console.log('#item-stub-resource-template'); - // @todo: get resource template from the API (via data attribute) - // @todo: change resource class, title property, description property accordingly + const itemStubForm = $('#item-stub-form'); + const resourceTemplate = $('#item-stub-resource-template'); + const resourceClass = $('#item-stub-resource-class'); + const title = $('#item-stub-title'); + const description = $('#item-stub-description'); + const resourceTemplateUrl = itemStubForm.data('templateUrl') + '/' + resourceTemplate.val(); + $.get(resourceTemplateUrl, function(data) { + const templateResourceClass = data['o:resource_class']; + const templateTitleProperty = data['o:title_property']; + const templateDescriptionProperty = data['o:description_property']; + if (templateResourceClass) { + resourceClass.val(templateResourceClass['o:id']); + resourceClass.trigger('chosen:updated'); + } + if (templateTitleProperty) { + // @todo: get property data from API (for label in particular) + title.data('property-id', templateTitleProperty['o:id']); + // @todo: get and set alt label, if any + } + }); }); initPage(); diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index 1517a51a3..66c5d2089 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -12,17 +12,21 @@ class ItemStubForm extends Form { use EventManagerAwareTrait; - protected $viewHelperManager; + protected $apiManager; - protected $valueIndex = []; + protected $urlHelper; public function init() { - $urlHelper = $this->viewHelperManager->get('url'); - $apiHelper = $this->viewHelperManager->get('api'); - $this->setAttribute('id', 'item-stub-form'); - $this->setAttribute('data-url', $urlHelper('admin/default', ['controller' => 'item', 'action' => 'add-item-stub'])); + $this->setAttribute('data-submit-url', $this->getUrlHelper()( + 'admin/default', + ['controller' => 'item', 'action' => 'add-item-stub'] + )); + $this->setAttribute('data-template-url', $this->getUrlHelper()( + 'api/default', + ['resource' => 'resource_templates'] + )); $this->add([ 'type' => OmekaElement\ResourceSelect::class, @@ -61,6 +65,10 @@ public function init() ], ]); + $property = $this->getApiManager()->search( + 'properties', + ['term' => 'dcterms:title'] + )->getContent()[0]; $this->add([ 'type' => 'textarea', 'name' => 'title', @@ -69,10 +77,17 @@ public function init() ], 'attributes' => [ 'id' => 'item-stub-title', - 'data-property-term' => 'dcterms:title', + 'data-property-id' => $property->id(), + 'data-type' => 'literal', + 'data-property-id-original' => $property->id(), + 'data-property-label-original' => 'Title', // @translate ], ]); + $property = $this->getApiManager()->search( + 'properties', + ['term' => 'dcterms:description'] + )->getContent()[0]; $this->add([ 'type' => 'textarea', 'name' => 'description', @@ -81,7 +96,10 @@ public function init() ], 'attributes' => [ 'id' => 'item-stub-description', - 'data-property-term' => 'dcterms:description', + 'data-property-id' => $property->id(), + 'data-type' => 'literal', + 'data-property-id-original' => $property->id(), + 'data-property-label-original' => 'Description', // @translate ], ]); @@ -94,9 +112,7 @@ public function init() ], ]); - // Allow modules to modify this form. Modules can add value elements by - // setting a "data-property-term" attribute with the property's term - // (e.g. dcterms:creator). + // Allow modules to modify this form. $addEvent = new Event('form.add_elements', $this); $this->getEventManager()->triggerEvent($addEvent); @@ -117,8 +133,23 @@ public function init() $this->getEventManager()->triggerEvent($filterEvent); } - public function setViewHelperManager($viewHelperManager) + public function setApiManager(ApiManager $apiManager) + { + $this->apiManager = $apiManager; + } + + public function getApiManager() + { + return $this->apiManager; + } + + public function setUrlHelper(Url $urlHelper) + { + $this->urlHelper = $urlHelper; + } + + public function getUrlHelper() { - $this->viewHelperManager = $viewHelperManager; + return $this->urlHelper; } } diff --git a/application/src/Service/Form/ItemStubFormFactory.php b/application/src/Service/Form/ItemStubFormFactory.php index 5dd18b1e8..63825b657 100644 --- a/application/src/Service/Form/ItemStubFormFactory.php +++ b/application/src/Service/Form/ItemStubFormFactory.php @@ -10,7 +10,8 @@ class ItemStubFormFactory implements FactoryInterface public function __invoke(ContainerInterface $services, $requestedName, array $options = null) { $form = new ItemStubForm; - $form->setViewHelperManager($services->get('ViewHelperManager')); + $form->setApiManager($services->get('Omeka\ApiManager')); + $form->setUrlHelper($services->get('ViewHelperManager')->get('Url')); $form->setEventManager($services->get('EventManager')); return $form; } From 45c742e40504b7620705e2084926e6cb7aeeb0df Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Mon, 15 Jul 2024 13:23:51 -0400 Subject: [PATCH 23/47] Continue dev --- application/asset/js/resource-form.js | 51 ++++++++++++++++--- application/src/Form/ItemStubForm.php | 39 ++++++++------ .../src/Service/Form/ItemStubFormFactory.php | 2 +- 3 files changed, 67 insertions(+), 25 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index 53c1e092c..eb6774306 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -448,25 +448,60 @@ Omeka.closeSidebar($('#select-resource')); }); }); + // Item stub form: handle resource template change. $(document).on('change', '#item-stub-resource-template', function(e) { const itemStubForm = $('#item-stub-form'); const resourceTemplate = $('#item-stub-resource-template'); const resourceClass = $('#item-stub-resource-class'); const title = $('#item-stub-title'); const description = $('#item-stub-description'); - const resourceTemplateUrl = itemStubForm.data('templateUrl') + '/' + resourceTemplate.val(); - $.get(resourceTemplateUrl, function(data) { - const templateResourceClass = data['o:resource_class']; - const templateTitleProperty = data['o:title_property']; - const templateDescriptionProperty = data['o:description_property']; + const resourceTemplateUrl = itemStubForm.data('resourceTemplateUrl') + '/' + resourceTemplate.val(); + $.get(resourceTemplateUrl, function(resourceTemplateData) { + const templateResourceClass = resourceTemplateData['o:resource_class']; + const templateTitleProperty = resourceTemplateData['o:title_property']; + const templateDescriptionProperty = resourceTemplateData['o:description_property']; if (templateResourceClass) { + // Set the template-defined class. resourceClass.val(templateResourceClass['o:id']); resourceClass.trigger('chosen:updated'); } if (templateTitleProperty) { - // @todo: get property data from API (for label in particular) - title.data('property-id', templateTitleProperty['o:id']); - // @todo: get and set alt label, if any + // Set the title defined by the template (including alt label). + const propertyUrl = itemStubForm.data('propertyUrl') + '/' + templateTitleProperty['o:id']; + $.get(propertyUrl, function(propertyData) { + let propertyLabel = propertyData['o:label']; + $.each(resourceTemplateData['o:resource_template_property'], function(key, value) { + if (value['o:property']['o:id'] === templateTitleProperty['o:id']) { + if (value['o:alternate_label']) propertyLabel = value['o:alternate_label']; + return false; + } + }); + title.data('propertyId', templateTitleProperty['o:id']); + title.closest('.field').find('[for="item-stub-title"]').text(propertyLabel); + }); + } else { + // Set the default title. + title.data('propertyId', title.data('propertyIdDefault')); + title.closest('.field').find('[for="item-stub-title"]').text(title.data('propertyLabelDefault')); + } + if (templateDescriptionProperty) { + // Set the description defined by the template (including alt label). + const propertyUrl = itemStubForm.data('propertyUrl') + '/' + templateDescriptionProperty['o:id']; + $.get(propertyUrl, function(propertyData) { + let propertyLabel = propertyData['o:label']; + $.each(resourceTemplateData['o:resource_template_property'], function(key, value) { + if (value['o:property']['o:id'] === templateDescriptionProperty['o:id']) { + if (value['o:alternate_label']) propertyLabel = value['o:alternate_label']; + return false; + } + }); + description.data('propertyId', templateDescriptionProperty['o:id']); + description.closest('.field').find('[for="item-stub-description"]').text(propertyLabel); + }); + } else { + // Set the default description. + description.data('propertyId', description.data('propertyIdDefault')); + description.closest('.field').find('[for="item-stub-description"]').text(description.data('propertyLabelDefault')); } }); }); diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index 66c5d2089..6080d540e 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -4,7 +4,7 @@ use Laminas\EventManager\Event; use Laminas\EventManager\EventManagerAwareTrait; use Laminas\Form\Form; -use Laminas\View\Helper\Url; +use Laminas\View\HelperPluginManager; use Omeka\Api\Manager as ApiManager; use Omeka\Form\Element as OmekaElement; @@ -14,19 +14,26 @@ class ItemStubForm extends Form protected $apiManager; - protected $urlHelper; + protected $viewHelperManager; public function init() { + $urlHelper = $this->getViewHelperManager()->get('url'); + $apiHelper = $this->getViewHelperManager()->get('api'); + $this->setAttribute('id', 'item-stub-form'); - $this->setAttribute('data-submit-url', $this->getUrlHelper()( + $this->setAttribute('data-submit-url', $urlHelper( 'admin/default', ['controller' => 'item', 'action' => 'add-item-stub'] )); - $this->setAttribute('data-template-url', $this->getUrlHelper()( + $this->setAttribute('data-resource-template-url', $urlHelper( 'api/default', ['resource' => 'resource_templates'] )); + $this->setAttribute('data-property-url', $urlHelper( + 'api/default', + ['resource' => 'properties'] + )); $this->add([ 'type' => OmekaElement\ResourceSelect::class, @@ -65,10 +72,10 @@ public function init() ], ]); - $property = $this->getApiManager()->search( + $property = $apiHelper->searchOne( 'properties', ['term' => 'dcterms:title'] - )->getContent()[0]; + )->getContent(); $this->add([ 'type' => 'textarea', 'name' => 'title', @@ -79,15 +86,15 @@ public function init() 'id' => 'item-stub-title', 'data-property-id' => $property->id(), 'data-type' => 'literal', - 'data-property-id-original' => $property->id(), - 'data-property-label-original' => 'Title', // @translate + 'data-property-id-default' => $property->id(), + 'data-property-label-default' => 'Title', // @translate ], ]); - $property = $this->getApiManager()->search( + $property = $apiHelper->searchOne( 'properties', ['term' => 'dcterms:description'] - )->getContent()[0]; + )->getContent(); $this->add([ 'type' => 'textarea', 'name' => 'description', @@ -98,8 +105,8 @@ public function init() 'id' => 'item-stub-description', 'data-property-id' => $property->id(), 'data-type' => 'literal', - 'data-property-id-original' => $property->id(), - 'data-property-label-original' => 'Description', // @translate + 'data-property-id-default' => $property->id(), + 'data-property-label-default' => 'Description', // @translate ], ]); @@ -143,13 +150,13 @@ public function getApiManager() return $this->apiManager; } - public function setUrlHelper(Url $urlHelper) + public function setViewHelperManager(HelperPluginManager $viewHelperManager) { - $this->urlHelper = $urlHelper; + $this->viewHelperManager = $viewHelperManager; } - public function getUrlHelper() + public function getViewHelperManager() { - return $this->urlHelper; + return $this->viewHelperManager; } } diff --git a/application/src/Service/Form/ItemStubFormFactory.php b/application/src/Service/Form/ItemStubFormFactory.php index 63825b657..6b573c3f7 100644 --- a/application/src/Service/Form/ItemStubFormFactory.php +++ b/application/src/Service/Form/ItemStubFormFactory.php @@ -11,7 +11,7 @@ public function __invoke(ContainerInterface $services, $requestedName, array $op { $form = new ItemStubForm; $form->setApiManager($services->get('Omeka\ApiManager')); - $form->setUrlHelper($services->get('ViewHelperManager')->get('Url')); + $form->setViewHelperManager($services->get('ViewHelperManager')); $form->setEventManager($services->get('EventManager')); return $form; } From b7d415a0e0668c6cc3cbf664f2c0d8cd3d2da065 Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Tue, 16 Jul 2024 13:04:01 -0400 Subject: [PATCH 24/47] Continue dev --- application/asset/js/resource-form.js | 2 +- application/src/Form/ItemStubForm.php | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index eb6774306..a1270671a 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -402,7 +402,7 @@ $(this).closest('.section-nav').find('li').toggleClass('active'); $('#item-section').hide(); $('#item-stub-section').show(); - $('.chosen-select').chosen(); + $('.chosen-select').chosen({allow_single_deselect: true}); }); // Item stub form: handle "Existing item" nav click. $(document).on('click', '#item-section-label', function(e) { diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index 6080d540e..82c257519 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -18,19 +18,20 @@ class ItemStubForm extends Form public function init() { - $urlHelper = $this->getViewHelperManager()->get('url'); - $apiHelper = $this->getViewHelperManager()->get('api'); + $url = $this->getViewHelperManager()->get('url'); + $translate = $this->getViewHelperManager()->get('translate'); + $api = $this->getViewHelperManager()->get('api'); $this->setAttribute('id', 'item-stub-form'); - $this->setAttribute('data-submit-url', $urlHelper( + $this->setAttribute('data-submit-url', $url( 'admin/default', ['controller' => 'item', 'action' => 'add-item-stub'] )); - $this->setAttribute('data-resource-template-url', $urlHelper( + $this->setAttribute('data-resource-template-url', $url( 'api/default', ['resource' => 'resource_templates'] )); - $this->setAttribute('data-property-url', $urlHelper( + $this->setAttribute('data-property-url', $url( 'api/default', ['resource' => 'properties'] )); @@ -72,7 +73,7 @@ public function init() ], ]); - $property = $apiHelper->searchOne( + $property = $api->searchOne( 'properties', ['term' => 'dcterms:title'] )->getContent(); @@ -87,11 +88,11 @@ public function init() 'data-property-id' => $property->id(), 'data-type' => 'literal', 'data-property-id-default' => $property->id(), - 'data-property-label-default' => 'Title', // @translate + 'data-property-label-default' => $translate('Title'), ], ]); - $property = $apiHelper->searchOne( + $property = $api->searchOne( 'properties', ['term' => 'dcterms:description'] )->getContent(); @@ -106,7 +107,7 @@ public function init() 'data-property-id' => $property->id(), 'data-type' => 'literal', 'data-property-id-default' => $property->id(), - 'data-property-label-default' => 'Description', // @translate + 'data-property-label-default' => $translate('Description'), ], ]); From feeb9d84118849a9bc957da3bd6dc6a3a306fd8a Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Tue, 16 Jul 2024 13:44:01 -0400 Subject: [PATCH 25/47] Continue dev --- application/asset/js/resource-form.js | 2 +- application/src/Form/ItemStubForm.php | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index a1270671a..2d361c1e4 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -427,7 +427,7 @@ const propertyValue = $(this); if (propertyValue.val()) { const propertyId = propertyValue.data('propertyId'); - const type = propertyValue.data('type'); + const type = propertyValue.data('type') ?? 'literal'; if (!itemData.hasOwnProperty(propertyId)) { itemData[propertyId] = []; } diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index 82c257519..a285f62e4 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -86,7 +86,6 @@ public function init() 'attributes' => [ 'id' => 'item-stub-title', 'data-property-id' => $property->id(), - 'data-type' => 'literal', 'data-property-id-default' => $property->id(), 'data-property-label-default' => $translate('Title'), ], @@ -105,7 +104,6 @@ public function init() 'attributes' => [ 'id' => 'item-stub-description', 'data-property-id' => $property->id(), - 'data-type' => 'literal', 'data-property-id-default' => $property->id(), 'data-property-label-default' => $translate('Description'), ], @@ -120,7 +118,10 @@ public function init() ], ]); - // Allow modules to modify this form. + // Allow modules to modify this form. Modules may add value elements by + // adding a "data-property-id" attribute to the element, set to the + // property ID. They may also add a "data-type" attribute to the element + // to set a data type that is not "literal". $addEvent = new Event('form.add_elements', $this); $this->getEventManager()->triggerEvent($addEvent); From 43b728026e21e87e884de36e0596523385d06ea9 Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Thu, 18 Jul 2024 16:04:32 -0400 Subject: [PATCH 26/47] Begin converting to template-based item stub form --- application/asset/js/resource-form.js | 9 +++ .../src/Controller/Admin/ItemController.php | 22 +++++++ application/src/Form/ItemStubForm.php | 62 +++++-------------- .../item/get-item-stub-property-values.phtml | 5 ++ .../omeka/admin/item/sidebar-select.phtml | 2 +- 5 files changed, 53 insertions(+), 47 deletions(-) create mode 100644 application/view/omeka/admin/item/get-item-stub-property-values.phtml diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index 2d361c1e4..8b9c21a74 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -397,6 +397,15 @@ $('#values-json').val(JSON.stringify(collectValues())); }); + /** ITEM STUB */ + + $('#select-resource').on('o:sidebar-content-loaded', function(e) { + const itemStubForm = $('#item-stub-form'); + $.post(itemStubForm.data('getItemStubPropertyValuesUrl'), function(data) { + console.log(data); + }); + }); + // Item stub form: handle "New item" nav click. $(document).on('click', '#item-stub-section-label', function(e) { $(this).closest('.section-nav').find('li').toggleClass('active'); diff --git a/application/src/Controller/Admin/ItemController.php b/application/src/Controller/Admin/ItemController.php index 0c8f70354..05fabd90c 100644 --- a/application/src/Controller/Admin/ItemController.php +++ b/application/src/Controller/Admin/ItemController.php @@ -238,6 +238,28 @@ public function addAction() return $view; } + public function getItemStubPropertyValuesAction() + { + $request = $this->getRequest(); + $response = $this->getResponse(); + if (!$request->isPost()) { + $response->setStatusCode(500); + return $response; + } + $postData = $this->params()->fromPost(); + $resourceTemplateId = $postData['resource_template_id'] ?? 0; + try { + $resourceTemplate = $this->api()->read('resource_templates', $resourceTemplateId)->getContent(); + } catch (\Omeka\Api\Exception\NotFoundException $e) { + $resourceTemplate = null; + } + + $view = new ViewModel; + $view->setTerminal(true); + $view->setVariable('resourceTemplate', $resourceTemplate); + return $view; + } + public function addItemStubAction() { $request = $this->getRequest(); diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index a285f62e4..4f303bb6e 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -27,16 +27,20 @@ public function init() 'admin/default', ['controller' => 'item', 'action' => 'add-item-stub'] )); - $this->setAttribute('data-resource-template-url', $url( - 'api/default', - ['resource' => 'resource_templates'] - )); - $this->setAttribute('data-property-url', $url( - 'api/default', - ['resource' => 'properties'] + $this->setAttribute('data-get-item-stub-property-values-url', $url( + 'admin/default', + ['controller' => 'item', 'action' => 'get-item-stub-property-values'] )); $this->add([ + 'type' => 'fieldset', + 'name' => 'fieldset-main', + 'attributes' => [ + 'id' => 'item-stub-fieldset-main' + ], + ]); + $fieldsetMain = $this->get('fieldset-main'); + $fieldsetMain->add([ 'type' => OmekaElement\ResourceSelect::class, 'name' => 'resource_template', 'options' => [ @@ -58,8 +62,7 @@ public function init() 'data-placeholder' => 'Select a template', // @translate ], ]); - - $this->add([ + $fieldsetMain->add([ 'type' => OmekaElement\ResourceClassSelect::class, 'name' => 'resource_class', 'options' => [ @@ -72,43 +75,13 @@ public function init() 'data-placeholder' => 'Select a class', // @translate ], ]); - - $property = $api->searchOne( - 'properties', - ['term' => 'dcterms:title'] - )->getContent(); - $this->add([ - 'type' => 'textarea', - 'name' => 'title', - 'options' => [ - 'label' => 'Title', // @translate - ], - 'attributes' => [ - 'id' => 'item-stub-title', - 'data-property-id' => $property->id(), - 'data-property-id-default' => $property->id(), - 'data-property-label-default' => $translate('Title'), - ], - ]); - - $property = $api->searchOne( - 'properties', - ['term' => 'dcterms:description'] - )->getContent(); $this->add([ - 'type' => 'textarea', - 'name' => 'description', - 'options' => [ - 'label' => 'Description', // @translate - ], + 'type' => 'fieldset', + 'name' => 'fieldset-property-values', 'attributes' => [ - 'id' => 'item-stub-description', - 'data-property-id' => $property->id(), - 'data-property-id-default' => $property->id(), - 'data-property-label-default' => $translate('Description'), + 'id' => 'item-stub-property-values' ], ]); - $this->add([ 'type' => 'submit', 'name' => 'submit', @@ -118,10 +91,7 @@ public function init() ], ]); - // Allow modules to modify this form. Modules may add value elements by - // adding a "data-property-id" attribute to the element, set to the - // property ID. They may also add a "data-type" attribute to the element - // to set a data type that is not "literal". + // Allow modules to modify this form. $addEvent = new Event('form.add_elements', $this); $this->getEventManager()->triggerEvent($addEvent); diff --git a/application/view/omeka/admin/item/get-item-stub-property-values.phtml b/application/view/omeka/admin/item/get-item-stub-property-values.phtml new file mode 100644 index 000000000..05ea31742 --- /dev/null +++ b/application/view/omeka/admin/item/get-item-stub-property-values.phtml @@ -0,0 +1,5 @@ + + + + + diff --git a/application/view/omeka/admin/item/sidebar-select.phtml b/application/view/omeka/admin/item/sidebar-select.phtml index b9e21934f..d5c71bd65 100644 --- a/application/view/omeka/admin/item/sidebar-select.phtml +++ b/application/view/omeka/admin/item/sidebar-select.phtml @@ -114,5 +114,5 @@ $expanded = $resourceClassId || $itemSetId || $id;
- form($itemStubForm, false); ?> + form($itemStubForm); ?>
From 1b61b17785a50cedacedb805f90eae7926c18a56 Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Fri, 19 Jul 2024 18:54:06 -0400 Subject: [PATCH 27/47] Continue dev --- application/asset/js/resource-form.js | 82 ++++--------------- .../src/Controller/Admin/ItemController.php | 2 +- application/src/Form/ItemStubForm.php | 8 +- application/src/View/Helper/DataType.php | 44 ++++++++++ .../common/value-annotation-wrapper.phtml | 4 +- .../admin/item/get-item-stub-fieldset.phtml | 1 + .../item/get-item-stub-property-values.phtml | 5 -- 7 files changed, 69 insertions(+), 77 deletions(-) create mode 100644 application/view/omeka/admin/item/get-item-stub-fieldset.phtml delete mode 100644 application/view/omeka/admin/item/get-item-stub-property-values.phtml diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index 8b9c21a74..da26d0482 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -397,29 +397,28 @@ $('#values-json').val(JSON.stringify(collectValues())); }); - /** ITEM STUB */ + /** ITEM STUB FORM */ $('#select-resource').on('o:sidebar-content-loaded', function(e) { const itemStubForm = $('#item-stub-form'); - $.post(itemStubForm.data('getItemStubPropertyValuesUrl'), function(data) { - console.log(data); + $.post(itemStubForm.data('getItemStubFieldsetUrl'), function(data) { + $('#item-stub-property-values').html(data); }); }); - - // Item stub form: handle "New item" nav click. + // Handle "New item" nav click. $(document).on('click', '#item-stub-section-label', function(e) { $(this).closest('.section-nav').find('li').toggleClass('active'); $('#item-section').hide(); $('#item-stub-section').show(); $('.chosen-select').chosen({allow_single_deselect: true}); }); - // Item stub form: handle "Existing item" nav click. + // Handle "Existing item" nav click. $(document).on('click', '#item-section-label', function(e) { $(this).closest('.section-nav').find('li').toggleClass('active'); $('#item-section').show(); $('#item-stub-section').hide(); }); - // Item stub form: handle item stub form submission. + // Handle item stub form submission. $(document).on('click', '#item-stub-submit', function(e) { e.preventDefault(); const itemStubForm = $('#item-stub-form'); @@ -432,21 +431,7 @@ if (resourceClass.val()) { itemData['o:resource_class'] = {'o:id': resourceClass.val()}; } - itemStubForm.find('[data-property-id]').each(function() { - const propertyValue = $(this); - if (propertyValue.val()) { - const propertyId = propertyValue.data('propertyId'); - const type = propertyValue.data('type') ?? 'literal'; - if (!itemData.hasOwnProperty(propertyId)) { - itemData[propertyId] = []; - } - itemData[propertyId].push({ - 'property_id': propertyId, - 'type': type, - '@value': propertyValue.val() - }); - } - }); + // @todo: Build the item data object. itemData['csrf'] = itemStubForm.find('input[name="csrf"]').val(); $.post(itemStubForm.data('submitUrl'), itemData, function(data) { const selectedResource = $('.selecting-resource').find('.selected-resource'); @@ -457,64 +442,27 @@ Omeka.closeSidebar($('#select-resource')); }); }); - // Item stub form: handle resource template change. + // Handle resource template change. $(document).on('change', '#item-stub-resource-template', function(e) { const itemStubForm = $('#item-stub-form'); const resourceTemplate = $('#item-stub-resource-template'); const resourceClass = $('#item-stub-resource-class'); - const title = $('#item-stub-title'); - const description = $('#item-stub-description'); const resourceTemplateUrl = itemStubForm.data('resourceTemplateUrl') + '/' + resourceTemplate.val(); - $.get(resourceTemplateUrl, function(resourceTemplateData) { - const templateResourceClass = resourceTemplateData['o:resource_class']; - const templateTitleProperty = resourceTemplateData['o:title_property']; - const templateDescriptionProperty = resourceTemplateData['o:description_property']; + $.get(resourceTemplateUrl, function(data) { + const templateResourceClass = data['o:resource_class']; if (templateResourceClass) { // Set the template-defined class. resourceClass.val(templateResourceClass['o:id']); resourceClass.trigger('chosen:updated'); } - if (templateTitleProperty) { - // Set the title defined by the template (including alt label). - const propertyUrl = itemStubForm.data('propertyUrl') + '/' + templateTitleProperty['o:id']; - $.get(propertyUrl, function(propertyData) { - let propertyLabel = propertyData['o:label']; - $.each(resourceTemplateData['o:resource_template_property'], function(key, value) { - if (value['o:property']['o:id'] === templateTitleProperty['o:id']) { - if (value['o:alternate_label']) propertyLabel = value['o:alternate_label']; - return false; - } - }); - title.data('propertyId', templateTitleProperty['o:id']); - title.closest('.field').find('[for="item-stub-title"]').text(propertyLabel); - }); - } else { - // Set the default title. - title.data('propertyId', title.data('propertyIdDefault')); - title.closest('.field').find('[for="item-stub-title"]').text(title.data('propertyLabelDefault')); - } - if (templateDescriptionProperty) { - // Set the description defined by the template (including alt label). - const propertyUrl = itemStubForm.data('propertyUrl') + '/' + templateDescriptionProperty['o:id']; - $.get(propertyUrl, function(propertyData) { - let propertyLabel = propertyData['o:label']; - $.each(resourceTemplateData['o:resource_template_property'], function(key, value) { - if (value['o:property']['o:id'] === templateDescriptionProperty['o:id']) { - if (value['o:alternate_label']) propertyLabel = value['o:alternate_label']; - return false; - } - }); - description.data('propertyId', templateDescriptionProperty['o:id']); - description.closest('.field').find('[for="item-stub-description"]').text(propertyLabel); - }); - } else { - // Set the default description. - description.data('propertyId', description.data('propertyIdDefault')); - description.closest('.field').find('[for="item-stub-description"]').text(description.data('propertyLabelDefault')); - } + }); + $.post(itemStubForm.data('getItemStubFieldsetUrl'), {resource_template_id: resourceTemplate.val()}, function(data) { + $('#item-stub-property-values').html(data); }); }); + /** END ITEM STUB FORM */ + initPage(); }); diff --git a/application/src/Controller/Admin/ItemController.php b/application/src/Controller/Admin/ItemController.php index 05fabd90c..bea7a09bc 100644 --- a/application/src/Controller/Admin/ItemController.php +++ b/application/src/Controller/Admin/ItemController.php @@ -238,7 +238,7 @@ public function addAction() return $view; } - public function getItemStubPropertyValuesAction() + public function getItemStubFieldsetAction() { $request = $this->getRequest(); $response = $this->getResponse(); diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index 4f303bb6e..178eee0f8 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -27,9 +27,13 @@ public function init() 'admin/default', ['controller' => 'item', 'action' => 'add-item-stub'] )); - $this->setAttribute('data-get-item-stub-property-values-url', $url( + $this->setAttribute('data-get-item-stub-fieldset-url', $url( 'admin/default', - ['controller' => 'item', 'action' => 'get-item-stub-property-values'] + ['controller' => 'item', 'action' => 'get-item-stub-fieldset'] + )); + $this->setAttribute('data-resource-template-url', $url( + 'api/default', + ['resource' => 'resource_templates'] )); $this->add([ diff --git a/application/src/View/Helper/DataType.php b/application/src/View/Helper/DataType.php index cd2a9bad7..5e25e722d 100644 --- a/application/src/View/Helper/DataType.php +++ b/application/src/View/Helper/DataType.php @@ -179,4 +179,48 @@ public function getValueAnnotationTemplates() } return $templates; } + + public function getItemStubFieldset($resourceTemplate = null) + { + $view = $this->getView(); + $form = []; + if ($resourceTemplate) { + // Build the form defined by the resource template. + foreach ($resourceTemplate->resourceTemplateProperties() as $rtProperty) { + $dataTypeNames = $rtProperty->dataTypes(); + if ($dataTypeNames) { + $dataTypeName = $dataTypeNames[0]; + if (in_array($dataTypeName, ['resource', 'resource:item', 'resource:itemset', 'resource:media', ])) { + // Set "resource" data types to "literal". + $dataTypeName = 'literal'; + } + $dataType = $this->manager->get($dataTypeName); + if (!($dataType instanceof ValueAnnotatingInterface)) { + // Set non-supported data types to "literal". + $dataType = $this->manager->get('literal'); + } + } else { + $dataType = $this->manager->get('literal'); + } + $property = $rtProperty->property(); + $form[] = $view->partial('common/value-annotation-wrapper', [ + 'dataType' => $dataType, + 'propertyId' => $property->id(), + 'propertyLabel' => $rtProperty->alternateLabel() ?? $property->label(), + ]); + } + } else { + // Build the default form. + $dataType = $this->manager->get('literal'); + foreach (['dcterms:title', 'dcterms:description'] as $propertyTerm) { + $property = $view->api()->searchOne('properties', ['term' => $propertyTerm])->getContent(); + $form[] = $view->partial('common/value-annotation-wrapper', [ + 'dataType' => $dataType, + 'propertyId' => $property->id(), + 'propertyLabel' => $property->label(), + ]); + } + } + return implode('', $form); + } } diff --git a/application/view/common/value-annotation-wrapper.phtml b/application/view/common/value-annotation-wrapper.phtml index e5b1dbf8a..2628db41c 100644 --- a/application/view/common/value-annotation-wrapper.phtml +++ b/application/view/common/value-annotation-wrapper.phtml @@ -2,7 +2,7 @@ $dataTypeName = (strpos('resource', $dataType->getName()) !== false) ? 'resource' : $dataType->getName(); ?>
-

+

valueAnnotationForm($this); ?>
diff --git a/application/view/omeka/admin/item/get-item-stub-fieldset.phtml b/application/view/omeka/admin/item/get-item-stub-fieldset.phtml new file mode 100644 index 000000000..1b1d423e0 --- /dev/null +++ b/application/view/omeka/admin/item/get-item-stub-fieldset.phtml @@ -0,0 +1 @@ +dataType()->getItemStubFieldset($resourceTemplate); ?> diff --git a/application/view/omeka/admin/item/get-item-stub-property-values.phtml b/application/view/omeka/admin/item/get-item-stub-property-values.phtml deleted file mode 100644 index 05ea31742..000000000 --- a/application/view/omeka/admin/item/get-item-stub-property-values.phtml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - From e2ef051ec0fa7d92e74e0c318e6234f0018fdc36 Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Fri, 19 Jul 2024 22:41:00 -0400 Subject: [PATCH 28/47] Continue dev --- application/asset/js/resource-form.js | 27 ++++++++---- .../src/Controller/Admin/ItemController.php | 22 ---------- application/src/Form/ItemStubForm.php | 4 -- application/src/View/Helper/DataType.php | 44 ------------------- .../admin/item/get-item-stub-fieldset.phtml | 1 - 5 files changed, 18 insertions(+), 80 deletions(-) delete mode 100644 application/view/omeka/admin/item/get-item-stub-fieldset.phtml diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index da26d0482..7da0ad925 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -401,9 +401,7 @@ $('#select-resource').on('o:sidebar-content-loaded', function(e) { const itemStubForm = $('#item-stub-form'); - $.post(itemStubForm.data('getItemStubFieldsetUrl'), function(data) { - $('#item-stub-property-values').html(data); - }); + // @todo: Set the default property values (title and description) }); // Handle "New item" nav click. $(document).on('click', '#item-stub-section-label', function(e) { @@ -447,17 +445,28 @@ const itemStubForm = $('#item-stub-form'); const resourceTemplate = $('#item-stub-resource-template'); const resourceClass = $('#item-stub-resource-class'); + const propertyValues = $('#item-stub-property-values'); const resourceTemplateUrl = itemStubForm.data('resourceTemplateUrl') + '/' + resourceTemplate.val(); - $.get(resourceTemplateUrl, function(data) { - const templateResourceClass = data['o:resource_class']; + $.get(resourceTemplateUrl, function(rtData) { + const templateResourceClass = rtData['o:resource_class']; + // Set the template-defined class. if (templateResourceClass) { - // Set the template-defined class. resourceClass.val(templateResourceClass['o:id']); resourceClass.trigger('chosen:updated'); } - }); - $.post(itemStubForm.data('getItemStubFieldsetUrl'), {resource_template_id: resourceTemplate.val()}, function(data) { - $('#item-stub-property-values').html(data); + // Set the proprerty values. + propertyValues.empty(); + $.each(rtData['o:resource_template_property'], function(index, rtProperty) { + let dataTypeName = rtProperty['o:data_type'][0]; + // // Set non-supported and "resource" data types to "literal". + if (dataTypeName === undefined || !(dataTypeName in vaTemplates) || ['resource', 'resource:item', 'resource:itemset', 'resource:media'].includes(dataTypeName)) { + dataTypeName = 'literal'; + } + const valueAnnotation = $($.parseHTML(vaTemplates[dataTypeName])); + // @todo: Hydrate the markup + $(document).trigger('o:prepare-value-annotation', [dataTypeName, valueAnnotation]); + propertyValues.append(valueAnnotation); + }); }); }); diff --git a/application/src/Controller/Admin/ItemController.php b/application/src/Controller/Admin/ItemController.php index bea7a09bc..0c8f70354 100644 --- a/application/src/Controller/Admin/ItemController.php +++ b/application/src/Controller/Admin/ItemController.php @@ -238,28 +238,6 @@ public function addAction() return $view; } - public function getItemStubFieldsetAction() - { - $request = $this->getRequest(); - $response = $this->getResponse(); - if (!$request->isPost()) { - $response->setStatusCode(500); - return $response; - } - $postData = $this->params()->fromPost(); - $resourceTemplateId = $postData['resource_template_id'] ?? 0; - try { - $resourceTemplate = $this->api()->read('resource_templates', $resourceTemplateId)->getContent(); - } catch (\Omeka\Api\Exception\NotFoundException $e) { - $resourceTemplate = null; - } - - $view = new ViewModel; - $view->setTerminal(true); - $view->setVariable('resourceTemplate', $resourceTemplate); - return $view; - } - public function addItemStubAction() { $request = $this->getRequest(); diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index 178eee0f8..da21b6705 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -27,10 +27,6 @@ public function init() 'admin/default', ['controller' => 'item', 'action' => 'add-item-stub'] )); - $this->setAttribute('data-get-item-stub-fieldset-url', $url( - 'admin/default', - ['controller' => 'item', 'action' => 'get-item-stub-fieldset'] - )); $this->setAttribute('data-resource-template-url', $url( 'api/default', ['resource' => 'resource_templates'] diff --git a/application/src/View/Helper/DataType.php b/application/src/View/Helper/DataType.php index 5e25e722d..cd2a9bad7 100644 --- a/application/src/View/Helper/DataType.php +++ b/application/src/View/Helper/DataType.php @@ -179,48 +179,4 @@ public function getValueAnnotationTemplates() } return $templates; } - - public function getItemStubFieldset($resourceTemplate = null) - { - $view = $this->getView(); - $form = []; - if ($resourceTemplate) { - // Build the form defined by the resource template. - foreach ($resourceTemplate->resourceTemplateProperties() as $rtProperty) { - $dataTypeNames = $rtProperty->dataTypes(); - if ($dataTypeNames) { - $dataTypeName = $dataTypeNames[0]; - if (in_array($dataTypeName, ['resource', 'resource:item', 'resource:itemset', 'resource:media', ])) { - // Set "resource" data types to "literal". - $dataTypeName = 'literal'; - } - $dataType = $this->manager->get($dataTypeName); - if (!($dataType instanceof ValueAnnotatingInterface)) { - // Set non-supported data types to "literal". - $dataType = $this->manager->get('literal'); - } - } else { - $dataType = $this->manager->get('literal'); - } - $property = $rtProperty->property(); - $form[] = $view->partial('common/value-annotation-wrapper', [ - 'dataType' => $dataType, - 'propertyId' => $property->id(), - 'propertyLabel' => $rtProperty->alternateLabel() ?? $property->label(), - ]); - } - } else { - // Build the default form. - $dataType = $this->manager->get('literal'); - foreach (['dcterms:title', 'dcterms:description'] as $propertyTerm) { - $property = $view->api()->searchOne('properties', ['term' => $propertyTerm])->getContent(); - $form[] = $view->partial('common/value-annotation-wrapper', [ - 'dataType' => $dataType, - 'propertyId' => $property->id(), - 'propertyLabel' => $property->label(), - ]); - } - } - return implode('', $form); - } } diff --git a/application/view/omeka/admin/item/get-item-stub-fieldset.phtml b/application/view/omeka/admin/item/get-item-stub-fieldset.phtml deleted file mode 100644 index 1b1d423e0..000000000 --- a/application/view/omeka/admin/item/get-item-stub-fieldset.phtml +++ /dev/null @@ -1 +0,0 @@ -dataType()->getItemStubFieldset($resourceTemplate); ?> From 4e7a5e1c35d694196d092d0c8900b56b434b12b6 Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Fri, 19 Jul 2024 22:45:12 -0400 Subject: [PATCH 29/47] Continue dev --- application/view/common/value-annotation-wrapper.phtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/application/view/common/value-annotation-wrapper.phtml b/application/view/common/value-annotation-wrapper.phtml index 2628db41c..e5b1dbf8a 100644 --- a/application/view/common/value-annotation-wrapper.phtml +++ b/application/view/common/value-annotation-wrapper.phtml @@ -2,7 +2,7 @@ $dataTypeName = (strpos('resource', $dataType->getName()) !== false) ? 'resource' : $dataType->getName(); ?>
-

+

valueAnnotationForm($this); ?>
From e459987ee8af58bf144c160ba4b18a7f4eeafc04 Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Sun, 21 Jul 2024 13:24:54 -0400 Subject: [PATCH 30/47] Continue dev --- application/asset/js/resource-form.js | 18 +++++++++++++++--- application/src/Form/ItemStubForm.php | 4 ++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index 7da0ad925..6b09fd32c 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -399,9 +399,21 @@ /** ITEM STUB FORM */ + // Handle building the initial item stub form. $('#select-resource').on('o:sidebar-content-loaded', function(e) { const itemStubForm = $('#item-stub-form'); - // @todo: Set the default property values (title and description) + const propertyValues = $('#item-stub-property-values'); + const properties = [ + itemStubForm.data('titleProperty'), + itemStubForm.data('descriptionProperty') + ]; + $.each(properties, function(key, property) { + const valueAnnotation = $($.parseHTML(vaTemplates['literal'])); + valueAnnotation.find('.value-annotation-heading').text(property['o:label']); + valueAnnotation.find('input.is_public').val('1'); + valueAnnotation.find('input.property_id').val(property['o:id']); + propertyValues.append(valueAnnotation); + }); }); // Handle "New item" nav click. $(document).on('click', '#item-stub-section-label', function(e) { @@ -458,12 +470,12 @@ propertyValues.empty(); $.each(rtData['o:resource_template_property'], function(index, rtProperty) { let dataTypeName = rtProperty['o:data_type'][0]; - // // Set non-supported and "resource" data types to "literal". + // Set non-supported and "resource" data types to "literal". if (dataTypeName === undefined || !(dataTypeName in vaTemplates) || ['resource', 'resource:item', 'resource:itemset', 'resource:media'].includes(dataTypeName)) { dataTypeName = 'literal'; } const valueAnnotation = $($.parseHTML(vaTemplates[dataTypeName])); - // @todo: Hydrate the markup + // @todo: Hydrate the markup (including alt label) $(document).trigger('o:prepare-value-annotation', [dataTypeName, valueAnnotation]); propertyValues.append(valueAnnotation); }); diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index da21b6705..5870dbe99 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -31,6 +31,10 @@ public function init() 'api/default', ['resource' => 'resource_templates'] )); + $titleProperty = $api->searchOne('properties', ['term' => 'dcterms:title'])->getContent(); + $this->setAttribute('data-title-property', json_encode($titleProperty)); + $descriptionProperty = $api->searchOne('properties', ['term' => 'dcterms:description'])->getContent(); + $this->setAttribute('data-description-property', json_encode($descriptionProperty)); $this->add([ 'type' => 'fieldset', From 8d6eb27f16747fd95050abb48f5d757e382e06e5 Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Mon, 22 Jul 2024 12:54:24 -0400 Subject: [PATCH 31/47] Continue dev --- application/asset/js/resource-form.js | 37 +++++++++++++++++++++++---- application/src/Form/ItemStubForm.php | 4 +-- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index 6b09fd32c..91fc7263e 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -435,14 +435,31 @@ const resourceTemplate = $('#item-stub-resource-template'); const resourceClass = $('#item-stub-resource-class'); const itemData = {}; + itemData['csrf'] = itemStubForm.find('input[name="csrf"]').val(); if (resourceTemplate.val()) { itemData['o:resource_template'] = {'o:id': resourceTemplate.val()}; } if (resourceClass.val()) { itemData['o:resource_class'] = {'o:id': resourceClass.val()}; } - // @todo: Build the item data object. - itemData['csrf'] = itemStubForm.find('input[name="csrf"]').val(); + // Build the property values. + $('#item-stub-property-values').children('.value-annotation').each(function() { + const valueAnnotation = $(this); + const value = valueAnnotation.find('[data-value-key="@value"]').val(); + if (value) { + const propertyId = valueAnnotation.find('input.property_id').val(); + const type = valueAnnotation.find('input.data_type').val(); + const isPublic = valueAnnotation.find('input.is_public').val(); + const language = valueAnnotation.find('[data-value-key="@language"]').val(); + itemData[propertyId] = [{ + 'type': type, + 'property_id': propertyId, + 'is_public': isPublic, + '@value': value, + '@language': language, + }]; + } + }); $.post(itemStubForm.data('submitUrl'), itemData, function(data) { const selectedResource = $('.selecting-resource').find('.selected-resource'); selectedResource.prev('span.default').hide(); @@ -466,16 +483,26 @@ resourceClass.val(templateResourceClass['o:id']); resourceClass.trigger('chosen:updated'); } - // Set the proprerty values. + // Get, hydrate, and append the property value markup. propertyValues.empty(); $.each(rtData['o:resource_template_property'], function(index, rtProperty) { let dataTypeName = rtProperty['o:data_type'][0]; // Set non-supported and "resource" data types to "literal". - if (dataTypeName === undefined || !(dataTypeName in vaTemplates) || ['resource', 'resource:item', 'resource:itemset', 'resource:media'].includes(dataTypeName)) { + if (dataTypeName === undefined + || !(dataTypeName in vaTemplates) + || ['resource', 'resource:item', 'resource:itemset', 'resource:media'].includes(dataTypeName) + ) { dataTypeName = 'literal'; } const valueAnnotation = $($.parseHTML(vaTemplates[dataTypeName])); - // @todo: Hydrate the markup (including alt label) + const propertyId = rtProperty['o:property']['o:id']; + // Account for an alternate label set by the resource template. + // Otherwise get the label from an existing property select. + const propertyLabel = rtProperty['o:alternate_label'] + ?? $('#value-annotation-property-select').find(`option[data-property-id="${propertyId}"]`).text(); + valueAnnotation.find('.value-annotation-heading').text(propertyLabel); + valueAnnotation.find('input.is_public').val('1'); + valueAnnotation.find('input.property_id').val(propertyId); $(document).trigger('o:prepare-value-annotation', [dataTypeName, valueAnnotation]); propertyValues.append(valueAnnotation); }); diff --git a/application/src/Form/ItemStubForm.php b/application/src/Form/ItemStubForm.php index 5870dbe99..f7e5280e3 100644 --- a/application/src/Form/ItemStubForm.php +++ b/application/src/Form/ItemStubForm.php @@ -100,12 +100,12 @@ public function init() $this->getEventManager()->triggerEvent($addEvent); $inputFilter = $this->getInputFilter(); - $inputFilter->add([ + $inputFilter->get('fieldset-main')->add([ 'name' => 'resource_template', 'required' => false, 'allow_empty' => true, ]); - $inputFilter->add([ + $inputFilter->get('fieldset-main')->add([ 'name' => 'resource_class', 'required' => false, 'allow_empty' => true, From 316c1d26cd4d0670c7cfbcc163a25f934a99664e Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Mon, 22 Jul 2024 21:00:05 -0400 Subject: [PATCH 32/47] Continue dev --- application/asset/js/resource-form.js | 153 +++++++++--------- .../src/Controller/Admin/ItemController.php | 2 +- 2 files changed, 74 insertions(+), 81 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index 91fc7263e..ac054790a 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -107,27 +107,7 @@ // Handle "Set annotations" click. vaSetButton.on('click', function(e) { e.preventDefault(); - const values = {}; - vaContainer.find('.value-annotation').each(function() { - const thisValueAnnotation = $(this); - if (thisValueAnnotation.data('removed')) { - // This annotation was flagged for removal. - return; - } - const value = {}; - // Map the the data-value-key attributes to the values object. - thisValueAnnotation.find(':input').each(function() { - const thisInput = $(this); - const valueKey = thisInput.data('valueKey'); - if (!valueKey) return; - value[valueKey] = thisInput.val(); - }); - const propertyTerm = thisValueAnnotation.find('.property_term').val(); - if (!values.hasOwnProperty(propertyTerm)) { - values[propertyTerm] = []; - } - values[propertyTerm].push(value); - }); + const values = collectValueAnnotationValues(vaContainer); annotatingValue.data('valueAnnotations', values); Omeka.closeSidebar(vaSidebar); }); @@ -399,22 +379,6 @@ /** ITEM STUB FORM */ - // Handle building the initial item stub form. - $('#select-resource').on('o:sidebar-content-loaded', function(e) { - const itemStubForm = $('#item-stub-form'); - const propertyValues = $('#item-stub-property-values'); - const properties = [ - itemStubForm.data('titleProperty'), - itemStubForm.data('descriptionProperty') - ]; - $.each(properties, function(key, property) { - const valueAnnotation = $($.parseHTML(vaTemplates['literal'])); - valueAnnotation.find('.value-annotation-heading').text(property['o:label']); - valueAnnotation.find('input.is_public').val('1'); - valueAnnotation.find('input.property_id').val(property['o:id']); - propertyValues.append(valueAnnotation); - }); - }); // Handle "New item" nav click. $(document).on('click', '#item-stub-section-label', function(e) { $(this).closest('.section-nav').find('li').toggleClass('active'); @@ -428,45 +392,21 @@ $('#item-section').show(); $('#item-stub-section').hide(); }); - // Handle item stub form submission. - $(document).on('click', '#item-stub-submit', function(e) { - e.preventDefault(); + // Handle building the initial item stub form. + $('#select-resource').on('o:sidebar-content-loaded', function(e) { const itemStubForm = $('#item-stub-form'); - const resourceTemplate = $('#item-stub-resource-template'); - const resourceClass = $('#item-stub-resource-class'); - const itemData = {}; - itemData['csrf'] = itemStubForm.find('input[name="csrf"]').val(); - if (resourceTemplate.val()) { - itemData['o:resource_template'] = {'o:id': resourceTemplate.val()}; - } - if (resourceClass.val()) { - itemData['o:resource_class'] = {'o:id': resourceClass.val()}; - } - // Build the property values. - $('#item-stub-property-values').children('.value-annotation').each(function() { - const valueAnnotation = $(this); - const value = valueAnnotation.find('[data-value-key="@value"]').val(); - if (value) { - const propertyId = valueAnnotation.find('input.property_id').val(); - const type = valueAnnotation.find('input.data_type').val(); - const isPublic = valueAnnotation.find('input.is_public').val(); - const language = valueAnnotation.find('[data-value-key="@language"]').val(); - itemData[propertyId] = [{ - 'type': type, - 'property_id': propertyId, - 'is_public': isPublic, - '@value': value, - '@language': language, - }]; - } - }); - $.post(itemStubForm.data('submitUrl'), itemData, function(data) { - const selectedResource = $('.selecting-resource').find('.selected-resource'); - selectedResource.prev('span.default').hide(); - const a = $('
', {href: data['admin_url']}).text(data['display_title']); - selectedResource.find('.o-title').removeClass().addClass('o-title items').html(a); - selectedResource.find('.value').val(data['o:id']); - Omeka.closeSidebar($('#select-resource')); + const propertyValues = $('#item-stub-property-values'); + const properties = { + 'dcterms:title': itemStubForm.data('titleProperty'), + 'dcterms:description': itemStubForm.data('descriptionProperty') + }; + $.each(properties, function(key, property) { + const valueAnnotation = $($.parseHTML(vaTemplates['literal'])); + valueAnnotation.find('.value-annotation-heading').text(property['o:label']); + valueAnnotation.find('input.is_public').val('1'); + valueAnnotation.find('input.property_id').val(property['o:id']); + valueAnnotation.find('input.property_term').val(key); + propertyValues.append(valueAnnotation); }); }); // Handle resource template change. @@ -494,20 +434,48 @@ ) { dataTypeName = 'literal'; } - const valueAnnotation = $($.parseHTML(vaTemplates[dataTypeName])); + // Hydrate the property values. Get property data (term and + // label) from an existing property select. We account for an + // alternate label set by the resource template. const propertyId = rtProperty['o:property']['o:id']; - // Account for an alternate label set by the resource template. - // Otherwise get the label from an existing property select. - const propertyLabel = rtProperty['o:alternate_label'] - ?? $('#value-annotation-property-select').find(`option[data-property-id="${propertyId}"]`).text(); + const property = $('#value-annotation-property-select').find(`option[data-property-id="${propertyId}"]`); + const propertyTerm = property.data('term'); + const propertyLabel = rtProperty['o:alternate_label'] ?? property.text(); + const valueAnnotation = $($.parseHTML(vaTemplates[dataTypeName])); valueAnnotation.find('.value-annotation-heading').text(propertyLabel); valueAnnotation.find('input.is_public').val('1'); valueAnnotation.find('input.property_id').val(propertyId); + valueAnnotation.find('input.property_term').val(propertyTerm); $(document).trigger('o:prepare-value-annotation', [dataTypeName, valueAnnotation]); propertyValues.append(valueAnnotation); }); }); }); + // Handle item stub form submission. + $(document).on('click', '#item-stub-submit', function(e) { + e.preventDefault(); + const itemStubForm = $('#item-stub-form'); + const resourceTemplate = $('#item-stub-resource-template'); + const resourceClass = $('#item-stub-resource-class'); + const itemData = {}; + itemData['csrf'] = itemStubForm.find('input[name="csrf"]').val(); + if (resourceTemplate.val()) { + itemData['o:resource_template'] = {'o:id': resourceTemplate.val()}; + } + if (resourceClass.val()) { + itemData['o:resource_class'] = {'o:id': resourceClass.val()}; + } + // Collect the property values, create the item, and populate the field. + const values = collectValueAnnotationValues($('#item-stub-property-values')); + $.post(itemStubForm.data('submitUrl'), {...itemData, ...values}, function(data) { + const selectedResource = $('.selecting-resource').find('.selected-resource'); + selectedResource.prev('span.default').hide(); + const a = $('', {href: data['admin_url']}).text(data['display_title']); + selectedResource.find('.o-title').removeClass().addClass('o-title items').html(a); + selectedResource.find('.value').val(data['o:id']); + Omeka.closeSidebar($('#select-resource')); + }); + }); /** END ITEM STUB FORM */ @@ -548,6 +516,31 @@ return values; }; + var collectValueAnnotationValues = function (vaContainer) { + const values = {}; + vaContainer.find('.value-annotation').each(function() { + const thisValueAnnotation = $(this); + if (thisValueAnnotation.data('removed')) { + // This annotation was flagged for removal. + return; + } + const value = {}; + // Map the the data-value-key attributes to the values object. + thisValueAnnotation.find(':input').each(function() { + const thisInput = $(this); + const valueKey = thisInput.data('valueKey'); + if (!valueKey) return; + value[valueKey] = thisInput.val(); + }); + const propertyTerm = thisValueAnnotation.find('.property_term').val(); + if (!values.hasOwnProperty(propertyTerm)) { + values[propertyTerm] = []; + } + values[propertyTerm].push(value); + }); + return values; + }; + /** * Make a new value. */ diff --git a/application/src/Controller/Admin/ItemController.php b/application/src/Controller/Admin/ItemController.php index 0c8f70354..c8a63dd64 100644 --- a/application/src/Controller/Admin/ItemController.php +++ b/application/src/Controller/Admin/ItemController.php @@ -253,7 +253,7 @@ public function addItemStubAction() $response->setStatusCode(500); return $response; } - $item = $this->api()->create('items', $itemData)->getContent(); + $item = $this->api(null, true)->create('items', $itemData)->getContent(); $itemJson = json_decode(json_encode($item), true); $itemJson['admin_url'] = $this->url()->fromRoute('admin/id', ['action' => 'show', 'id' => $item->id()], true); $itemJson['display_title'] = $item->displayTitle(); From bfc19a547ddcb1e720b1d02de79baefec2c3b925 Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Mon, 22 Jul 2024 21:29:35 -0400 Subject: [PATCH 33/47] Continue dev --- application/asset/js/resource-form.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index ac054790a..ed10ed97a 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -465,16 +465,20 @@ if (resourceClass.val()) { itemData['o:resource_class'] = {'o:id': resourceClass.val()}; } - // Collect the property values, create the item, and populate the field. + // Collect property values, create the item, and populate the field. const values = collectValueAnnotationValues($('#item-stub-property-values')); - $.post(itemStubForm.data('submitUrl'), {...itemData, ...values}, function(data) { - const selectedResource = $('.selecting-resource').find('.selected-resource'); - selectedResource.prev('span.default').hide(); - const a = $('', {href: data['admin_url']}).text(data['display_title']); - selectedResource.find('.o-title').removeClass().addClass('o-title items').html(a); - selectedResource.find('.value').val(data['o:id']); - Omeka.closeSidebar($('#select-resource')); - }); + $.post(itemStubForm.data('submitUrl'), {...itemData, ...values}) + .done(function(data) { + const selectedResource = $('.selecting-resource').find('.selected-resource'); + selectedResource.prev('span.default').hide(); + const a = $('', {href: data['admin_url']}).text(data['display_title']); + selectedResource.find('.o-title').removeClass().addClass('o-title items').html(a); + selectedResource.find('.value').val(data['o:id']); + Omeka.closeSidebar($('#select-resource')); + }) + .fail(function(data) { + Omeka.closeSidebar($('#select-resource')); + }); }); /** END ITEM STUB FORM */ From 8f731e1f0c692535fb57b47220ee53348fa52c7b Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Tue, 23 Jul 2024 14:27:12 -0400 Subject: [PATCH 34/47] Continue dev --- application/asset/js/resource-form.js | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index ed10ed97a..5255c899d 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -446,6 +446,9 @@ valueAnnotation.find('input.is_public').val('1'); valueAnnotation.find('input.property_id').val(propertyId); valueAnnotation.find('input.property_term').val(propertyTerm); + if (rtProperty['o:is_required']) { + valueAnnotation.addClass('required'); + } $(document).trigger('o:prepare-value-annotation', [dataTypeName, valueAnnotation]); propertyValues.append(valueAnnotation); }); @@ -465,8 +468,22 @@ if (resourceClass.val()) { itemData['o:resource_class'] = {'o:id': resourceClass.val()}; } - // Collect property values, create the item, and populate the field. - const values = collectValueAnnotationValues($('#item-stub-property-values')); + // Validate the values according to the required flag. + const propertyValues = $('#item-stub-property-values'); + let hasError = false; + propertyValues.children('.value-annotation').each(function(key, value) { + const valueAnnotation = $(this); + const valueInput = valueAnnotation.find('[data-value-key="@value"]'); + if (valueAnnotation.hasClass('required') && !valueInput.val()) { + valueInput[0].setCustomValidity('This value is required'); + valueInput[0].reportValidity(); + hasError = true; + return false; + } + }); + if (hasError) return; + // Collect values, create the item, and populate the field. + const values = collectValueAnnotationValues(propertyValues); $.post(itemStubForm.data('submitUrl'), {...itemData, ...values}) .done(function(data) { const selectedResource = $('.selecting-resource').find('.selected-resource'); From 121ef5dfdca50e2ea7751f5e5fdf4679ef9c6c0f Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Tue, 23 Jul 2024 21:01:32 -0400 Subject: [PATCH 35/47] Continue dev --- application/asset/js/resource-form.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index 5255c899d..6f7e9f67a 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -443,9 +443,15 @@ const propertyLabel = rtProperty['o:alternate_label'] ?? property.text(); const valueAnnotation = $($.parseHTML(vaTemplates[dataTypeName])); valueAnnotation.find('.value-annotation-heading').text(propertyLabel); - valueAnnotation.find('input.is_public').val('1'); valueAnnotation.find('input.property_id').val(propertyId); valueAnnotation.find('input.property_term').val(propertyTerm); + valueAnnotation.find('input.is_public').val(rtProperty['o:is_private'] ? '0' : '1'); + if (rtProperty['o:is_private']) { + valueAnnotation.find('input.is_public').val('0'); + valueAnnotation.find('.value-annotation-visibility').removeClass('o-icon-public').addClass('o-icon-private'); + } else { + valueAnnotation.find('input.is_public').val('1'); + } if (rtProperty['o:is_required']) { valueAnnotation.addClass('required'); } From 76dba5046456d13740f31d1631fe148955c68c7d Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Tue, 23 Jul 2024 22:08:13 -0400 Subject: [PATCH 36/47] Continue dev --- application/asset/js/resource-form.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index 6f7e9f67a..c1b4089ef 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -400,12 +400,12 @@ 'dcterms:title': itemStubForm.data('titleProperty'), 'dcterms:description': itemStubForm.data('descriptionProperty') }; - $.each(properties, function(key, property) { + $.each(properties, function(term, property) { const valueAnnotation = $($.parseHTML(vaTemplates['literal'])); valueAnnotation.find('.value-annotation-heading').text(property['o:label']); - valueAnnotation.find('input.is_public').val('1'); valueAnnotation.find('input.property_id').val(property['o:id']); - valueAnnotation.find('input.property_term').val(key); + valueAnnotation.find('input.property_term').val(term); + valueAnnotation.find('input.is_public').val('1'); propertyValues.append(valueAnnotation); }); }); @@ -445,7 +445,6 @@ valueAnnotation.find('.value-annotation-heading').text(propertyLabel); valueAnnotation.find('input.property_id').val(propertyId); valueAnnotation.find('input.property_term').val(propertyTerm); - valueAnnotation.find('input.is_public').val(rtProperty['o:is_private'] ? '0' : '1'); if (rtProperty['o:is_private']) { valueAnnotation.find('input.is_public').val('0'); valueAnnotation.find('.value-annotation-visibility').removeClass('o-icon-public').addClass('o-icon-private'); @@ -466,6 +465,7 @@ const itemStubForm = $('#item-stub-form'); const resourceTemplate = $('#item-stub-resource-template'); const resourceClass = $('#item-stub-resource-class'); + // Build the item data. const itemData = {}; itemData['csrf'] = itemStubForm.find('input[name="csrf"]').val(); if (resourceTemplate.val()) { @@ -481,7 +481,7 @@ const valueAnnotation = $(this); const valueInput = valueAnnotation.find('[data-value-key="@value"]'); if (valueAnnotation.hasClass('required') && !valueInput.val()) { - valueInput[0].setCustomValidity('This value is required'); + valueInput[0].setCustomValidity(Omeka.jsTranslate('Required field must be completed')); valueInput[0].reportValidity(); hasError = true; return false; @@ -500,6 +500,7 @@ Omeka.closeSidebar($('#select-resource')); }) .fail(function(data) { + alert(Omeka.jsTranslate('Something went wrong')); Omeka.closeSidebar($('#select-resource')); }); }); From 74d38ba733e804653c888970c9c5b8013d6bdab9 Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Wed, 24 Jul 2024 10:47:53 -0400 Subject: [PATCH 37/47] Continue dev --- application/asset/js/resource-form.js | 12 +++++++++++- .../view/common/value-annotation-wrapper.phtml | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index c1b4089ef..af0019d1a 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -147,7 +147,17 @@ e.preventDefault(); const thisVisibilityIcon = $(this); const isPublicInput = thisVisibilityIcon.closest('.value').find('input.is_public'); - isPublicInput.val(thisVisibilityIcon.hasClass('o-icon-public') ? 1 : 0); + if (thisVisibilityIcon.hasClass('o-icon-public')) { + thisVisibilityIcon + .attr('title', Omeka.jsTranslate('Make private')) + .attr('aria-label', Omeka.jsTranslate('Make private')); + isPublicInput.val('1'); + } else { + thisVisibilityIcon + .attr('title', Omeka.jsTranslate('Make public')) + .attr('aria-label', Omeka.jsTranslate('Make public')); + isPublicInput.val('0'); + } }); // Select property diff --git a/application/view/common/value-annotation-wrapper.phtml b/application/view/common/value-annotation-wrapper.phtml index e5b1dbf8a..03c67f695 100644 --- a/application/view/common/value-annotation-wrapper.phtml +++ b/application/view/common/value-annotation-wrapper.phtml @@ -10,7 +10,7 @@ $dataTypeName = (strpos('resource', $dataType->getName()) !== false) ? 'resource
  • hyperlink('', '#', ['class' => 'o-icon-delete value-annotation-remove', 'title' => $this->translate('Remove value'), 'aria-label' => $this->translate('Remove value')]); ?>
  • hyperlink('', '#', ['class' => 'o-icon-undo value-annotation-restore', 'title' => $this->translate('Restore value'), 'aria-label' => $this->translate('Restore value'), 'style' => 'display: none;']); ?>
  • -
  • hyperlink('', '#', ['class' => 'o-icon-public value-annotation-visibility', 'title' => $this->translate('Make public'), 'aria-label' => $this->translate('Make public')]); ?>
  • +
  • hyperlink('', '#', ['class' => 'o-icon-public value-annotation-visibility', 'title' => $this->translate('Make private'), 'aria-label' => $this->translate('Make private')]); ?>
From 33356f8281fd9f9445f181ae8d0047b3871b518a Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Wed, 24 Jul 2024 11:36:08 -0400 Subject: [PATCH 38/47] Continue dev --- application/asset/js/resource-form.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index af0019d1a..8a7aee9ea 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -405,6 +405,9 @@ // Handle building the initial item stub form. $('#select-resource').on('o:sidebar-content-loaded', function(e) { const itemStubForm = $('#item-stub-form'); + if (!itemStubForm.length) { + return; // Build the form only when needed. + } const propertyValues = $('#item-stub-property-values'); const properties = { 'dcterms:title': itemStubForm.data('titleProperty'), From 3a26c0b245bb3917d1843185a64e2a40420ed8f9 Mon Sep 17 00:00:00 2001 From: Jim Safley Date: Wed, 24 Jul 2024 14:12:56 -0400 Subject: [PATCH 39/47] Continue dev --- application/asset/js/resource-form.js | 20 ++++++++----------- .../omeka/admin/item/sidebar-select.phtml | 14 +++++++------ 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/application/asset/js/resource-form.js b/application/asset/js/resource-form.js index 8a7aee9ea..707269d0b 100644 --- a/application/asset/js/resource-form.js +++ b/application/asset/js/resource-form.js @@ -389,18 +389,14 @@ /** ITEM STUB FORM */ - // Handle "New item" nav click. - $(document).on('click', '#item-stub-section-label', function(e) { - $(this).closest('.section-nav').find('li').toggleClass('active'); - $('#item-section').hide(); - $('#item-stub-section').show(); - $('.chosen-select').chosen({allow_single_deselect: true}); - }); - // Handle "Existing item" nav click. - $(document).on('click', '#item-section-label', function(e) { - $(this).closest('.section-nav').find('li').toggleClass('active'); - $('#item-section').show(); - $('#item-stub-section').hide(); + $(document).on('click', '.sidebar-section-nav button', function(e) { + const thisButton = $(this); + // Set "active" status on nav list items. + thisButton.closest('.sidebar-section-nav').find('li').removeClass('active'); + thisButton.closest('li').addClass('active'); + // Set "active" status on sections. + $('.sidebar-section').removeClass('active'); + $(`#${thisButton.data('id')}`).addClass('active'); }); // Handle building the initial item stub form. $('#select-resource').on('o:sidebar-content-loaded', function(e) { diff --git a/application/view/omeka/admin/item/sidebar-select.phtml b/application/view/omeka/admin/item/sidebar-select.phtml index d5c71bd65..71d15b768 100644 --- a/application/view/omeka/admin/item/sidebar-select.phtml +++ b/application/view/omeka/admin/item/sidebar-select.phtml @@ -6,12 +6,14 @@ $itemsFound = count($items) > 0; $expanded = $resourceClassId || $itemSetId || $id; ?> -sectionNav([ - 'item-section' => $translate('Existing item'), - 'item-stub-section' => $translate('New item'), -]); ?> + -
+