mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-10-31 17:28:23 +00:00 
			
		
		
		
	Compare commits
	
		
			88 Commits
		
	
	
		
			425-rename
			...
			testing202
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| aabf62d399 | |||
| d2d297a377 | |||
| 0541995a60 | |||
| 29e054bd10 | |||
| da0099aafc | |||
| 3a18ea42fe | |||
| e60435b8cc | |||
| ab6ab19499 | |||
| 2a1762ea8d | |||
| 18ababbca9 | |||
| f6179cd3a3 | |||
| ddf8da4cee | |||
| bf2181c2f1 | |||
| d508fde8d2 | |||
| 14dba22181 | |||
| 7dc7e77c62 | |||
| 9d58904969 | |||
| 4d90c7028f | |||
| 3abb76d268 | |||
| d62dd4396e | |||
| 59e8d9d516 | |||
| 7dcb8abe38 | |||
| a0b2d92ba2 | |||
| 7843e5dfd1 | |||
| 32c847267b | |||
| 9b353f4d1b | |||
| 81a858f07a | |||
| 6a2ee232a9 | |||
| 56c43a0a76 | |||
| eb724a730c | |||
| 18f98b6795 | |||
| d73994edd0 | |||
| 70603570c8 | |||
| df09dd2017 | |||
| 1c87280b1e | |||
| 445e093a28 | |||
| 3f91c65b30 | |||
| 9bc3c16b58 | |||
| 12dff82248 | |||
| ab23a4efb5 | |||
| 204fb20475 | |||
| f430d97152 | |||
| 4fa4d3b65c | |||
| bd4c34cc1d | |||
| 4cea678e93 | |||
| 5e6833975b | |||
| f523b9adb3 | |||
| a211549432 | |||
| 17b1363113 | |||
| 3356ed8e57 | |||
| 2a7fa517ee | |||
| 85781c8e14 | |||
| 00eb435896 | |||
| ed71cffd6a | |||
| ae679e6997 | |||
| e1d308fd97 | |||
| d9acda67e3 | |||
| e88da74882 | |||
| 591c44d1a0 | |||
| bf04b7981c | |||
| df33eec30f | |||
| c657c98918 | |||
| ef5eb5b907 | |||
| d683fe002d | |||
| 555bbca59b | |||
| e9e9d5c458 | |||
| b1842a33ae | |||
| 6afeaccf24 | |||
| fb76bac480 | |||
| 6ded185289 | |||
| 95adc29f9d | |||
| 4d0c3e683f | |||
| 018aafc773 | |||
| c4aea4efc2 | |||
| 225e3ca13f | |||
| 8c1fa7956a | |||
| e253d1b276 | |||
| a52aac2d98 | |||
| 9e8cf60dd8 | |||
| 7682d81d50 | |||
| 5d31ce96c1 | |||
| 81ef64a246 | |||
| 49d1f78001 | |||
| 0d0f3528e2 | |||
| d97d5e689a | |||
| 95d80ce13e | |||
| 668720984d | |||
| 245c3fa121 | 
							
								
								
									
										6
									
								
								.changes/unreleased/Feature-20250211-142243.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.changes/unreleased/Feature-20250211-142243.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| kind: Feature | ||||
| body: Allow the merge of two accompanying period works | ||||
| time: 2025-02-11T14:22:43.134106669+01:00 | ||||
| custom: | ||||
|     Issue: "359" | ||||
|     SchemaChange: No schema change | ||||
							
								
								
									
										6
									
								
								.changes/unreleased/Feature-20250403-100311.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.changes/unreleased/Feature-20250403-100311.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| kind: Feature | ||||
| body: Duplication of a document to another accompanying period work evaluation | ||||
| time: 2025-04-03T10:03:11.796736107+02:00 | ||||
| custom: | ||||
|     Issue: "369" | ||||
|     SchemaChange: No schema change | ||||
							
								
								
									
										6
									
								
								.changes/unreleased/Feature-20250403-100857.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.changes/unreleased/Feature-20250403-100857.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| kind: Feature | ||||
| body: Fusion of two accompanying period works | ||||
| time: 2025-04-03T10:08:57.25079018+02:00 | ||||
| custom: | ||||
|     Issue: "359" | ||||
|     SchemaChange: No schema change | ||||
| @@ -4,6 +4,7 @@ import { StoredObject, StoredObjectVersion } from "../../types"; | ||||
| import DropFileWidget from "ChillDocStoreAssets/vuejs/DropFileWidget/DropFileWidget.vue"; | ||||
| import { computed, reactive } from "vue"; | ||||
| import { useToast } from "vue-toast-notification"; | ||||
| import { DOCUMENT_REPLACE, DOCUMENT_ADD, trans } from "translator"; | ||||
|  | ||||
| interface DropFileConfig { | ||||
|     allowRemove: boolean; | ||||
| @@ -75,10 +76,10 @@ function closeModal(): void { | ||||
|         @click="openModal" | ||||
|         class="btn btn-create" | ||||
|     > | ||||
|         Ajouter un document | ||||
|         {{ trans(DOCUMENT_ADD) }} | ||||
|     </button> | ||||
|     <button v-else @click="openModal" class="btn btn-edit"> | ||||
|         Remplacer le document | ||||
|     <button v-else @click="openModal" class="dropdown-item"> | ||||
|         {{ trans(DOCUMENT_REPLACE) }} | ||||
|     </button> | ||||
|     <modal | ||||
|         v-if="state.showModal" | ||||
|   | ||||
| @@ -23,6 +23,8 @@ See the document: Voir le document | ||||
|  | ||||
| document: | ||||
|     Any title: Aucun titre | ||||
|     replace: Remplacer | ||||
|     Add: Ajouter un document | ||||
|  | ||||
| generic_doc: | ||||
|     filter: | ||||
|   | ||||
| @@ -280,11 +280,17 @@ | ||||
|     </div> | ||||
| {% endblock %} | ||||
|  | ||||
| {% block pick_linked_entities_widget %} | ||||
|     <input type="hidden" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value|escape('html_attr') }}" {% endif %} data-input-uniqid="{{ form.vars['uniqid'] }}" /> | ||||
|     <div data-input-uniqid="{{ form.vars['uniqid'] }}" data-module="pick-linked-entities" data-pick-entities-type="{{ form.vars['pick-entities-type'] }}" | ||||
|     ></div> | ||||
|  | ||||
| {% block pick_linked_entities_widget %} | ||||
|     <input type="hidden" {{ block('widget_attributes') }} | ||||
|         {% if value is not empty %}value="{{ value|escape('html_attr') }}" {% endif %} | ||||
|        data-input-uniqid="{{ form.vars['uniqid'] }}"/> | ||||
|     <div | ||||
|         data-input-uniqid="{{ form.vars['uniqid'] }}" | ||||
|         data-module="pick-linked-entities" | ||||
|         data-pick-entities-type="{{ form.vars['pick-entities-type'] }}" | ||||
|          data-suggested="{{ form.vars['suggested']|json_encode|escape('html_attr') }}" | ||||
|     ></div> | ||||
| {% endblock %} | ||||
|  | ||||
| {% block pick_postal_code_widget %} | ||||
|   | ||||
| @@ -18,6 +18,7 @@ use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepos | ||||
| use Chill\PersonBundle\Service\AccompanyingPeriodWork\AccompanyingPeriodWorkMergeService; | ||||
| use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
| use Symfony\Component\HttpFoundation\Response; | ||||
| use Symfony\Component\HttpFoundation\Session\Session; | ||||
| use Symfony\Component\Routing\Annotation\Route; | ||||
| use Symfony\Component\Translation\TranslatableMessage; | ||||
| @@ -32,7 +33,7 @@ class AccompanyingPeriodWorkDuplicateController extends AbstractController | ||||
|      * @ParamConverter("accompanyingPeriodWork", options={"id": "acpw_id"}) | ||||
|      */ | ||||
|     #[Route(path: '{_locale}/person/accompanying-period/work/{id}/assign-duplicate', name: 'chill_person_accompanying_period_work_assign_duplicate')] | ||||
|     public function assignDuplicate(AccompanyingPeriodWork $acpw, Request $request) | ||||
|     public function assignDuplicate(AccompanyingPeriodWork $acpw, Request $request): Response | ||||
|     { | ||||
|         $accompanyingPeriod = $acpw->getAccompanyingPeriod(); | ||||
|  | ||||
| @@ -79,7 +80,7 @@ class AccompanyingPeriodWorkDuplicateController extends AbstractController | ||||
|      * @ParamConverter("acpw2", options={"id": "acpw2_id"}) | ||||
|      */ | ||||
|     #[Route(path: '/{_locale}/person/{acpw1_id}/duplicate/{acpw2_id}/confirm', name: 'chill_person_acpw_duplicate_confirm')] | ||||
|     public function confirmAction(AccompanyingPeriodWork $acpw1, AccompanyingPeriodWork $acpw2, Request $request) | ||||
|     public function confirmAction(AccompanyingPeriodWork $acpw1, AccompanyingPeriodWork $acpw2, Request $request): Response | ||||
|     { | ||||
|         $accompanyingPeriod = $acpw1->getAccompanyingPeriod(); | ||||
|  | ||||
| @@ -98,6 +99,7 @@ class AccompanyingPeriodWorkDuplicateController extends AbstractController | ||||
|                     $session->getFlashBag()->add('success', new TranslatableMessage('acpw_duplicate.Successfully merged')); | ||||
|                 } | ||||
|  | ||||
|  | ||||
|                 return $this->redirectToRoute('chill_person_accompanying_period_work_show', ['id' => $acpw1->getId()]); | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -12,6 +12,7 @@ declare(strict_types=1); | ||||
| namespace Chill\PersonBundle\Controller; | ||||
|  | ||||
| use Chill\MainBundle\Routing\ChillUrlGeneratorInterface; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument; | ||||
| use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter; | ||||
| use Chill\PersonBundle\Service\AccompanyingPeriodWorkEvaluationDocument\AccompanyingPeriodWorkEvaluationDocumentDuplicator; | ||||
| @@ -24,15 +25,16 @@ use Symfony\Component\Routing\Annotation\Route; | ||||
| use Symfony\Component\Security\Core\Security; | ||||
| use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; | ||||
| use Symfony\Component\Serializer\SerializerInterface; | ||||
| use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; | ||||
|  | ||||
| class AccompanyingPeriodWorkEvaluationDocumentDuplicateController | ||||
| readonly class AccompanyingPeriodWorkEvaluationDocumentDuplicateController | ||||
| { | ||||
|     public function __construct( | ||||
|         private readonly AccompanyingPeriodWorkEvaluationDocumentDuplicator $duplicator, | ||||
|         private readonly Security $security, | ||||
|         private readonly SerializerInterface $serializer, | ||||
|         private readonly EntityManagerInterface $entityManager, | ||||
|         private readonly ChillUrlGeneratorInterface $urlGenerator, | ||||
|         private AccompanyingPeriodWorkEvaluationDocumentDuplicator $duplicator, | ||||
|         private Security $security, | ||||
|         private SerializerInterface $serializer, | ||||
|         private EntityManagerInterface $entityManager, | ||||
|         private ChillUrlGeneratorInterface $urlGenerator, | ||||
|     ) {} | ||||
|  | ||||
|     #[Route('/api/1.0/person/accompanying-course-work-evaluation-document/{id}/duplicate', methods: ['POST'])] | ||||
| @@ -56,6 +58,32 @@ class AccompanyingPeriodWorkEvaluationDocumentDuplicateController | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @ParamConverter("document", options={"id": "document_id"}) | ||||
|      * @ParamConverter("evaluation", options={"id": "evaluation_id"}) | ||||
|      */ | ||||
|     #[Route('/api/1.0/person/accompanying-course-work-evaluation-document/{document_id}/evaluation/{evaluation_id}/duplicate', methods: ['POST'])] | ||||
|     public function duplicateToEvaluationApi(AccompanyingPeriodWorkEvaluationDocument $document, AccompanyingPeriodWorkEvaluation $evaluation): Response | ||||
|     { | ||||
|         $work = $evaluation->getAccompanyingPeriodWork(); | ||||
|  | ||||
|         if (!$this->security->isGranted(AccompanyingPeriodWorkVoter::UPDATE, $work)) { | ||||
|             throw new AccessDeniedHttpException('not allowed to edit this accompanying period work'); | ||||
|         } | ||||
|  | ||||
|         $duplicatedDocument = $this->duplicator->duplicateToEvaluation($document, $evaluation); | ||||
|  | ||||
|         $this->entityManager->persist($duplicatedDocument); | ||||
|         $this->entityManager->persist($duplicatedDocument->getStoredObject()); | ||||
|         $this->entityManager->persist($evaluation); | ||||
|         $this->entityManager->flush(); | ||||
|  | ||||
|         return new JsonResponse( | ||||
|             $this->serializer->serialize($duplicatedDocument, 'json', [AbstractNormalizer::GROUPS => ['read']]), | ||||
|             json: true | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     #[Route('/{_locale}/person/accompanying-course-work-evaluation-document/{id}/duplicate', name: 'chill_person_accompanying_period_work_evaluation_document_duplicate', methods: ['POST'])] | ||||
|     public function duplicate(AccompanyingPeriodWorkEvaluationDocument $document): Response | ||||
|     { | ||||
|   | ||||
| @@ -0,0 +1,58 @@ | ||||
| <?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\PersonBundle\Controller; | ||||
|  | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument; | ||||
| use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Symfony\Component\HttpFoundation\JsonResponse; | ||||
| use Symfony\Component\HttpFoundation\Response; | ||||
| use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; | ||||
| use Symfony\Component\Routing\Annotation\Route; | ||||
| use Symfony\Component\Security\Core\Security; | ||||
| use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; | ||||
| use Symfony\Component\Serializer\SerializerInterface; | ||||
| use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; | ||||
|  | ||||
| readonly class AccompanyingPeriodWorkEvaluationDocumentMoveController | ||||
| { | ||||
|     public function __construct( | ||||
|         private Security $security, | ||||
|         private SerializerInterface $serializer, | ||||
|         private EntityManagerInterface $entityManager, | ||||
|     ) {} | ||||
|  | ||||
|     /** | ||||
|      * @ParamConverter("document", options={"id": "document_id"}) | ||||
|      * @ParamConverter("evaluation", options={"id": "evaluation_id"}) | ||||
|      */ | ||||
|     #[Route('/api/1.0/person/accompanying-course-work-evaluation-document/{document_id}/evaluation/{evaluation_id}/move', methods: ['POST'])] | ||||
|     public function moveToEvaluationApi(AccompanyingPeriodWorkEvaluationDocument $document, AccompanyingPeriodWorkEvaluation $evaluation): Response | ||||
|     { | ||||
|         $work = $evaluation->getAccompanyingPeriodWork(); | ||||
|  | ||||
|         if (!$this->security->isGranted(AccompanyingPeriodWorkVoter::UPDATE, $work)) { | ||||
|             throw new AccessDeniedHttpException('not allowed to edit this accompanying period work'); | ||||
|         } | ||||
|  | ||||
|         $document->setAccompanyingPeriodWorkEvaluation($evaluation); | ||||
|  | ||||
|         $this->entityManager->persist($document); | ||||
|         $this->entityManager->flush(); | ||||
|  | ||||
|         return new JsonResponse( | ||||
|             $this->serializer->serialize($document, 'json', [AbstractNormalizer::GROUPS => ['read']]), | ||||
|             json: true | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| @@ -98,16 +98,6 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct | ||||
|  | ||||
|     public function setAccompanyingPeriodWorkEvaluation(?AccompanyingPeriodWorkEvaluation $accompanyingPeriodWorkEvaluation): AccompanyingPeriodWorkEvaluationDocument | ||||
|     { | ||||
|         // if an evaluation is already associated, we cannot change the association (removing the association, | ||||
|         // by setting a null value, is allowed. | ||||
|         if ( | ||||
|             $this->accompanyingPeriodWorkEvaluation instanceof AccompanyingPeriodWorkEvaluation | ||||
|             && $accompanyingPeriodWorkEvaluation instanceof AccompanyingPeriodWorkEvaluation | ||||
|         ) { | ||||
|             if ($this->accompanyingPeriodWorkEvaluation !== $accompanyingPeriodWorkEvaluation) { | ||||
|                 throw new \RuntimeException('It is not allowed to change the evaluation for a document'); | ||||
|             } | ||||
|         } | ||||
|         $this->accompanyingPeriodWorkEvaluation = $accompanyingPeriodWorkEvaluation; | ||||
|  | ||||
|         return $this; | ||||
|   | ||||
| @@ -24,7 +24,7 @@ class FindAccompanyingPeriodWorkType extends AbstractType | ||||
|     { | ||||
|         $builder | ||||
|             ->add('acpw', PickLinkedAccompanyingPeriodWorkType::class, [ | ||||
|                 'label' => 'Social action', | ||||
|                 'label' => 'Accompanying period work', | ||||
|                 'multiple' => false, | ||||
|                 'accompanyingPeriod' => $options['accompanyingPeriod'], | ||||
|             ]) | ||||
|   | ||||
| @@ -16,18 +16,26 @@ use Symfony\Component\Form\AbstractType; | ||||
| use Symfony\Component\Form\FormInterface; | ||||
| use Symfony\Component\Form\FormView; | ||||
| use Symfony\Component\OptionsResolver\OptionsResolver; | ||||
| use Symfony\Component\Serializer\Normalizer\NormalizerInterface; | ||||
|  | ||||
| class PickLinkedAccompanyingPeriodWorkType extends AbstractType | ||||
| { | ||||
|     public function __construct(private readonly NormalizerInterface $normalizer) {} | ||||
|  | ||||
|     public function buildView(FormView $view, FormInterface $form, array $options) | ||||
|     { | ||||
|         $view->vars['multiple'] = $options['multiple']; | ||||
|         $view->vars['types'] = ['acpw']; | ||||
|         $view->vars['uniqid'] = uniqid('pick_acpw_dyn'); | ||||
|         $view->vars['suggested'] = []; | ||||
|         $view->vars['as_id'] = true === $options['as_id'] ? '1' : '0'; | ||||
|         $view->vars['submit_on_adding_new_entity'] = false; | ||||
|         $view->vars['pick-entities-type'] = 'acpw'; | ||||
|         $view->vars['attr']['data-accompanying-period-id'] = $options['accompanyingPeriod']->getId(); | ||||
|  | ||||
|         foreach ($options['suggested'] as $suggestion) { | ||||
|             $view->vars['suggested'][] = $this->normalizer->normalize($suggestion, 'json', ['groups' => 'read']); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public function configureOptions(OptionsResolver $resolver) | ||||
| @@ -38,6 +46,7 @@ class PickLinkedAccompanyingPeriodWorkType extends AbstractType | ||||
|             ->setDefault('multiple', false) | ||||
|             ->setAllowedTypes('multiple', ['bool']) | ||||
|             ->setDefault('compound', false) | ||||
|             ->setDefault('suggested', []) | ||||
|             ->setDefault('as_id', false) | ||||
|             ->setAllowedTypes('as_id', ['bool']) | ||||
|             ->setDefault('submit_on_adding_new_entity', false) | ||||
|   | ||||
| @@ -41,7 +41,8 @@ document.addEventListener("DOMContentLoaded", () => { | ||||
|             methods: { | ||||
|                 pickWork: function (payload: { work: AccompanyingPeriodWork }) { | ||||
|                     console.log("payload", payload); | ||||
|                     input.value = payload.work.id.toString(); | ||||
|  | ||||
|                     input.value = payload.work.id?.toString() ?? ""; | ||||
|                 }, | ||||
|             }, | ||||
|         }); | ||||
|   | ||||
| @@ -84,7 +84,7 @@ export interface AccompanyingPeriodWorkEvaluationDocument { | ||||
| } | ||||
|  | ||||
| export interface AccompanyingPeriodWork { | ||||
|     id: number; | ||||
|     id?: number; | ||||
|     accompanyingPeriod?: AccompanyingPeriod; | ||||
|     accompanyingPeriodWorkEvaluations: AccompanyingPeriodWorkEvaluation[]; | ||||
|     createdAt?: string; | ||||
|   | ||||
| @@ -972,7 +972,7 @@ div#workEditor { | ||||
|                 font-size: 85%; | ||||
|             } | ||||
|  | ||||
|             i.fa { | ||||
|             & > i.fa { | ||||
|                 padding: 0.25rem; | ||||
|                 color: $white; | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,31 @@ | ||||
| <template> | ||||
|     <div class="row mb-3"> | ||||
|         <label class="col-sm-4 col-form-label visually-hidden">{{ | ||||
|             trans(EVALUATION_PUBLIC_COMMENT) | ||||
|         }}</label> | ||||
|         <div class="col-sm-12"> | ||||
|             <ckeditor | ||||
|                 :editor="ClassicEditor" | ||||
|                 :config="classicEditorConfig" | ||||
|                 :placeholder="trans(EVALUATION_COMMENT_PLACEHOLDER)" | ||||
|                 :value="comment" | ||||
|                 @input="$emit('update:comment', $event)" | ||||
|                 tag-name="textarea" | ||||
|             ></ckeditor> | ||||
|         </div> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <script setup> | ||||
| import { Ckeditor } from "@ckeditor/ckeditor5-vue"; | ||||
| import { ClassicEditor } from "ckeditor5"; | ||||
| import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config"; | ||||
| import { | ||||
|     EVALUATION_PUBLIC_COMMENT, | ||||
|     EVALUATION_COMMENT_PLACEHOLDER, | ||||
|     trans, | ||||
| } from "translator"; | ||||
|  | ||||
| defineProps(["comment"]); | ||||
| defineEmits(["update:comment"]); | ||||
| </script> | ||||
| @@ -0,0 +1,71 @@ | ||||
| <template> | ||||
|     <div class="row mb-3"> | ||||
|         <label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label"> | ||||
|             {{ trans(EVALUATION_STARTDATE) }} | ||||
|         </label> | ||||
|         <div class="col-8 col-sm-4 col-md-8 col-lg-4"> | ||||
|             <input | ||||
|                 class="form-control form-control-sm" | ||||
|                 type="date" | ||||
|                 :value="startDate" | ||||
|                 @input="$emit('update:startDate', $event.target.value)" | ||||
|             /> | ||||
|         </div> | ||||
|  | ||||
|         <label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label"> | ||||
|             {{ trans(EVALUATION_ENDDATE) }} | ||||
|         </label> | ||||
|         <div class="col-8 col-sm-4 col-md-8 col-lg-4"> | ||||
|             <input | ||||
|                 class="form-control form-control-sm" | ||||
|                 type="date" | ||||
|                 :value="endDate" | ||||
|                 @input="$emit('update:endDate', $event.target.value)" | ||||
|             /> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     <div class="row mb-3"> | ||||
|         <label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label"> | ||||
|             {{ trans(EVALUATION_MAXDATE) }} | ||||
|         </label> | ||||
|         <div class="col-8 col-sm-4 col-md-8 col-lg-4"> | ||||
|             <input | ||||
|                 class="form-control form-control-sm" | ||||
|                 type="date" | ||||
|                 :value="maxDate" | ||||
|                 @input="$emit('update:maxDate', $event.target.value)" | ||||
|             /> | ||||
|         </div> | ||||
|  | ||||
|         <label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label"> | ||||
|             {{ trans(EVALUATION_WARNING_INTERVAL) }} | ||||
|         </label> | ||||
|         <div class="col-8 col-sm-4 col-md-8 col-lg-4"> | ||||
|             <input | ||||
|                 class="form-control form-control-sm" | ||||
|                 type="number" | ||||
|                 :value="warningInterval" | ||||
|                 @input="$emit('update:warningInterval', $event.target.value)" | ||||
|             /> | ||||
|         </div> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <script setup> | ||||
| import { | ||||
|     EVALUATION_STARTDATE, | ||||
|     EVALUATION_ENDDATE, | ||||
|     EVALUATION_MAXDATE, | ||||
|     EVALUATION_WARNING_INTERVAL, | ||||
|     trans, | ||||
| } from "translator"; | ||||
|  | ||||
| defineProps(["startDate", "endDate", "maxDate", "warningInterval"]); | ||||
| defineEmits([ | ||||
|     "update:startDate", | ||||
|     "update:endDate", | ||||
|     "update:maxDate", | ||||
|     "update:warningInterval", | ||||
| ]); | ||||
| </script> | ||||
| @@ -0,0 +1,51 @@ | ||||
| <template> | ||||
|     <div class="row mb-3"> | ||||
|         <h6>{{ trans(EVALUATION_DOCUMENT_ADD) }} :</h6> | ||||
|         <pick-template | ||||
|             entityClass="Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation" | ||||
|             :id="evaluation.id" | ||||
|             :templates="templates" | ||||
|             :preventDefaultMoveToGenerate="true" | ||||
|             @go-to-generate-document="$emit('submitBeforeGenerate', $event)" | ||||
|         > | ||||
|             <template v-slot:title> | ||||
|                 <label class="col-form-label">{{ | ||||
|                     trans(EVALUATION_GENERATE_A_DOCUMENT) | ||||
|                 }}</label> | ||||
|             </template> | ||||
|         </pick-template> | ||||
|         <div> | ||||
|             <label class="col-form-label">{{ | ||||
|                 trans(EVALUATION_DOCUMENT_UPLOAD) | ||||
|             }}</label> | ||||
|             <ul class="record_actions document-upload"> | ||||
|                 <li> | ||||
|                     <drop-file-modal | ||||
|                         :allow-remove="false" | ||||
|                         @add-document="$emit('addDocument', $event)" | ||||
|                     ></drop-file-modal> | ||||
|                 </li> | ||||
|             </ul> | ||||
|         </div> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <script setup> | ||||
| import PickTemplate from "ChillDocGeneratorAssets/vuejs/_components/PickTemplate.vue"; | ||||
| import DropFileModal from "ChillDocStoreAssets/vuejs/DropFileWidget/DropFileModal.vue"; | ||||
| import { | ||||
|     EVALUATION_DOCUMENT_ADD, | ||||
|     EVALUATION_DOCUMENT_UPLOAD, | ||||
|     EVALUATION_GENERATE_A_DOCUMENT, | ||||
|     trans, | ||||
| } from "translator"; | ||||
|  | ||||
| defineProps(["evaluation", "templates"]); | ||||
| defineEmits(["addDocument", "submitBeforeGenerate"]); | ||||
| </script> | ||||
|  | ||||
| <style scoped> | ||||
| ul.document-upload { | ||||
|     justify-content: flex-start; | ||||
| } | ||||
| </style> | ||||
| @@ -0,0 +1,361 @@ | ||||
| <template> | ||||
|     <div class="row mb-3"> | ||||
|         <h5>{{ trans(EVALUATION_DOCUMENTS) }} :</h5> | ||||
|         <div class="flex-table"> | ||||
|             <div | ||||
|                 class="item-bloc" | ||||
|                 v-for="(d, i) in documents" | ||||
|                 :key="d.id" | ||||
|                 :class="[ | ||||
|                     parseInt(docAnchorId) === d.id ? 'bg-blink' : 'nothing', | ||||
|                 ]" | ||||
|             > | ||||
|                 <div :id="'document_' + d.id" class="item-row"> | ||||
|                     <div class="input-group input-group-lg mb-3 row"> | ||||
|                         <label class="col-sm-3 col-form-label" | ||||
|                             >Titre du document:</label | ||||
|                         > | ||||
|                         <div class="col-sm-9"> | ||||
|                             <input | ||||
|                                 class="form-control document-title" | ||||
|                                 type="text" | ||||
|                                 :value="d.title" | ||||
|                                 :id="d.id" | ||||
|                                 :data-key="i" | ||||
|                                 @input="$emit('inputDocumentTitle', $event)" | ||||
|                             /> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="item-row"> | ||||
|                     <div class="item-col item-meta"> | ||||
|                         <p v-if="d.createdBy" class="createdBy"> | ||||
|                             Créé par {{ d.createdBy.text }}<br /> | ||||
|                             Le | ||||
|                             {{ | ||||
|                                 $d(ISOToDatetime(d.createdAt.datetime), "long") | ||||
|                             }} | ||||
|                         </p> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="item-row"> | ||||
|                     <div class="item-col"> | ||||
|                         <ul class="record_actions"> | ||||
|                             <li | ||||
|                                 v-if=" | ||||
|                                     d.workflows_availables.length > 0 || | ||||
|                                     d.workflows.length > 0 | ||||
|                                 " | ||||
|                             > | ||||
|                                 <list-workflow-modal | ||||
|                                     :workflows="d.workflows" | ||||
|                                     :allowCreate="true" | ||||
|                                     relatedEntityClass="Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument" | ||||
|                                     :relatedEntityId="d.id" | ||||
|                                     :workflowsAvailables=" | ||||
|                                         d.workflows_availables | ||||
|                                     " | ||||
|                                     :preventDefaultMoveToGenerate="true" | ||||
|                                     :goToGenerateWorkflowPayload="{ doc: d }" | ||||
|                                     @go-to-generate-workflow=" | ||||
|                                         $emit('goToGenerateWorkflow', $event) | ||||
|                                     " | ||||
|                                 ></list-workflow-modal> | ||||
|                             </li> | ||||
|                             <li> | ||||
|                                 <button | ||||
|                                     v-if="AmIRefferer" | ||||
|                                     class="btn btn-notify" | ||||
|                                     @click=" | ||||
|                                         $emit( | ||||
|                                             'goToGenerateNotification', | ||||
|                                             d, | ||||
|                                             false, | ||||
|                                         ) | ||||
|                                     " | ||||
|                                 ></button> | ||||
|                                 <template v-else> | ||||
|                                     <button | ||||
|                                         id="btnGroupNotifyButtons" | ||||
|                                         type="button" | ||||
|                                         class="btn btn-notify dropdown-toggle" | ||||
|                                         :title=" | ||||
|                                             trans(EVALUATION_NOTIFICATION_SEND) | ||||
|                                         " | ||||
|                                         data-bs-toggle="dropdown" | ||||
|                                         aria-expanded="false" | ||||
|                                     > | ||||
|                                           | ||||
|                                     </button> | ||||
|                                     <ul | ||||
|                                         class="dropdown-menu" | ||||
|                                         aria-labelledby="btnGroupNotifyButtons" | ||||
|                                     > | ||||
|                                         <li> | ||||
|                                             <a | ||||
|                                                 class="dropdown-item" | ||||
|                                                 @click=" | ||||
|                                                     $emit( | ||||
|                                                         'goToGenerateNotification', | ||||
|                                                         d, | ||||
|                                                         true, | ||||
|                                                     ) | ||||
|                                                 " | ||||
|                                             > | ||||
|                                                 {{ | ||||
|                                                     trans( | ||||
|                                                         EVALUATION_NOTIFICATION_NOTIFY_REFERRER, | ||||
|                                                     ) | ||||
|                                                 }} | ||||
|                                             </a> | ||||
|                                         </li> | ||||
|                                         <li> | ||||
|                                             <a | ||||
|                                                 class="dropdown-item" | ||||
|                                                 @click=" | ||||
|                                                     $emit( | ||||
|                                                         'goToGenerateNotification', | ||||
|                                                         d, | ||||
|                                                         false, | ||||
|                                                     ) | ||||
|                                                 " | ||||
|                                             > | ||||
|                                                 {{ | ||||
|                                                     trans( | ||||
|                                                         EVALUATION_NOTIFICATION_NOTIFY_ANY, | ||||
|                                                     ) | ||||
|                                                 }} | ||||
|                                             </a> | ||||
|                                         </li> | ||||
|                                     </ul> | ||||
|                                 </template> | ||||
|                             </li> | ||||
|                             <li> | ||||
|                                 <document-action-buttons-group | ||||
|                                     :stored-object="d.storedObject" | ||||
|                                     :filename="d.title" | ||||
|                                     :can-edit="true" | ||||
|                                     :execute-before-leave=" | ||||
|                                         submitBeforeLeaveToEditor | ||||
|                                     " | ||||
|                                     :davLink=" | ||||
|                                         d.storedObject._links?.dav_link.href | ||||
|                                     " | ||||
|                                     :davLinkExpiration=" | ||||
|                                         d.storedObject._links?.dav_link | ||||
|                                             .expiration | ||||
|                                     " | ||||
|                                     @on-stored-object-status-change=" | ||||
|                                         $emit('statusDocumentChanged', $event) | ||||
|                                     " | ||||
|                                 ></document-action-buttons-group> | ||||
|                             </li> | ||||
|                             <li v-if="Number.isInteger(d.id)"> | ||||
|                                 <div class="duplicate-dropdown"> | ||||
|                                     <button | ||||
|                                         class="btn btn-edit dropdown-toggle" | ||||
|                                         type="button" | ||||
|                                         data-bs-toggle="dropdown" | ||||
|                                         aria-expanded="false" | ||||
|                                     > | ||||
|                                         {{ trans(EVALUATION_DOCUMENT_EDIT) }} | ||||
|                                     </button> | ||||
|                                     <ul class="dropdown-menu"> | ||||
|                                         <!--delete--> | ||||
|                                         <li v-if="d.workflows.length === 0"> | ||||
|                                             <a | ||||
|                                                 class="dropdown-item" | ||||
|                                                 @click=" | ||||
|                                                     $emit('removeDocument', d) | ||||
|                                                 " | ||||
|                                             > | ||||
|                                                 <i | ||||
|                                                     class="fa fa-trash-o" | ||||
|                                                     aria-hidden="true" | ||||
|                                                 ></i> | ||||
|                                                 {{ | ||||
|                                                     trans( | ||||
|                                                         EVALUATION_DOCUMENT_DELETE, | ||||
|                                                     ) | ||||
|                                                 }} | ||||
|                                             </a> | ||||
|                                         </li> | ||||
|                                         <!--replace document--> | ||||
|                                         <li | ||||
|                                             v-if=" | ||||
|                                                 d.storedObject._permissions | ||||
|                                                     .canEdit | ||||
|                                             " | ||||
|                                         > | ||||
|                                             <drop-file-modal | ||||
|                                                 :existing-doc="d.storedObject" | ||||
|                                                 :allow-remove="false" | ||||
|                                                 @add-document=" | ||||
|                                                     (arg) => | ||||
|                                                         $emit( | ||||
|                                                             'replaceDocument', | ||||
|                                                             d, | ||||
|                                                             arg.stored_object, | ||||
|                                                             arg.stored_object_version, | ||||
|                                                         ) | ||||
|                                                 " | ||||
|                                             ></drop-file-modal> | ||||
|                                         </li> | ||||
|                                         <!--duplicate document--> | ||||
|                                         <li> | ||||
|                                             <a | ||||
|                                                 class="dropdown-item" | ||||
|                                                 @click=" | ||||
|                                                     $emit( | ||||
|                                                         'duplicateDocument', | ||||
|                                                         d, | ||||
|                                                     ) | ||||
|                                                 " | ||||
|                                             > | ||||
|                                                 <i | ||||
|                                                     class="fa fa-copy" | ||||
|                                                     aria-hidden="true" | ||||
|                                                 ></i> | ||||
|                                                 {{ | ||||
|                                                     trans( | ||||
|                                                         EVALUATION_DOCUMENT_DUPLICATE_HERE, | ||||
|                                                     ) | ||||
|                                                 }} | ||||
|                                             </a> | ||||
|                                         </li> | ||||
|                                         <li> | ||||
|                                             <a | ||||
|                                                 class="dropdown-item" | ||||
|                                                 @click=" | ||||
|                                                     prepareDocumentDuplicationToWork( | ||||
|                                                         d, | ||||
|                                                     ) | ||||
|                                                 " | ||||
|                                             > | ||||
|                                                 <i | ||||
|                                                     class="fa fa-copy" | ||||
|                                                     aria-hidden="true" | ||||
|                                                 ></i> | ||||
|                                                 {{ | ||||
|                                                     trans( | ||||
|                                                         EVALUATION_DOCUMENT_DUPLICATE_TO_OTHER_EVALUATION, | ||||
|                                                     ) | ||||
|                                                 }}</a | ||||
|                                             > | ||||
|                                         </li> | ||||
|                                         <!--move document--> | ||||
|                                         <li | ||||
|                                             v-if=" | ||||
|                                                 d.storedObject._permissions | ||||
|                                                     .canEdit | ||||
|                                             " | ||||
|                                         > | ||||
|                                             <a | ||||
|                                                 class="dropdown-item" | ||||
|                                                 @click=" | ||||
|                                                     prepareDocumentMoveToWork(d) | ||||
|                                                 " | ||||
|                                             > | ||||
|                                                 <i | ||||
|                                                     class="fa fa-arrows" | ||||
|                                                     aria-hidden="true" | ||||
|                                                 ></i> | ||||
|                                                 {{ | ||||
|                                                     trans( | ||||
|                                                         EVALUATION_DOCUMENT_MOVE, | ||||
|                                                     ) | ||||
|                                                 }}</a | ||||
|                                             > | ||||
|                                         </li> | ||||
|                                     </ul> | ||||
|                                 </div> | ||||
|                             </li> | ||||
|                         </ul> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     <AccompanyingPeriodWorkSelectorModal | ||||
|         v-if="showAccompanyingPeriodSelector" | ||||
|         v-model:selectedAcpw="selectedAcpw" | ||||
|         :accompanying-period-id="accompanyingPeriodId" | ||||
|         :is-evaluation-selector="true" | ||||
|         :ignore-accompanying-period-work-ids="[]" | ||||
|         @close-modal="showAccompanyingPeriodSelector = false" | ||||
|         @update:selectedEvaluation="selectedEvaluation = $event" | ||||
|     /> | ||||
| </template> | ||||
|  | ||||
| <script setup> | ||||
| import { ISOToDatetime } from "ChillMainAssets/chill/js/date"; | ||||
| import ListWorkflowModal from "ChillMainAssets/vuejs/_components/EntityWorkflow/ListWorkflowModal.vue"; | ||||
| import DocumentActionButtonsGroup from "ChillDocStoreAssets/vuejs/DocumentActionButtonsGroup.vue"; | ||||
| import DropFileModal from "ChillDocStoreAssets/vuejs/DropFileWidget/DropFileModal.vue"; | ||||
| import { | ||||
|     EVALUATION_NOTIFICATION_NOTIFY_REFERRER, | ||||
|     EVALUATION_NOTIFICATION_NOTIFY_ANY, | ||||
|     EVALUATION_NOTIFICATION_SEND, | ||||
|     EVALUATION_DOCUMENTS, | ||||
|     EVALUATION_DOCUMENT_MOVE, | ||||
|     EVALUATION_DOCUMENT_DELETE, | ||||
|     EVALUATION_DOCUMENT_EDIT, | ||||
|     EVALUATION_DOCUMENT_DUPLICATE_HERE, | ||||
|     EVALUATION_DOCUMENT_DUPLICATE_TO_OTHER_EVALUATION, | ||||
|     trans, | ||||
| } from "translator"; | ||||
| import { ref, watch } from "vue"; | ||||
| import AccompanyingPeriodWorkSelectorModal from "ChillPersonAssets/vuejs/_components/AccompanyingPeriodWorkSelector/AccompanyingPeriodWorkSelectorModal.vue"; | ||||
|  | ||||
| defineProps([ | ||||
|     "documents", | ||||
|     "docAnchorId", | ||||
|     "accompanyingPeriodId", | ||||
|     "accompanyingPeriodWorkId", | ||||
| ]); | ||||
| const emit = defineEmits([ | ||||
|     "inputDocumentTitle", | ||||
|     "removeDocument", | ||||
|     "duplicateDocument", | ||||
|     "statusDocumentChanged", | ||||
|     "goToGenerateWorkflow", | ||||
|     "goToGenerateNotification", | ||||
|     "duplicateDocumentToWork", | ||||
| ]); | ||||
|  | ||||
| const showAccompanyingPeriodSelector = ref(false); | ||||
| const selectedEvaluation = ref(null); | ||||
| const selectedDocumentToDuplicate = ref(null); | ||||
| const selectedDocumentToMove = ref(null); | ||||
|  | ||||
| const prepareDocumentDuplicationToWork = (d) => { | ||||
|     selectedDocumentToDuplicate.value = d; | ||||
|     /** ensure selectedDocumentToMove is null */ | ||||
|     selectedDocumentToMove.value = null; | ||||
|  | ||||
|     showAccompanyingPeriodSelector.value = true; | ||||
| }; | ||||
|  | ||||
| const prepareDocumentMoveToWork = (d) => { | ||||
|     selectedDocumentToMove.value = d; | ||||
|     /** ensure selectedDocumentToDuplicate is null */ | ||||
|     selectedDocumentToDuplicate.value = null; | ||||
|  | ||||
|     showAccompanyingPeriodSelector.value = true; | ||||
| }; | ||||
|  | ||||
| watch(selectedEvaluation, (val) => { | ||||
|     if (selectedDocumentToDuplicate.value) { | ||||
|         emit("duplicateDocumentToEvaluation", { | ||||
|             evaluation: val, | ||||
|             document: selectedDocumentToDuplicate.value, | ||||
|         }); | ||||
|     } else { | ||||
|         emit("moveDocumentToEvaluation", { | ||||
|             evaluationDest: val, | ||||
|             document: selectedDocumentToMove.value, | ||||
|         }); | ||||
|     } | ||||
| }); | ||||
| </script> | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,32 @@ | ||||
| <template> | ||||
|     <div class="row mb-3"> | ||||
|         <label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label"> | ||||
|             {{ trans(EVALUATION_TIME_SPENT) }} | ||||
|         </label> | ||||
|         <div class="col-8 col-sm-4 col-md-8 col-lg-4"> | ||||
|             <select | ||||
|                 class="form-control form-control-sm" | ||||
|                 :value="timeSpent" | ||||
|                 @input="$emit('update:timeSpent', $event.target.value)" | ||||
|             > | ||||
|                 <option disabled value=""> | ||||
|                     {{ trans(EVALUATION_TIME_SPENT) }} | ||||
|                 </option> | ||||
|                 <option | ||||
|                     v-for="time in timeSpentChoices" | ||||
|                     :value="time.value" | ||||
|                     :key="time.value" | ||||
|                 > | ||||
|                     {{ time.text }} | ||||
|                 </option> | ||||
|             </select> | ||||
|         </div> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <script setup> | ||||
| import { EVALUATION_TIME_SPENT, trans } from "translator"; | ||||
|  | ||||
| defineProps(["timeSpent", "timeSpentChoices"]); | ||||
| defineEmits(["update:timeSpent"]); | ||||
| </script> | ||||
| @@ -11,12 +11,13 @@ import { findSocialActionsBySocialIssue } from "ChillPersonAssets/vuejs/_api/Soc | ||||
| import { create } from "ChillPersonAssets/vuejs/_api/AccompanyingCourseWork.js"; | ||||
| import { fetchResults, makeFetch } from "ChillMainAssets/lib/api/apiMethods.ts"; | ||||
| import { fetchTemplates } from "ChillDocGeneratorAssets/api/pickTemplate.js"; | ||||
| import { duplicate } from "../_api/accompanyingCourseWorkEvaluationDocument"; | ||||
| import { | ||||
|   duplicate, | ||||
|   duplicateDocumentToEvaluation, | ||||
|   moveDocumentToEvaluation, | ||||
| } from "../_api/accompanyingCourseWorkEvaluationDocument"; | ||||
|  | ||||
| const debug = process.env.NODE_ENV !== "production"; | ||||
| const evalFQDN = encodeURIComponent( | ||||
|   "Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluation", | ||||
| ); | ||||
|  | ||||
| const store = createStore({ | ||||
|   strict: debug, | ||||
| @@ -298,15 +299,47 @@ const store = createStore({ | ||||
|       ); | ||||
|     }, | ||||
|     addDuplicatedDocument(state, { document, evaluation_key }) { | ||||
|       console.log("add duplicated document", document); | ||||
|       console.log("add duplicated dcuemnt - evaluation key", evaluation_key); | ||||
|  | ||||
|       let evaluation = state.evaluationsPicked.find( | ||||
|         (e) => e.key === evaluation_key, | ||||
|       ); | ||||
|       document.key = evaluation.documents.length + 1; | ||||
|       evaluation.documents.splice(0, 0, document); | ||||
|     }, | ||||
|     addDuplicatedDocumentToEvaluation(state, { document, evaluation }) { | ||||
|       let evaluationDest = state.evaluationsPicked.find( | ||||
|         (e) => e.id === evaluation.id, | ||||
|       ); | ||||
|       if (evaluationDest) { | ||||
|         console.log("add duplicated document to evaluation", evaluationDest); | ||||
|         document.key = evaluationDest.documents.length + 1; | ||||
|         evaluationDest.documents.splice(0, 0, document); | ||||
|       } | ||||
|     }, | ||||
|     moveDocumentToEvaluation( | ||||
|       state, | ||||
|       { evaluationInitial, evaluationDest, document }, | ||||
|     ) { | ||||
|       let evaluationA = state.evaluationsPicked.find( | ||||
|         (e) => e.id === evaluationInitial.id, | ||||
|       ); | ||||
|       let evaluationB = state.evaluationsPicked.find( | ||||
|         (e) => e.id === evaluationDest.id, | ||||
|       ); | ||||
|  | ||||
|       if (evaluationB) { | ||||
|         // add document to chosen evaluation if evaluation is part of the same social work | ||||
|         document.key = evaluationB.documents.length + 1; | ||||
|         evaluationB.documents.splice(0, 0, document); | ||||
|       } | ||||
|  | ||||
|       // remove document from original evaluation | ||||
|       const indexToRemove = evaluationA.documents.findIndex( | ||||
|         (doc) => doc.id === document.id, | ||||
|       ); | ||||
|       if (indexToRemove !== -1) { | ||||
|         evaluationA.documents.splice(indexToRemove, 1); | ||||
|       } | ||||
|     }, | ||||
|     /** | ||||
|      * Replaces a document in the state with a new document. | ||||
|      * | ||||
| @@ -603,6 +636,44 @@ const store = createStore({ | ||||
|       const newDoc = await duplicate(document.id); | ||||
|       commit("addDuplicatedDocument", { document: newDoc, evaluation_key }); | ||||
|     }, | ||||
|     async duplicateDocumentToEvaluation({ commit }, { document, evaluation }) { | ||||
|       try { | ||||
|         const newDoc = await duplicateDocumentToEvaluation( | ||||
|           document.id, | ||||
|           evaluation.id, | ||||
|         ); | ||||
|         commit("addDuplicatedDocumentToEvaluation", { | ||||
|           document: newDoc, | ||||
|           evaluation, | ||||
|         }); | ||||
|  | ||||
|         return newDoc; | ||||
|       } catch (error) { | ||||
|         console.error("Failed to move document:", error); | ||||
|         throw error; | ||||
|       } | ||||
|     }, | ||||
|     async moveDocumentToEvaluation( | ||||
|       { commit }, | ||||
|       { evaluationInitial, evaluationDest, document }, | ||||
|     ) { | ||||
|       try { | ||||
|         const response = await moveDocumentToEvaluation( | ||||
|           document.id, | ||||
|           evaluationDest.id, | ||||
|         ); | ||||
|         commit("moveDocumentToEvaluation", { | ||||
|           evaluationInitial, | ||||
|           evaluationDest, | ||||
|           document, | ||||
|         }); | ||||
|  | ||||
|         return response; | ||||
|       } catch (error) { | ||||
|         console.error("Failed to move document:", error); | ||||
|         throw error; | ||||
|       } | ||||
|     }, | ||||
|     removeDocument({ commit }, payload) { | ||||
|       commit("removeDocument", payload); | ||||
|     }, | ||||
|   | ||||
| @@ -9,3 +9,23 @@ export const duplicate = async ( | ||||
|         `/api/1.0/person/accompanying-course-work-evaluation-document/${id}/duplicate`, | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| export const duplicateDocumentToEvaluation = async ( | ||||
|     document_id: number, | ||||
|     evaluation_id: number, | ||||
| ): Promise<AccompanyingPeriodWorkEvaluationDocument> => { | ||||
|     return makeFetch<null, AccompanyingPeriodWorkEvaluationDocument>( | ||||
|         "POST", | ||||
|         `/api/1.0/person/accompanying-course-work-evaluation-document/${document_id}/evaluation/${evaluation_id}/duplicate`, | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| export const moveDocumentToEvaluation = async ( | ||||
|     document_id: number, | ||||
|     evaluation_id: number, | ||||
| ): Promise<AccompanyingPeriodWorkEvaluationDocument> => { | ||||
|     return makeFetch<null, AccompanyingPeriodWorkEvaluationDocument>( | ||||
|         "POST", | ||||
|         `/api/1.0/person/accompanying-course-work-evaluation-document/${document_id}/evaluation/${evaluation_id}/move`, | ||||
|     ); | ||||
| }; | ||||
|   | ||||
| @@ -0,0 +1,70 @@ | ||||
| <template> | ||||
|     <div class="container"> | ||||
|         <div class="item-bloc"> | ||||
|             <div class="item-row"> | ||||
|                 <h2 class="badge-title"> | ||||
|                     <span class="title_label"></span> | ||||
|                     <span class="title_action"> | ||||
|                         <span> | ||||
|                             {{ trans(EVALUATION) }}: | ||||
|                             <span class="badge bg-light text-dark"> | ||||
|                                 {{ eval?.evaluation?.title.fr }} | ||||
|                             </span> | ||||
|                         </span> | ||||
|  | ||||
|                         <ul class="small_in_title columns mt-1"> | ||||
|                             <li> | ||||
|                                 <span class="item-key"> | ||||
|                                     {{ | ||||
|                                         trans( | ||||
|                                             ACCOMPANYING_COURSE_WORK_START_DATE, | ||||
|                                         ) | ||||
|                                     }} | ||||
|                                     : | ||||
|                                 </span> | ||||
|                                 <b>{{ formatDate(eval.startDate) }}</b> | ||||
|                             </li> | ||||
|  | ||||
|                             <li v-if="eval.endDate"> | ||||
|                                 <span class="item-key"> | ||||
|                                     {{ | ||||
|                                         trans(ACCOMPANYING_COURSE_WORK_END_DATE) | ||||
|                                     }} | ||||
|                                     : | ||||
|                                 </span> | ||||
|                                 <b>{{ formatDate(eval.endDate) }}</b> | ||||
|                             </li> | ||||
|                         </ul> | ||||
|                     </span> | ||||
|                 </h2> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import { | ||||
|     ACCOMPANYING_COURSE_WORK_END_DATE, | ||||
|     ACCOMPANYING_COURSE_WORK_START_DATE, | ||||
|     EVALUATION, | ||||
|     trans, | ||||
| } from "translator"; | ||||
| import { ISOToDate } from "ChillMainAssets/chill/js/date"; | ||||
| import { DateTime } from "ChillMainAssets/types"; | ||||
| import { AccompanyingPeriodWorkEvaluation } from "../../../types"; | ||||
|  | ||||
| // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||||
| const props = defineProps<{ eval: AccompanyingPeriodWorkEvaluation }>(); | ||||
| const formatDate = (dateObject: DateTime) => { | ||||
|     if (dateObject) { | ||||
|         const parsedDate = ISOToDate(dateObject.datetime); | ||||
|         if (parsedDate) { | ||||
|             return new Intl.DateTimeFormat("default", { | ||||
|                 dateStyle: "short", | ||||
|             }).format(parsedDate); | ||||
|         } else { | ||||
|             return ""; | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| </script> | ||||
| @@ -0,0 +1,47 @@ | ||||
| <template> | ||||
|     <div class="results"> | ||||
|         <div | ||||
|             v-for="evaluation in evaluations" | ||||
|             :key="evaluation.id" | ||||
|             class="list-item" | ||||
|         > | ||||
|             <label class="acpw-item"> | ||||
|                 <div> | ||||
|                     <input | ||||
|                         type="radio" | ||||
|                         :value="evaluation" | ||||
|                         v-model="selectedEvaluation" | ||||
|                         name="item" | ||||
|                     /> | ||||
|                 </div> | ||||
|  | ||||
|                 <accompanying-period-work-evaluation-item :eval="evaluation" /> | ||||
|             </label> | ||||
|         </div> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import { AccompanyingPeriodWorkEvaluation } from "../../../types"; | ||||
| import { defineProps, ref, watch } from "vue"; | ||||
| import AccompanyingPeriodWorkEvaluationItem from "ChillPersonAssets/vuejs/_components/AccompanyingPeriodWorkSelector/AccompanyingPeriodWorkEvaluationItem.vue"; | ||||
|  | ||||
| // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||||
| const props = defineProps<{ | ||||
|     evaluations: AccompanyingPeriodWorkEvaluation[]; | ||||
| }>(); | ||||
| const selectedEvaluation = ref<AccompanyingPeriodWorkEvaluation | null>(null); | ||||
|  | ||||
| // eslint-disable-next-line vue/valid-define-emits | ||||
| const emit = defineEmits(); | ||||
|  | ||||
| watch(selectedEvaluation, (newValue) => { | ||||
|     emit("update:selectedEvaluation", newValue); | ||||
| }); | ||||
| </script> | ||||
|  | ||||
| <style> | ||||
| .acpw-item { | ||||
|     display: flex; | ||||
| } | ||||
| </style> | ||||
| @@ -26,14 +26,24 @@ import AccompanyingPeriodWorkItem from "./AccompanyingPeriodWorkItem.vue"; | ||||
| import { AccompanyingPeriodWork } from "../../../types"; | ||||
| import { defineProps, ref, watch } from "vue"; | ||||
|  | ||||
| // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||||
| const props = defineProps<{ | ||||
|     accompanyingPeriodWorks: AccompanyingPeriodWork[]; | ||||
|     selectedAcpw?: AccompanyingPeriodWork | null; | ||||
| }>(); | ||||
| const selectedAcpw = ref<AccompanyingPeriodWork | null>(null); | ||||
| const selectedAcpw = ref<AccompanyingPeriodWork | null>( | ||||
|     props.selectedAcpw ?? null, | ||||
| ); | ||||
|  | ||||
| // eslint-disable-next-line vue/valid-define-emits | ||||
| const emit = defineEmits(); | ||||
| const emit = defineEmits<{ | ||||
|     "update:selectedAcpw": [value: AccompanyingPeriodWork | null]; | ||||
| }>(); | ||||
|  | ||||
| watch( | ||||
|     () => props.selectedAcpw, | ||||
|     (val) => { | ||||
|         selectedAcpw.value = val ?? null; | ||||
|     }, | ||||
| ); | ||||
|  | ||||
| watch(selectedAcpw, (newValue) => { | ||||
|     emit("update:selectedAcpw", newValue); | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| <template> | ||||
|     <div> | ||||
|         <div class="row justify-content-end"> | ||||
|         <div class="row justify-content-end" v-if="!isEvaluationSelector"> | ||||
|             <div class="col-md-6 col-sm-10" v-if="selectedAcpw"> | ||||
|                 <ul class="list-suggest remove-items"> | ||||
|                     <li> | ||||
| @@ -14,7 +14,7 @@ | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <ul class="record_actions"> | ||||
|         <ul v-if="!showModal" class="record_actions"> | ||||
|             <li> | ||||
|                 <a class="btn btn-sm btn-create mt-3" @click="openModal"> | ||||
|                     {{ trans(ACPW_DUPLICATE_SELECT_ACCOMPANYING_PERIOD_WORK) }} | ||||
| @@ -40,9 +40,15 @@ | ||||
|  | ||||
|                 <template #body> | ||||
|                     <accompanying-period-work-list | ||||
|                         v-if="evaluations.length === 0" | ||||
|                         :accompanying-period-works="accompanyingPeriodWorks" | ||||
|                         v-model:selectedAcpw="selectedAcpw" | ||||
|                     /> | ||||
|                     <accompanying-period-work-evaluation-list | ||||
|                         v-if="evaluations.length > 0" | ||||
|                         :evaluations="evaluations" | ||||
|                         v-model:selectedEvaluation="selectedEvaluation" | ||||
|                     /> | ||||
|                 </template> | ||||
|  | ||||
|                 <template #footer> | ||||
| @@ -60,58 +66,109 @@ | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import { onMounted, ref } from "vue"; | ||||
| import { ref, watch, onMounted } from "vue"; | ||||
| import Modal from "ChillMainAssets/vuejs/_components/Modal.vue"; | ||||
| import AccompanyingPeriodWorkList from "./AccompanyingPeriodWorkList.vue"; | ||||
| import { AccompanyingPeriodWork } from "../../../types"; | ||||
| import { | ||||
|     trans, | ||||
|     ACPW_DUPLICATE_SELECT_ACCOMPANYING_PERIOD_WORK, | ||||
|     CONFIRM, | ||||
|     trans, | ||||
| } from "translator"; | ||||
| import { fetchResults } from "ChillMainAssets/lib/api/apiMethods"; | ||||
|  | ||||
| interface AccompanyingPeriodWorkSelectorModalProps { | ||||
|     accompanyingPeriodId: number; | ||||
| } | ||||
| import AccompanyingPeriodWorkEvaluationList from "ChillPersonAssets/vuejs/_components/AccompanyingPeriodWorkSelector/AccompanyingPeriodWorkEvaluationList.vue"; | ||||
| import { AccompanyingPeriodWorkEvaluation } from "../../../types"; | ||||
|  | ||||
| const selectedAcpw = ref<AccompanyingPeriodWork | null>(null); | ||||
| const selectedEvaluation = ref<AccompanyingPeriodWorkEvaluation | null>(null); | ||||
| const showModal = ref(false); | ||||
| const accompanyingPeriodWorks = ref<AccompanyingPeriodWork[]>([]); | ||||
| const props = defineProps<AccompanyingPeriodWorkSelectorModalProps>(); | ||||
| const evaluations = ref<AccompanyingPeriodWorkEvaluation[]>([]); | ||||
|  | ||||
| const props = defineProps<{ | ||||
|     accompanyingPeriodId: string; | ||||
|     isEvaluationSelector: boolean; | ||||
|     ignoreAccompanyingPeriodWorkIds: number[]; | ||||
| }>(); | ||||
|  | ||||
| const emit = defineEmits<{ | ||||
|     pickWork: [payload: { work: AccompanyingPeriodWork | null }]; | ||||
|     closeModal: []; | ||||
|     "update:selectedEvaluation": [evaluation: AccompanyingPeriodWorkEvaluation]; | ||||
| }>(); | ||||
|  | ||||
| onMounted(() => { | ||||
|     if (props.accompanyingPeriodId) { | ||||
|         getAccompanyingPeriodWorks(props.accompanyingPeriodId); | ||||
|         getAccompanyingPeriodWorks(parseInt(props.accompanyingPeriodId)); | ||||
|     } else { | ||||
|         console.error("No accompanyingperiod id was given"); | ||||
|     } | ||||
|  | ||||
|     showModal.value = true; | ||||
| }); | ||||
| const getAccompanyingPeriodWorks = async (periodId: number) => { | ||||
|     const url = `/api/1.0/person/accompanying-course/${periodId}/works.json`; | ||||
|  | ||||
|     try { | ||||
|         accompanyingPeriodWorks.value = await fetchResults(url); | ||||
|     } catch (error) { | ||||
|         console.log(error); | ||||
|     const accompanyingPeriodWorksFetched = | ||||
|         await fetchResults<AccompanyingPeriodWork>(url); | ||||
|     if (props.isEvaluationSelector) { | ||||
|         accompanyingPeriodWorks.value = accompanyingPeriodWorksFetched.filter( | ||||
|             (acpw: AccompanyingPeriodWork) => | ||||
|                 acpw.accompanyingPeriodWorkEvaluations.length > 0 && | ||||
|                 typeof acpw.id !== "undefined" && | ||||
|                 !props.ignoreAccompanyingPeriodWorkIds.includes(acpw.id), | ||||
|         ); | ||||
|     } else { | ||||
|         accompanyingPeriodWorks.value = accompanyingPeriodWorksFetched; | ||||
|     } | ||||
|     /*  makeFetch<number, AccompanyingPeriodWork[]>("GET", url) | ||||
|     .then((response) => { | ||||
|       accompanyingPeriodWorks.value = response; | ||||
|     }) | ||||
|     .catch((error) => { | ||||
|       console.log(error); | ||||
|     });*/ | ||||
| }; | ||||
|  | ||||
| const openModal = () => (showModal.value = true); | ||||
| const closeModal = () => (showModal.value = false); | ||||
| watch(selectedAcpw, (newValue) => { | ||||
|     const inputField = document.getElementById( | ||||
|         "find_accompanying_period_work_acpw", | ||||
|     ) as HTMLInputElement; | ||||
|     if (inputField) { | ||||
|         inputField.value = String(newValue?.id || ""); | ||||
|     } | ||||
|  | ||||
|     /*  if (!props.isEvaluationSelector) { | ||||
|     console.log("Emitting from watch:", { work: newValue }); | ||||
|     emit("pickWork", { work: newValue }); | ||||
|   }*/ | ||||
| }); | ||||
|  | ||||
| const openModal = () => { | ||||
|     showModal.value = true; | ||||
| }; | ||||
| const closeModal = () => { | ||||
|     showModal.value = false; | ||||
|     selectedEvaluation.value = null; | ||||
|     // selectedAcpw.value = null; | ||||
|     emit("closeModal"); | ||||
| }; | ||||
| const confirmSelection = () => { | ||||
|     emit("pickWork", { work: selectedAcpw.value }); | ||||
|     closeModal(); | ||||
|     selectedAcpw.value = selectedAcpw.value; | ||||
|     console.log("selectedAcpw", selectedAcpw.value); | ||||
|  | ||||
|     if (!props.isEvaluationSelector) { | ||||
|         if (selectedAcpw.value) { | ||||
|             // only emit if something is actually selected! | ||||
|             emit("pickWork", { work: selectedAcpw.value }); | ||||
|             closeModal(); | ||||
|         } | ||||
|         // optionally show some error or warning if not selected | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if (selectedAcpw.value && props.isEvaluationSelector) { | ||||
|         evaluations.value = | ||||
|             selectedAcpw.value.accompanyingPeriodWorkEvaluations; | ||||
|     } | ||||
|  | ||||
|     if (selectedEvaluation.value && props.isEvaluationSelector) { | ||||
|         // console.log('evaluation log in modal', selectedEvaluation.value) | ||||
|         emit("update:selectedEvaluation", selectedEvaluation.value); | ||||
|         closeModal(); | ||||
|     } | ||||
| }; | ||||
| </script> | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| {%- macro details(w, accompanyingCourse, options) -%} | ||||
|     {% include '@ChillPerson/AccompanyingCourseWork/_item.html.twig' with { | ||||
|         'displayAction': false, | ||||
|         'displayAction': true, | ||||
|         'displayContent': 'short', | ||||
|         'displayFontSmall': true, | ||||
|         'itemBlocClass': '', | ||||
|         'displayNotification': false | ||||
|         'displayNotification': true | ||||
|     } %} | ||||
| {% endmacro %} | ||||
|   | ||||
| @@ -2,10 +2,10 @@ | ||||
|  | ||||
| {% set activeRouteKey = 'chill_person_accompanying_period_work_assign_duplicate' %} | ||||
|  | ||||
| {% block title %}{{ 'Assign an accompanying period work duplicate' }}{% endblock %} | ||||
|  | ||||
| {% import '@ChillPerson/AccompanyingPeriodWorkDuplicate/_details.html.twig' as details %} | ||||
|  | ||||
| {% block title %}{{ 'Assign an accompanying period work duplicate' }}{% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|     <div class="person-duplicate"> | ||||
|  | ||||
| @@ -18,7 +18,7 @@ | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
|         <h3>{{ 'acpw_duplicate.Assign duplicate'|trans }}</h3> | ||||
|         <h1>{{ 'acpw_duplicate.Assign duplicate'|trans }}</h1> | ||||
|         {{ form_start(form) }} | ||||
|         {%- if form.acpw is defined -%} | ||||
|             {{ form_row(form.acpw) }} | ||||
|   | ||||
| @@ -12,6 +12,7 @@ declare(strict_types=1); | ||||
| namespace Chill\PersonBundle\Service\AccompanyingPeriodWorkEvaluationDocument; | ||||
|  | ||||
| use Chill\DocStoreBundle\Service\StoredObjectDuplicate; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument; | ||||
| use Symfony\Component\Clock\ClockInterface; | ||||
| use Symfony\Contracts\Translation\TranslatorInterface; | ||||
| @@ -36,4 +37,17 @@ class AccompanyingPeriodWorkEvaluationDocumentDuplicator | ||||
|  | ||||
|         return $newDocument; | ||||
|     } | ||||
|  | ||||
|     public function duplicateToEvaluation(AccompanyingPeriodWorkEvaluationDocument $document, AccompanyingPeriodWorkEvaluation $evaluation): AccompanyingPeriodWorkEvaluationDocument | ||||
|     { | ||||
|         $newDocument = new AccompanyingPeriodWorkEvaluationDocument(); | ||||
|         $newDocument | ||||
|             ->setTitle($document->getTitle().' ('.$this->translator->trans('accompanying_course_evaluation_document.duplicated_at', ['at' => $this->clock->now()]).')') | ||||
|             ->setStoredObject($this->storedObjectDuplicate->duplicate($document->getStoredObject())) | ||||
|         ; | ||||
|  | ||||
|         $evaluation->addDocument($newDocument); | ||||
|  | ||||
|         return $newDocument; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1993,3 +1993,33 @@ paths: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 type: object | ||||
|  | ||||
|   /1.0/person/accompanying-course-work-evaluation-document/{document_id}/evaluation/{evaluation_id}/duplicate: | ||||
|     post: | ||||
|       tags: | ||||
|         - accompanying-course-work-evaluation-document | ||||
|       summary: Dupliate an an accompanying period work evaluation document to another evaluation | ||||
|       parameters: | ||||
|         - in: path | ||||
|           name: document_id | ||||
|           required: true | ||||
|           description: The document's id | ||||
|           schema: | ||||
|             type: integer | ||||
|             format: integer | ||||
|             minimum: 1 | ||||
|         - in: path | ||||
|           name: evaluation_id | ||||
|           required: true | ||||
|           description: The evaluation's id | ||||
|           schema: | ||||
|             type: integer | ||||
|             format: integer | ||||
|             minimum: 1 | ||||
|       responses: | ||||
|         200: | ||||
|           description: "OK" | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 type: object | ||||
|   | ||||
| @@ -753,6 +753,42 @@ evaluation: | ||||
|     delay: Délai | ||||
|     notificationDelay: Délai de notification | ||||
|     url: Lien internet | ||||
|     title: Ecrire une évaluation | ||||
|     status: Statut | ||||
|     choose_a_status: Choisir un statut | ||||
|     startdate: Date d'ouverture | ||||
|     enddate: Date de fin | ||||
|     maxdate: Date d'échéance | ||||
|     warning_interval: Rappel (jours) | ||||
|     public_comment: Note publique | ||||
|     comment_placeholder: Commencez à écrire ... | ||||
|     generate_a_document: Générer un document | ||||
|     choose_a_template: Choisir un modèle | ||||
|     add_a_document: Ajouter un document | ||||
|     add: Ajouter une évaluation | ||||
|     time_spent: Temps de rédaction | ||||
|     select_time_spent: Indiquez le temps de rédaction | ||||
|     Documents: Documents | ||||
|     document_add: Générer ou téléverser un document | ||||
|     document_upload: Téléverser un document | ||||
|     document_title: Titre du document | ||||
|     template_title: Nom du template | ||||
|     browse: Ajouter un document | ||||
|     replace: Remplacer | ||||
|     download: Télécharger le fichier existant | ||||
|     notification_notify_referrer: Notifier le référent | ||||
|     notification_notify_any: Notifier d'autres utilisateurs | ||||
|     notification_send: Envoyer une notification | ||||
|     document: | ||||
|       edit: Modifier | ||||
|       delete: Supprimer | ||||
|       move: Déplacer | ||||
|       duplicate: Dupliquer | ||||
|       duplicate_here: Dupliquer ici | ||||
|       duplicate_to_other_evaluation: Dupliquer vers une autre évaluation | ||||
|       duplicate_success: Le document d'évaluation a été dupliquer | ||||
|       move_success: Le document d'évaluation a été déplacer | ||||
|  | ||||
|  | ||||
| goal: | ||||
|    desactivationDate: Date de désactivation | ||||
| @@ -777,7 +813,6 @@ relation: | ||||
|     reverseTitle: Deuxième membre | ||||
|  | ||||
| days: jours | ||||
| months: mois | ||||
| years: années | ||||
|  | ||||
| # specific to closing motive | ||||
| @@ -1525,3 +1560,6 @@ my_parcours_filters: | ||||
|   parcours_intervening: Intervenant | ||||
|   is_open: Parcours ouverts | ||||
|   is_closed: Parcours clôturés | ||||
|  | ||||
| document_duplicate: | ||||
|     to_evaluation_success: "Le document a été dupliquer" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user