Merge branch 'master' into issue425_errorMessage_closeParcours

This commit is contained in:
Julien Fastré 2022-02-01 18:42:59 +01:00
commit 7879a99197
26 changed files with 371 additions and 149 deletions

View File

@ -14,14 +14,19 @@ and this project adheres to
* renommer "dossier numéro" en "parcours numéro" dans les résultats de recherche
* renomme date de début en date d'ouverture dans le formulaire parcours
* [parcours]: validation + message for closing parcours adjusted.
* [household]: household composition double edit button replaced by a delete action (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/426)
[fast_actions] improve fast-actions buttons override mechanism, fix https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/413
[homepage widget] add vue homepage_widget with asynchone loading, give a global view resume of the user concerned actions, notifications, etc.
* [person]: Comment on marital status is possible even if marital status is not defined (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/421)
* [parcours]: In the list of person results the requestor is not displayed if defined as anonymous (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/424)
* [bugfix]: modal closes and newly created person/thirdparty is selected when multiple persons/thirdparties are created through the modal (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/429)
* [person_resource]: Onthefly button added to view person/thirdparty and badge differentiation for a contact-thirdparty (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/428)
* [workflow][notification] improve how notifications and workflows are 'attached' to entities: contextual list, counter, buttons and vue modal
## Test releases
### test release 2021-01-31
[fast_actions] improve fast-actions buttons override mechanism, fix https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/413
[homepage widget] add vue homepage_widget with asynchone loading, give a global view resume of the user concerned actions, notifications, etc.
* [person] accompanying course: optimisation: do not fetch some resources for the banner (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/409)
* [person] accompanying course: close modal when edit participation (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/420)
* [person] accompanying course: treat validation error when editing on-the-fly entities (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/420)
@ -32,7 +37,6 @@ and this project adheres to
* [user]: page with accompanying periods to which is user is referent (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/408)
* [person] age added to renderstring + renderbox/ vue component created to display person text (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/389)
* [household member editor] allow to push to existing household
* [workflow][notification] improve how notifications and workflows are 'attached' to entities: contextual list, counter, buttons and vue modal
### test release 2021-01-28

View File

@ -34,6 +34,7 @@ use Psr\Log\LoggerInterface;
use RuntimeException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
@ -200,12 +201,36 @@ final class ActivityController extends AbstractController
'role' => new Role('CHILL_ACTIVITY_UPDATE'),
'activityType' => $entity->getActivityType(),
'accompanyingPeriod' => $accompanyingPeriod,
])->handleRequest($request);
]);
if ($form->has('documents')) {
$form->add('gendocTemplateId', HiddenType::class, [
'mapped' => false,
'data' => null,
'attr' => [
// required for js
'data-template-id' => 'data-template-id',
],
]);
}
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->entityManager->persist($entity);
$this->entityManager->flush();
if ($form->has('gendocTemplateId') && '' !== $form['gendocTemplateId']) {
return $this->redirectToRoute(
'chill_docgenerator_generate_from_template',
[
'template' => $form->get('gendocTemplateId')->getData(),
'entityClassName' => Activity::class,
'entityId' => $entity->getId(),
]
);
}
$this->addFlash('success', $this->get('translator')->trans('Success : activity updated!'));
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
@ -393,12 +418,36 @@ final class ActivityController extends AbstractController
'role' => new Role('CHILL_ACTIVITY_CREATE'),
'activityType' => $entity->getActivityType(),
'accompanyingPeriod' => $accompanyingPeriod,
])->handleRequest($request);
]);
if ($form->has('documents')) {
$form->add('gendocTemplateId', HiddenType::class, [
'mapped' => false,
'data' => null,
'attr' => [
// required for js
'data-template-id' => 'data-template-id',
],
]);
}
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->entityManager->persist($entity);
$this->entityManager->flush();
if ($form->has('gendocTemplateId') && '' !== $form['gendocTemplateId']) {
return $this->redirectToRoute(
'chill_docgenerator_generate_from_template',
[
'template' => $form->get('gendocTemplateId')->getData(),
'entityClassName' => Activity::class,
'entityId' => $entity->getId(),
]
);
}
$this->addFlash('success', $this->get('translator')->trans('Success : activity created!'));
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);

View File

@ -2,11 +2,15 @@ import { createApp } from 'vue';
import { _createI18n } from 'ChillMainAssets/vuejs/_js/i18n'
import { activityMessages } from './i18n'
import store from './store'
import PickTemplate from 'ChillDocGeneratorAssets/vuejs/_components/PickTemplatePreventMoving.vue';
import {fetchTemplates} from 'ChillDocGeneratorAssets/api/pickTemplate.js';
import App from './App.vue';
const i18n = _createI18n(activityMessages);
// app for activity
const hasSocialIssues = document.querySelector('#social-issues-acc') !== null;
const hasLocation = document.querySelector('#location') !== null;
const hasPerson = document.querySelector('#add-persons') !== null;
@ -29,3 +33,54 @@ const app = createApp({
.use(i18n)
.component('app', App)
.mount('#activity');
// app for picking template
const i18nGendoc = _createI18n({});
document.querySelectorAll('div[data-docgen-template-picker]').forEach(el => {
fetchTemplates(el.dataset.entityClass).then(templates => {
const picker = {
template:
'<pick-template :templates="this.templates" :preventDefaultMoveToGenerate="true" ' +
':entityClass="faked" @go-to-generate-document="generateDoc"></pick-template>',
components: {
PickTemplate,
},
data() {
return {
templates: templates,
entityId: el.dataset.entityId,
}
},
methods: {
generateDoc({event, link, template}) {
console.log('generateDoc');
console.log('link', link);
console.log('template', template);
let hiddenInput = document.querySelector("input[data-template-id]");
if (hiddenInput === null) {
console.error('hidden input not found');
return;
}
hiddenInput.value = template;
let form = document.querySelector('form[name="chill_activitybundle_activity"');
if (form === null) {
console.error('form not found');
return;
}
form.submit();
}
}
};
createApp(picker).use(i18nGendoc).mount(el);
})
});

View File

@ -89,9 +89,9 @@
{%- if edit_form.documents is defined -%}
{{ form_row(edit_form.documents) }}
<div data-docgen-template-picker="data-docgen-template-picker" data-entity-class="Chill\ActivityBundle\Entity\Activity" data-entity-id="{{ entity.id }}"></div>
{% endif %}
<div data-docgen-template-picker="data-docgen-template-picker" data-entity-class="Chill\ActivityBundle\Entity\Activity" data-entity-id="{{ entity.id }}"></div>
{% set person_id = null %}
{% if entity.person %}

View File

@ -24,12 +24,10 @@
window.activity = {{ activity_json|json_encode|raw }};
</script>
{{ encore_entry_script_tags('vue_activity') }}
{{ encore_entry_script_tags('mod_docgen_picktemplate') }}
{% endblock %}
{% block css %}
{{ parent() }}
{{ encore_entry_link_tags('mod_async_upload') }}
{{ encore_entry_link_tags('vue_activity') }}
{{ encore_entry_link_tags('mod_docgen_picktemplate') }}
{% endblock %}

View File

@ -39,11 +39,9 @@
window.activity = {{ activity_json|json_encode|raw }};
</script>
{{ encore_entry_script_tags('vue_activity') }}
{{ encore_entry_script_tags('mod_docgen_picktemplate') }}
{% endblock %}
{% block css %}
{{ encore_entry_link_tags('mod_async_upload') }}
{{ encore_entry_link_tags('vue_activity') }}
{{ encore_entry_link_tags('mod_docgen_picktemplate') }}
{% endblock %}

View File

@ -87,6 +87,7 @@
{%- if form.documents is defined -%}
{{ form_row(form.documents) }}
<div data-docgen-template-picker="data-docgen-template-picker" data-entity-class="Chill\ActivityBundle\Entity\Activity" data-entity-id="{{ entity.id }}"></div>
{% endif %}
{%- if form.attendee is defined -%}

View File

@ -17,10 +17,6 @@
{{ parent() }}
{{ encore_entry_script_tags('mod_async_upload') }}
<script type="text/javascript">
window.addEventListener('DOMContentLoaded', function (e) {
chill.displayAlertWhenLeavingUnsubmittedForm('form[name="{{ form.vars.form.vars.name }}"]',
'{{ "You are going to leave a page with unsubmitted data. Are you sure you want to leave ?"|trans }}');
});
window.activity = {{ activity_json|json_encode|raw }};
{% if default_location is not null %}window.default_location_id = {{ default_location.id }}{% endif %};
</script>

View File

@ -17,7 +17,6 @@ use Chill\DocGeneratorBundle\Context\DocGeneratorContextWithPublicFormInterface;
use Chill\DocGeneratorBundle\Context\Exception\UnexpectedTypeException;
use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate;
use Chill\DocGeneratorBundle\Service\Context\BaseContextData;
use Chill\DocStoreBundle\Entity\Document;
use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\DocStoreBundle\Repository\DocumentCategoryRepository;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
@ -210,11 +209,8 @@ class ActivityContext implements
*/
public function storeGenerated(DocGeneratorTemplate $template, StoredObject $storedObject, object $entity, array $contextGenerationData): void
{
$doc = new StoredObject();
// TODO push document to remote
$entity->addDocument($storedObject);
$this->em->persist($doc);
$entity->addDocument($doc);
$this->em->persist($storedObject);
}
}

View File

@ -0,0 +1,13 @@
const buildLink = function(templateId, entityId, entityClass) {
const
entityIdEncoded = encodeURI(entityId),
returnPath = encodeURIComponent(window.location.pathname + window.location.search + window.location.hash),
entityClassEncoded = encodeURI(entityClass),
url = `/fr/doc/gen/generate/from/${templateId}/for/${entityClassEncoded}/${entityIdEncoded}?returnPath=${returnPath}`
;
console.log('computed Url');
return url;
};
export {buildLink};

View File

@ -20,8 +20,8 @@
<option v-bind:value="t.id">{{ t.name.fr || 'Aucun nom défini' }}</option>
</template>
</select>
<button v-if="canGenerate" class="btn btn-update btn-sm change-icon" type="button" @click="generateDocument"><i class="fa fa-fw fa-cog"></i></button>
<button v-else class="btn btn-update btn-sm change-icon" type="button" disabled ><i class="fa fa-fw fa-cog"></i></button>
<a v-if="canGenerate" class="btn btn-update btn-sm change-icon" :href="buildUrlGenerate" @click.prevent="clickGenerate($event, buildUrlGenerate)"><i class="fa fa-fw fa-cog"></i></a>
<a v-else class="btn btn-update btn-sm change-icon" href="#" disabled ><i class="fa fa-fw fa-cog"></i></a>
</div>
</div>
</div>
@ -39,24 +39,27 @@
<script>
import {buildLink} from 'ChillDocGeneratorAssets/lib/document-generator';
export default {
name: "PickTemplate",
props: {
entityId: [String, Number],
entityClass: {
type: String,
required: true,
required: false,
},
templates: {
type: Array,
required: true,
},
// beforeMove execute "something" before
beforeMove: {
type: Function,
preventDefaultMoveToGenerate: {
type: Boolean,
required: false,
default: false,
}
},
emits: ['goToGenerateDocument'],
data() {
return {
template: null,
@ -74,66 +77,37 @@ export default {
return true;
},
getDescription() {
if (null === this.template) {
return '';
}
let desc = this.templates.find(t => t.id === this.template);
if (null === desc) {
return '';
}
return desc.description || '';
},
buildUrlGenerate() {
if (null === this.template) {
return '#';
}
return buildLink(this.template, this.entityId, this.entityClass);
}
},
methods: {
generateDocument() {
console.log('generateDocument');
console.log('beforeMove', this.beforeMove);
if (this.beforeMove != null) {
console.log('execute before move');
let r = this.beforeMove();
if (r instanceof Promise) {
r.then((obj) => this.goToGenerate(obj));
} else {
this.goToGenerate();
}
} else {
this.goToGenerate();
}
},
goToGenerate(obj) {
console.log('goToGenerate');
console.log('obj', obj);
console.log('entityId', this.entityId);
let
realId = this.entityId,
realEntityClass = this.entityClass
;
if (obj !== undefined) {
if (obj.entityId !== undefined) {
realId = obj.entityId;
}
if (obj.entityClass !== undefined) {
realEntityClass = obj.entityClass;
}
clickGenerate(event, link) {
if (!this.preventDefaultMoveToGenerate) {
window.location.assign(link);
}
console.log('realId', realId);
console.log('realEntityClass', realEntityClass);
const
entityId = encodeURI(realId),
returnPath = encodeURIComponent(window.location.pathname + window.location.search + window.location.hash),
fqdnEntityClass = encodeURI(realEntityClass),
url = `/fr/doc/gen/generate/from/${this.template}/for/${fqdnEntityClass}/${entityId}?returnPath=${returnPath}`
;
console.log('I will generate your doc at', url);
window.location.assign(url);
this.$emit('goToGenerateDocument', {event, link, template: this.template});
},
},
i18n: {
messages: {
fr: {
generate_document: 'Générer un document',
select_a_template: 'Choisir un gabarit',
select_a_template: 'Choisir un modèle',
choose_a_template: 'Choisir',
}
}

View File

@ -44,7 +44,6 @@ class NotificationNormalizer implements NormalizerAwareInterface, NormalizerInte
*/
public function normalize($object, ?string $format = null, array $context = [])
{
dump($object);
$entity = $this->entityManager
->getRepository($object->getRelatedEntityClass())
->find($object->getRelatedEntityId());

View File

@ -99,7 +99,7 @@ class AccompanyingPeriodWorkEvaluationApiController
if ($request->query->getBoolean('countOnly', false)) {
return new JsonResponse(
$this->serializer->serialize(new Counter($total), 'json', ['groups' => 'read']),
$this->serializer->serialize(new Counter($total), 'json', ['groups' => ['read']]),
JsonResponse::HTTP_OK,
[],
true
@ -117,7 +117,7 @@ class AccompanyingPeriodWorkEvaluationApiController
$collection = new Collection($works, $paginator);
return new JsonResponse(
$this->serializer->serialize($collection, 'json', ['groups' => 'read']),
$this->serializer->serialize($collection, 'json', ['groups' => ['read', 'read:evaluation:include-work']]),
JsonResponse::HTTP_OK,
[],
true

View File

@ -16,9 +16,12 @@ use Chill\PersonBundle\Entity\Household\Household;
use Chill\PersonBundle\Entity\Household\HouseholdComposition;
use Chill\PersonBundle\Form\HouseholdCompositionType;
use Chill\PersonBundle\Repository\Household\HouseholdCompositionRepository;
use Chill\PersonBundle\Repository\Household\HouseholdRepository;
use Chill\PersonBundle\Security\Authorization\HouseholdVoter;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
@ -31,7 +34,7 @@ use Symfony\Component\Security\Core\Security;
use Symfony\Component\Templating\EngineInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class HouseholdCompositionController
class HouseholdCompositionController extends AbstractController
{
private EngineInterface $engine;
@ -41,6 +44,8 @@ class HouseholdCompositionController
private HouseholdCompositionRepository $householdCompositionRepository;
private HouseholdRepository $householdRepository;
private PaginatorFactory $paginatorFactory;
private Security $security;
@ -52,6 +57,7 @@ class HouseholdCompositionController
public function __construct(
Security $security,
HouseholdCompositionRepository $householdCompositionRepository,
HouseholdRepository $householdRepository,
PaginatorFactory $paginatorFactory,
FormFactoryInterface $formFactory,
EntityManagerInterface $entityManager,
@ -67,6 +73,59 @@ class HouseholdCompositionController
$this->translator = $translator;
$this->engine = $engine;
$this->urlGenerator = $urlGenerator;
$this->householdRepository = $householdRepository;
}
/**
* @Route("/{_locale}/person/household/{household_id}/composition/{composition_id}/delete", name="chill_person_household_composition_delete")
*
* @param mixed $household_id
* @param mixed $composition_id
*/
public function deleteAction(Request $request, $household_id, $composition_id): Response
{
$composition = $this->householdCompositionRepository->find($composition_id);
$household = $this->householdRepository->find($household_id);
$this->denyAccessUnlessGranted(HouseholdVoter::EDIT, $household);
if (null === $composition) {
throw $this->createNotFoundException('Unable to find composition entity.');
}
$form = $this->createFormBuilder()
->setAction($this->generateUrl('chill_person_household_composition_delete', [
'composition_id' => $composition_id,
'household_id' => $household_id,
]))
->setMethod('DELETE')
->add('submit', SubmitType::class, ['label' => 'Delete'])
->getForm();
if ($request->getMethod() === Request::METHOD_DELETE) {
$form->handleRequest($request);
if ($form->isValid()) {
$this->entityManager->remove($composition);
$this->entityManager->flush();
$this->addFlash('success', $this->translator
->trans('The composition has been successfully removed.'));
return $this->redirectToRoute('chill_person_household_composition_index', [
'id' => $household_id,
]);
}
}
return $this->render(
'ChillPersonBundle:HouseholdComposition:delete.html.twig',
[
'household' => $household,
'composition' => $composition,
'form' => $form->createView(),
]
);
}
/**

View File

@ -44,7 +44,8 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
{
/**
* @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class)
* @Serializer\Groups({"read"})
* @Serializer\Groups({"read", "read:accompanyingPeriodWork:light"})
* @Serializer\Context(normalizationContext={"groups": {"read"}}, groups={"read:accompanyingPeriodWork:light"})
*/
private ?AccompanyingPeriod $accompanyingPeriod = null;
@ -63,26 +64,26 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
/**
* @ORM\Column(type="datetime_immutable")
* @Serializer\Groups({"read", "docgen:read"})
* @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"})
*/
private ?DateTimeImmutable $createdAt = null;
/**
* @ORM\Column(type="boolean")
* @Serializer\Groups({"read", "docgen:read"})
* @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"})
*/
private bool $createdAutomatically = false;
/**
* @ORM\Column(type="text")
* @Serializer\Groups({"read", "docgen:read"})
* @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"})
*/
private string $createdAutomaticallyReason = '';
/**
* @ORM\ManyToOne(targetEntity=User::class)
* @ORM\JoinColumn(nullable=false)
* @Serializer\Groups({"read", "docgen:read"})
* @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"})
*/
private ?User $createdBy = null;
@ -90,7 +91,7 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
* @Serializer\Groups({"accompanying_period_work:create"})
* @Serializer\Groups({"accompanying_period_work:edit"})
* @Serializer\Groups({"read", "docgen:read"})
* @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"})
* @Assert\GreaterThan(propertyPath="startDate",
* message="accompanying_course_work.The endDate should be greater than the start date"
* )
@ -122,7 +123,7 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
* @Serializer\Groups({"read", "docgen:read"})
* @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light", "read:evaluation:include-work"})
*/
private ?int $id = null;
@ -135,7 +136,7 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
/**
* @ORM\ManyToMany(targetEntity=Person::class)
* @ORM\JoinTable(name="chill_person_accompanying_period_work_person")
* @Serializer\Groups({"read", "docgen:read"})
* @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"})
* @Serializer\Groups({"accompanying_period_work:edit"})
* @Serializer\Groups({"accompanying_period_work:create"})
*/
@ -151,8 +152,9 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
/**
* @ORM\ManyToOne(targetEntity=SocialAction::class)
* @Serializer\Groups({"read", "docgen:read"})
* @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"})
* @Serializer\Groups({"accompanying_period_work:create"})
* @Serializer\Context(normalizationContext={"groups": {"read"}}, groups={"read:accompanyingPeriodWork:light"})
*/
private ?SocialAction $socialAction = null;
@ -160,7 +162,7 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
* @ORM\Column(type="date_immutable")
* @Serializer\Groups({"accompanying_period_work:create"})
* @Serializer\Groups({"accompanying_period_work:edit"})
* @Serializer\Groups({"read", "docgen:read"})
* @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"})
*/
private ?DateTimeImmutable $startDate = null;

View File

@ -39,6 +39,8 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU
* targetEntity=AccompanyingPeriodWork::class,
* inversedBy="accompanyingPeriodWorkEvaluations"
* )
* @Serializer\Groups({"read:evaluation:include-work"})
* @Serializer\Context(normalizationContext={"groups": {"read:accompanyingPeriodWork:light"}}, groups={"read:evaluation:include-work"})
*/
private ?AccompanyingPeriodWork $accompanyingPeriodWork = null;

View File

@ -92,7 +92,8 @@
entityClass="Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation"
:id="evaluation.id"
:templates="getTemplatesAvailables"
:beforeMove="submitBeforeGenerate"
:preventDefaultMoveToGenerate="true"
@go-to-generate-document="submitBeforeGenerate"
>
<template v-slot:title>
<label class="col-sm-4 col-form-label">{{ $t('evaluation_generate_a_document') }}</label>
@ -109,6 +110,7 @@ import CKEditor from '@ckeditor/ckeditor5-vue';
import ClassicEditor from 'ChillMainAssets/module/ckeditor5/index.js';
import { mapGetters, mapState } from 'vuex';
import PickTemplate from 'ChillDocGeneratorAssets/vuejs/_components/PickTemplate.vue';
import {buildLink} from 'ChillDocGeneratorAssets/lib/document-generator';
const i18n = {
messages: {
@ -123,7 +125,7 @@ const i18n = {
evaluation_public_comment: "Note publique",
evaluation_comment_placeholder: "Commencez à écrire ...",
evaluation_generate_a_document: "Générer un document",
evaluation_choose_a_template: "Choisir un gabarit",
evaluation_choose_a_template: "Choisir un modèle",
evaluation_add_a_document: "Ajouter un document",
evaluation_add: "Ajouter une évaluation",
Documents: "Documents",
@ -207,10 +209,11 @@ export default {
return `/wopi/edit/${storedObject.uuid}?returnPath=` + encodeURIComponent(
window.location.pathname + window.location.search + window.location.hash);
},
submitBeforeGenerate() {
submitBeforeGenerate({template}) {
const callback = (data) => {
let evaluationId = data.accompanyingPeriodWorkEvaluations.find(e => e.key === this.evaluation.key).id;
return Promise.resolve({entityId: evaluationId});
window.location.assign(buildLink(template, evaluationId, 'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluation'));
};
return this.$store.dispatch('submit', callback).catch(e => { console.log(e); throw e; });

View File

@ -195,18 +195,18 @@ export default {
setTimeout(function() {
if (query === "") {
this.loadSuggestions([]);
return;
this.loadSuggestions([]);
return;
}
if (query === this.search.query) {
if (this.currentSearchQueryController !== undefined) {
this.currentSearchQueryController.abort()
}
this.currentSearchQueryController = new AbortController();
searchEntities({ query, options: this.options }, this.currentSearchQueryController)
if (this.currentSearchQueryController !== undefined) {
this.currentSearchQueryController.abort()
}
this.currentSearchQueryController = new AbortController();
searchEntities({ query, options: this.options }, this.currentSearchQueryController)
.then(suggested => new Promise((resolve, reject) => {
this.loadSuggestions(suggested.results);
resolve();
this.loadSuggestions(suggested.results);
resolve();
}));
}
}.bind(this), query.length > 3 ? 300 : 700);
@ -241,13 +241,12 @@ export default {
return item.result.type + item.result.id;
},
addPriorSuggestion() {
//console.log('addPriorSuggestion', this.hasPriorSuggestion);
// console.log('prior suggestion', this.priorSuggestion);
if (this.hasPriorSuggestion) {
console.log('addPriorSuggestion',);
// console.log('addPriorSuggestion',);
this.suggested.unshift(this.priorSuggestion);
this.selected.unshift(this.priorSuggestion);
console.log('reset priorSuggestion');
this.newPriorSuggestion(null);
}
},
@ -260,13 +259,14 @@ export default {
result: entity
}
this.search.priorSuggestion = suggestion;
console.log('search priorSuggestion', this.search.priorSuggestion);
// console.log('search priorSuggestion', this.search.priorSuggestion);
this.addPriorSuggestion(suggestion);
} else {
this.search.priorSuggestion = {};
}
},
saveFormOnTheFly({ type, data }) {
console.log('saveFormOnTheFly from addPersons, type', type, ', data', data);
// console.log('saveFormOnTheFly from addPersons, type', type, ', data', data);
if (type === 'person') {
makeFetch('POST', '/api/1.0/person/person.json', data)
.then(response => {
@ -276,10 +276,10 @@ export default {
.catch((error) => {
if (error.name === 'ValidationException') {
for (let v of error.violations) {
this.$toast.open({message: v });
this.$toast.open({message: v });
}
} else {
this.$toast.open({message: 'An error occurred'});
this.$toast.open({message: 'An error occurred'});
}
})
}
@ -292,13 +292,14 @@ export default {
.catch((error) => {
if (error.name === 'ValidationException') {
for (let v of error.violations) {
this.$toast.open({message: v });
this.$toast.open({message: v });
}
} else {
this.$toast.open({message: 'An error occurred'});
this.$toast.open({message: 'An error occurred'});
}
})
}
this.canCloseOnTheFlyModal = false;
}
},
}

View File

@ -0,0 +1,38 @@
{% extends '@ChillPerson/Household/layout.html.twig' %}
{% set activeRouteKey = 'chill_person_household_composition_index' %}
{% block title 'Remove household composition'|trans %}
{% block display_content %}
<p>{{ 'Concerns household n°%id%'|trans({ '%id%' : household.id } ) }}</p>
<div class="wl-row">
<div class="wl-col title">
<h3>{{ 'Composition'|trans }}:</h3>
</div>
<div class="wl-col list">
{% for m in household.members %}
<span class="wl-item">
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
action: 'show', displayBadge: true,
targetEntity: { name: 'person', id: m.person.id },
buttonText: m.person|chill_entity_render_string,
isDead: m.person.deathdate is not null
} %}
</span>
{% endfor %}
</div>
</div>
{% endblock %}
{% block content %}
{{ include('@ChillMain/Util/confirmation_template.html.twig',
{
'title' : 'Remove household composition'|trans,
'confirm_question' : 'Are you sure you want to remove this composition?'|trans,
'display_content' : block('display_content'),
'cancel_route' : 'chill_person_household_composition_index',
'cancel_parameters' : { 'composition_id' : composition.id, 'id' : household.id },
'form' : form
} ) }}
{% endblock %}

View File

@ -22,7 +22,7 @@
<h3>{{ c.householdCompositionType.label|localize_translatable_string }}</h3>
<p>{{ 'household_composition.numberOfChildren'|trans }}: {{ c.numberOfChildren }}</p>
</div>
<div class="item-col">{{ 'household_composition.Since'|trans({'startDate': c.startDate}) }}</div>
<div class="item-col" style="justify-content: flex-end">{{ 'household_composition.Since'|trans({'startDate': c.startDate}) }}</div>
</div>
<div class="item-row">
<div class="item-col">
@ -45,7 +45,10 @@
<a href="{{ path('chill_person_household_composition_index', {'id': c.household.id, 'edit': c.id}) }}" class="btn btn-edit"></a>
</li>
<li>
<a href="{{ path('chill_person_household_composition_index', {'id': c.household.id, 'edit': c.id}) }}" class="btn btn-edit"></a>
<a href="{{ chill_path_add_return_path('chill_person_household_composition_delete', {'composition_id': c.id,
'household_id': c.household.id}) }}"
class="btn btn-delete"
title="{{ 'Delete'|trans }}"></a>
</li>
</ul>
</div>
@ -57,8 +60,8 @@
{{ form_widget(form) }}
<ul class="record_actions">
<li class="cancel">
<a href="{{ path('chill_person_household_composition_index', {'id': c.household.id}) }}">{{ 'Cancel'|trans }}</a>
<li class="cancel" style="margin-right: auto;">
<a class="btn btn-cancel" href="{{ path('chill_person_household_composition_index', {'id': c.household.id}) }}">{{ 'Cancel'|trans }}</a>
</li>
<li>
<button type="submit" class="btn btn-create">{{ 'Save'|trans }}</button>

View File

@ -85,9 +85,11 @@
</div>
<div id="maritalStatusDate">
{{ form_row(form.maritalStatusDate, { 'label' : 'Date of last marital status change'} ) }}
{{ form_row(form.maritalStatusComment, { 'label' : 'Comment on the marital status'} ) }}
</div>
{%- endif -%}
<div id="maritalStatusComment">
{{ form_row(form.maritalStatusComment, { 'label' : 'Comment on the marital status'} ) }}
</div>
</fieldset>
{%- endif -%}

View File

@ -99,11 +99,12 @@
{% endif %}
</div>
<div class="ms-auto">
{% if acp.requestorPerson == person %}
{% if acp.requestoranonymous == false and acp.requestorPerson == person %}
<span class="as-requestor badge bg-info" title="{{ 'Requestor'|trans|e('html_attr') }}">
{{ 'Requestor'|trans({'gender': person.gender}) }}
</span>
{% endif %}
{% if acp.emergency %}
<span class="badge rounded-pill bg-danger">{{- 'Emergency'|trans|upper -}}</span>
{% endif %}
@ -186,39 +187,39 @@
</a>
</li>
</ul>
{% if (acp.requestorPerson is not null and acp.requestorPerson.id != person.id) or acp.requestorThirdParty is not null %}
<div class="wl-row">
<div class="wl-col title">
<h3>
{% if acp.requestorPerson is not null %}
{{ 'Requestor'|trans({'gender': acp.requestorPerson.gender}) }}
{% if acp.requestoranonymous == false %}
{% if (acp.requestorPerson is not null and acp.requestorPerson.id != person.id) or acp.requestorThirdParty is not null %}
<div class="wl-row">
<div class="wl-col title">
<h3>
{% if acp.requestorPerson is not null %}
{{ 'Requestor'|trans({'gender': acp.requestorPerson.gender}) }}
{% else %}
{{ 'Requestor'|trans({'gender': 'other'})}}
{% endif %}
</h3>
</div>
<div class="wl-col list">
{% if acp.requestorThirdParty is not null %}
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
targetEntity: { name: 'thirdparty', id: acp.requestorThirdParty.id },
action: 'show',
displayBadge: true,
buttonText: acp.requestorThirdParty|chill_entity_render_string
} %}
{% else %}
{{ 'Requestor'|trans({'gender': 'other'})}}
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
targetEntity: { name: 'person', id: acp.requestorPerson.id },
action: 'show',
displayBadge: true,
buttonText: acp.requestorPerson|chill_entity_render_string,
isDead: acp.requestorPerson.deathdate is not null
} %}
{% endif %}
</h3>
</div>
</div>
<div class="wl-col list">
{% if acp.requestorThirdParty is not null %}
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
targetEntity: { name: 'thirdparty', id: acp.requestorThirdParty.id },
action: 'show',
displayBadge: true,
buttonText: acp.requestorThirdParty|chill_entity_render_string
} %}
{% else %}
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
targetEntity: { name: 'person', id: acp.requestorPerson.id },
action: 'show',
displayBadge: true,
buttonText: acp.requestorPerson|chill_entity_render_string,
isDead: acp.requestorPerson.deathdate is not null
} %}
{% endif %}
</div>
</div>
{% endif %}
{% endif %}
</div>
</div>
{% endfor %}

View File

@ -23,7 +23,7 @@
{% for resource in personResources %}
<div class="item-bloc">
<div class="item-row">
<div class="item-col">
<div class="item-col" style="width: 50%">
{% if resource.person is not null %}
<div class="denomination h3">
<span class="name">{{ resource.person }}</span>
@ -32,10 +32,14 @@
{% elseif resource.thirdparty is not null %}
<div class="denomination h3">
<span class="name">{{ resource.thirdparty }}</span>
<span class="badge rounded-pill bg-thirdparty">
<span class="badge rounded-pill bg-thirdparty">
{% if resource.thirdparty.parent is not null %}
{{ 'Contact person'|trans|capitalize }}
{% else %}
{{ 'thirdparty'|trans|capitalize }}
<i class="fa fa-fw fa-user-md"></i>
</span>
{% endif %}
<i class="fa fa-fw fa-user-md"></i>
</span>
</div>
{% else %}
<div class="denomination h3">
@ -43,7 +47,7 @@
</div>
{% endif %}
</div>
<div class="item-col">
<div class="item-col" style="justify-content: flex-end; ">
{% if resource.kind %}
<span>{{ resource.kind.title.fr|capitalize }}</span>
{% endif %}
@ -56,7 +60,7 @@
</section>
</div>
{% endif %}
{% if is_granted('CHILL_PERSON_UPDATE', resource.person) %}
{% if is_granted('CHILL_PERSON_UPDATE', resource.personOwner) %}
<div class="item-row separator">
<div class="item-col">
<ul class="record_actions">
@ -72,6 +76,25 @@
class="btn btn-sm btn-delete"
title="{{ 'Delete'|trans }}"></a>
</li>
<li>
{% if resource.person is not null %}
<span class="wl-item">
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
action: 'show', displayBadge: false,
targetEntity: { name: 'person', id: resource.person.id },
} %}
</span>
{% endif %}
{% if resource.thirdparty is not null %}
<span class="wl-item">
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
action: 'show', displayBadge: false,
targetEntity: { name: 'thirdparty', id: resource.thirdparty.id },
parent: resource.thirdparty.parent
} %}
</span>
{% endif %}
</li>
</ul>
</div>
</div>

View File

@ -44,6 +44,7 @@ class AccompanyingPeriodWorkEvaluationNormalizer implements ContextAwareNormaliz
*/
public function normalize($object, ?string $format = null, array $context = []): array
{
dump($context);
$initial = $this->normalizer->normalize($object, $format, array_merge(
$context,
[self::IGNORE_EVALUATION => spl_object_hash($object)]

View File

@ -109,7 +109,6 @@ final class AccompanyingPeriodConfidentialTest extends WebTestCase
$user = new stdClass();
$user->id = 0;
$user->type = 'user';
dump($user);
$this->client->request(
Request::METHOD_PATCH,

View File

@ -237,6 +237,7 @@ no comment found: "Aucun commentaire"
Select a type: "Choisissez un type"
Select a person: "Choisissez un usager"
Select a thirdparty: "Choisissez un tiers"
Contact person: "Personne de contact"
# pickAPersonType
@ -486,6 +487,10 @@ Household summary: Résumé du ménage
Edit household address: Modifier l'adresse du ménage
Show household: Voir le ménage
Back to household: Revenir au ménage
Remove household composition: Supprimer composition familiale
Are you sure you want to remove this composition?: Etes-vous sûr de vouloir supprimer cette composition familiale ?
Concerns household n°%id%: Concerne le ménage n°%id%
Composition: Composition
# accompanying course work
Accompanying Course Actions: Actions d'accompagnements