diff --git a/CHANGELOG.md b/CHANGELOG.md index 36832794f..e6d1208e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,17 @@ and this project adheres to ## Unreleased +* [asideactivity] creation of aside activity category fixed (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/262) +* [vendee/person] fix typo "situation professionelle" => "situation professionnelle" +* [main] add availableForUsers condition from locationType in the location API endpoint (champs-libres/departement-de-la-vendee/accent-suivi-developpement#248) +* [main] add the current location of the user as API point + add it in the activity location list (champs-libres/departement-de-la-vendee/accent-suivi-developpement#247) +* [activity] improve show/new/edit templates, fix SEE and SEE_DETAILS acl +* [badges] create specific badge for TMS, and make person/thirdparty badges clickable with on-the-fly modal in : + * concerned groups items (activity, calendar) + * accompanyingCourseWork lists + * accompanyingCourse lists +* [acompanyingCourse] add initial comment on Resume page +* [person] create button full width (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/330) ## Test releases @@ -35,6 +46,8 @@ and this project adheres to * [asideactivity] creation of aside activity category fixed (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/262) * [vendee/person] fix typo "situation professionelle" => "situation professionnelle" * [accompanyingcourse_work] Changes in layout/behavior of edit form (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/321) +* [badge-entity] design coherency between pills badge-person and 3 kinds of badge-thirdparty +* [AddPersons] suggestions row are clickable, not only checkbox ### test release 2021-12-06 @@ -51,10 +64,6 @@ and this project adheres to * [visgraph] improve and fix bugs on vis-network relationship graph * [bugfix] posting of birth- and deathdate through api fixed. * [suggestions] improve suggestions lists -* [badge-entity] design coherency between badge-person and 3 kinds of badge-thirdparty -* [AddPersons] suggestions row are clickable, not only checkbox -* [activity] improve show/new/edit templates, fix SEE and SEE_DETAILS acl -* [activity][calendar] concerned groups items are clickable with on-the-fly modal, create specific badge for TMS column ### Test release 2021-11-19 - bis diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/api.js b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/api.js index 8d4bcac3b..edc0a616c 100644 --- a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/api.js +++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/api.js @@ -17,6 +17,14 @@ const getLocations = () => fetchResults('/api/1.0/main/location.json'); const getLocationTypes = () => fetchResults('/api/1.0/main/location-type.json'); +const getUserCurrentLocation = + () => fetch('/api/1.0/main/user-current-location.json') + .then(response => { + if (response.ok) { return response.json(); } + throw Error('Error with request resource response'); + }); + + /* * Load Location Type by defaultFor * @param {string} entity - can be "person" or "thirdparty" @@ -48,5 +56,6 @@ export { getLocations, getLocationTypes, getLocationTypeByDefaultFor, - postLocation + postLocation, + getUserCurrentLocation }; diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location.vue b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location.vue index 9a4b78334..50eb14799 100644 --- a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location.vue +++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/Location.vue @@ -15,7 +15,7 @@ :searchable="true" :placeholder="$t('activity.choose_location')" :custom-label="customLabel" - :options="locations" + :options="availableLocations" group-values="locations" group-label="locationGroup" v-model="location" @@ -32,7 +32,7 @@ import { mapState, mapGetters } from "vuex"; import VueMultiselect from "vue-multiselect"; import NewLocation from "./Location/NewLocation.vue"; -import { getLocations, getLocationTypeByDefaultFor } from "../api.js"; +import { getLocations, getLocationTypeByDefaultFor, getUserCurrentLocation } from "../api.js"; export default { name: "Location", @@ -40,13 +40,8 @@ export default { NewLocation, VueMultiselect, }, - data() { - return { - locations: [], - }; - }, computed: { - ...mapState(["activity"]), + ...mapState(["activity", "availableLocations"]), ...mapGetters(["suggestedEntities"]), location: { get() { @@ -57,53 +52,6 @@ export default { }, }, }, - mounted() { - getLocations().then( - (results) => { - getLocationTypeByDefaultFor('person').then( - (personLocationType) => { - if (personLocationType) { - const personLocation = this.makeAccompanyingPeriodLocation(personLocationType); - const concernedPersonsLocation = - this.makeConcernedPersonsLocation(personLocationType); - getLocationTypeByDefaultFor('thirdparty').then( - thirdpartyLocationType => { - const concernedThirdPartiesLocation = - this.makeConcernedThirdPartiesLocation(thirdpartyLocationType); - this.locations = [ - { - locationGroup: 'Localisation du parcours', - locations: [personLocation] - }, - { - locationGroup: 'Parties concernées', - locations: [...concernedPersonsLocation, ...concernedThirdPartiesLocation] - }, - { - locationGroup: 'Autres localisations', - locations: results - } - ]; - } - ) - } else { - this.locations = [ - { - locationGroup: 'Localisations', - locations: response.results - } - ]; - } - if (window.default_location_id) { - let location = this.locations.filter( - (l) => l.id === window.default_location_id - ); - this.$store.dispatch("updateLocation", location); - } - } - ) - }) - }, methods: { labelAccompanyingCourseLocation(value) { return `${value.address.text} (${value.locationType.title.fr})` @@ -117,58 +65,6 @@ export default { : value.locationType.title.fr : ''; }, - makeConcernedPersonsLocation(locationType) { - let locations = []; - this.suggestedEntities.forEach( - (e) => { - if (e.type === 'person' && e.current_household_address !== null){ - locations.push({ - type: 'location', - id: -this.suggestedEntities.indexOf(e)*10, - onthefly: true, - name: e.text, - address: { - id: e.current_household_address.address_id, - }, - locationType: locationType - }); - } - } - ) - return locations; - }, - makeConcernedThirdPartiesLocation(locationType) { - let locations = []; - this.suggestedEntities.forEach( - (e) => { - if (e.type === 'thirdparty' && e.address !== null){ - locations.push({ - type: 'location', - id: -this.suggestedEntities.indexOf(e)*10, - onthefly: true, - name: e.text, - address: { id: e.address.address_id }, - locationType: locationType - }); - } - } - ) - return locations; - }, - makeAccompanyingPeriodLocation(locationType) { - const accPeriodLocation = this.activity.accompanyingPeriod.location; - return { - type: 'location', - id: -1, - onthefly: true, - name: '__AccompanyingCourseLocation__', - address: { - id: accPeriodLocation.address_id, - text: `${accPeriodLocation.text} - ${accPeriodLocation.postcode.code} ${accPeriodLocation.postcode.name}` - }, - locationType: locationType - } - } }, }; diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.js b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.js index 1ca9f9cc2..4bf70b006 100644 --- a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.js +++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.js @@ -1,6 +1,7 @@ import 'es6-promise/auto'; import { createStore } from 'vuex'; import { postLocation } from './api'; +import prepareLocations from './store.locations.js'; const debug = process.env.NODE_ENV !== 'production'; //console.log('window.activity', window.activity); @@ -25,6 +26,7 @@ const store = createStore({ activity: window.activity, socialIssuesOther: [], socialActionsList: [], + availableLocations: [], }, getters: { suggestedEntities(state) { @@ -200,6 +202,9 @@ const store = createStore({ console.log("### mutation: updateLocation", value); state.activity.location = value; }, + addAvailableLocationGroup(state, group) { + state.availableLocations.push(group); + } }, actions: { addIssueSelected({ commit }, issue) { @@ -335,4 +340,6 @@ const store = createStore({ }, }); +prepareLocations(store); + export default store; diff --git a/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.locations.js b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.locations.js new file mode 100644 index 000000000..311bdc219 --- /dev/null +++ b/src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.locations.js @@ -0,0 +1,123 @@ +import {getLocations, getLocationTypeByDefaultFor, getUserCurrentLocation} from "./api"; + +const makeConcernedPersonsLocation = (locationType, store) => { + let locations = []; + store.getters.suggestedEntities.forEach( + (e) => { + if (e.type === 'person' && e.current_household_address !== null){ + locations.push({ + type: 'location', + id: -store.getters.suggestedEntities.indexOf(e)*10, + onthefly: true, + name: e.text, + address: { + id: e.current_household_address.address_id, + }, + locationType: locationType + }); + } + } + ) + return locations; +}; +const makeConcernedThirdPartiesLocation = (locationType, store) => { + let locations = []; + store.getters.suggestedEntities.forEach( + (e) => { + if (e.type === 'thirdparty' && e.address !== null){ + locations.push({ + type: 'location', + id: -store.getters.suggestedEntities.indexOf(e)*10, + onthefly: true, + name: e.text, + address: { id: e.address.address_id }, + locationType: locationType + }); + } + } + ) + return locations; +}; +const makeAccompanyingPeriodLocation = (locationType, store) => { + const accPeriodLocation = store.state.activity.accompanyingPeriod.location; + return { + type: 'location', + id: -1, + onthefly: true, + name: '__AccompanyingCourseLocation__', + address: { + id: accPeriodLocation.address_id, + text: `${accPeriodLocation.text} - ${accPeriodLocation.postcode.code} ${accPeriodLocation.postcode.name}` + }, + locationType: locationType + } +}; + +export default function prepareLocations(store) { + +// find the locations + let allLocations = getLocations().then( + (results) => { + store.commit('addAvailableLocationGroup', { + locationGroup: 'Autres localisations', + locations: results + }); + } + ); + + let currentLocation = getUserCurrentLocation().then( + userCurrentLocation => { + if (null !== userCurrentLocation) { + store.commit('addAvailableLocationGroup', { + locationGroup: 'Ma localisation', + locations: [userCurrentLocation] + }); + } + } + ); + + let partiesLocations = [], partyPromise; + ['person', 'thirdparty'].forEach(kind => { + partyPromise = getLocationTypeByDefaultFor(kind).then( + (kindLocationType) => { + if (kindLocationType) { + let concernedKindLocations; + if (kind === 'person') { + concernedKindLocations = makeConcernedPersonsLocation(kindLocationType, store); + // add location for the parcours into suggestions + const personLocation = makeAccompanyingPeriodLocation(kindLocationType, store); + store.commit('addAvailableLocationGroup', { + locationGroup: 'Localisation du parcours', + locations: [personLocation] + }); + } else { + concernedKindLocations = makeConcernedThirdPartiesLocation(kindLocationType, store); + } + + store.commit('addAvailableLocationGroup', { + locationGroup: kind === 'person' ? 'Usagers concernés' : 'Tiers concernés', + locations: concernedKindLocations, + }); + } + } + ); + partiesLocations.push(partyPromise); + }); + +// when all location are loaded + Promise.all([allLocations, currentLocation, ...partiesLocations]).then(() => { + console.log('current location in activity', store.state.activity.location); + console.log('default loation id', window.default_location_id); + if (window.default_location_id) { + for (let group of store.state.availableLocations) { + console.log(group); + let location = group.locations.find((l) => l.id === window.default_location_id); + console.log(location); + if (location !== undefined) { + store.dispatch('updateLocation', location); + break; + } + } + } + }); +} diff --git a/src/Bundle/ChillActivityBundle/Resources/views/Activity/list.html.twig b/src/Bundle/ChillActivityBundle/Resources/views/Activity/list.html.twig index 8efdd0148..3f49e67cc 100644 --- a/src/Bundle/ChillActivityBundle/Resources/views/Activity/list.html.twig +++ b/src/Bundle/ChillActivityBundle/Resources/views/Activity/list.html.twig @@ -127,24 +127,25 @@ {% endif %} + {% if activity.comment.comment is not empty and is_granted('CHILL_ACTIVITY_SEE_DETAILS', activity) %} +
+
+

{{ 'Comment'|trans }}

+
+
+ {{ activity.comment|chill_entity_render_box({ + 'disable_markdown': false, + 'limit_lines': 3, + 'metadata': false + }) }} +
+
+ {% endif %} + {# Only if ACL SEE_DETAILS AND/OR only on template SHOW ?? durationTime travelTime comment - {% if activity.comment.comment is not empty and is_granted('CHILL_ACTIVITY_SEE_DETAILS', activity) %} -
-
-

{{ 'Comment'|trans }}

-
-
- {{ activity.comment|chill_entity_render_box({ - 'disable_markdown': false, - 'limit_lines': 3, - 'metadata': false - }) }} -
-
- {% endif %} documents attendee #} diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js index edfb7f236..db2950bd4 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js @@ -1,6 +1,10 @@ import 'es6-promise/auto'; import { createStore } from 'vuex'; import { postLocation } from 'ChillActivityAssets/vuejs/Activity/api'; +import { + getLocations, getLocationTypeByDefaultFor, + getUserCurrentLocation +} from "../../../../../ChillActivityBundle/Resources/public/vuejs/Activity/api"; const debug = process.env.NODE_ENV !== 'production'; @@ -82,7 +86,7 @@ const store = createStore({ } }, mutations: { - + // ConcernedGroups addPersonsInvolved(state, payload) { //console.log('### mutation addPersonsInvolved', payload.result.type); @@ -94,7 +98,7 @@ const store = createStore({ state.activity.thirdParties.push(payload.result); break; case 'user': - state.activity.users.push(payload.result); + state.activity.users.push(payload.result); break; }; }, @@ -108,7 +112,7 @@ const store = createStore({ state.activity.thirdParties = state.activity.thirdParties.filter(thirdparty => thirdparty !== payload); break; case 'user': - state.activity.users = state.activity.users.filter(user => user !== payload); + state.activity.users = state.activity.users.filter(user => user !== payload); break; }; }, @@ -217,9 +221,7 @@ const store = createStore({ hiddenLocation.value = value.id; } commit("updateLocation", value); - } - } }); diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/listByAccompanyingCourse.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/listByAccompanyingCourse.html.twig index 07aed8686..215b7bb55 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/listByAccompanyingCourse.html.twig +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/listByAccompanyingCourse.html.twig @@ -92,8 +92,11 @@ %}
- - {% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {'context': accompanyingCourse, 'with_display': 'row', 'entity': calendar } %} + {% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with { + 'context': accompanyingCourse, + 'with_display': 'row', + 'entity': calendar + } %}
{% if calendar.comment.comment is not empty %} @@ -123,4 +126,4 @@ -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/src/Bundle/ChillMainBundle/Controller/LocationApiController.php b/src/Bundle/ChillMainBundle/Controller/LocationApiController.php index 525475e3c..aa5f46f1a 100644 --- a/src/Bundle/ChillMainBundle/Controller/LocationApiController.php +++ b/src/Bundle/ChillMainBundle/Controller/LocationApiController.php @@ -21,11 +21,14 @@ class LocationApiController extends ApiController { public function customizeQuery(string $action, Request $request, $query): void { - $query->andWhere( - $query->expr()->andX( + $query + ->leftJoin('e.locationType', 'lt') + ->andWhere( + $query->expr()->andX( $query->expr()->eq('e.availableForUsers', "'TRUE'"), + $query->expr()->eq('lt.availableForUsers', "'TRUE'"), $query->expr()->eq('e.active', "'TRUE'"), ) - ); + ); } } diff --git a/src/Bundle/ChillMainBundle/Controller/UserApiController.php b/src/Bundle/ChillMainBundle/Controller/UserApiController.php index 75e566048..d1fd4d5bb 100644 --- a/src/Bundle/ChillMainBundle/Controller/UserApiController.php +++ b/src/Bundle/ChillMainBundle/Controller/UserApiController.php @@ -17,6 +17,27 @@ use Symfony\Component\Routing\Annotation\Route; class UserApiController extends ApiController { + /** + * @Route( + * "/api/1.0/main/user-current-location.{_format}", + * name="chill_main_user_current_location", + * requirements={ + * "_format": "json" + * } + * ) + * + * @param mixed $_format + */ + public function currentLocation($_format): JsonResponse + { + return $this->json( + $this->getUser()->getCurrentLocation(), + JsonResponse::HTTP_OK, + [], + ['groups' => ['read']] + ); + } + /** * @Route( * "/api/1.0/main/whoami.{_format}", diff --git a/src/Bundle/ChillMainBundle/Resources/public/chill/scss/record_actions.scss b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/record_actions.scss index bdb3c60a6..18ebe4a59 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/chill/scss/record_actions.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/record_actions.scss @@ -33,6 +33,13 @@ ul.record_actions { margin-right: auto; } } + + ul.dropdown-menu { + li { + display: block; + margin-right: 0; + } + } } .sticky-form-buttons { margin-top: 4em; diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/UserApiControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/UserApiControllerTest.php index 813e9bc40..d96f9647a 100644 --- a/src/Bundle/ChillMainBundle/Tests/Controller/UserApiControllerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Controller/UserApiControllerTest.php @@ -55,6 +55,15 @@ final class UserApiControllerTest extends WebTestCase return $data['results'][0]; } + public function testUserCurrentLocation() + { + $client = $this->getClientAuthenticated(); + + $client->request(Request::METHOD_GET, '/api/1.0/main/user-current-location.json'); + + $this->assertResponseIsSuccessful(); + } + public function testWhoami() { $client = $this->getClientAuthenticated(); diff --git a/src/Bundle/ChillMainBundle/chill.api.specs.yaml b/src/Bundle/ChillMainBundle/chill.api.specs.yaml index fba3cfc19..db4430e48 100644 --- a/src/Bundle/ChillMainBundle/chill.api.specs.yaml +++ b/src/Bundle/ChillMainBundle/chill.api.specs.yaml @@ -546,6 +546,14 @@ paths: responses: 200: description: "ok" + /1.0/main/user-current-location.json: + get: + tags: + - user + summary: Return the current location of the currently authenticated user + responses: + 200: + description: "ok" /1.0/main/user/{id}.json: get: tags: diff --git a/src/Bundle/ChillMainBundle/translations/messages.fr.yml b/src/Bundle/ChillMainBundle/translations/messages.fr.yml index 78363d080..4ae23f1e3 100644 --- a/src/Bundle/ChillMainBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillMainBundle/translations/messages.fr.yml @@ -56,6 +56,7 @@ centers: centres Centers: Centres comment: commentaire Comment: Commentaire +Pinned comment: Commentaire épinglé Any comment: Aucun commentaire # comment embeddable diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseCommentController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseCommentController.php new file mode 100644 index 000000000..c5b8ed878 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseCommentController.php @@ -0,0 +1,86 @@ +setAccompanyingPeriod($accompanyingCourse); + + $form = $this->createCommentForm($newComment, 'new'); + + if ($request->query->has('edit')) { + foreach ($accompanyingCourse->getComments() as $comment) { + if ($comment->getId() === $request->query->getInt('edit')) { + $editForm = $this->createCommentForm($comment, 'edit'); + $commentEditId = $comment->getId(); + } + } + $pinnedComment = $accompanyingCourse->getPinnedComment(); + if ($pinnedComment->getId() === $request->query->getInt('edit')) { + $editForm = $this->createCommentForm($pinnedComment, 'edit'); + $commentEditId = $pinnedComment->getId(); + } + } + + if ($request->getMethod() === Request::METHOD_POST) { + if (array_key_exists('edit', $request->request->all()[$editForm->getName()])) { + $currentForm = $editForm->handleRequest($request); + $isEditingNew = false; + } else { + $currentForm = $form->handleRequest($request); + $isEditingNew = true; + } + + if ($currentForm->isSubmitted() && $currentForm->isValid()) { + $em = $this->getDoctrine()->getManager(); + if ($isEditingNew) { + $em->persist($newComment); + } + $em->flush(); + } + + return $this->redirectToRoute('chill_person_accompanying_period_comment_list', [ + 'accompanying_period_id' => $accompanyingCourse->getId() + ]); + } + + return $this->render('@ChillPerson/AccompanyingCourse/comment_list.html.twig', [ + 'accompanyingCourse' => $accompanyingCourse, + 'form' => $form->createView(), + 'edit_form' => isset($editForm) ? $editForm->createView() : null, + 'commentEditId' => $commentEditId ?? null, + ]); + } + + private function createCommentForm(AccompanyingPeriod\Comment $comment, string $step): FormInterface + { + $form = $this->createForm(AccompanyingCourseCommentType::class, $comment); + + if ('edit' === $step) { + $form->add('edit', HiddenType::class, ['mapped' => false ]); + } + + return $form; + } +} diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodWork.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodWork.php index 64c7d2701..d34c705ac 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodWork.php +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadAccompanyingPeriodWork.php @@ -95,7 +95,7 @@ class LoadAccompanyingPeriodWork extends \Doctrine\Bundle\FixturesBundle\Fixture // 1 of 10, force an evaluation if (0 === $i % 10) { $evaluation = $this->getRandomEvaluation(); - $action = $evaluation->getSocialAction(); + $action = $evaluation->getSocialActions()->first(); $issue = $action->getIssue(); $period->addSocialIssue($issue); diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php index 5b4293226..685010836 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php @@ -180,14 +180,6 @@ class AccompanyingPeriod implements */ private ?int $id = null; - /** - * @ORM\ManyToOne( - * targetEntity=Comment::class - * ) - * @Groups({"read"}) - */ - private ?Comment $initialComment = null; - /** * @var string * @ORM\Column(type="string", nullable=true) @@ -229,6 +221,14 @@ class AccompanyingPeriod implements */ private ?Person $personLocation = null; + /** + * @ORM\ManyToOne( + * targetEntity=Comment::class + * ) + * @Groups({"read"}) + */ + private ?Comment $pinnedComment = null; + /** * @ORM\Column(type="text") * @Groups({"read", "write"}) @@ -563,7 +563,7 @@ class AccompanyingPeriod implements public function getComments(): Collection { return $this->comments->filter(function (Comment $c) { - return $c !== $this->initialComment; + return $c !== $this->pinnedComment; }); } @@ -603,14 +603,6 @@ class AccompanyingPeriod implements return $this->id; } - /** - * @Groups({"read"}) - */ - public function getInitialComment(): ?Comment - { - return $this->initialComment; - } - public function getIntensity(): ?string { return $this->intensity; @@ -738,6 +730,14 @@ class AccompanyingPeriod implements ); } + /** + * @Groups({"read"}) + */ + public function getPinnedComment(): ?Comment + { + return $this->pinnedComment; + } + /** * @return Collection|SocialAction[] All the descendant social actions of all * the descendants of the entity @@ -1027,24 +1027,6 @@ class AccompanyingPeriod implements return $this; } - /** - * @Groups({"write"}) - */ - public function setInitialComment(?Comment $comment = null): self - { - if (null !== $this->initialComment) { - $this->removeComment($this->initialComment); - } - - if ($comment instanceof Comment) { - $this->addComment($comment); - } - - $this->initialComment = $comment; - - return $this; - } - public function setIntensity(string $intensity): self { $this->intensity = $intensity; @@ -1083,6 +1065,24 @@ class AccompanyingPeriod implements return $this; } + /** + * @Groups({"write"}) + */ + public function setPinnedComment(?Comment $comment = null): self + { + if (null !== $this->pinnedComment) { + $this->removeComment($this->pinnedComment); + } + + if ($comment instanceof Comment) { + $this->addComment($comment); + } + + $this->pinnedComment = $comment; + + return $this; + } + public function setRemark(?string $remark = null): self { $this->remark = (string) $remark; diff --git a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php index 75d1b2857..105633e43 100644 --- a/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php +++ b/src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod/Comment.php @@ -112,6 +112,11 @@ class Comment implements TrackCreationInterface, TrackUpdateInterface return $this->updatedBy; } + public function isPinned(): bool + { + return $this->getAccompanyingPeriod()->getPinnedComment() === $this; + } + public function setAccompanyingPeriod(?AccompanyingPeriod $accompanyingPeriod): self { $this->accompanyingPeriod = $accompanyingPeriod; diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php index a3524d306..882be10ed 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person.php @@ -244,7 +244,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI * @Assert\Date( * groups={"general", "creation"} * ) - * @Assert\GreaterThan(propertyPath="birthDate") + * @Assert\GreaterThanOrEqual(propertyPath="birthdate") * @Assert\LessThanOrEqual("today") */ private ?DateTimeImmutable $deathdate = null; diff --git a/src/Bundle/ChillPersonBundle/Entity/SocialWork/Evaluation.php b/src/Bundle/ChillPersonBundle/Entity/SocialWork/Evaluation.php index aeb8d0a8d..1350ae6d8 100644 --- a/src/Bundle/ChillPersonBundle/Entity/SocialWork/Evaluation.php +++ b/src/Bundle/ChillPersonBundle/Entity/SocialWork/Evaluation.php @@ -12,6 +12,8 @@ declare(strict_types=1); namespace Chill\PersonBundle\Entity\SocialWork; use DateInterval; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation as Serializer; @@ -45,12 +47,13 @@ class Evaluation private ?DateInterval $notificationDelay = null; /** - * @ORM\ManyToOne( + * @ORM\ManyToMany( * targetEntity=SocialAction::class, * inversedBy="evaluations" * ) + * @ORM\JoinTable(name="chill_person_social_work_evaluation_action") */ - private ?SocialAction $socialAction = null; + private Collection $socialActions; /** * @ORM\Column(type="json") @@ -59,6 +62,20 @@ class Evaluation */ private array $title = []; + public function __construct() + { + $this->socialActions = new ArrayCollection(); + } + + public function addSocialAction(SocialAction $socialAction): self + { + if (!$this->socialActions->contains($socialAction)) { + $this->socialActions->add($socialAction); + } + + return $this; + } + public function getDelay(): ?DateInterval { return $this->delay; @@ -74,9 +91,9 @@ class Evaluation return $this->notificationDelay; } - public function getSocialAction(): ?SocialAction + public function getSocialActions(): Collection { - return $this->socialAction; + return $this->socialActions; } public function getTitle(): array @@ -84,6 +101,15 @@ class Evaluation return $this->title; } + public function removeSocialAction(SocialAction $socialAction): self + { + if ($this->socialActions->contains($socialAction)) { + $this->socialActions->remove($socialAction); + } + + return $this; + } + public function setDelay(DateInterval $delay): self { $this->delay = $delay; @@ -98,13 +124,6 @@ class Evaluation return $this; } - public function setSocialAction(?SocialAction $socialAction): self - { - $this->socialAction = $socialAction; - - return $this; - } - public function setTitle(array $title): self { $this->title = $title; diff --git a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php index 64e4e79d8..ec5e5a8e5 100644 --- a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php +++ b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php @@ -46,9 +46,9 @@ class SocialAction private $desactivationDate; /** - * @ORM\OneToMany( + * @ORM\ManyToMany( * targetEntity=Evaluation::class, - * mappedBy="socialAction" + * mappedBy="socialActions" * ) */ private Collection $evaluations; @@ -71,6 +71,11 @@ class SocialAction */ private $issue; + /** + * @ORM\Column(type="float", name="ordering", options={"default": 0.0}) + */ + private float $ordering = 0.0; + /** * @ORM\ManyToOne(targetEntity=SocialAction::class, inversedBy="children") */ @@ -92,6 +97,7 @@ class SocialAction $this->children = new ArrayCollection(); $this->goals = new ArrayCollection(); $this->results = new ArrayCollection(); + $this->evaluations = new ArrayCollection(); } public function addChild(self $child): self @@ -199,6 +205,11 @@ class SocialAction return $this->issue; } + public function getOrdering(): float + { + return $this->ordering; + } + public function getParent(): ?self { return $this->parent; @@ -273,6 +284,13 @@ class SocialAction return $this; } + public function setOrdering(float $ordering): SocialAction + { + $this->ordering = $ordering; + + return $this; + } + /** * @internal use $parent->addChild() instead (@see{self::addChild()}) */ diff --git a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php index b0be1ae00..c735c0132 100644 --- a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php +++ b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialIssue.php @@ -44,6 +44,11 @@ class SocialIssue */ private $id; + /** + * @ORM\Column(type="float", name="ordering", options={"default": 0.0}) + */ + private float $ordering = 0.0; + /** * @ORM\ManyToOne(targetEntity=SocialIssue::class, inversedBy="children") */ @@ -215,6 +220,11 @@ class SocialIssue return $this->id; } + public function getOrdering(): float + { + return $this->ordering; + } + public function getParent(): ?self { return $this->parent; @@ -305,6 +315,13 @@ class SocialIssue return $this; } + public function setOrdering(float $ordering): SocialIssue + { + $this->ordering = $ordering; + + return $this; + } + /** * @internal use @see{SocialIssue::addChild()} instead */ diff --git a/src/Bundle/ChillPersonBundle/Form/AccompanyingCourseCommentType.php b/src/Bundle/ChillPersonBundle/Form/AccompanyingCourseCommentType.php new file mode 100644 index 000000000..b123a4c4d --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Form/AccompanyingCourseCommentType.php @@ -0,0 +1,37 @@ +add('content', ChillTextareaType::class, []); + } + + /** + * @return void + */ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefault('class', Comment::class); + } +} diff --git a/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php b/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php index fed840954..60455b201 100644 --- a/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php +++ b/src/Bundle/ChillPersonBundle/Menu/AccompanyingCourseMenuBuilder.php @@ -73,6 +73,13 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface ], ]) ->setExtras(['order' => 40]); + $menu->addChild($this->translator->trans('Accompanying Course Comment'), [ + 'route' => 'chill_person_accompanying_period_comment_list', + 'routeParameters' => [ + 'accompanying_period_id' => $period->getId(), + ], ]) + ->setExtras(['order' => 50]); + $workflow = $this->registry->get($period, 'accompanying_period_lifecycle'); if ($workflow->can($period, 'close')) { diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Comment.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Comment.vue index 7f5b04f99..5df43cdac 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Comment.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Comment.vue @@ -20,10 +20,10 @@ tag-name="textarea"> -
+ @@ -32,7 +32,7 @@
  • -
  • +
  • {{ $t('action.delete') }} @@ -66,15 +66,15 @@ export default { } }, computed: { - initialComment() { - return this.$store.state.accompanyingCourse.initialComment; + pinnedComment() { + return this.$store.state.accompanyingCourse.pinnedComment; }, content: { set(value) { this.formdata.content = value; }, get() { - return (this.initialComment)? this.initialComment.content : {}; + return (this.pinnedComment)? this.pinnedComment.content : {}; } }, errors() { @@ -107,7 +107,7 @@ export default { /* * TODO * - [x] delete button in ul record_actions, but not in form -* - [ ] display updatedAt => initialComment fetch PATCH content changes MUST NOT change object id !! +* - [ ] display updatedAt => pinnedComment fetch PATCH content changes MUST NOT change object id !! */ 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 d4bb6a678..7e58ebba8 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/js/i18n.js +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/js/i18n.js @@ -132,10 +132,6 @@ const appMessages = { sure_description: "Une fois le changement confirmé, il ne sera plus possible de le remettre à l'état de brouillon !", ok: "Confirmer le parcours" }, - action: { - choose_other_social_issue: "Veuillez choisir un autre problématique", - cancel: "Annuler", - }, // catch errors 'Error while updating AccompanyingPeriod Course.': "Erreur du serveur lors de la mise à jour du parcours d'accompagnement.", 'Error while retriving AccompanyingPeriod Course.': "Erreur du serveur lors du chargement du parcours d'accompagnement.", 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 a1858c6b3..d092adb0b 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/store/index.js +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/store/index.js @@ -163,7 +163,7 @@ let initPromise = Promise.all([scopesPromise, accompanyingCoursePromise]) }, postFirstComment(state, comment) { //console.log('### mutation: postFirstComment', comment); - state.accompanyingCourse.initialComment = comment; + state.accompanyingCourse.pinnedComment = comment; }, updateSocialIssues(state, value) { console.log('updateSocialIssues', value); @@ -565,11 +565,11 @@ let initPromise = Promise.all([scopesPromise, accompanyingCoursePromise]) }, postFirstComment({ commit }, payload) { const url = `/api/1.0/person/accompanying-course/${id}.json` - const body = { type: "accompanying_period", initialComment: payload } + const body = { type: "accompanying_period", pinnedComment: payload } return makeFetch('PATCH', url, body) .then((response) => { - commit('postFirstComment', response.initialComment); + commit('postFirstComment', response.pinnedComment); }) .catch((error) => { commit('catchError', error); diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/App.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/App.vue index e30c90d08..2cbc0cdac 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/App.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/App.vue @@ -8,10 +8,10 @@

    {{ $t('pick_social_issue_linked_with_action') }}

    - {{ si.text }} + {{ si.text }}
    -
    +
    @@ -35,7 +35,7 @@

    {{ $t('pick_an_action') }}

    -
    +
    {{ $t('form_has_errors') }}

      -
    • +
    • {{ e }}
    @@ -120,10 +120,11 @@ const i18n = { endDate: "Date de fin", form_has_errors: "Le formulaire comporte des erreurs", pick_social_issue: "Choisir une problématique sociale", + pick_other_social_issue: "Veuillez choisir un autre problématique", pick_an_action: "Choisir une action d'accompagnement", pick_social_issue_linked_with_action: "Indiquez la problématique sociale liée à l'action d'accompagnement", persons_involved: "Usagers concernés", - + choose_other_social_issue: "Veuillez choisir un autre problématique", } } } @@ -178,12 +179,10 @@ export default { personsPicked: { get() { let s = this.$store.state.personsPicked.map(p => p.id); - // console.log('persons picked', s); return s; }, set(v) { - // console.log('persons picked', v); this.$store.commit('setPersonsPickedIds', v); } }, @@ -226,6 +225,11 @@ export default { this.$store.commit('setEndDate', ISOToDate(value)); } }, + setSocialIssue: { + set() { + this.$store.dispatch('setSocialIssue', socialIssues[socialIssues.length - 1]) + } + } } } @@ -280,4 +284,4 @@ span.badge { grid-area: confirm; } } - \ No newline at end of file + diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/store.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/store.js index 8633c003d..408115257 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/store.js +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/store.js @@ -31,7 +31,6 @@ const store = createStore({ return null !== state.socialActionPicked; }, hasSocialIssuePicked(state) { - console.log(state.socialIssuePicked); return null !== state.socialIssuePicked; }, isLoadingSocialActions(state) { @@ -74,36 +73,27 @@ const store = createStore({ }, mutations: { setSocialActionsReachables(state, actions) { - // console.log('set social action reachables'); - // console.log(actions); - state.socialActionsReachables = actions; }, setSocialAction(state, socialAction) { - // console.log('socialAction', socialAction); state.socialActionPicked = socialAction; }, setSocialIssue(state, socialIssueId) { - // console.log('set social issue', socialIssueId); if (socialIssueId === null) { state.socialIssuePicked = null; } else { let mapped = state.socialIssues .find(e => e.id === socialIssueId); state.socialIssuePicked = mapped; - // console.log('social issue setted', state.socialIssuePicked); } }, addIssueInList(state, issue) { - //console.log('add issue list', issue.id); state.socialIssues.push(issue); }, updateIssuesOther(state, payload) { - //console.log('update issues other'); state.socialIssuesOther = payload; }, removeIssueInOther(state, issue) { - //console.log('remove issue other', issue.id); state.socialIssuesOther = state.socialIssuesOther.filter( (i) => i.id !== issue.id ); @@ -124,12 +114,12 @@ const store = createStore({ state.endDate = date; }, setPersonsPickedIds(state, ids) { - console.log('persons ids', ids); + state.personsPicked = state.personsReachables .filter(p => ids.includes(p.id)) }, addErrors(state, { errors, cancel_posting }) { - console.log('add errors', errors); + state.errors = errors; if (cancel_posting) { state.isPostingWork = false; @@ -138,8 +128,6 @@ const store = createStore({ }, actions: { pickSocialIssue({ commit }, socialIssueId) { - console.log('pick social issue'); - commit('setIsLoadingSocialActions', true); commit('setSocialAction', null); commit('setSocialActionsReachables', []); diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/HouseholdMembersEditor/components/HouseholdAddress.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/HouseholdMembersEditor/components/HouseholdAddress.vue index 9b2fe94a0..70716ec81 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/HouseholdMembersEditor/components/HouseholdAddress.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/HouseholdMembersEditor/components/HouseholdAddress.vue @@ -3,7 +3,7 @@
    {% endif %} + {% if accompanyingCourse.pinnedComment is not empty %} +
    +

    {{ 'Pinned comment'|trans }}

    +
    + {{ accompanyingCourse.pinnedComment.content }} + +
    +
    + {% endif %} + {% if accompanyingCourse.scopes is not empty %}

    {{ 'Scopes'|trans }}

    diff --git a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/index.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/index.html.twig index 844b2d611..cf91a4e20 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/index.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/index.html.twig @@ -65,11 +65,12 @@
    {% for p in w.persons %} - - {{ p|chill_entity_render_box({ - 'render': 'raw', - 'addAltNames': false - }) }} + + {% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with { + action: 'show', displayBadge: true, + targetEntity: { name: 'person', id: p.id }, + buttonText: p|chill_entity_render_string + } %} {% endfor %}
    @@ -82,11 +83,12 @@

    {{ 'Thirdparty handling'|trans }}

    - - {{ w.handlingThierParty|chill_entity_render_box({ - 'render': 'raw', - 'addAltNames': false - }) }} + + {% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with { + action: 'show', displayBadge: true, + targetEntity: { name: 'thirdparty', id: w.handlingThierParty.id }, + buttonText: w.handlingThierParty|chill_entity_render_string + } %}
    @@ -153,7 +155,6 @@
    - {# SEULEMENT SI DÉTAILLÉ {% if w.results|length > 0 %}
    @@ -192,7 +193,6 @@
    {% endfor %} {% endif %} - #}
    diff --git a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/list_recent_by_accompanying_period.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/list_recent_by_accompanying_period.html.twig index b5fcb6c40..4bab107c5 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/list_recent_by_accompanying_period.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/list_recent_by_accompanying_period.html.twig @@ -43,7 +43,39 @@
      - {% for e in w.accompanyingPeriodWorkEvaluations %} + A{% for g in w.goals %} +
    • + {{ 'accompanying_course_work.goal'|trans ~ ' : ' }} + {{ g.goal.title|localize_translatable_string }} + {% if g.results|length > 0 %} + {{ 'accompanying_course_work.results'|trans }} +
        + {% for r in g.results %} +
      • + {{ r.title|localize_translatable_string }} +
      • + {% endfor %} +
      + {% endif %} +
    • + {% endfor %} + B{% if w.results|length > 0 %} +
    • + {{ 'accompanying_course_work.goal'|trans }} +

      {{ 'accompanying_course_work.results without objective'|trans }}

      + {% if w.results %} + {{ 'accompanying_course_work.results'|trans }} +
        + {% for r in w.results %} +
      • + {{ r.title|localize_translatable_string }} +
      • + {% endfor %} +
      + {% endif %} +
    • + {% endif %} + C{% for e in w.accompanyingPeriodWorkEvaluations %}
    • {{ 'accompanying_course_work.social_evaluation'|trans ~ ' : ' }} {{ e.evaluation.title|localize_translatable_string }} @@ -55,7 +87,7 @@
    • {% endif %} {% if e.endDate %} -
    • +
    • {{ 'accompanying_course_work.end_date'|trans ~ ' : ' }} {{ e.endDate|format_date('short') }}
    • diff --git a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/_list.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/_list.html.twig index af8657e28..ebfbed604 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/_list.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/_list.html.twig @@ -66,10 +66,22 @@

      {{ 'Requestor'|trans({'gender': null }) }}

      {% if accompanying_period.requestorPerson is not null %} - {{ accompanying_period.requestorPerson|chill_entity_render_string }} + + {% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with { + action: 'show', displayBadge: true, + targetEntity: { name: 'person', id: accompanying_period.requestorPerson.id }, + buttonText: accompanying_period.requestorPerson|chill_entity_render_string + } %} + {% endif %} {% if accompanying_period.requestorThirdParty is not null %} - {{ accompanying_period.requestorThirdParty|chill_entity_render_string }} + + {% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with { + action: 'show', displayBadge: true, + targetEntity: { name: 'thirdparty', id: accompanying_period.requestorThirdParty.id }, + buttonText: accompanying_period.requestorThirdParty|chill_entity_render_string + } %} + {% endif %}
    @@ -80,13 +92,12 @@

    {{ 'Participants'|trans }}

    {% for p in accompanying_period.getCurrentParticipations %} - - - {{ p.person|chill_entity_render_string }} - - {# or in renderbox mode - {{ p.person|chill_entity_render_box({'render': 'label', 'addAltNames': false, 'addLink': true, 'hLevel': 5 }) }} - #} + + {% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with { + action: 'show', displayBadge: true, + targetEntity: { name: 'person', id: p.person.id }, + buttonText: p.person|chill_entity_render_string + } %} {% endfor %}
    diff --git a/src/Bundle/ChillPersonBundle/Resources/views/Household/summary.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/Household/summary.html.twig index 3567d1f7e..e88e07013 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/Household/summary.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/Household/summary.html.twig @@ -133,7 +133,7 @@ {% macro customButtons(member, household) %}
  • + class="btn btn-sm btn-misc" title="{{ 'household.person.leave'|trans }}">
  • diff --git a/src/Bundle/ChillPersonBundle/Resources/views/Person/household_history.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/Person/household_history.html.twig index 5dff4b074..d75106132 100644 --- a/src/Bundle/ChillPersonBundle/Resources/views/Person/household_history.html.twig +++ b/src/Bundle/ChillPersonBundle/Resources/views/Person/household_history.html.twig @@ -4,176 +4,163 @@ {% block title 'household.Household history for person'|trans %} +{% macro bloc_content(p) %} +
    +
    + +
    +
    + {% if p.endDate %} +
    + Jusqu'au {{ p.endDate|format_date('long') }} +
    + {% endif %} +
    +
    +
    +
    +
    +
    +
    +

    En tant que

    +
    +
    +

    {{ p.position.label|localize_translatable_string }} + {% if p.holder %} + {{ 'household.holder'|trans }} + {% endif %} +

    +
    +
    +
    +
    +

    {{ 'household.Members at same time'|trans }}

    +
    +
    + {% set simultaneous = p.household.getMembersDuringMembership(p) %} + {% if simultaneous|length == 0 %} +

    + {{ 'household.Any simultaneous members'|trans }} +

    + {% else %} + {% for m in simultaneous -%} + {% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with { + action: 'show', displayBadge: true, + targetEntity: { name: 'person', id: m.person.id }, + buttonText: m.person|chill_entity_render_string + } %} + {%- endfor -%} + {% endif %} +
    +
    +
    +
    +{% endmacro %} + {% block personcontent %}
    +

    {{ 'household.Household history'|trans }}

    -

    {{ 'household.Household history'|trans }}

    -

    {{ 'household.Household shared'|trans }}

    +
    +

    {{ 'household.Household shared'|trans }}

    + {% set memberships = person.getHouseholdParticipationsShareHousehold() %} - {% set memberships = person.getHouseholdParticipationsShareHousehold() %} + {% if memberships|length == 0 %} +

    {{ 'household.Never in any household'|trans }}

    - {% if memberships|length == 0 %} -

    {{ 'household.Never in any household'|trans }}

    + + {% else %} +
    + {% for p in memberships %} +
    + + {{ _self.bloc_content(p) }} + +
    + +
    + +
    + {% endfor %} +
    + + {% if not person.isSharingHousehold() %} - - {% else %} - -
    -
    - - {% if not person.isSharingHousehold() %} - - {% endif %} - - {% for p in memberships %} -
    -
    -
    -
    - {{ p.startDate|format_date('long') }} -
    -
    -
    -
    -
    - -
    -
    -

    - - - {{ 'household.Household number'|trans({'household_num': p.household.id }) }} - -

    -

    {{ p.position.label|localize_translatable_string }} {% if p.holder %}{{ 'household.holder'|trans }}{% endif %} -

    -
    - {% set simultaneous = p.household.getMembersDuringMembership(p) %} - {% if simultaneous|length == 0 %} -

    - {{ 'household.Any simultaneous members'|trans }} -

    - {% else %} - {{ 'household.Members at same time'|trans }}: - {% for p in simultaneous -%} - {{- p.person|chill_entity_render_box({'addLink': true }) -}} - {%- if p.holder %} {{'household.holder'|trans }} {% endif %} - {%- if not loop.last %}, {% endif -%} - {%- endfor -%} - {% endif %} - -
    -
    -
    -
    -
    - {% endfor %} -
    - -
    {% endif %} -

    {{ 'household.Household not shared'|trans }}

    + {% endif %} - {% set memberships = person.getHouseholdParticipationsNotShareHousehold() %} +
    +
    + {% set memberships = person.getHouseholdParticipationsNotShareHousehold() %} + {% if memberships|length > 0 %} - {% if memberships|length == 0 %} -

    {{ 'household.Never in any household'|trans }}

    - {% else %} - - - - - - - - - - {% for p in memberships %} - - - - - - - {% endfor %} - -
    {{ 'household.from'|trans }}{{ 'household.to'|trans }}{{ 'household.Household'|trans }}
    {{ p.startDate|format_date('long') }} - {% if p.endDate is not empty %} - {{ p.endDate|format_date('long') }} - {% else %} - {{ 'household.Membership currently running'|trans }} - {% endif %} - -
    -

    - - - {{ 'household.Household number'|trans({'household_num': p.household.id }) }} - -

    -

    - {{ p.position.label|localize_translatable_string }} - {% if p.holder %} - {{ 'household.holder'|trans }} - {% endif %} -

    -
    - {% set simultaneous = p.household.getMembersDuringMembership(p) %} - {% if simultaneous|length == 0 %} -

    - {{ 'household.Any simultaneous members'|trans }} -

    - {% else %} - {{ 'household.Members at same time'|trans }}: - {% for p in simultaneous -%} - {{- p.person|chill_entity_render_box({'addLink': true }) -}} - {%- if p.holder %} {{'household.holder'|trans }} {% endif %} - {%- if not loop.last %}, {% endif -%} - {%- endfor -%} - {% endif %} -
    -
    - -
    - {% endif %} +

    {{ 'household.Household not shared'|trans }}

    + +
    + {% for p in memberships %} +
    + + {{ _self.bloc_content(p) }} + +
    +
      +
    • + +
    • +
    +
    + +
    + {% endfor %} +
    + {% endif %} +
    {% endblock %} diff --git a/src/Bundle/ChillPersonBundle/Service/Import/SocialWorkMetadata.php b/src/Bundle/ChillPersonBundle/Service/Import/SocialWorkMetadata.php index a432d6837..621b97b7e 100644 --- a/src/Bundle/ChillPersonBundle/Service/Import/SocialWorkMetadata.php +++ b/src/Bundle/ChillPersonBundle/Service/Import/SocialWorkMetadata.php @@ -192,7 +192,7 @@ final class SocialWorkMetadata implements SocialWorkMetadataInterface /** @var Evaluation $eval */ $eval = $this->getOrCreateEntity($this->evaluationRepository, 'title', ['fr' => $evaluationTitle]); $eval->setTitle(['fr' => $evaluationTitle]); - $eval->setSocialAction($socialAction); + $eval->addSocialAction($socialAction); $this->entityManager->persist($eval); @@ -212,7 +212,7 @@ final class SocialWorkMetadata implements SocialWorkMetadataInterface $socialAction->addGoal($goal); $goal->addSocialAction($socialAction); - //$this->entityManager->persist($socialAction); + $this->entityManager->persist($socialAction); $this->entityManager->persist($goal); return $goal; @@ -239,7 +239,7 @@ final class SocialWorkMetadata implements SocialWorkMetadataInterface } $this->entityManager->persist($result); - //$this->entityManager->persist($socialAction); + $this->entityManager->persist($socialAction); return $result; } @@ -253,6 +253,8 @@ final class SocialWorkMetadata implements SocialWorkMetadataInterface ?string $socialActionTitle, ?string $socialActionChildTitle, SocialIssue $socialIssue, + float $orderingParent, + float $orderingChild, ?SocialAction $previousSocialAction, ?SocialAction $previousSocialActionChild ): array { @@ -271,7 +273,8 @@ final class SocialWorkMetadata implements SocialWorkMetadataInterface ]; $parentIsSame = true; } else { - $return['socialAction'] = $parent = (new SocialAction())->setTitle(['fr' => $socialActionTitle]); + $return['socialAction'] = $parent = (new SocialAction())->setTitle(['fr' => $socialActionTitle]) + ->setOrdering($orderingParent); $parent->setIssue($socialIssue); $this->entityManager->persist($parent); $parentIsSame = false; @@ -284,7 +287,7 @@ final class SocialWorkMetadata implements SocialWorkMetadataInterface } else { $return['socialActionChild'] = $child = (new SocialAction())->setTitle(['fr' => $socialActionChildTitle]); $parent->addChild($child); - $child->setIssue($socialIssue); + $child->setIssue($socialIssue)->setOrdering($orderingChild); $this->entityManager->persist($child); } @@ -299,6 +302,8 @@ final class SocialWorkMetadata implements SocialWorkMetadataInterface private function handleSocialIssue( ?string $socialIssueTitle, ?string $socialIssueChildTitle, + float $orderingParent, + float $orderingChild, ?SocialIssue $previousSocialIssue, ?SocialIssue $previousSocialIssueChild ): array { @@ -310,7 +315,8 @@ final class SocialWorkMetadata implements SocialWorkMetadataInterface ]; $parentIsSame = true; } elseif (null !== $socialIssueTitle) { - $return['socialIssue'] = $parent = (new SocialIssue())->setTitle(['fr' => $socialIssueTitle]); + $return['socialIssue'] = $parent = (new SocialIssue())->setTitle(['fr' => $socialIssueTitle]) + ->setOrdering($orderingParent); $this->entityManager->persist($parent); $parentIsSame = false; } else { @@ -323,7 +329,8 @@ final class SocialWorkMetadata implements SocialWorkMetadataInterface if ($parentIsSame && null !== $previousSocialIssueChild && ($previousSocialIssueChild->getTitle()['fr'] === $socialIssueChildTitle)) { $return['socialIssueChild'] = $previousSocialIssueChild; } elseif (null !== $socialIssueChildTitle) { - $return['socialIssueChild'] = $child = (new SocialIssue())->setTitle(['fr' => $socialIssueChildTitle]); + $return['socialIssueChild'] = $child = (new SocialIssue())->setTitle(['fr' => $socialIssueChildTitle]) + ->setOrdering($orderingChild); $parent->addChild($child); $this->entityManager->persist($child); } else { @@ -353,10 +360,14 @@ final class SocialWorkMetadata implements SocialWorkMetadataInterface */ private function import1(int $key, array $row, array $previousRow): array { + $baseOrdering = $key * 10.0; + $socialIssues = $this ->handleSocialIssue( $row[0], $row[1], + $key + 1.0, + $key + 3.0, $previousRow['socialIssues']['socialIssue'] ?? null, $previousRow['socialIssues']['socialIssueChild'] ?? null ); @@ -372,6 +383,8 @@ final class SocialWorkMetadata implements SocialWorkMetadataInterface $row[2], $row[3], $socialIssue, + $key + 5.0, + $key + 7.0, $previousRow['socialActions']['socialAction'] ?? null, $previousRow['socialActions']['socialActionChild'] ?? null ); @@ -380,8 +393,8 @@ final class SocialWorkMetadata implements SocialWorkMetadataInterface if (null !== $socialAction) { $goal = $this->handleGoal($row[4], $socialAction); - $result = $this->handleResult($row[5], $socialActions['socialAction'], $goal); - $eval = $this->handleEvaluation($row[6], $socialActions['socialAction']); + $result = $this->handleResult($row[5], $socialAction, $goal); + $eval = $this->handleEvaluation($row[6], $socialAction); } $this->entityManager->flush(); diff --git a/src/Bundle/ChillPersonBundle/Tests/Entity/AccompanyingPeriodTest.php b/src/Bundle/ChillPersonBundle/Tests/Entity/AccompanyingPeriodTest.php index 9bbea0f1c..a459c3c18 100644 --- a/src/Bundle/ChillPersonBundle/Tests/Entity/AccompanyingPeriodTest.php +++ b/src/Bundle/ChillPersonBundle/Tests/Entity/AccompanyingPeriodTest.php @@ -60,32 +60,6 @@ final class AccompanyingPeriodTest extends \PHPUnit\Framework\TestCase $this->assertFalse($period->isClosingAfterOpening()); } - public function testInitialComment() - { - $period = new AccompanyingPeriod(new DateTime()); - $comment = new Comment(); - $replacingComment = new Comment(); - - $period->setInitialComment(null); - $this->assertNull($period->getInitialComment()); - - $period->setInitialComment($comment); - $this->assertSame($period->getInitialComment(), $comment); - $this->assertSame($period, $comment->getAccompanyingPeriod()); - $this->assertEquals(0, count($period->getComments()), 'The initial comment should not appears in the list of comments'); - - $period->setInitialComment($replacingComment); - $this->assertSame($period->getInitialComment(), $replacingComment); - $this->assertSame($period, $replacingComment->getAccompanyingPeriod()); - $this->assertEquals(0, count($period->getComments()), 'The initial comment should not appears in the list of comments'); - $this->assertNull($comment->getAccompanyingPeriod()); - - $period->setInitialComment(null); - $this->assertNull($period->getInitialComment()); - $this->assertNull($replacingComment->getAccompanyingPeriod()); - $this->assertEquals(0, count($period->getComments()), 'The initial comment should not appears in the list of comments'); - } - public function testIsClosed() { $period = new AccompanyingPeriod(new DateTime()); @@ -145,6 +119,32 @@ final class AccompanyingPeriodTest extends \PHPUnit\Framework\TestCase $this->assertEquals(1, $period->getParticipationsContainsPerson($person4)->count()); } + public function testPinnedComment() + { + $period = new AccompanyingPeriod(new DateTime()); + $comment = new Comment(); + $replacingComment = new Comment(); + + $period->setPinnedComment(null); + $this->assertNull($period->getPinnedComment()); + + $period->setPinnedComment($comment); + $this->assertSame($period->getPinnedComment(), $comment); + $this->assertSame($period, $comment->getAccompanyingPeriod()); + $this->assertEquals(0, count($period->getComments()), 'The initial comment should not appears in the list of comments'); + + $period->setPinnedComment($replacingComment); + $this->assertSame($period->getPinnedComment(), $replacingComment); + $this->assertSame($period, $replacingComment->getAccompanyingPeriod()); + $this->assertEquals(0, count($period->getComments()), 'The initial comment should not appears in the list of comments'); + $this->assertNull($comment->getAccompanyingPeriod()); + + $period->setPinnedComment(null); + $this->assertNull($period->getPinnedComment()); + $this->assertNull($replacingComment->getAccompanyingPeriod()); + $this->assertEquals(0, count($period->getComments()), 'The initial comment should not appears in the list of comments'); + } + public function testRequestor() { $period = new AccompanyingPeriod(new DateTime()); diff --git a/src/Bundle/ChillPersonBundle/chill.api.specs.yaml b/src/Bundle/ChillPersonBundle/chill.api.specs.yaml index 3c49cc264..218904e5e 100644 --- a/src/Bundle/ChillPersonBundle/chill.api.specs.yaml +++ b/src/Bundle/ChillPersonBundle/chill.api.specs.yaml @@ -554,7 +554,7 @@ paths: value: type: accompanying_period id: 2668, - initialComment: + pinnedComment: type: accompanying_period_comment content: > This is my an initial comment. @@ -1139,7 +1139,7 @@ paths: description: "OK" 400: description: "transition cannot be applyed" - + /1.0/person/accompanying-course/{id}/confidential.json: post: tags: diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20211213150253.php b/src/Bundle/ChillPersonBundle/migrations/Version20211213150253.php new file mode 100644 index 000000000..f02ad75b0 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/migrations/Version20211213150253.php @@ -0,0 +1,44 @@ +addSql('ALTER TABLE chill_person_accompanying_period DROP CONSTRAINT FK_E260A868B0804E90'); + $this->addSql('DROP INDEX IDX_E260A868B0804E90'); + $this->addSql('ALTER TABLE chill_person_accompanying_period RENAME COLUMN pinnedcomment_id TO initialcomment_id'); + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD CONSTRAINT fk_e260a8683111d50b FOREIGN KEY (initialcomment_id) REFERENCES chill_person_accompanying_period_comment (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('CREATE INDEX idx_e260a8683111d50b ON chill_person_accompanying_period (initialcomment_id)'); + } + + public function getDescription(): string + { + return 'rename initialComment attribute to pinnedComment'; + } + + public function up(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_person_accompanying_period DROP CONSTRAINT fk_e260a8683111d50b'); + $this->addSql('DROP INDEX idx_e260a8683111d50b'); + $this->addSql('ALTER TABLE chill_person_accompanying_period RENAME COLUMN initialcomment_id TO pinnedcomment_id'); + $this->addSql('ALTER TABLE chill_person_accompanying_period ADD CONSTRAINT FK_E260A868B0804E90 FOREIGN KEY (pinnedcomment_id) REFERENCES chill_person_accompanying_period_comment (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('CREATE INDEX IDX_E260A868B0804E90 ON chill_person_accompanying_period (pinnedcomment_id)'); + } +} diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20211213203147.php b/src/Bundle/ChillPersonBundle/migrations/Version20211213203147.php new file mode 100644 index 000000000..53282e83f --- /dev/null +++ b/src/Bundle/ChillPersonBundle/migrations/Version20211213203147.php @@ -0,0 +1,50 @@ +addSql('DROP TABLE chill_person_social_work_evaluation_action'); + $this->addSql('ALTER TABLE chill_person_social_work_evaluation ADD socialaction_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE chill_person_social_work_evaluation ADD CONSTRAINT fk_2e23f3febf32a3da FOREIGN KEY (socialaction_id) REFERENCES chill_person_social_action (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('CREATE INDEX idx_2e23f3febf32a3da ON chill_person_social_work_evaluation (socialaction_id)'); + } + + public function getDescription(): string + { + return 'an evaluation may be linked with multiple social actions'; + } + + public function up(Schema $schema): void + { + $this->addSql('CREATE TABLE chill_person_social_work_evaluation_action (evaluation_id INT NOT NULL, socialaction_id INT NOT NULL, PRIMARY KEY(evaluation_id, socialaction_id))'); + $this->addSql('CREATE INDEX IDX_DF34CCFB456C5646 ON chill_person_social_work_evaluation_action (evaluation_id)'); + $this->addSql('CREATE INDEX IDX_DF34CCFB3DC32179 ON chill_person_social_work_evaluation_action (socialaction_id)'); + $this->addSql('ALTER TABLE chill_person_social_work_evaluation_action ADD CONSTRAINT FK_DF34CCFB456C5646 FOREIGN KEY (evaluation_id) REFERENCES chill_person_social_work_evaluation (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_person_social_work_evaluation_action ADD CONSTRAINT FK_DF34CCFB3DC32179 FOREIGN KEY (socialaction_id) REFERENCES chill_person_social_action (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + + $this->addSql('INSERT INTO chill_person_social_work_evaluation_action (evaluation_id, socialaction_id) ' . + 'SELECT id, socialaction_ID FROM chill_person_social_work_evaluation'); + + $this->addSql('ALTER TABLE chill_person_social_work_evaluation DROP CONSTRAINT fk_2e23f3febf32a3da'); + $this->addSql('DROP INDEX idx_2e23f3febf32a3da'); + $this->addSql('ALTER TABLE chill_person_social_work_evaluation DROP socialaction_id'); + } +} diff --git a/src/Bundle/ChillPersonBundle/migrations/Version20211213213755.php b/src/Bundle/ChillPersonBundle/migrations/Version20211213213755.php new file mode 100644 index 000000000..347ea35bf --- /dev/null +++ b/src/Bundle/ChillPersonBundle/migrations/Version20211213213755.php @@ -0,0 +1,35 @@ +addSql('ALTER TABLE chill_person_social_action DROP ordering'); + $this->addSql('ALTER TABLE chill_person_social_issue DROP ordering'); + } + + public function getDescription(): string + { + return 'Add ordering to social issue and social actions'; + } + + public function up(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_person_social_action ADD ordering DOUBLE PRECISION DEFAULT \'0\' NOT NULL'); + $this->addSql('ALTER TABLE chill_person_social_issue ADD ordering DOUBLE PRECISION DEFAULT \'0\' NOT NULL'); + } +} diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index 4a712633d..f461e5bec 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -408,6 +408,14 @@ Associate at least one member with an household, and set an address to this hous Locate by: Localiser auprès de fix it: Compléter +# Accompanying Course comments +Accompanying Course Comment: Commentaire +Accompanying Course Comment list: Commentaires du parcours +pinned: épinglé +Post a new comment: Poster un nouveau commentaire +Write a new comment: Écrire un nouveau commentaire +Edit a comment: Modifier le commentaire + # Household Household: Ménage Summary: Résumé diff --git a/src/Bundle/ChillThirdPartyBundle/Entity/ThirdParty.php b/src/Bundle/ChillThirdPartyBundle/Entity/ThirdParty.php index c3334f781..002dda45e 100644 --- a/src/Bundle/ChillThirdPartyBundle/Entity/ThirdParty.php +++ b/src/Bundle/ChillThirdPartyBundle/Entity/ThirdParty.php @@ -219,10 +219,9 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface private ?string $telephone = null; /** - * @var array|null * @ORM\Column(name="types", type="json", nullable=true) */ - private $types; + private ?array $thirdPartyTypes = []; /** * @ORM\Column(name="updated_at", type="datetime_immutable", nullable=true) @@ -303,18 +302,18 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface return $this; } - public function addType(?string $type): self + public function addThirdPartyTypes(?string $type): self { if (null === $type) { return $this; } - if (!in_array($type, $this->types ?? [], true)) { - $this->types[] = $type; + if (!in_array($type, $this->thirdPartyTypes ?? [], true)) { + $this->thirdPartyTypes[] = $type; } foreach ($this->children as $child) { - $child->addType($type); + $child->addThirdPartyTypes($type); } return $this; @@ -329,7 +328,7 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface } if (is_string($typeAndCategory)) { - $this->addType($typeAndCategory); + $this->addThirdPartyTypes($typeAndCategory); return $this; } @@ -473,16 +472,16 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface * * @return array|null */ - public function getTypes() + public function getThirdPartyTypes() { - return $this->types; + return $this->thirdPartyTypes ?? []; } public function getTypesAndCategories(): array { return array_merge( $this->getCategories()->toArray(), - $this->getTypes() ?? [] + $this->getThirdPartyTypes() ?? [] ); } @@ -574,18 +573,18 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface return $this; } - public function removeType(?string $type): self + public function removeThirdPartyTypes(?string $type): self { if (null === $type) { return $this; } - if (in_array($type, $this->types ?? [], true)) { - $this->types = array_filter($this->types, fn ($e) => !in_array($e, $this->types, true)); + if (in_array($type, $this->thirdPartyTypes ?? [], true)) { + $this->thirdPartyTypes = array_filter($this->thirdPartyTypes, fn ($e) => !in_array($e, $this->thirdPartyTypes, true)); } foreach ($this->children as $child) { - $child->removeType($type); + $child->removeThirdPartyTypes($type); } return $this; @@ -600,7 +599,7 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface } if (is_string($typeAndCategory)) { - $this->removeType($typeAndCategory); + $this->removeThirdPartyTypes($typeAndCategory); return $this; } @@ -799,13 +798,13 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface * * @return ThirdParty */ - public function setTypes(?array $type = null) + public function setThirdPartyTypes(?array $type = []) { // remove all keys from the input data - $this->types = array_values($type); + $this->thirdPartyTypes = array_values($type); foreach ($this->children as $child) { - $child->setTypes($type); + $child->setThirdPartyTypes($type); } return $this; @@ -814,7 +813,7 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface public function setTypesAndCategories(array $typesAndCategories): self { $types = array_filter($typesAndCategories, static fn ($item) => !$item instanceof ThirdPartyCategory); - $this->setTypes($types); + $this->setThirdPartyTypes($types); // handle categories foreach ($typesAndCategories as $t) { diff --git a/src/Bundle/ChillThirdPartyBundle/Form/ThirdPartyType.php b/src/Bundle/ChillThirdPartyBundle/Form/ThirdPartyType.php index a32c0ade2..4146e98a3 100644 --- a/src/Bundle/ChillThirdPartyBundle/Form/ThirdPartyType.php +++ b/src/Bundle/ChillThirdPartyBundle/Form/ThirdPartyType.php @@ -134,15 +134,6 @@ class ThirdPartyType extends AbstractType // Institutional ThirdParty (parent) } else { $builder - ->add('address', PickAddressType::class, [ - 'label' => 'Address', - ]) - ->add('address2', PickAddressType::class, [ - 'label' => 'Address', - 'use_valid_from' => true, - 'use_valid_to' => true, - 'mapped' => false, - ]) ->add('nameCompany', TextType::class, [ 'label' => 'thirdparty.NameCompany', 'required' => false, @@ -170,6 +161,9 @@ class ThirdPartyType extends AbstractType if (ThirdParty::KIND_CHILD !== $options['kind']) { $builder + ->add('address', PickAddressType::class, [ + 'label' => 'Address', + ]) ->add('typesAndCategories', PickThirdPartyTypeCategoryType::class, [ 'label' => 'thirdparty.Categories', ]) diff --git a/src/Bundle/ChillThirdPartyBundle/Resources/public/vuejs/_components/OnTheFly/ThirdParty.vue b/src/Bundle/ChillThirdPartyBundle/Resources/public/vuejs/_components/OnTheFly/ThirdParty.vue index 2d540530d..dc9025886 100644 --- a/src/Bundle/ChillThirdPartyBundle/Resources/public/vuejs/_components/OnTheFly/ThirdParty.vue +++ b/src/Bundle/ChillThirdPartyBundle/Resources/public/vuejs/_components/OnTheFly/ThirdParty.vue @@ -26,17 +26,19 @@
  • @@ -97,26 +99,16 @@ import ThirdPartyRenderBox from '../Entity/ThirdPartyRenderBox.vue'; import AddAddress from 'ChillMainAssets/vuejs/Address/components/AddAddress'; import { getThirdparty } from '../../_api/OnTheFly'; - -const i18n = { - messages: { - fr: { - tparty: { - contact: "Personne physique", - company: "Personne morale" - } - } - } -}; +import BadgeEntity from 'ChillMainAssets/vuejs/_components/BadgeEntity.vue'; export default { name: "OnTheFlyThirdParty", props: ['id', 'type', 'action'], components: { ThirdPartyRenderBox, - AddAddress + AddAddress, + BadgeEntity }, - i18n, data() { return { //context: {}, <-- diff --git a/src/Bundle/ChillThirdPartyBundle/Resources/views/ThirdParty/_form.html.twig b/src/Bundle/ChillThirdPartyBundle/Resources/views/ThirdParty/_form.html.twig index c53764871..6b76b5cb0 100644 --- a/src/Bundle/ChillThirdPartyBundle/Resources/views/ThirdParty/_form.html.twig +++ b/src/Bundle/ChillThirdPartyBundle/Resources/views/ThirdParty/_form.html.twig @@ -28,7 +28,9 @@ {{ form_widget(form.activeChildren) }} {% endif %} -{{ form_row(form.address) }} +{% if form.address is defined %} + {{ form_row(form.address) }} +{% endif %} {{ form_row(form.comment) }} diff --git a/src/Bundle/ChillThirdPartyBundle/Resources/views/ThirdParty/index.html.twig b/src/Bundle/ChillThirdPartyBundle/Resources/views/ThirdParty/index.html.twig index cb9c4bcf5..66b321504 100644 --- a/src/Bundle/ChillThirdPartyBundle/Resources/views/ThirdParty/index.html.twig +++ b/src/Bundle/ChillThirdPartyBundle/Resources/views/ThirdParty/index.html.twig @@ -62,7 +62,3 @@ {% endblock %} {% endembed %} {% endblock %} - -{% block css %} - {{ encore_entry_link_tags('page_3party_3party_index') }} -{% endblock %} diff --git a/src/Bundle/ChillThirdPartyBundle/Resources/views/ThirdParty/update.html.twig b/src/Bundle/ChillThirdPartyBundle/Resources/views/ThirdParty/update.html.twig index 75e165270..2d9c39002 100644 --- a/src/Bundle/ChillThirdPartyBundle/Resources/views/ThirdParty/update.html.twig +++ b/src/Bundle/ChillThirdPartyBundle/Resources/views/ThirdParty/update.html.twig @@ -12,7 +12,7 @@ {% block crud_content_header %}

    {{ 'Update third party %name%'|trans({ '%name%': thirdParty.name }) }} - {{ (thirdParty.active ? 'Active' : 'Inactive')|trans }} diff --git a/src/Bundle/ChillThirdPartyBundle/Tests/Entity/ThirdPartyTest.php b/src/Bundle/ChillThirdPartyBundle/Tests/Entity/ThirdPartyTest.php index 0ec7d065e..4dc6dbc55 100644 --- a/src/Bundle/ChillThirdPartyBundle/Tests/Entity/ThirdPartyTest.php +++ b/src/Bundle/ChillThirdPartyBundle/Tests/Entity/ThirdPartyTest.php @@ -35,8 +35,8 @@ final class ThirdPartyTest extends TestCase $this->assertTrue($tp->getCategories()->contains($cat2)); $this->assertCount(2, $tp->getCategories()); - $this->assertCount(1, $tp->getTypes()); - $this->assertContains('type', $tp->getTypes()); + $this->assertCount(1, $tp->getThirdPartyTypes()); + $this->assertContains('type', $tp->getThirdPartyTypes()); $this->assertCount(3, $tp->getTypesAndCategories()); $this->assertContains($cat1, $tp->getTypesAndCategories()); @@ -54,8 +54,8 @@ final class ThirdPartyTest extends TestCase $this->assertFalse($tp->getCategories()->contains($cat2)); $this->assertCount(1, $tp->getCategories()); - $this->assertCount(0, $tp->getTypes()); - $this->assertNotContains('type', $tp->getTypes()); + $this->assertCount(0, $tp->getThirdPartyTypes()); + $this->assertNotContains('type', $tp->getThirdPartyTypes()); $this->assertCount(1, $tp->getTypesAndCategories()); $this->assertContains($cat1, $tp->getTypesAndCategories()); @@ -77,9 +77,9 @@ final class ThirdPartyTest extends TestCase $this->assertTrue($tp->getCategories()->contains($cat2)); $this->assertCount(2, $tp->getCategories()); - $this->assertCount(2, $tp->getTypes()); - $this->assertContains('type1', $tp->getTypes()); - $this->assertContains('type2', $tp->getTypes()); + $this->assertCount(2, $tp->getThirdPartyTypes()); + $this->assertContains('type1', $tp->getThirdPartyTypes()); + $this->assertContains('type2', $tp->getThirdPartyTypes()); $this->assertCount(4, $tp->getTypesAndCategories()); $this->assertContains($cat1, $tp->getTypesAndCategories()); @@ -93,9 +93,9 @@ final class ThirdPartyTest extends TestCase $this->assertFalse($tp->getCategories()->contains($cat2)); $this->assertCount(1, $tp->getCategories()); - $this->assertCount(1, $tp->getTypes()); - $this->assertContains('type1', $tp->getTypes()); - $this->assertNotContains('type2', $tp->getTypes()); + $this->assertCount(1, $tp->getThirdPartyTypes()); + $this->assertContains('type1', $tp->getThirdPartyTypes()); + $this->assertNotContains('type2', $tp->getThirdPartyTypes()); $this->assertCount(2, $tp->getTypesAndCategories()); $this->assertContains($cat1, $tp->getTypesAndCategories()); diff --git a/src/Bundle/ChillThirdPartyBundle/Tests/Serializer/Normalizer/ThirdPartyJsonDenormalizerTest.php b/src/Bundle/ChillThirdPartyBundle/Tests/Serializer/Normalizer/ThirdPartyJsonDenormalizerTest.php new file mode 100644 index 000000000..611a0d7c7 --- /dev/null +++ b/src/Bundle/ChillThirdPartyBundle/Tests/Serializer/Normalizer/ThirdPartyJsonDenormalizerTest.php @@ -0,0 +1,54 @@ +normalizer = self::$container->get(DenormalizerInterface::class); + } + + public function testDenormalizeContact() + { + $str = <<<'JSON' + { + "type": "thirdparty", + "name": "badaboum", + "email": "badaboum@email.com", + "telephone": "+32486540660", + "kind": "contact" + } + JSON; + + $actual = $this->normalizer->denormalize(json_decode($str, true), ThirdParty::class, 'json', [ + 'groups' => ['write'], + ]); + + $this->assertInstanceOf(ThirdParty::class, $actual); + $this->assertEquals('badaboum', $actual->getName()); + $this->assertEquals('badaboum@email.com', $actual->getEmail()); + $this->assertEquals(ThirdParty::KIND_CONTACT, $actual->getKind()); + } +} diff --git a/src/Bundle/ChillThirdPartyBundle/Tests/Serializer/Normalizer/ThirdpartyDocGenNormalizerTest.php b/src/Bundle/ChillThirdPartyBundle/Tests/Serializer/Normalizer/ThirdpartyDocGenNormalizerTest.php index 0b8169d69..cc2b7b33b 100644 --- a/src/Bundle/ChillThirdPartyBundle/Tests/Serializer/Normalizer/ThirdpartyDocGenNormalizerTest.php +++ b/src/Bundle/ChillThirdPartyBundle/Tests/Serializer/Normalizer/ThirdpartyDocGenNormalizerTest.php @@ -44,8 +44,6 @@ final class ThirdpartyDocGenNormalizerTest extends KernelTestCase $actual = $this->normalizer->normalize($thirdparty, 'docgen', ['groups' => ['docgen:read']]); - var_dump($actual); - $this->assertIsArray($actual); } }