From 81262335535272cd495e01cd239a8f97b8f7c1ee Mon Sep 17 00:00:00 2001 From: Benjamin Dalsass Date: Tue, 5 Sep 2023 15:12:48 +0200 Subject: [PATCH] poc form SDK (extends to form) --- js/DI/collection.js | 78 ++++++++++++++++++- js/DI/form.js | 6 +- sources/DI/Controller/ObjectController.php | 70 ++++++++++++++--- sources/DI/Form/Builder/AttributeBuilder.php | 5 +- .../DI/Form/Listener/ObjectFormListener.php | 5 +- .../Form/Type/Attribute/ExternalKeyType.php | 7 +- .../DI/Form/Type/Attribute/LinkSetType.php | 1 + sources/DI/Form/Type/Compound/ObjectType.php | 10 +-- .../DI/Services/ObjectPresentationService.php | 7 +- templates/DI/base.html.twig | 18 +++-- templates/DI/form/classic_theme.html.twig | 2 +- templates/DI/object/edit.html.twig | 4 +- 12 files changed, 171 insertions(+), 42 deletions(-) diff --git a/js/DI/collection.js b/js/DI/collection.js index 06b4d45f1..b6dd117d9 100644 --- a/js/DI/collection.js +++ b/js/DI/collection.js @@ -3,10 +3,11 @@ * * @param oForm * @param objectFormUrl + * @param objectSaveUrl * @returns {{handleElement: handleElement}} * @constructor */ -const Collection = function(oForm, objectFormUrl){ +const Collection = function(oForm, objectFormUrl, objectSaveUrl){ /** * Listen for add item buttons. @@ -101,9 +102,13 @@ const Collection = function(oForm, objectFormUrl){ */ function createObject(e){ + let objectId = e.currentTarget.closest('form').dataset.objectId; + // set modal loading state $('#object_modal .modal-body').html('loading...'); + const cont = e.currentTarget.closest('.link_set_widget_container'); + // open modal const myModalAlternative = new bootstrap.Modal('#object_modal', []); myModalAlternative.show(); @@ -115,14 +120,15 @@ const Collection = function(oForm, objectFormUrl){ // prepare request data const aLockedAttributes = {}; - aLockedAttributes[e.currentTarget.dataset.extKeyToMe] = 0; + aLockedAttributes[e.currentTarget.dataset.extKeyToMe] = objectId; const aData = { - locked_attributes: aLockedAttributes + locked_attributes: aLockedAttributes, + att_code: cont.dataset.attCode } // fetch url fetch(url, { - method: 'post', + method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' @@ -154,6 +160,70 @@ const Collection = function(oForm, objectFormUrl){ listenRemoveItem(oContainer); } + + function listenSaveModalobject(){ + const oSave = document.querySelector('[data-action="save_modal_object"]'); + + oSave.addEventListener('click', function(e){ + + const oForm = document.querySelector('form[name="new"]'); + + + for(let instanceName in CKEDITOR.instances) { + + CKEDITOR.instances[instanceName].updateElement(); + } + + const data = new URLSearchParams(); + for (const pair of new FormData(oForm)) { + + console.log(pair[0] + ' = ' + pair[1]); + + data.append(pair[0], pair[1]); + } + data.append('locked_attributes', ''); + + // compute object form url + const url = objectSaveUrl + .replaceAll('object_class', oForm.dataset.objectClass) + .replaceAll('form_name', 'new'); + + // fetch url + fetch(url, { + method: 'POST', + body: new URLSearchParams(new FormData(oForm)) + }) + .then((response) => response.json()) + .then((data) => { + + let form = $(data.template); + + console.log(form); + // + // console.log(oForm.dataset.attCode); + // + // const fragment = oToolkit.createElementFromHtml(data.template); + // const inner = fragment.querySelector('form').innerHTML; + // const el = oToolkit.createElementFromHtml(inner); + // console.log(el); + // + // const myModalAlternative = new bootstrap.Modal('#object_modal', []); + // myModalAlternative.hide(); + + console.log($(`[data-att-code="${oForm.dataset.attCode}"] tbody`)); + + $(`[data-att-code="${oForm.dataset.attCode}"] tbody`).append($(form.innerHTML)); + + }) + .catch(function (error) { + + console.error(error); + }); + }); + } + + listenSaveModalobject(); + return { handleElement } diff --git a/js/DI/form.js b/js/DI/form.js index e86f8d778..6f9867999 100644 --- a/js/DI/form.js +++ b/js/DI/form.js @@ -91,6 +91,8 @@ const Form = function(oWidget, oDynamic){ }); }); + const aAllAttCodes = aDependentAttCodes.concat(aDependenciesAttCodes); + ///////////////////////////////// // II - PREPARE RELOAD REQUEST @@ -99,7 +101,7 @@ const Form = function(oWidget, oDynamic){ let $bFirst = true; // iterate throw dependencies... - aDependenciesAttCodes.forEach(function(sAtt) { + aAllAttCodes.forEach(function(sAtt) { const oDependsOnElement = oElement.querySelector(String.format(aSelectors.dataAttCode, sAtt)); if(!$bFirst){ @@ -110,7 +112,7 @@ const Form = function(oWidget, oDynamic){ }); sRequestBody += '&att_codes=' + aDependentAttCodes.join(','); - sRequestBody += '&dependency_att_codes=' + aDependenciesAttCodes.join(','); + sRequestBody += '&dependency_att_codes=' + aAllAttCodes.join(','); ///////////////////////////////// // III - UPDATE THE FORM diff --git a/sources/DI/Controller/ObjectController.php b/sources/DI/Controller/ObjectController.php index 6770b74a7..bdb97e705 100644 --- a/sources/DI/Controller/ObjectController.php +++ b/sources/DI/Controller/ObjectController.php @@ -142,6 +142,11 @@ class ObjectController extends AbstractController // decode data $aData = json_decode($request->getContent(), true); + // locked attributes + foreach($aData['locked_attributes'] as $sKey => $sValue){ + $oObject->Set($sKey, $sValue); + } + // create object form $oForm = $oFormFactory->createNamed($name, ObjectType::class, $oObject, [ 'object_class' => $class, @@ -150,10 +155,40 @@ class ObjectController extends AbstractController 'data-reload-url' => $this->generateUrl('object_reload', [ 'class' => $class, 'id' => $id - ]) + ]), + 'data-object-class' => $class, + 'data-att-code' => $aData['att_code'] ] ]); + // return object form + return new JsonResponse([ + 'template' => $this->renderView('DI/form.html.twig', [ + 'id' => $id, + 'class' => $class, + 'form' => $oForm->createView(), + ]) + ]); + } + + /** + * @Route("/{class<\w+>}/{id<\d+>}/{name<\w+>}/save", name="object_save", methods={"POST"}) + */ + public function objectSave(Request $request, string $name, string $class, int $id, ObjectService $oObjectService, FormFactoryInterface $oFormFactory) : Response + { + // retrieve object + try{ + $oObject = $oObjectService->getObject($class, $id); + } + catch(Exception $e){ + throw $this->createNotFoundException("The $class $id does not exist"); + } + + // create object form + $oForm = $oFormFactory->createNamed($name, ObjectType::class, $oObject, [ + 'object_class' => $class, + ]); + // handle HTTP request $oForm->handleRequest($request); @@ -161,18 +196,32 @@ class ObjectController extends AbstractController if ($oForm->isSubmitted() && $oForm->isValid()) { try { - // handle link set (apply DbInsert, DbDelete, DbUpdate) could be automatic ? - $oObjectService->handleLinkSetDB($oObject); - // save object - $oObject->DBUpdate(); + if($id === 0){ + $id = $oObject->DBInsert(); + } + else{ + $oObject->DBUpdate(); + } } catch(Exception $e){ throw new HttpException(500, 'Error while trying to save object'); } - // redirect to view object - return new JsonResponse(); + // create object form + $oForm = $oFormFactory->createNamed($name, ObjectType::class, $oObject, [ + 'object_class' => $class, + 'z_list' => 'list' + ]); + + // return object form + return new JsonResponse([ + 'template' => $this->renderView('DI/form.html.twig', [ + 'id' => $id, + 'class' => $class, + 'form' => $oForm->createView(), + ]) + ]); } // return object form @@ -198,10 +247,13 @@ class ObjectController extends AbstractController throw $this->createNotFoundException("The $class $id does not exist"); } + $aDependencyAttCodes = explode(',', $request->get('dependency_att_codes')); + $aAttCodes = explode(',', $request->get('att_codes')); + // create form with request data (dependent field) $oForm = $this->createForm(PartialObjectType::class, $oObject, [ 'object_class' => $class, - 'att_codes' => explode(',', $request->get('dependency_att_codes')) + 'att_codes' => array_merge($aDependencyAttCodes, $aAttCodes) ]); // handle form data @@ -213,7 +265,7 @@ class ObjectController extends AbstractController // create a new form for affected field with updated (but not persist) data $oForm = $this->createForm(PartialObjectType::class, $oObject, [ 'object_class' => $class, - 'att_codes' => explode(',', $request->get('att_codes')) + 'att_codes' => $aAttCodes ]); // return object form diff --git a/sources/DI/Form/Builder/AttributeBuilder.php b/sources/DI/Form/Builder/AttributeBuilder.php index 4e4637c18..f44aa4aa1 100644 --- a/sources/DI/Form/Builder/AttributeBuilder.php +++ b/sources/DI/Form/Builder/AttributeBuilder.php @@ -79,7 +79,7 @@ class AttributeBuilder 'required' => !$oAttributeDefinition->IsNullAllowed(), 'disabled' => !$oAttributeDefinition->IsWritable() || $bIsLocked, 'attr' => [ - 'data-att-code' => $sCode + 'data-att-code' => $sCode, ], 'row_attr' => [ 'data-block' => 'container' @@ -87,7 +87,8 @@ class AttributeBuilder 'label_attr' => [ 'class' => $bIsLocked ? 'locked' : '' ] - ] + ], + 'create_hidden' => $bIsLocked ]; // register dependencies diff --git a/sources/DI/Form/Listener/ObjectFormListener.php b/sources/DI/Form/Listener/ObjectFormListener.php index 90ff17433..cdc7bf04b 100644 --- a/sources/DI/Form/Listener/ObjectFormListener.php +++ b/sources/DI/Form/Listener/ObjectFormListener.php @@ -191,9 +191,10 @@ class ObjectFormListener implements EventSubscriberInterface $aOptions['disabled'] = true; } - // ignore fields hidden + // ignore fields hidden ISSUE WITH LINKSET PRESENTATION if ($iFlags & (OPT_ATT_HIDDEN)) { - return null; +// $aOptions['attr']['class'] = 'd-none'; +// return null; } return $aOptions; diff --git a/sources/DI/Form/Type/Attribute/ExternalKeyType.php b/sources/DI/Form/Type/Attribute/ExternalKeyType.php index 01881e105..9d963e549 100644 --- a/sources/DI/Form/Type/Attribute/ExternalKeyType.php +++ b/sources/DI/Form/Type/Attribute/ExternalKeyType.php @@ -63,8 +63,11 @@ class ExternalKeyType extends AbstractType implements IFormTypeOptionModifier } // !!! ensure current value is part of result - $object = MetaModel::GetObject($aInitialOptions['object_class'], $iVal); - $aInitialOptions['choices'][$object->GetName()] = $iVal; + if($iVal > 0){ + $object = MetaModel::GetObject($aInitialOptions['object_class'], $iVal); + $aInitialOptions['choices'][$object->GetName()] = $iVal; + } + } catch(Exception $e){ diff --git a/sources/DI/Form/Type/Attribute/LinkSetType.php b/sources/DI/Form/Type/Attribute/LinkSetType.php index f3658bca9..be4cb060d 100644 --- a/sources/DI/Form/Type/Attribute/LinkSetType.php +++ b/sources/DI/Form/Type/Attribute/LinkSetType.php @@ -57,6 +57,7 @@ class LinkSetType extends AbstractType $view->vars['labels'] = $this->oObjectService->getFormPresentationLabels($options['entry_options']['object_class'], 'list', $options['entry_options']['ext_key_to_me']); $view->vars['object_class'] = $options['entry_options']['object_class']; $view->vars['ext_key_to_me'] = $options['entry_options']['ext_key_to_me']; + $view->vars['att_code'] = $options['attr']['data-att-code']; $view->vars['target_class'] = $options['target_class']; $view->vars['is_indirect'] = $options['is_indirect']; $view->vars['is_abstract'] = $options['is_abstract']; diff --git a/sources/DI/Form/Type/Compound/ObjectType.php b/sources/DI/Form/Type/Compound/ObjectType.php index 142aa3aff..5ddf28803 100644 --- a/sources/DI/Form/Type/Compound/ObjectType.php +++ b/sources/DI/Form/Type/Compound/ObjectType.php @@ -27,12 +27,6 @@ class ObjectType extends AbstractType /** @var ObjectPresentationService object presentation service */ private ObjectPresentationService $objectPresentationService; - /** @var \Combodo\iTop\DI\Form\Builder\AttributeBuilder attribute builder */ - private AttributeBuilder $oAttributeBuilder; - - /** @var \Combodo\iTop\DI\Form\Builder\LayoutBuilder layout builder */ - private LayoutBuilder $oLayoutBuilder; - /** * Constructor. * @@ -41,12 +35,10 @@ class ObjectType extends AbstractType * @param \Combodo\iTop\DI\Form\Builder\AttributeBuilder $oAttributeBuilder * @param \Combodo\iTop\DI\Form\Builder\LayoutBuilder $oLayoutBuilder */ - public function __construct(ObjectFormListener $oObjectFormModifier, ObjectPresentationService $objectPresentationService, AttributeBuilder $oAttributeBuilder, LayoutBuilder $oLayoutBuilder) + public function __construct(ObjectFormListener $oObjectFormModifier, ObjectPresentationService $objectPresentationService) { $this->oObjectFormModifier = $oObjectFormModifier; $this->objectPresentationService = $objectPresentationService; - $this->oAttributeBuilder = $oAttributeBuilder; - $this->oLayoutBuilder = $oLayoutBuilder; } /** @inheritdoc */ diff --git a/sources/DI/Services/ObjectPresentationService.php b/sources/DI/Services/ObjectPresentationService.php index 65868f62f..d4f87bc2e 100644 --- a/sources/DI/Services/ObjectPresentationService.php +++ b/sources/DI/Services/ObjectPresentationService.php @@ -6,6 +6,7 @@ use Combodo\iTop\DI\Form\Builder\AttributeBuilder; use Combodo\iTop\DI\Form\Builder\LayoutBuilder; use Dict; use MetaModel; +use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\Form\FormBuilderInterface; /** @@ -57,6 +58,10 @@ class ObjectPresentationService $level = $this->handleLevel($aPresentation, $class, $lockedAttributes); foreach ($level as $key => $value) { $builder->add($key, $value['type'], $value['options']); + +// if(array_key_exists('create_hidden', $value) && $value['create_hidden'] === true){ +// $builder->add($key,HiddenType::class); +// } } } @@ -107,7 +112,7 @@ class ObjectPresentationService $aPresentation = MetaModel::GetZListItems($class, $zList); $aPresentation = $this->filterLinkSetpresentation($aPresentation, $class, $sExtKeyToMe); - $level = $this->handleLevel($aPresentation, $class, null, null); + $level = $this->handleLevel($aPresentation, $class, null); $aLabels = []; foreach ($level as $key => $value) { $value['options']['attr']['data-att-code'] = $key; diff --git a/templates/DI/base.html.twig b/templates/DI/base.html.twig index 25ece686e..492cbf38a 100644 --- a/templates/DI/base.html.twig +++ b/templates/DI/base.html.twig @@ -32,7 +32,7 @@ - + + {# - BLOCK BODY - #}
- - {# - BLOCK BODY - #} {% block body %}{% endblock %}
+ {# - BLOCK TOASTS - #}
- - {# - BLOCK TOASTS - #} {% block toasts %}{% endblock %} -
@@ -102,7 +99,7 @@

Create object

- +
+
+ + +
+