mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-10-10 15:29:41 +00:00
Merge branch 'master' into migrate_to_sf72
# Conflicts: # src/Bundle/ChillMainBundle/Controller/UserProfileController.php # src/Bundle/ChillMainBundle/Entity/User.php # src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodWorkDuplicateController.php # src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodWorkEvaluationDocumentDuplicateController.php # src/Bundle/ChillPersonBundle/Form/Type/PickLinkedAccompanyingPeriodWorkType.php
This commit is contained in:
@@ -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\Attribute\Route;
|
||||
use Symfony\Component\Translation\TranslatableMessage;
|
||||
@@ -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;
|
||||
@@ -23,15 +24,16 @@ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
use Symfony\Bundle\SecurityBundle\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,
|
||||
) {}
|
||||
|
||||
#[\Symfony\Component\Routing\Attribute\Route('/api/1.0/person/accompanying-course-work-evaluation-document/{id}/duplicate', methods: ['POST'])]
|
||||
@@ -55,6 +57,32 @@ class AccompanyingPeriodWorkEvaluationDocumentDuplicateController
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ParamConverter("document", options={"id": "document_id"})
|
||||
* @ParamConverter("evaluation", options={"id": "evaluation_id"})
|
||||
*/
|
||||
#[\Symfony\Component\Routing\Attribute\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
|
||||
);
|
||||
}
|
||||
|
||||
#[\Symfony\Component\Routing\Attribute\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): void
|
||||
{
|
||||
$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): void
|
||||
@@ -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,76 @@
|
||||
<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="submitBeforeGenerate"
|
||||
>
|
||||
<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";
|
||||
import { buildLink } from "ChillDocGeneratorAssets/lib/document-generator";
|
||||
import { useStore } from "vuex";
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const props = defineProps(["evaluation", "templates"]);
|
||||
const emit = defineEmits(["addDocument"]);
|
||||
|
||||
async function submitBeforeGenerate({ template }) {
|
||||
const callback = (data) => {
|
||||
let evaluationId = data.accompanyingPeriodWorkEvaluations.find(
|
||||
(e) => e.key === props.evaluation.key,
|
||||
).id;
|
||||
|
||||
window.location.assign(
|
||||
buildLink(
|
||||
template,
|
||||
evaluationId,
|
||||
"Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluation",
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
return store.dispatch("submit", callback).catch((e) => {
|
||||
console.log(e);
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
ul.document-upload {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
</style>
|
@@ -0,0 +1,455 @@
|
||||
<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="
|
||||
goToGenerateWorkflowEvaluationDocument
|
||||
"
|
||||
></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="
|
||||
goToGenerateDocumentNotification(
|
||||
d,
|
||||
false,
|
||||
)
|
||||
"
|
||||
>
|
||||
{{
|
||||
trans(
|
||||
EVALUATION_NOTIFICATION_NOTIFY_REFERRER,
|
||||
)
|
||||
}}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
class="dropdown-item"
|
||||
@click="
|
||||
goToGenerateDocumentNotification(
|
||||
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>
|
||||
<!--replace document-->
|
||||
<li
|
||||
v-if="
|
||||
Number.isInteger(d.id) &&
|
||||
d.storedObject._permissions.canEdit
|
||||
"
|
||||
>
|
||||
<drop-file-modal
|
||||
:existing-doc="d.storedObject"
|
||||
:allow-remove="false"
|
||||
@add-document="
|
||||
(arg) =>
|
||||
replaceDocument(
|
||||
d,
|
||||
arg.stored_object,
|
||||
arg.stored_object_version,
|
||||
)
|
||||
"
|
||||
></drop-file-modal>
|
||||
</li>
|
||||
<li v-if="Number.isInteger(d.id)">
|
||||
<div class="duplicate-dropdown">
|
||||
<button
|
||||
class="btn btn-outline-primary dropdown-toggle"
|
||||
type="button"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<i class="bi bi-lightning-fill"></i>
|
||||
</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>
|
||||
<!--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_DUPLICATE_HERE,
|
||||
EVALUATION_DOCUMENT_DUPLICATE_TO_OTHER_EVALUATION,
|
||||
trans,
|
||||
} from "translator";
|
||||
import { computed, ref, watch } from "vue";
|
||||
import AccompanyingPeriodWorkSelectorModal from "ChillPersonAssets/vuejs/_components/AccompanyingPeriodWorkSelector/AccompanyingPeriodWorkSelectorModal.vue";
|
||||
import { buildLinkCreate } from "ChillMainAssets/lib/entity-workflow/api";
|
||||
import { buildLinkCreate as buildLinkCreateNotification } from "ChillMainAssets/lib/entity-notification/api";
|
||||
import { useStore } from "vuex";
|
||||
|
||||
const props = defineProps([
|
||||
"documents",
|
||||
"docAnchorId",
|
||||
"accompanyingPeriodId",
|
||||
"evaluation",
|
||||
]);
|
||||
const emit = defineEmits([
|
||||
"inputDocumentTitle",
|
||||
"removeDocument",
|
||||
"duplicateDocument",
|
||||
"statusDocumentChanged",
|
||||
"duplicateDocumentToWork",
|
||||
]);
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const showAccompanyingPeriodSelector = ref(false);
|
||||
const selectedEvaluation = ref(null);
|
||||
const selectedDocumentToDuplicate = ref(null);
|
||||
const selectedDocumentToMove = ref(null);
|
||||
|
||||
const AmIRefferer = computed(() => {
|
||||
return !(
|
||||
store.state.work.accompanyingPeriod.user &&
|
||||
store.state.me &&
|
||||
store.state.work.accompanyingPeriod.user.id !== store.state.me.id
|
||||
);
|
||||
});
|
||||
|
||||
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,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
async function goToGenerateWorkflowEvaluationDocument({
|
||||
workflowName,
|
||||
payload,
|
||||
}) {
|
||||
const callback = (data) => {
|
||||
let evaluation = data.accompanyingPeriodWorkEvaluations.find(
|
||||
(e) => e.key === props.evaluation.key,
|
||||
);
|
||||
let updatedDocument = evaluation.documents.find(
|
||||
(d) => d.key === payload.doc.key,
|
||||
);
|
||||
window.location.assign(
|
||||
buildLinkCreate(
|
||||
workflowName,
|
||||
"Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument",
|
||||
updatedDocument.id,
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
return store.dispatch("submit", callback).catch((e) => {
|
||||
console.log(e);
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces a document in the store with a new document.
|
||||
*
|
||||
* @param {Object} oldDocument - The document to be replaced.
|
||||
* @param {StoredObject} storedObject - The stored object of the new document.
|
||||
* @param {StoredObjectVersion} storedObjectVersion - The new version of the document
|
||||
* @return {void}
|
||||
*/
|
||||
async function replaceDocument(oldDocument, storedObject, storedObjectVersion) {
|
||||
let document = {
|
||||
type: "accompanying_period_work_evaluation_document",
|
||||
storedObject: storedObject,
|
||||
title: oldDocument.title,
|
||||
};
|
||||
|
||||
return store.commit("replaceDocument", {
|
||||
key: props.evaluation.key,
|
||||
document,
|
||||
oldDocument: oldDocument,
|
||||
stored_object_version: storedObjectVersion,
|
||||
});
|
||||
}
|
||||
|
||||
async function goToGenerateDocumentNotification(document, tos) {
|
||||
const callback = (data) => {
|
||||
let evaluation = data.accompanyingPeriodWorkEvaluations.find(
|
||||
(e) => e.key === props.evaluation.key,
|
||||
);
|
||||
let updatedDocument = evaluation.documents.find(
|
||||
(d) => d.key === document.key,
|
||||
);
|
||||
window.location.assign(
|
||||
buildLinkCreateNotification(
|
||||
"Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument",
|
||||
updatedDocument.id,
|
||||
tos === true
|
||||
? store.state.work.accompanyingPeriod.user?.id
|
||||
: null,
|
||||
window.location.pathname +
|
||||
window.location.search +
|
||||
window.location.hash,
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
return store.dispatch("submit", callback).catch((e) => {
|
||||
console.log(e);
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
|
||||
async function submitBeforeLeaveToEditor() {
|
||||
console.log("submit beore edit 2");
|
||||
// empty callback
|
||||
const callback = () => null;
|
||||
return store.dispatch("submit", callback).catch((e) => {
|
||||
console.log(e);
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
</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) }}
|
||||
@@ -30,19 +30,21 @@
|
||||
>
|
||||
<template #header>
|
||||
<h3>
|
||||
{{
|
||||
trans(
|
||||
ACPW_DUPLICATE_SELECT_ACCOMPANYING_PERIOD_WORK,
|
||||
)
|
||||
}}
|
||||
{{ getModalTitle() }}
|
||||
</h3>
|
||||
</template>
|
||||
|
||||
<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 +62,116 @@
|
||||
</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 {
|
||||
ACPW_DUPLICATE_SELECT_ACCOMPANYING_PERIOD_WORK,
|
||||
CONFIRM,
|
||||
trans,
|
||||
ACPW_DUPLICATE_SELECT_ACCOMPANYING_PERIOD_WORK,
|
||||
ACPW_DUPLICATE_SELECT_AN_EVALUATION,
|
||||
CONFIRM,
|
||||
} 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];
|
||||
}>();
|
||||
|
||||
const getModalTitle = () =>
|
||||
evaluations.value.length > 0
|
||||
? trans(ACPW_DUPLICATE_SELECT_AN_EVALUATION)
|
||||
: trans(ACPW_DUPLICATE_SELECT_ACCOMPANYING_PERIOD_WORK);
|
||||
|
||||
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é dupliqué
|
||||
move_success: Le document d'évaluation a été déplacé
|
||||
|
||||
|
||||
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
|
||||
@@ -1508,7 +1543,8 @@ entity_display_title:
|
||||
acpw_duplicate:
|
||||
title: Fusionner les actions d'accompagnement
|
||||
description: Cette fusion conservera la date de début la plus ancienne, la date de fin la plus récente, toutes les évaluations, documents et workflows. Les agents traitants seront additionnés ainsi que les tiers intervenants. Les commentaires seront mis l'un à la suite de l'autre.
|
||||
Select accompanying period work: Selectionner un action d'accompagnement
|
||||
Select accompanying period work: Sélectionner une action d'accompagnement
|
||||
Select an evaluation: Sélectionner une évaluation
|
||||
Assign duplicate: Désigner un action d'accompagnement doublon
|
||||
Accompanying period work to delete: Action d'accompagnement à supprimer
|
||||
Accompanying period work to delete explanation: Cet action d'accompagnement sera supprimé.
|
||||
@@ -1525,3 +1561,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