diff --git a/CHANGELOG.md b/CHANGELOG.md index d1d184e46..e4b2368b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to ## Unreleased +* [parcours] Toggle emergency/intensity only by referrer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/442) * [docstore] Add an API entrypoint for StoredObject (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/466) * [person] Add the possibility of uploading existing documents to AccPeriodWorkEvaluationDocument (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/466) * [person] Add title to AccPeriodWorkEvaluationDocument (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/466) @@ -48,10 +49,9 @@ and this project adheres to * [thirdparty_contact]: in search results the 'qualité' is displayed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/465) * [bug]: fix confidential toggle of address in thirdpartyrenderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/460) + ## Test releases * Creation of PickCivilityType, and implementation in PersonType and ThirdpartyType -* [renderbox]: Fix display of address (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/462) -* [renderbox]: Add email in personRenderBox, this was not yet displayed. ### test release 2022-02-14 @@ -68,6 +68,7 @@ and this project adheres to * [parcours]: Mes parcours brouillon added to user menu (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/440) * [Documents]: List view adapted to display more information (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/414) * [person]: style fix in parcours listing per person. (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/432) +* [parcours]: Only the referrer can toggle the intensity of the parcours (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/442) * [household]: display address of current household (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/415) * ajoute un ordre dans les localisation (api) * [pick entity]: fix translations in modal (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/419) @@ -316,6 +317,7 @@ and this project adheres to * add an endpoint for checking permissions. See https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/232 * [activity] for a new activity: suggest and create on-the-fly locations based on the accompanying course location + location of the suggested parties * [calendar] for a new rdv: suggest and create on-the-fly locations based on the accompanying course location + location of the suggested parties +* [period] Validation added when period is confidential and confirmed -> user cannot be null. ## Test releases diff --git a/composer b/composer new file mode 100755 index 000000000..0e7ab8212 Binary files /dev/null and b/composer differ diff --git a/src/Bundle/ChillMainBundle/Resources/public/chill/scss/render_box.scss b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/render_box.scss index c42c592a9..37d4f97c4 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/chill/scss/render_box.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/render_box.scss @@ -72,7 +72,7 @@ section.chill-entity { } } p { - // display: inline-block; + display: inline-block; margin: 0 0 0 1.5em; text-indent: -1.5em; diff --git a/src/Bundle/ChillMainBundle/Resources/public/lib/api/apiMethods.js b/src/Bundle/ChillMainBundle/Resources/public/lib/api/apiMethods.js index 5ad119858..67f3e2f42 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/lib/api/apiMethods.js +++ b/src/Bundle/ChillMainBundle/Resources/public/lib/api/apiMethods.js @@ -1,7 +1,7 @@ /** * Generic api method that can be adapted to any fetch request */ - const makeFetch = (method, url, body) => { +const makeFetch = (method, url, body) => { return fetch(url, { method: method, headers: { @@ -11,19 +11,20 @@ }) .then(response => { if (response.ok) { + console.log('200 error') return response.json(); } if (response.status === 422) { + console.log('422 error') return response.json().then(response => { throw ValidationException(response) }); } if (response.status === 403) { - return response.json().then(() => { - throw AccessException(); - }); + console.log('403 error') + throw AccessException(response); } throw { @@ -88,14 +89,13 @@ const ValidationException = (response) => { error.violations = response.violations.map((violation) => `${violation.title}: ${violation.propertyPath}`); error.titles = response.violations.map((violation) => violation.title); error.propertyPaths = response.violations.map((violation) => violation.propertyPath); - return error; } -const AccessException = () => { +const AccessException = (response) => { const error = {}; error.name = 'AccessException'; - error.violations = ['You are no longer permitted to perform this action']; + error.violations = ['You are not allowed to perform this action']; return error; } diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php index 3da40db4c..f1306640b 100644 --- a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseApiController.php @@ -322,19 +322,39 @@ final class AccompanyingCourseApiController extends ApiController /** * @Route("/api/1.0/person/accompanying-course/{id}/confidential.json", name="chill_api_person_accompanying_period_confidential") * @ParamConverter("accompanyingCourse", options={"id": "id"}) + * + * @param mixed $id */ - public function toggleConfidentialApi(AccompanyingPeriod $accompanyingCourse, Request $request) + public function toggleConfidentialApi(AccompanyingPeriod $accompanyingCourse, $id, Request $request) { if ($request->getMethod() === 'POST') { $this->denyAccessUnlessGranted(AccompanyingPeriodVoter::TOGGLE_CONFIDENTIAL, $accompanyingCourse); $accompanyingCourse->setConfidential(!$accompanyingCourse->isConfidential()); + $this->getDoctrine()->getManager()->flush(); } return $this->json($accompanyingCourse->isConfidential(), Response::HTTP_OK, [], ['groups' => ['read']]); } + /** + * @Route("/api/1.0/person/accompanying-course/{id}/intensity.json", name="chill_api_person_accompanying_period_intensity") + * @ParamConverter("accompanyingCourse", options={"id": "id"}) + */ + public function toggleIntensityApi(AccompanyingPeriod $accompanyingCourse, Request $request) + { + if ($request->getMethod() === 'POST') { + $this->denyAccessUnlessGranted(AccompanyingPeriodVoter::TOGGLE_INTENSITY, $accompanyingCourse); + + $status = $accompanyingCourse->getIntensity() === 'regular' ? 'occasional' : 'regular'; + $accompanyingCourse->setIntensity($status); + $this->getDoctrine()->getManager()->flush(); + } + + return $this->json($accompanyingCourse->getIntensity(), Response::HTTP_OK, [], ['groups' => ['read']]); + } + public function workApi($id, Request $request, string $_format): Response { return $this->addRemoveSomething( diff --git a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php index 716ef9ee8..b05da5626 100644 --- a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php +++ b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php @@ -395,16 +395,16 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE, ], ], - 'confidential' => [ - 'methods' => [ - Request::METHOD_POST => true, - Request::METHOD_GET => true, - ], - 'controller_action' => 'toggleConfidentialApi', - 'roles' => [ - Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::TOGGLE_CONFIDENTIAL, - ], - ], + // 'confidential' => [ + // 'methods' => [ + // Request::METHOD_POST => true, + // Request::METHOD_GET => true, + // ], + // 'controller_action' => 'toggleConfidentialApi', + // 'roles' => [ + // Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::TOGGLE_CONFIDENTIAL, + // ], + // ], 'findAccompanyingPeriodsByPerson' => [ 'path' => '/by-person/{person_id}.{_format}', 'controller_action' => 'getAccompanyingPeriodsByPerson', diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php index 0012f341d..d75ade12b 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php @@ -30,6 +30,8 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod\Resource; use Chill\PersonBundle\Entity\AccompanyingPeriod\UserHistory; use Chill\PersonBundle\Entity\SocialWork\SocialIssue; use Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\AccompanyingPeriodValidity; +use Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\ConfidentialCourseMustHaveReferrer; +use Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\LocationValidity; use Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\ParticipationOverlap; use Chill\PersonBundle\Validator\Constraints\AccompanyingPeriod\ResourceDuplicateCheck; use Chill\ThirdPartyBundle\Entity\ThirdParty; @@ -62,12 +64,9 @@ use const SORT_REGULAR; * "accompanying_period": AccompanyingPeriod::class * }) * @Assert\GroupSequenceProvider - * @Assert\Expression( - * "this.isConfidential and this.getUser === NULL", - * message="If the accompanying course is confirmed and confidential, a referrer must remain assigned." - * ) - * * @AccompanyingPeriodValidity(groups={AccompanyingPeriod::STEP_DRAFT, AccompanyingPeriod::STEP_CONFIRMED}) + * @LocationValidity(groups={AccompanyingPeriod::STEP_DRAFT, AccompanyingPeriod::STEP_CONFIRMED}) + * @ConfidentialCourseMustHaveReferrer(groups={AccompanyingPeriod::STEP_DRAFT, AccompanyingPeriod::STEP_CONFIRMED}) */ class AccompanyingPeriod implements GroupSequenceProviderInterface, @@ -201,7 +200,7 @@ class AccompanyingPeriod implements /** * @var string * @ORM\Column(type="string", nullable=true) - * @Groups({"read", "write"}) + * @Groups({"read"}) * @Assert\NotBlank(groups={AccompanyingPeriod::STEP_CONFIRMED}) */ private $intensity = self::INTENSITY_OCCASIONAL; @@ -1000,7 +999,7 @@ class AccompanyingPeriod implements } /** - * Validation function. + * Validation functions. */ public function isDateConsistent(ExecutionContextInterface $context) { diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Banner/ToggleFlags.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Banner/ToggleFlags.vue index 39fe50acc..a24277fa0 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Banner/ToggleFlags.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Banner/ToggleFlags.vue @@ -58,7 +58,7 @@ export default { this.$store.dispatch('toggleIntensity', value) .catch(({name, violations}) => { if (name === 'ValidationException' || name === 'AccessException') { - violations.forEach((violation) => this.$toast.open({message: violation})); + this.$toast.open({message: this.$t('Only the referrer can toggle the intensity of an accompanying course')}) } else { this.$toast.open({message: 'An error occurred'}) } @@ -75,20 +75,15 @@ export default { }); }, toggleConfidential() { - this.$store.dispatch('fetchPermissions').then(() => { - if (!this.$store.getters.canTogglePermission) { - this.$toast.open({message: "Seul le référent peut modifier la confidentialité"}); - return Promise.resolve(); - } else { - return this.$store.dispatch('toggleConfidential', (!this.isConfidential)); - } - }).catch(({name, violations}) => { - if (name === 'ValidationException' || name === 'AccessException') { - violations.forEach((violation) => this.$toast.open({message: violation})); - } else { - this.$toast.open({message: 'An error occurred'}) - } - }); + this.$store.dispatch('toggleConfidential') + .catch(({name, violations}) => { + console.log(name); + if (name === 'ValidationException' || name === 'AccessException') { + this.$toast.open({message: this.$t('Only the referrer can toggle the confidentiality of an accompanying course')}) + } else { + this.$toast.open({message: 'An error occurred'}) + } + }); }, }, } diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/index.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/index.js index 8440e50d5..4cf073eb4 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/index.js +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/index.js @@ -46,6 +46,12 @@ if (root === 'banner') { }) .use(store) .use(i18n) + .use(VueToast, { + position: "bottom-right", + type: "error", + duration: 5000, + dismissible: true + }) .component('banner', Banner) .mount('#banner-accompanying-course'); }); diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/js/i18n.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/js/i18n.js index 49253eab8..5f0321c70 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/js/i18n.js +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/js/i18n.js @@ -167,6 +167,8 @@ const appMessages = { 'Error while retriving users.': "Erreur du serveur lors du chargement de la liste des travailleurs.", 'Error while getting whoami.': "Erreur du serveur lors de la requête 'qui suis-je ?'", 'Error while retriving origin\'s list.': "Erreur du serveur lors du chargement de la liste des origines de la demande.", + 'Only the referrer can toggle the intensity of an accompanying course': "Seul le référent peut modifier l'intensité d'un parcours.", + 'Only the referrer can toggle the confidentiality of an accompanying course': "Seul le référent peut modifier la confidentialité d'un parcours." } }; diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/store/index.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/store/index.js index 05960aaea..f7fd59b32 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/store/index.js +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/store/index.js @@ -420,24 +420,24 @@ let initPromise = (root) => Promise.all([getScopesPromise(root), accompanyingCou const url = `/api/1.0/person/accompanying-course/resource/${id}.json`; return makeFetch('PATCH', url, body) - .then((response) => { - commit('patchResource', response); - }) - .catch((error) => { - commit('catchError', error); - throw error; - }) + .then((response) => { + commit('patchResource', response); + }) + .catch((error) => { + commit('catchError', error); + throw error; + }) }, /** * Update accompanying course intensity/emergency/confidentiality */ toggleIntensity({ commit }, payload) { - const url = `/api/1.0/person/accompanying-course/${id}.json` + const url = `/api/1.0/person/accompanying-course/${id}/intensity.json` const body = { type: "accompanying_period", 'intensity': payload } - return makeFetch('PATCH', url, body) + return makeFetch('POST', url, body) .then((response) => { - commit('toggleIntensity', response.intensity); + commit('toggleIntensity', response); }) .catch((error) => { @@ -459,14 +459,18 @@ let initPromise = (root) => Promise.all([getScopesPromise(root), accompanyingCou }) }, toggleConfidential({ commit }, payload) { - const url = `/api/1.0/person/accompanying-course/${id}.json` + const url = `/api/1.0/person/accompanying-course/${id}/confidential.json` const body = { type: "accompanying_period", confidential: payload } - return makeFetch('PATCH', url, body) + console.log('url', url, 'body', body); + + return makeFetch('POST', url, body) .then((response) => { - commit('toggleConfidential', response.confidential); + console.log('response', response); + commit('toggleConfidential', response); }) .catch((error) => { + console.log('error', error) commit('catchError', error); throw error; }) @@ -737,10 +741,10 @@ let initPromise = (root) => Promise.all([getScopesPromise(root), accompanyingCou "object": { "type": "accompanying_period", "id": id - }, - "class": "Chill\\PersonBundle\\Entity\\AccompanyingPeriod", - "roles": [ - "CHILL_PERSON_ACCOMPANYING_PERIOD_TOGGLE_CONFIDENTIAL" + }, + "class": "Chill\\PersonBundle\\Entity\\AccompanyingPeriod", + "roles": [ + "CHILL_PERSON_ACCOMPANYING_PERIOD_TOGGLE_CONFIDENTIAL" ] } diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/Entity/PersonRenderBox.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/Entity/PersonRenderBox.vue index d87e0f50c..f77f006db 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/Entity/PersonRenderBox.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/Entity/PersonRenderBox.vue @@ -113,15 +113,6 @@
{{ $t('renderbox.no_data') }}
-{{ $t('renderbox.no_data') }}
-