Frontend: display and behavior of pickUserOrMe form field

This commit is contained in:
Julie Lenaerts 2025-03-10 19:19:51 +01:00
parent fe6949ea26
commit ec5c4d51b3
5 changed files with 135 additions and 9 deletions

View File

@ -0,0 +1,82 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MainBundle\Form\Type;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Form\Type\DataTransformer\EntityToJsonTransformer;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\SerializerInterface;
/**
* Pick user dymically, using vuejs module "AddPerson".
*
* Possible options:
*
* - `multiple`: pick one or more users
* - `suggested`: a list of suggested users
* - `suggest_myself`: append the current user to the list of suggested
* - `as_id`: only the id will be set in the returned data
* - `submit_on_adding_new_entity`: the browser will immediately submit the form when new users are checked
*/
class PickUserOrMeDynamicType extends AbstractType
{
public function __construct(
private readonly DenormalizerInterface $denormalizer,
private readonly SerializerInterface $serializer,
private readonly NormalizerInterface $normalizer,
) {}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addViewTransformer(new EntityToJsonTransformer($this->denormalizer, $this->serializer, $options['multiple'], 'user'));
}
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['multiple'] = $options['multiple'];
$view->vars['types'] = ['user'];
$view->vars['uniqid'] = uniqid('pick_user_or_me_dyn');
$view->vars['suggested'] = [];
$view->vars['as_id'] = true === $options['as_id'] ? '1' : '0';
$view->vars['submit_on_adding_new_entity'] = true === $options['submit_on_adding_new_entity'] ? '1' : '0';
foreach ($options['suggested'] as $user) {
$view->vars['suggested'][] = $this->normalizer->normalize($user, 'json', ['groups' => 'read']);
}
// $user = /* should come from context */ $options['context'];
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver
->setDefault('multiple', false)
->setAllowedTypes('multiple', ['bool'])
->setDefault('compound', false)
->setDefault('suggested', [])
// if set to true, only the id will be set inside the content. The denormalization will not work.
->setDefault('as_id', false)
->setAllowedTypes('as_id', ['bool'])
->setDefault('submit_on_adding_new_entity', false)
->setAllowedTypes('submit_on_adding_new_entity', ['bool']);
}
public function getBlockPrefix()
{
return 'pick_entity_dynamic';
}
}

View File

@ -12,6 +12,11 @@ function loadDynamicPicker(element) {
let apps = element.querySelectorAll('[data-module="pick-dynamic"]');
apps.forEach(function (el) {
let suggested;
let as_id;
let submit_on_adding_new_entity;
let label;
let isCurrentUserPicker;
const isMultiple = parseInt(el.dataset.multiple) === 1,
uniqId = el.dataset.uniqid,
input = element.querySelector(
@ -22,12 +27,13 @@ function loadDynamicPicker(element) {
? JSON.parse(input.value)
: input.value === "[]" || input.value === ""
? null
: [JSON.parse(input.value)],
suggested = JSON.parse(el.dataset.suggested),
as_id = parseInt(el.dataset.asId) === 1,
submit_on_adding_new_entity =
parseInt(el.dataset.submitOnAddingNewEntity) === 1,
label = el.dataset.label;
: [JSON.parse(input.value)];
suggested = JSON.parse(el.dataset.suggested);
as_id = parseInt(el.dataset.asId) === 1;
submit_on_adding_new_entity =
parseInt(el.dataset.submitOnAddingNewEntity) === 1;
label = el.dataset.label;
isCurrentUserPicker = uniqId.startsWith("pick_user_or_me_dyn");
if (!isMultiple) {
if (input.value === "[]") {
@ -44,6 +50,7 @@ function loadDynamicPicker(element) {
':uniqid="uniqid" ' +
':suggested="notPickedSuggested" ' +
':label="label" ' +
':isCurrentUserPicker="isCurrentUserPicker" ' +
'@addNewEntity="addNewEntity" ' +
'@removeEntity="removeEntity" ' +
'@addNewEntityProcessEnded="addNewEntityProcessEnded"' +
@ -61,6 +68,7 @@ function loadDynamicPicker(element) {
as_id,
submit_on_adding_new_entity,
label,
isCurrentUserPicker
};
},
computed: {
@ -89,7 +97,8 @@ function loadDynamicPicker(element) {
const ids = this.picked.map((el) => el.id);
input.value = ids.join(",");
}
console.log(entity);
console.log(this.picked)
// console.log(entity);
}
} else {
if (

View File

@ -1,10 +1,22 @@
<template>
<ul :class="listClasses" v-if="picked.length && displayPicked">
<li v-for="p in picked" @click="removeEntity(p)" :key="p.type + p.id">
<span class="chill_denomination">{{ p.text }}</span>
<!-- todo: use translations-->
<span v-if="'me' === p" class="chill_denomination">utilisateur courant</span>
<span v-else class="chill_denomination">{{ p.text }}</span>
</li>
</ul>
<ul class="record_actions">
<li>
<label class="flex items-center gap-2">
<input
ref="itsMeCheckbox"
:type="multiple ? 'checkbox' : 'radio'"
@change="selectItsMe"
/>
Utilisateur courant {{ currentUser }}
</label>
</li>
<li class="add-persons">
<add-persons
:options="addPersonsOptions"
@ -27,6 +39,7 @@
<script>
import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons.vue";
import { appMessages } from "./i18n";
import { trans } from "translator";
export default {
name: "PickEntity",
@ -63,6 +76,10 @@ export default {
type: String,
required: false,
},
isCurrentUserPicker: {
type: Boolean,
default: false
}
},
emits: ["addNewEntity", "removeEntity", "addNewEntityProcessEnded"],
components: {
@ -113,6 +130,7 @@ export default {
}
},
listClasses() {
console.log(this.isCurrentUserPicker)
return {
"list-suggest": true,
"remove-items": this.$props.removableIfSet,
@ -120,6 +138,13 @@ export default {
},
},
methods: {
selectItsMe(event) {
if (event.target.checked) {
this.addNewSuggested('me')
} else {
this.removeEntity('me')
}
},
addNewSuggested(entity) {
this.$emit("addNewEntity", { entity: entity });
},
@ -135,6 +160,11 @@ export default {
if (!this.$props.removableIfSet) {
return;
}
if ('me' === entity) {
if (this.$refs.itsMeCheckbox) {
this.$refs.itsMeCheckbox.checked = false;
}
}
this.$emit("removeEntity", { entity: entity });
},
},

View File

@ -49,6 +49,7 @@ Name: Nom
Label: Nom
user:
current_user: Utilisateur courant
profile:
title: Mon profil
Phonenumber successfully updated!: Numéro de téléphone mis à jour!

View File

@ -14,6 +14,7 @@ namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters;
use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Form\Type\PickUserDynamicType;
use Chill\MainBundle\Form\Type\PickUserOrMeDynamicType;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
use Chill\PersonBundle\Export\Declarations;
@ -66,9 +67,12 @@ class ReferrerFilter implements FilterInterface
public function buildForm(FormBuilderInterface $builder)
{
$builder
->add('accepted_referrers', PickUserDynamicType::class, [
->add('accepted_referrers', PickUserOrMeDynamicType::class, [
'multiple' => true,
])
/* ->add('accepted_referrers', PickUserDynamicType::class, [
'multiple' => true,
])*/
->add('date_calc', PickRollingDateType::class, [
'label' => 'export.filter.course.by_referrer.Computation date for referrer',
'required' => true,