From 45dd21e02a61a208d3fe0060584cf954ddede684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 3 Jan 2022 15:42:24 +0100 Subject: [PATCH] add component and type to add user dynamically --- .../ChillMainBundle/Form/NotificationType.php | 6 +- .../DataTransformer/UserToJsonTransformer.php | 70 +++++++++++++ .../Form/Type/PickUserDynamicType.php | 59 +++++++++++ .../public/module/pick-entity/index.js | 59 +++++++++++ .../public/vuejs/PickEntity/PickEntity.vue | 97 +++++++++++++++++++ .../Resources/public/vuejs/PickEntity/i18n.js | 17 ++++ .../Resources/views/Form/fields.html.twig | 5 + .../views/Notification/create.html.twig | 10 ++ .../views/Notification/edit.html.twig | 10 ++ .../ChillMainBundle/chill.webpack.config.js | 1 + .../ChillMainBundle/config/services.yaml | 4 +- .../public/vuejs/_components/AddPersons.vue | 2 + 12 files changed, 334 insertions(+), 6 deletions(-) create mode 100644 src/Bundle/ChillMainBundle/Form/Type/DataTransformer/UserToJsonTransformer.php create mode 100644 src/Bundle/ChillMainBundle/Form/Type/PickUserDynamicType.php create mode 100644 src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js create mode 100644 src/Bundle/ChillMainBundle/Resources/public/vuejs/PickEntity/PickEntity.vue create mode 100644 src/Bundle/ChillMainBundle/Resources/public/vuejs/PickEntity/i18n.js diff --git a/src/Bundle/ChillMainBundle/Form/NotificationType.php b/src/Bundle/ChillMainBundle/Form/NotificationType.php index b54752cde..fa06007a2 100644 --- a/src/Bundle/ChillMainBundle/Form/NotificationType.php +++ b/src/Bundle/ChillMainBundle/Form/NotificationType.php @@ -14,6 +14,7 @@ namespace Chill\MainBundle\Form; use Chill\MainBundle\Entity\Notification; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Form\Type\ChillTextareaType; +use Chill\MainBundle\Form\Type\PickUserDynamicType; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; @@ -24,11 +25,8 @@ class NotificationType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options) { $builder - ->add('addressees', EntityType::class, [ - 'class' => User::class, - 'choice_label' => 'label', + ->add('addressees', PickUserDynamicType::class, [ 'multiple' => true, - 'by_reference' => true, ]) ->add('message', ChillTextareaType::class, [ 'required' => false, diff --git a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/UserToJsonTransformer.php b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/UserToJsonTransformer.php new file mode 100644 index 000000000..497cbcdd9 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/UserToJsonTransformer.php @@ -0,0 +1,70 @@ +denormalizer = $denormalizer; + $this->serializer = $serializer; + $this->multiple = $multiple; + } + + /** + * @param User|User[] $value + */ + public function transform($value): string + { + if (null === $value) { + return $this->multiple ? "null" : "[]"; + } + + return $this->serializer->serialize($value, 'json', [ + AbstractNormalizer::GROUPS => ['read'], + ]); + } + + public function reverseTransform($value) + { + if ($this->multiple) { + return \array_map( + function($item) { return $this->denormalizeOne($item);}, + json_decode($value, true) + ); + } + + return $this->denormalizeOne(json_decode($value, true)); + } + + private function denormalizeOne(array $item): User + { + if (!array_key_exists('type', $item)) { + throw new TransformationFailedException('the key "type" is missing on element'); + } + if (!array_key_exists('id', $item)) { + throw new TransformationFailedException('the key "id" is missing on element'); + } + + return + $this->denormalizer->denormalize( + ['type' => $item['type'], 'id' => $item['id']], + User::class, + 'json', + [AbstractNormalizer::GROUPS => ['read']], + ); + } +} diff --git a/src/Bundle/ChillMainBundle/Form/Type/PickUserDynamicType.php b/src/Bundle/ChillMainBundle/Form/Type/PickUserDynamicType.php new file mode 100644 index 000000000..0ddff7b1e --- /dev/null +++ b/src/Bundle/ChillMainBundle/Form/Type/PickUserDynamicType.php @@ -0,0 +1,59 @@ +denormalizer = $denormalizer; + $this->serializer = $serializer; + } + + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder->addViewTransformer(new UserToJsonTransformer($this->denormalizer, $this->serializer, $options['multiple'])); + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver + ->setDefault('multiple', false) + ->setAllowedTypes('multiple', ['bool']) + ->setDefault('compound', false) + ; + } + + public function buildView(FormView $view, FormInterface $form, array $options) + { + $view->vars['multiple'] = $options['multiple']; + $view->vars['types'] = ['user']; + $view->vars['uniqid'] = uniqid('pick_user_dyn'); + } + + public function getBlockPrefix() + { + return 'pick_user_dynamic'; + } + +} diff --git a/src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js b/src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js new file mode 100644 index 000000000..26cbff735 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js @@ -0,0 +1,59 @@ +import {createApp} from 'vue'; +import PickEntity from 'ChillMainAssets/vuejs/PickEntity/PickEntity.vue'; +import { _createI18n } from 'ChillMainAssets/vuejs/_js/i18n' +import {activityMessages} from "../../../../../ChillActivityBundle/Resources/public/vuejs/Activity/i18n"; + +window.addEventListener('DOMContentLoaded', function(e) { + let + apps = document.querySelectorAll('[data-module="pick-dynamic"]'); + + apps.forEach(function(el) { + const + isMultiple = parseInt(el.dataset.multiple) === 1, + input = document.querySelector('[data-input-uniqid="'+ el.dataset.uniqid +'"]'), + picked = isMultiple ? JSON.parse(input.value) : [JSON.parse(input.value)], + i18n = _createI18n({}); + + createApp({ + template: '', + components: { + PickEntity, + }, + data() { + return { + multiple: isMultiple, + types: JSON.parse(el.dataset.types), + picked, + uniqid: el.dataset.uniqid, + } + }, + methods: { + addNewEntity(entity) { + console.log('addNewEntity', entity); + if (this.multiple) { + console.log('adding multiple'); + if (!this.picked.some(el => { + return el.type === entity.type && el.id === entity.id; + })) { + this.picked.push(entity); + input.value = JSON.stringify(this.picked); + } + } else { + if (!this.picked.some(el => { + return el.type === entity.type && el.id === entity.id; + })) { + this.picked.splice(0, this.picked.length); + this.picked.push(entity); + input.value = JSON.stringify(this.picked[0]); + } + } + }, + removeEntity(entity) { + console.log('removeEntity', entity); + this.picked = this.picked.filter(e => !(e.type === entity.type && e.id === entity.id)); + input.value = JSON.stringify(this.picked); + }, + } + }).use(i18n).mount(el); + }); +}); diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickEntity/PickEntity.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickEntity/PickEntity.vue new file mode 100644 index 000000000..32dad3c36 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickEntity/PickEntity.vue @@ -0,0 +1,97 @@ + + + + + diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickEntity/i18n.js b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickEntity/i18n.js new file mode 100644 index 000000000..78a0a9c90 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickEntity/i18n.js @@ -0,0 +1,17 @@ +import { personMessages } from 'ChillPersonAssets/vuejs/_js/i18n' + +const messages = { + fr: { + pick_entity: { + add: 'Ajouter', + modal_title: 'Ajouter des', + user: 'Utilisateurs', + person: 'Usagers', + thirdparty: 'Tiers', + } + } +} + +const full = Object.assign(messages, personMessages); + +export default full; diff --git a/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig index 1426841bb..25f1363c3 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig @@ -215,3 +215,8 @@ {{ form_widget(form.center) }} {% endif %} {% endblock %} + +{% block pick_user_dynamic_widget %} + +
+{% endblock %} diff --git a/src/Bundle/ChillMainBundle/Resources/views/Notification/create.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Notification/create.html.twig index a6a52acf7..db06caefa 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Notification/create.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Notification/create.html.twig @@ -1,5 +1,15 @@ {% extends "@ChillMain/layout.html.twig" %} +{% block js %} + {{ parent() }} + {{ encore_entry_script_tags('mod_pickentity_type') }} +{% endblock %} + +{% block css %} + {{ parent() }} + {{ encore_entry_link_tags('mod_pickentity_type') }} +{% endblock %} + {% block content %}
diff --git a/src/Bundle/ChillMainBundle/Resources/views/Notification/edit.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Notification/edit.html.twig index a6a52acf7..db06caefa 100644 --- a/src/Bundle/ChillMainBundle/Resources/views/Notification/edit.html.twig +++ b/src/Bundle/ChillMainBundle/Resources/views/Notification/edit.html.twig @@ -1,5 +1,15 @@ {% extends "@ChillMain/layout.html.twig" %} +{% block js %} + {{ parent() }} + {{ encore_entry_script_tags('mod_pickentity_type') }} +{% endblock %} + +{% block css %} + {{ parent() }} + {{ encore_entry_link_tags('mod_pickentity_type') }} +{% endblock %} + {% block content %}
diff --git a/src/Bundle/ChillMainBundle/chill.webpack.config.js b/src/Bundle/ChillMainBundle/chill.webpack.config.js index adc4ba3c8..47aa32865 100644 --- a/src/Bundle/ChillMainBundle/chill.webpack.config.js +++ b/src/Bundle/ChillMainBundle/chill.webpack.config.js @@ -63,6 +63,7 @@ module.exports = function(encore, entries) encore.addEntry('mod_blur', __dirname + '/Resources/public/module/blur/index.js'); encore.addEntry('mod_input_address', __dirname + '/Resources/public/vuejs/Address/mod_input_address_index.js'); encore.addEntry('mod_notification_toggle_read_status', __dirname + '/Resources/public/module/notification/toggle_read.js'); + encore.addEntry('mod_pickentity_type', __dirname + '/Resources/public/module/pick-entity/index.js'); // Vue entrypoints encore.addEntry('vue_address', __dirname + '/Resources/public/vuejs/Address/index.js'); diff --git a/src/Bundle/ChillMainBundle/config/services.yaml b/src/Bundle/ChillMainBundle/config/services.yaml index 8ee24d7b7..adf38988e 100644 --- a/src/Bundle/ChillMainBundle/config/services.yaml +++ b/src/Bundle/ChillMainBundle/config/services.yaml @@ -18,8 +18,8 @@ services: Chill\MainBundle\Form\Type\: resource: '../Form/Type' - tags: - - { name: form.type } + autoconfigure: true + autowire: true Chill\MainBundle\Doctrine\Event\: resource: '../Doctrine/Event/' diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/AddPersons.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/AddPersons.vue index f118671ed..f384aae54 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/AddPersons.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/AddPersons.vue @@ -93,9 +93,11 @@ import PersonSuggestion from './AddPersons/PersonSuggestion'; import { searchEntities } from 'ChillPersonAssets/vuejs/_api/AddPersons'; import { postPerson } from "ChillPersonAssets/vuejs/_api/OnTheFly"; import { postThirdparty } from "ChillThirdPartyAssets/vuejs/_api/OnTheFly"; +import {messages} from 'ChillPersonAssets/vuejs/_js/i18n.js'; export default { name: 'AddPersons', + messages, components: { Modal, PersonSuggestion,