diff --git a/.changes/unreleased/Fixed-20240916-151843.yaml b/.changes/unreleased/Fixed-20240916-151843.yaml deleted file mode 100644 index ba89d3a70..000000000 --- a/.changes/unreleased/Fixed-20240916-151843.yaml +++ /dev/null @@ -1,6 +0,0 @@ -kind: Fixed -body: Show only the current referrer in the page "show" for an accompanying period - workf -time: 2024-09-16T15:18:43.017401122+02:00 -custom: - Issue: "308" diff --git a/.changes/v3.1.1.md b/.changes/v3.1.1.md new file mode 100644 index 000000000..06bf33077 --- /dev/null +++ b/.changes/v3.1.1.md @@ -0,0 +1,6 @@ +## v3.1.1 - 2024-10-01 +### Fixed +* ([#308](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/308)) Show only the current referrer in the page "show" for an accompanying period workf +* ([#309](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/309)) Correctly compute the grouping by referrer aggregator + +* Fixed typing of custom field long choice and custom field group diff --git a/.changes/v3.2.0.md b/.changes/v3.2.0.md new file mode 100644 index 000000000..25dd295c8 --- /dev/null +++ b/.changes/v3.2.0.md @@ -0,0 +1,3 @@ +## v3.2.0 - 2024-10-30 +### Feature +* Introduce a gender entity diff --git a/.changes/v3.2.1.md b/.changes/v3.2.1.md new file mode 100644 index 000000000..dd1466922 --- /dev/null +++ b/.changes/v3.2.1.md @@ -0,0 +1,4 @@ +## v3.2.1 - 2024-10-31 +### Fixed +* Add the possibility of unknown to the gender entity +* Fix the fusion of person doubles by excluding accompanyingPeriod work entities to be deleted. They are moved instead. diff --git a/.changes/v3.2.2.md b/.changes/v3.2.2.md new file mode 100644 index 000000000..7ab01bf62 --- /dev/null +++ b/.changes/v3.2.2.md @@ -0,0 +1,3 @@ +## v3.2.2 - 2024-10-31 +### Fixed +* Fix gender translation for unknown diff --git a/.changes/v3.2.3.md b/.changes/v3.2.3.md new file mode 100644 index 000000000..b7064350a --- /dev/null +++ b/.changes/v3.2.3.md @@ -0,0 +1,4 @@ +## v3.2.3 - 2024-11-05 +### Fixed +* ([#315](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/315)) Fix display of accompanying period work referrers. Only current referrers should be displayed. +Fix color of Chill footer diff --git a/.changes/v3.2.4.md b/.changes/v3.2.4.md new file mode 100644 index 000000000..f89cf37eb --- /dev/null +++ b/.changes/v3.2.4.md @@ -0,0 +1,3 @@ +## v3.2.4 - 2024-11-06 +### Fixed +* Fix compilation of chill assets diff --git a/CHANGELOG.md b/CHANGELOG.md index 5272cd5a9..c5bed63c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,22 +6,57 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html), and is generated by [Changie](https://github.com/miniscruff/changie). +## v3.2.4 - 2024-11-06 +### Fixed +* Fix compilation of chill assets + +## v3.2.3 - 2024-11-05 +### Fixed +* ([#315](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/315)) Fix display of accompanying period work referrers. Only current referrers should be displayed. +Fix color of Chill footer + +## v3.2.2 - 2024-10-31 +### Fixed +* Fix gender translation for unknown + +## v3.2.1 - 2024-10-31 +### Fixed +* Add the possibility of unknown to the gender entity +* Fix the fusion of person doubles by excluding accompanyingPeriod work entities to be deleted. They are moved instead. + +## v3.2.0 - 2024-10-30 +### Feature +* Introduce a gender entity + +## v3.1.1 - 2024-10-01 +### Fixed +* ([#308](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/308)) Show only the current referrer in the page "show" for an accompanying period workf +* ([#309](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/309)) Correctly compute the grouping by referrer aggregator + +* Fixed typing of custom field long choice and custom field group + ## v3.1.0 - 2024-08-30 ### Feature -* Add export aggregator to aggregate activities by household + filter persons that are not part of an accompanyingperiod during a certain timeframe. +* Add export aggregator to aggregate activities by household + filter persons that are not part of an accompanyingperiod during a certain timeframe. ## v3.0.0 - 2024-08-26 ### Fixed -* Fix delete action for accompanying periods in draft state -* Fix connection to azure when making an calendar event in chill -* CollectionType js fixes for remove button and adding multiple entries +* Fix delete action for accompanying periods in draft state +* Fix connection to azure when making an calendar event in chill +* CollectionType js fixes for remove button and adding multiple entries ## v2.24.0 - 2024-09-11 ### Feature -* ([#306](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/306)) When a document is converted or downloaded in the browser, this document is removed from the browser memory after 45s. Future click on the button re-download the document. +* ([#306](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/306)) When a document is converted or downloaded in the browser, this document is removed from the browser memory after 45s. Future click on the button re-download the document. -## v2.23.0 - 2024-07-19 & 2024-07-23 +## v2.23.0 - 2024-07-23 & 2024-07-19 ### Feature +* ([#221](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/221)) [DX] move async-upload-bundle features into chill-bundles +* Add job bundle (module emploi) +* Upgrade import of address list to the last version of compiled addresses of belgian-best-address + +* Upgrade CKEditor and refactor configuration with use of typescript + * ([#123](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/123)) Add a button to duplicate calendar ranges from a week to another one * [admin] filter users by active / inactive in the admin user's list * ([#273](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/273)) Add the possibility to mark all notifications as read @@ -31,6 +66,8 @@ and is generated by [Changie](https://github.com/miniscruff/changie). * Do not update the "createdAt" column when importing postal code which does not change * Display filename on file upload within the UI interface ### Fixed +* Fix resolving of centers for an household, which will fix in turn the access control +* Resolved type hinting error in activity list export * ([#271](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/271)) Take into account the acp closing date in the acp works date filter ### Traduction française des principaux changements @@ -43,25 +80,15 @@ and is generated by [Changie](https://github.com/miniscruff/changie). - Agrandit l'icône du type de fichier dans l'interface de dépôt de fichier; - correction: tient compte de la date de fermeture du parcours dans les filtres sur les actions d'accompagnement. -* ([#221](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/221)) [DX] move async-upload-bundle features into chill-bundles -* Add job bundle (module emploi) -* Upgrade import of address list to the last version of compiled addresses of belgian-best-address - -* Upgrade CKEditor and refactor configuration with use of typescript - -### Fixed -* Fix resolving of centers for an household, which will fix in turn the access control -* Resolved type hinting error in activity list export - ## v2.22.2 - 2024-07-03 ### Fixed -* Remove scope required for event participation stats +* Remove scope required for event participation stats ## v2.22.1 - 2024-07-01 ### Fixed -* Remove debug word +* Remove debug word ### DX -* Add a command for reading official address DB from Luxembourg and update chill addresses +* Add a command for reading official address DB from Luxembourg and update chill addresses ## v2.22.0 - 2024-06-25 ### Feature @@ -104,7 +131,7 @@ and is generated by [Changie](https://github.com/miniscruff/changie). ## v2.20.1 - 2024-06-05 ### Fixed -* Do not allow StoredObjectCreated for edit and convert buttons +* Do not allow StoredObjectCreated for edit and convert buttons ## v2.20.0 - 2024-06-05 ### Fixed @@ -151,96 +178,96 @@ and is generated by [Changie](https://github.com/miniscruff/changie). ## v2.18.2 - 2024-04-12 ### Fixed -* ([#250](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/250)) Postal codes import : fix the source URL and the keys to handle each record +* ([#250](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/250)) Postal codes import : fix the source URL and the keys to handle each record ## v2.18.1 - 2024-03-26 ### Fixed -* Fix layout issue in document generation for admin (minor) +* Fix layout issue in document generation for admin (minor) ## v2.18.0 - 2024-03-26 ### Feature -* ([#268](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/268)) Improve admin UX to configure document templates for document generation +* ([#268](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/268)) Improve admin UX to configure document templates for document generation ### Fixed -* ([#267](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/267)) Fix the join between job and user in the user list (admin): show only the current user job +* ([#267](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/267)) Fix the join between job and user in the user list (admin): show only the current user job ## v2.17.0 - 2024-03-19 ### Feature -* ([#237](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/237)) New export filter for social actions with an evaluation created between two dates -* ([#258](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/258)) In the list of accompangying period, add the list of person's centers and the duration of the course -* ([#238](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/238)) Allow to customize list person with new fields +* ([#237](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/237)) New export filter for social actions with an evaluation created between two dates +* ([#258](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/258)) In the list of accompangying period, add the list of person's centers and the duration of the course +* ([#238](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/238)) Allow to customize list person with new fields * ([#159](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/159)) Admin can publish news on the homepage ### Fixed -* ([#264](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/264)) Fix languages: load the languages in all availables languages configured for Chill -* ([#259](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/259)) Keep a consistent behaviour between the filtering of activities within the document generation (model "accompanying period with activities"), and the same filter in the list of activities for an accompanying period +* ([#264](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/264)) Fix languages: load the languages in all availables languages configured for Chill +* ([#259](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/259)) Keep a consistent behaviour between the filtering of activities within the document generation (model "accompanying period with activities"), and the same filter in the list of activities for an accompanying period ## v2.16.3 - 2024-02-26 ### Fixed -* ([#236](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/236)) Fix translation of user job -> 'service' must be 'métier' +* ([#236](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/236)) Fix translation of user job -> 'service' must be 'métier' ### UX -* ([#232](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/232)) Order user jobs and services alphabetically in export filters +* ([#232](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/232)) Order user jobs and services alphabetically in export filters ## v2.16.2 - 2024-02-21 ### Fixed -* Check for null values in closing motive of parcours d'accompagnement for correct rendering of template +* Check for null values in closing motive of parcours d'accompagnement for correct rendering of template ## v2.16.1 - 2024-02-09 ### Fixed -* Force bootstrap version to avoid error in builds with newer version +* Force bootstrap version to avoid error in builds with newer version ## v2.16.0 - 2024-02-08 ### Feature -* ([#231](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/231)) Create new filter for persons having a participation in an accompanying period during a certain time span -* ([#241](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/241)) [Export][List of accompanyign period] Add two columns: the list of persons participating to the period, and their ids -* ([#244](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/244)) Add capability to generate export about change of steps of accompanying period, and generate exports for this -* ([#253](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/253)) Export: group accompanying period by person participating -* ([#243](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/243)) Export: add filter for courses not linked to a reference address -* ([#229](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/229)) Allow to group activities linked with accompanying period by reason -* ([#115](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/115)) Prevent social work to be saved when another user edited conccurently the social work -* Modernize the event bundle, with some new fields and multiple improvements +* ([#231](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/231)) Create new filter for persons having a participation in an accompanying period during a certain time span +* ([#241](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/241)) [Export][List of accompanyign period] Add two columns: the list of persons participating to the period, and their ids +* ([#244](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/244)) Add capability to generate export about change of steps of accompanying period, and generate exports for this +* ([#253](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/253)) Export: group accompanying period by person participating +* ([#243](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/243)) Export: add filter for courses not linked to a reference address +* ([#229](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/229)) Allow to group activities linked with accompanying period by reason +* ([#115](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/115)) Prevent social work to be saved when another user edited conccurently the social work +* Modernize the event bundle, with some new fields and multiple improvements ### Fixed -* ([#220](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/220)) Fix error in logs about wrong typing of eventArgs in onEditNotificationComment method -* ([#256](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/256)) Fix the conditions upon which social actions should be optional or required in relation to social issues within the activity creation form +* ([#220](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/220)) Fix error in logs about wrong typing of eventArgs in onEditNotificationComment method +* ([#256](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/256)) Fix the conditions upon which social actions should be optional or required in relation to social issues within the activity creation form ### UX -* ([#260](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/260)) Order list of centers alphabetically in dropdown 'user' section admin. +* ([#260](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/260)) Order list of centers alphabetically in dropdown 'user' section admin. ## v2.15.2 - 2024-01-11 ### Fixed -* Fix the id_seq used when creating a new accompanying period participation during fusion of two person files +* Fix the id_seq used when creating a new accompanying period participation during fusion of two person files ### DX -* Set placeholder to False for expanded EntityType form fields where required is set to False. +* Set placeholder to False for expanded EntityType form fields where required is set to False. ## v2.15.1 - 2023-12-20 ### Fixed -* Fix the household export query to exclude accompanying periods that are in draft state. +* Fix the household export query to exclude accompanying periods that are in draft state. ### DX -* ([#167](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/167)) Fixed readthedocs compilation by updating readthedocs config file and requirements for Sphinx +* ([#167](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/167)) Fixed readthedocs compilation by updating readthedocs config file and requirements for Sphinx ## v2.15.0 - 2023-12-11 ### Feature -* ([#191](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/191)) Add export "number of household associate with an exchange" -* ([#235](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/235)) Export: add dates on the filter "filter course by activity type" +* ([#191](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/191)) Add export "number of household associate with an exchange" +* ([#235](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/235)) Export: add dates on the filter "filter course by activity type" ### Fixed -* ([#214](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/214)) Fix error when posting an empty comment on an accompanying period. -* ([#233](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/233)) Fix "filter evaluation by evaluation type" (and add select2 to the list of evaluation types to pick) +* ([#214](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/214)) Fix error when posting an empty comment on an accompanying period. +* ([#233](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/233)) Fix "filter evaluation by evaluation type" (and add select2 to the list of evaluation types to pick) * ([#234](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/234)) Fix "filter aside activity by date" - -* ([#228](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/228)) Fix export of activity for people created before the introduction of the createdAt column on person (during v1) -* ([#246](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/246)) Do not show activities, evaluations and social work when associated to a confidential accompanying period, except for the users which are allowed to see them + +* ([#228](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/228)) Fix export of activity for people created before the introduction of the createdAt column on person (during v1) +* ([#246](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/246)) Do not show activities, evaluations and social work when associated to a confidential accompanying period, except for the users which are allowed to see them ## v2.14.1 - 2023-11-29 ### Fixed -* Export: fix list person with custom fields -* ([#100](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/100)) Add a paginator to budget elements (resource and charge types) in the admin -* Fix error in ListEvaluation when "handling agents" are alone +* Export: fix list person with custom fields +* ([#100](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/100)) Add a paginator to budget elements (resource and charge types) in the admin +* Fix error in ListEvaluation when "handling agents" are alone ## v2.14.0 - 2023-11-24 ### Feature -* ([#161](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/161)) Export: in filter "Filter accompanying period work (social action) by type, goal and result", order the items alphabetically or with the defined order +* ([#161](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/161)) Export: in filter "Filter accompanying period work (social action) by type, goal and result", order the items alphabetically or with the defined order ### Fixed -* ([#141](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/141)) Export: on filter "action by type goals, and results", restore the fields when editing a saved export -* ([#219](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/219)) Export: fix the list of accompanying period work, when the "calc date" is null -* ([#222](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/222)) Fix rendering of custom fields -* Fix various errors in custom fields administration +* ([#141](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/141)) Export: on filter "action by type goals, and results", restore the fields when editing a saved export +* ([#219](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/219)) Export: fix the list of accompanying period work, when the "calc date" is null +* ([#222](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/222)) Fix rendering of custom fields +* Fix various errors in custom fields administration ## v2.13.0 - 2023-11-21 ### Feature @@ -254,7 +281,7 @@ and is generated by [Changie](https://github.com/miniscruff/changie). ## v2.12.1 - 2023-11-16 ### Fixed -* ([#208](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/208)) Export: fix loading of form for "filter action by type, goal and result" +* ([#208](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/208)) Export: fix loading of form for "filter action by type, goal and result" ## v2.12.0 - 2023-11-15 ### Feature @@ -285,36 +312,36 @@ and is generated by [Changie](https://github.com/miniscruff/changie). ## v2.11.0 - 2023-11-07 ### Feature -* ([#194](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/194)) Export: add a filter "filter activity by creator job" +* ([#194](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/194)) Export: add a filter "filter activity by creator job" ### Fixed -* ([#185](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/185)) Export: fix "group accompanying period by geographical unit": take into account the accompanying periods when the period is not located within an unit -* Fix "group activity by creator job" aggregator +* ([#185](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/185)) Export: fix "group accompanying period by geographical unit": take into account the accompanying periods when the period is not located within an unit +* Fix "group activity by creator job" aggregator ## v2.10.6 - 2023-11-07 ### Fixed -* ([#182](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/182)) Fix merging of double person files. Adjustement relationship sql statement -* ([#185](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/185)) Export: fix aggregator by geographical unit on person: avoid inconsistencies +* ([#182](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/182)) Fix merging of double person files. Adjustement relationship sql statement +* ([#185](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/185)) Export: fix aggregator by geographical unit on person: avoid inconsistencies ## v2.10.5 - 2023-11-05 ### Fixed -* ([#183](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/183)) Fix "problem during download" on some filters, which used a wrong data type -* ([#184](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/184)) Fix filter "activity by date" +* ([#183](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/183)) Fix "problem during download" on some filters, which used a wrong data type +* ([#184](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/184)) Fix filter "activity by date" ## v2.10.4 - 2023-10-26 ### Fixed -* Fix null value constraint errors when merging relationships in doubles +* Fix null value constraint errors when merging relationships in doubles ## v2.10.3 - 2023-10-26 ### Fixed -* ([#175](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/175)) Replace old method of getting translator with injection of translatorInterface +* ([#175](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/175)) Replace old method of getting translator with injection of translatorInterface ## v2.10.2 - 2023-10-26 ### Fixed -* ([#175](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/175)) Use injection of translator instead of ->get(). +* ([#175](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/175)) Use injection of translator instead of ->get(). ## v2.10.1 - 2023-10-24 ### Fixed -* Fix export controller when generating an export without any data in session +* Fix export controller when generating an export without any data in session ## v2.10.0 - 2023-10-24 ### Feature @@ -339,11 +366,11 @@ and is generated by [Changie](https://github.com/miniscruff/changie). ## v2.9.2 - 2023-10-17 ### Fixed -* Fix possible null values in string's entities +* Fix possible null values in string's entities ## v2.9.1 - 2023-10-17 ### Fixed -* Fix the handling of activity form when editing or creating an activity in an accompanying period with multiple centers +* Fix the handling of activity form when editing or creating an activity in an accompanying period with multiple centers ## v2.9.0 - 2023-10-17 ### Feature @@ -391,57 +418,57 @@ But if you do not need this any more, you must ensure that the configuration key ## v2.7.0 - 2023-09-27 ### Feature -* ([#155](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/155)) The regulation list load accompanying periods by exact postal code (address associated with postal code), and not by the content of the postal code (postal code with same code's string) +* ([#155](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/155)) The regulation list load accompanying periods by exact postal code (address associated with postal code), and not by the content of the postal code (postal code with same code's string) ### Fixed -* ([#142](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/142)) Fix the label of filter ActivityTypeFilter to a more obvious one -* ([#140](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/140)) [export] Fix association of filter "filter location by type" which did not appears on "list of activities" +* ([#142](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/142)) Fix the label of filter ActivityTypeFilter to a more obvious one +* ([#140](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/140)) [export] Fix association of filter "filter location by type" which did not appears on "list of activities" ## v2.6.3 - 2023-09-19 ### Fixed -* Remove id property from document -mappedsuperclass +* Remove id property from document +mappedsuperclass ## v2.6.2 - 2023-09-18 ### Fixed -* Fix doctrine mapping of AbstractTaskPlaceEvent and SingleTaskPlaceEvent: id property moved. +* Fix doctrine mapping of AbstractTaskPlaceEvent and SingleTaskPlaceEvent: id property moved. ## v2.6.1 - 2023-09-14 ### Fixed -* Filter out active centers in exports, which uses a different PickCenterType. +* Filter out active centers in exports, which uses a different PickCenterType. ## v2.6.0 - 2023-09-14 ### Feature -* ([#133](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/133)) Add locations in Aside Activity. By default, suggest user location, otherwise a select with all locations. -* ([#133](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/133)) Adapt Aside Activity exports: display location, filter by location, group by location -* Use the CRUD controller for center entity + add the isActive property to be able to mask instances of Center that are no longer in use. +* ([#133](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/133)) Add locations in Aside Activity. By default, suggest user location, otherwise a select with all locations. +* ([#133](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/133)) Adapt Aside Activity exports: display location, filter by location, group by location +* Use the CRUD controller for center entity + add the isActive property to be able to mask instances of Center that are no longer in use. ### Fixed -* ([#107](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/107)) reinstate the fusion of duplicate persons -* Missing translation in Work Actions exports -* Reimplement the mission type filter on tasks, only for instances that have a config parameter indicating true for this. -* ([#135](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/135)) Corrects a typing error in 2 filters, which caused an +* ([#107](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/107)) reinstate the fusion of duplicate persons +* Missing translation in Work Actions exports +* Reimplement the mission type filter on tasks, only for instances that have a config parameter indicating true for this. +* ([#135](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/135)) Corrects a typing error in 2 filters, which caused an error when trying to reedit a saved export - -* ([#136](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/136)) [household] when moving a person to a sharing position to a not-sharing position on the same household on the same date, remove the previous household membership on the same household. This fix duplicate member. + +* ([#136](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/136)) [household] when moving a person to a sharing position to a not-sharing position on the same household on the same date, remove the previous household membership on the same household. This fix duplicate member. * Add missing translation for comment field placeholder in repositionning household editor. - -* Do not send an email to creator twice when adding a comment to a notification -* ([#107](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/107)) Fix gestion doublon functionality to work with chill bundles v2 + +* Do not send an email to creator twice when adding a comment to a notification +* ([#107](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/107)) Fix gestion doublon functionality to work with chill bundles v2 ### UX * Uniformize badge-person in household banner (background, size) - + ## v2.5.3 - 2023-07-20 ### Fixed -* ([#132](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/132)) Rendez-vous documents created would appear in all documents lists of all persons with an accompanying period. Or statements are now added to the where clause to filter out documents that come from unrelated accompanying period/ or person rendez-vous. +* ([#132](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/132)) Rendez-vous documents created would appear in all documents lists of all persons with an accompanying period. Or statements are now added to the where clause to filter out documents that come from unrelated accompanying period/ or person rendez-vous. ## v2.5.2 - 2023-07-15 ### Fixed -* [Collate Address] when updating address point, do not use the point's address reference if the similarity is below the requirement for associating the address reference and the address (it uses the postcode's center instead) +* [Collate Address] when updating address point, do not use the point's address reference if the similarity is below the requirement for associating the address reference and the address (it uses the postcode's center instead) ## v2.5.1 - 2023-07-14 ### Fixed -* [collate addresses] block collating addresses to another address reference where the address reference is already the best match +* [collate addresses] block collating addresses to another address reference where the address reference is already the best match ## v2.5.0 - 2023-07-14 ### Feature diff --git a/package.json b/package.json index 05750d5c9..ae6d5437e 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,8 @@ "vue-i18n": "^9.1.6", "vue-multiselect": "3.0.0-alpha.2", "vue-toast-notification": "^3.1.2", - "vuex": "^4.0.0" + "vuex": "^4.0.0", + "bootstrap-icons": "^1.11.3" }, "browserslist": [ "Firefox ESR" diff --git a/src/Bundle/ChillActivityBundle/Security/Authorization/ActivityStoredObjectVoter.php b/src/Bundle/ChillActivityBundle/Security/Authorization/ActivityStoredObjectVoter.php index 78def7318..6a2a27140 100644 --- a/src/Bundle/ChillActivityBundle/Security/Authorization/ActivityStoredObjectVoter.php +++ b/src/Bundle/ChillActivityBundle/Security/Authorization/ActivityStoredObjectVoter.php @@ -16,7 +16,7 @@ use Chill\ActivityBundle\Repository\ActivityRepository; use Chill\DocStoreBundle\Repository\AssociatedEntityToStoredObjectInterface; use Chill\DocStoreBundle\Security\Authorization\StoredObjectRoleEnum; use Chill\DocStoreBundle\Security\Authorization\StoredObjectVoter\AbstractStoredObjectVoter; -use Chill\DocStoreBundle\Service\WorkflowStoredObjectPermissionHelper; +use Chill\MainBundle\Workflow\Helper\WorkflowRelatedEntityPermissionHelper; use Symfony\Component\Security\Core\Security; class ActivityStoredObjectVoter extends AbstractStoredObjectVoter @@ -24,7 +24,7 @@ class ActivityStoredObjectVoter extends AbstractStoredObjectVoter public function __construct( private readonly ActivityRepository $repository, Security $security, - WorkflowStoredObjectPermissionHelper $workflowDocumentService, + WorkflowRelatedEntityPermissionHelper $workflowDocumentService, ) { parent::__construct($security, $workflowDocumentService); } diff --git a/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldLongChoice.php b/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldLongChoice.php index 54d63b978..3a0adbdcc 100644 --- a/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldLongChoice.php +++ b/src/Bundle/ChillCustomFieldsBundle/CustomFields/CustomFieldLongChoice.php @@ -42,8 +42,8 @@ class CustomFieldLongChoice extends AbstractCustomField $translatableStringHelper = $this->translatableStringHelper; $builder->add($customField->getSlug(), Select2ChoiceType::class, [ 'choices' => $entries, - 'choice_label' => static fn (Option $option) => $translatableStringHelper->localize($option->getText()), - 'choice_value' => static fn (Option $key): ?int => null === $key ? null : $key->getId(), + 'choice_label' => static fn (?Option $option) => $translatableStringHelper->localize($option->getText()), + 'choice_value' => static fn (?Option $key): ?int => $key?->getId(), 'multiple' => false, 'expanded' => false, 'required' => $customField->isRequired(), diff --git a/src/Bundle/ChillCustomFieldsBundle/Entity/CustomFieldsGroup.php b/src/Bundle/ChillCustomFieldsBundle/Entity/CustomFieldsGroup.php index 55f09597c..723b47612 100644 --- a/src/Bundle/ChillCustomFieldsBundle/Entity/CustomFieldsGroup.php +++ b/src/Bundle/ChillCustomFieldsBundle/Entity/CustomFieldsGroup.php @@ -46,11 +46,8 @@ class CustomFieldsGroup #[ORM\GeneratedValue(strategy: 'AUTO')] private ?int $id = null; - /** - * @var array - */ #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] - private $name; + private array|string $name; #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] private array $options = []; @@ -181,7 +178,7 @@ class CustomFieldsGroup * * @return CustomFieldsGroup */ - public function setName($name) + public function setName(array|string $name) { $this->name = $name; diff --git a/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoter/AbstractStoredObjectVoter.php b/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoter/AbstractStoredObjectVoter.php index 9d77211c2..f8713f2dc 100644 --- a/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoter/AbstractStoredObjectVoter.php +++ b/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoter/AbstractStoredObjectVoter.php @@ -15,7 +15,7 @@ use Chill\DocStoreBundle\Entity\StoredObject; use Chill\DocStoreBundle\Repository\AssociatedEntityToStoredObjectInterface; use Chill\DocStoreBundle\Security\Authorization\StoredObjectRoleEnum; use Chill\DocStoreBundle\Security\Authorization\StoredObjectVoterInterface; -use Chill\DocStoreBundle\Service\WorkflowStoredObjectPermissionHelper; +use Chill\MainBundle\Workflow\Helper\WorkflowRelatedEntityPermissionHelper; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Security; @@ -34,7 +34,7 @@ abstract class AbstractStoredObjectVoter implements StoredObjectVoterInterface public function __construct( private readonly Security $security, - private readonly ?WorkflowStoredObjectPermissionHelper $workflowDocumentService = null, + private readonly ?WorkflowRelatedEntityPermissionHelper $workflowDocumentService = null, ) {} public function supports(StoredObjectRoleEnum $attribute, StoredObject $subject): bool @@ -49,6 +49,11 @@ abstract class AbstractStoredObjectVoter implements StoredObjectVoterInterface // Retrieve the related accompanying course document $entity = $this->getRepository()->findAssociatedEntityToStoredObject($subject); + if ($this->workflowDocumentService->isAllowedByWorkflow($entity)) { + // read and write permissions are granted by workflow + return true; + } + // Determine the attribute to pass to AccompanyingCourseDocumentVoter $voterAttribute = $this->attributeToRole($attribute); diff --git a/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoter/AccompanyingCourseDocumentStoredObjectVoter.php b/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoter/AccompanyingCourseDocumentStoredObjectVoter.php index 94ff9149d..e1a9add7d 100644 --- a/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoter/AccompanyingCourseDocumentStoredObjectVoter.php +++ b/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoter/AccompanyingCourseDocumentStoredObjectVoter.php @@ -16,7 +16,7 @@ use Chill\DocStoreBundle\Repository\AccompanyingCourseDocumentRepository; use Chill\DocStoreBundle\Repository\AssociatedEntityToStoredObjectInterface; use Chill\DocStoreBundle\Security\Authorization\AccompanyingCourseDocumentVoter; use Chill\DocStoreBundle\Security\Authorization\StoredObjectRoleEnum; -use Chill\DocStoreBundle\Service\WorkflowStoredObjectPermissionHelper; +use Chill\MainBundle\Workflow\Helper\WorkflowRelatedEntityPermissionHelper; use Symfony\Component\Security\Core\Security; final class AccompanyingCourseDocumentStoredObjectVoter extends AbstractStoredObjectVoter @@ -24,7 +24,7 @@ final class AccompanyingCourseDocumentStoredObjectVoter extends AbstractStoredOb public function __construct( private readonly AccompanyingCourseDocumentRepository $repository, Security $security, - WorkflowStoredObjectPermissionHelper $workflowDocumentService, + WorkflowRelatedEntityPermissionHelper $workflowDocumentService, ) { parent::__construct($security, $workflowDocumentService); } diff --git a/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoter/PersonDocumentStoredObjectVoter.php b/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoter/PersonDocumentStoredObjectVoter.php index 4c8ae693e..16833c535 100644 --- a/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoter/PersonDocumentStoredObjectVoter.php +++ b/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoter/PersonDocumentStoredObjectVoter.php @@ -16,7 +16,7 @@ use Chill\DocStoreBundle\Repository\AssociatedEntityToStoredObjectInterface; use Chill\DocStoreBundle\Repository\PersonDocumentRepository; use Chill\DocStoreBundle\Security\Authorization\PersonDocumentVoter; use Chill\DocStoreBundle\Security\Authorization\StoredObjectRoleEnum; -use Chill\DocStoreBundle\Service\WorkflowStoredObjectPermissionHelper; +use Chill\MainBundle\Workflow\Helper\WorkflowRelatedEntityPermissionHelper; use Symfony\Component\Security\Core\Security; class PersonDocumentStoredObjectVoter extends AbstractStoredObjectVoter @@ -24,7 +24,7 @@ class PersonDocumentStoredObjectVoter extends AbstractStoredObjectVoter public function __construct( private readonly PersonDocumentRepository $repository, Security $security, - WorkflowStoredObjectPermissionHelper $workflowDocumentService, + WorkflowRelatedEntityPermissionHelper $workflowDocumentService, ) { parent::__construct($security, $workflowDocumentService); } diff --git a/src/Bundle/ChillDocStoreBundle/Tests/Security/Authorization/AbstractStoredObjectVoterTest.php b/src/Bundle/ChillDocStoreBundle/Tests/Security/Authorization/AbstractStoredObjectVoterTest.php index a045a1fd6..0090496db 100644 --- a/src/Bundle/ChillDocStoreBundle/Tests/Security/Authorization/AbstractStoredObjectVoterTest.php +++ b/src/Bundle/ChillDocStoreBundle/Tests/Security/Authorization/AbstractStoredObjectVoterTest.php @@ -15,7 +15,7 @@ use Chill\DocStoreBundle\Entity\StoredObject; use Chill\DocStoreBundle\Repository\AssociatedEntityToStoredObjectInterface; use Chill\DocStoreBundle\Security\Authorization\StoredObjectRoleEnum; use Chill\DocStoreBundle\Security\Authorization\StoredObjectVoter\AbstractStoredObjectVoter; -use Chill\DocStoreBundle\Service\WorkflowStoredObjectPermissionHelper; +use Chill\MainBundle\Workflow\Helper\WorkflowRelatedEntityPermissionHelper; use Chill\MainBundle\Entity\User; use PHPUnit\Framework\TestCase; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; @@ -30,16 +30,16 @@ class AbstractStoredObjectVoterTest extends TestCase { private AssociatedEntityToStoredObjectInterface $repository; private Security $security; - private WorkflowStoredObjectPermissionHelper $workflowDocumentService; + private WorkflowRelatedEntityPermissionHelper $workflowDocumentService; protected function setUp(): void { $this->repository = $this->createMock(AssociatedEntityToStoredObjectInterface::class); $this->security = $this->createMock(Security::class); - $this->workflowDocumentService = $this->createMock(WorkflowStoredObjectPermissionHelper::class); + $this->workflowDocumentService = $this->createMock(WorkflowRelatedEntityPermissionHelper::class); } - private function buildStoredObjectVoter(bool $canBeAssociatedWithWorkflow, AssociatedEntityToStoredObjectInterface $repository, Security $security, ?WorkflowStoredObjectPermissionHelper $workflowDocumentService = null): AbstractStoredObjectVoter + private function buildStoredObjectVoter(bool $canBeAssociatedWithWorkflow, AssociatedEntityToStoredObjectInterface $repository, Security $security, ?WorkflowRelatedEntityPermissionHelper $workflowDocumentService = null): AbstractStoredObjectVoter { // Anonymous class extending the abstract class return new class ($canBeAssociatedWithWorkflow, $repository, $security, $workflowDocumentService) extends AbstractStoredObjectVoter { @@ -47,7 +47,7 @@ class AbstractStoredObjectVoterTest extends TestCase private readonly bool $canBeAssociatedWithWorkflow, private readonly AssociatedEntityToStoredObjectInterface $repository, Security $security, - ?WorkflowStoredObjectPermissionHelper $workflowDocumentService = null, + ?WorkflowRelatedEntityPermissionHelper $workflowDocumentService = null, ) { parent::__construct($security, $workflowDocumentService); } @@ -99,6 +99,25 @@ class AbstractStoredObjectVoterTest extends TestCase $this->workflowDocumentService->method('notBlockedByWorkflow')->willReturn($workflowAllowed); } + public function testIsAllowedByWorkflow(): void + { + [$user, $token, $subject, $entity] = $this->setupMockObjects(); + $workflowRelatedEntityPermissionHelper = $this->createMock(WorkflowRelatedEntityPermissionHelper::class); + $workflowRelatedEntityPermissionHelper->method('isAllowedByWorkflow')->withAnyParameters()->willReturn(true); + + $associatedObjectRepository = $this->createMock(AssociatedEntityToStoredObjectInterface::class); + $associatedObjectRepository->method('findAssociatedEntityToStoredObject')->willReturn($entity); + + $voter = $this->buildStoredObjectVoter( + true, + $associatedObjectRepository, + $this->createMock(Security::class), + $workflowRelatedEntityPermissionHelper + ); + + self::assertTrue($voter->voteOnAttribute(StoredObjectRoleEnum::EDIT, $subject, $token)); + } + public function testSupportsOnAttribute(): void { [$user, $token, $subject, $entity] = $this->setupMockObjects(); diff --git a/src/Bundle/ChillEventBundle/Security/Authorization/EventStoredObjectVoter.php b/src/Bundle/ChillEventBundle/Security/Authorization/EventStoredObjectVoter.php index 9a23d6d85..7e61db7d6 100644 --- a/src/Bundle/ChillEventBundle/Security/Authorization/EventStoredObjectVoter.php +++ b/src/Bundle/ChillEventBundle/Security/Authorization/EventStoredObjectVoter.php @@ -14,7 +14,7 @@ namespace Chill\EventBundle\Security\Authorization; use Chill\DocStoreBundle\Repository\AssociatedEntityToStoredObjectInterface; use Chill\DocStoreBundle\Security\Authorization\StoredObjectRoleEnum; use Chill\DocStoreBundle\Security\Authorization\StoredObjectVoter\AbstractStoredObjectVoter; -use Chill\DocStoreBundle\Service\WorkflowStoredObjectPermissionHelper; +use Chill\MainBundle\Workflow\Helper\WorkflowRelatedEntityPermissionHelper; use Chill\EventBundle\Entity\Event; use Chill\EventBundle\Repository\EventRepository; use Chill\EventBundle\Security\EventVoter; @@ -25,7 +25,7 @@ class EventStoredObjectVoter extends AbstractStoredObjectVoter public function __construct( private readonly EventRepository $repository, Security $security, - WorkflowStoredObjectPermissionHelper $workflowDocumentService, + WorkflowRelatedEntityPermissionHelper $workflowDocumentService, ) { parent::__construct($security, $workflowDocumentService); } diff --git a/src/Bundle/ChillJobBundle/src/Resources/public/sass/csconnectes.scss b/src/Bundle/ChillJobBundle/src/Resources/public/sass/csconnectes.scss deleted file mode 100644 index 6405c0f00..000000000 --- a/src/Bundle/ChillJobBundle/src/Resources/public/sass/csconnectes.scss +++ /dev/null @@ -1,19 +0,0 @@ -footer.footer { - padding: 0; - background-color: white; - border-top: 1px solid grey; - div.sponsors { - p { - padding-bottom: 10px; - color: #000; - font-size: 16px; - } - background-color: white; - padding: 2em 0; - img { - display: block; - margin: auto; - } - } -} - diff --git a/src/Bundle/ChillJobBundle/src/Resources/public/sass/index.js b/src/Bundle/ChillJobBundle/src/Resources/public/sass/index.js index 657c9677d..e69de29bb 100644 --- a/src/Bundle/ChillJobBundle/src/Resources/public/sass/index.js +++ b/src/Bundle/ChillJobBundle/src/Resources/public/sass/index.js @@ -1 +0,0 @@ -require('./csconnectes.scss'); diff --git a/src/Bundle/ChillJobBundle/src/chill.webpack.config.js b/src/Bundle/ChillJobBundle/src/chill.webpack.config.js index b648e23bb..882a1013d 100644 --- a/src/Bundle/ChillJobBundle/src/chill.webpack.config.js +++ b/src/Bundle/ChillJobBundle/src/chill.webpack.config.js @@ -5,8 +5,7 @@ module.exports = function(encore, chillEntries) personal_situation_edit_file = __dirname + '/Resources/public/module/personal_situation/index.js', cv_edit_file = __dirname + '/Resources/public/module/cv_edit/index.js', immersion_edit_file = __dirname + '/Resources/public/module/immersion_edit/index.js', - images = __dirname + '/Resources/public/images/index.js', - sass_styles = __dirname + '/Resources/public/sass/index.js' + images = __dirname + '/Resources/public/images/index.js' ; encore.addEntry('dispositifs_edit', dispositif_edit_file); @@ -15,6 +14,4 @@ module.exports = function(encore, chillEntries) encore.addEntry('images', images); encore.addEntry('cs_cv', cv_edit_file); - chillEntries.push(sass_styles); - }; diff --git a/src/Bundle/ChillMainBundle/Controller/GenderApiController.php b/src/Bundle/ChillMainBundle/Controller/GenderApiController.php new file mode 100644 index 000000000..96fae4024 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Controller/GenderApiController.php @@ -0,0 +1,32 @@ +andWhere( + $query->expr()->eq('e.active', "'TRUE'") + ); + } + + protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator, $_format) + { + return $query->addOrderBy('e.order', 'ASC'); + } +} diff --git a/src/Bundle/ChillMainBundle/Controller/GenderController.php b/src/Bundle/ChillMainBundle/Controller/GenderController.php new file mode 100644 index 000000000..a556145d4 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Controller/GenderController.php @@ -0,0 +1,26 @@ +addOrderBy('e.order', 'ASC'); + + return parent::orderQuery($action, $query, $request, $paginator); + } +} diff --git a/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadGenders.php b/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadGenders.php new file mode 100644 index 000000000..2d74e6977 --- /dev/null +++ b/src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadGenders.php @@ -0,0 +1,63 @@ + ['en' => 'man', 'fr' => 'homme'], + 'genderTranslation' => GenderEnum::MALE, + 'icon' => GenderIconEnum::MALE, + ], + [ + 'label' => ['en' => 'woman', 'fr' => 'femme'], + 'genderTranslation' => GenderEnum::FEMALE, + 'icon' => GenderIconEnum::FEMALE, + ], + [ + 'label' => ['en' => 'neutral', 'fr' => 'neutre'], + 'genderTranslation' => GenderEnum::NEUTRAL, + 'icon' => GenderIconEnum::NEUTRAL, + ], + ]; + + public function getOrder() + { + return 100; + } + + public function load(ObjectManager $manager) + { + echo "loading genders... \n"; + + foreach ($this->genders as $g) { + echo $g['label']['fr'].' '; + $new_g = new Gender(); + $new_g->setGenderTranslation($g['genderTranslation']); + $new_g->setLabel($g['label']); + $new_g->setIcon($g['icon']); + + $this->addReference('g_'.$g['genderTranslation']->value, $new_g); + $manager->persist($new_g); + } + + $manager->flush(); + } +} diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php index 999277ed1..9a005be4a 100644 --- a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php +++ b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php @@ -17,6 +17,8 @@ use Chill\MainBundle\Controller\CivilityApiController; use Chill\MainBundle\Controller\CivilityController; use Chill\MainBundle\Controller\CountryApiController; use Chill\MainBundle\Controller\CountryController; +use Chill\MainBundle\Controller\GenderApiController; +use Chill\MainBundle\Controller\GenderController; use Chill\MainBundle\Controller\GeographicalUnitApiController; use Chill\MainBundle\Controller\LanguageController; use Chill\MainBundle\Controller\LocationController; @@ -54,6 +56,7 @@ use Chill\MainBundle\Doctrine\Type\PointType; use Chill\MainBundle\Entity\Center; use Chill\MainBundle\Entity\Civility; use Chill\MainBundle\Entity\Country; +use Chill\MainBundle\Entity\Gender; use Chill\MainBundle\Entity\GeographicalUnitLayer; use Chill\MainBundle\Entity\Language; use Chill\MainBundle\Entity\Location; @@ -66,6 +69,7 @@ use Chill\MainBundle\Entity\UserJob; use Chill\MainBundle\Form\CenterType; use Chill\MainBundle\Form\CivilityType; use Chill\MainBundle\Form\CountryType; +use Chill\MainBundle\Form\GenderType; use Chill\MainBundle\Form\LanguageType; use Chill\MainBundle\Form\LocationFormType; use Chill\MainBundle\Form\LocationTypeType; @@ -511,6 +515,28 @@ class ChillMainExtension extends Extension implements ], ], ], + [ + 'class' => Gender::class, + 'name' => 'main_gender', + 'base_path' => '/admin/main/gender', + 'base_role' => 'ROLE_ADMIN', + 'form_class' => GenderType::class, + 'controller' => GenderController::class, + 'actions' => [ + 'index' => [ + 'role' => 'ROLE_ADMIN', + 'template' => '@ChillMain/Gender/index.html.twig', + ], + 'new' => [ + 'role' => 'ROLE_ADMIN', + 'template' => '@ChillMain/Gender/new.html.twig', + ], + 'edit' => [ + 'role' => 'ROLE_ADMIN', + 'template' => '@ChillMain/Gender/edit.html.twig', + ], + ], + ], [ 'class' => Language::class, 'name' => 'main_language', @@ -814,6 +840,21 @@ class ChillMainExtension extends Extension implements ], ], ], + [ + 'class' => Gender::class, + 'name' => 'gender', + 'base_path' => '/api/1.0/main/gender', + 'base_role' => 'ROLE_USER', + 'controller' => GenderApiController::class, + 'actions' => [ + '_index' => [ + 'methods' => [ + Request::METHOD_GET => true, + Request::METHOD_HEAD => true, + ], + ], + ], + ], [ 'class' => GeographicalUnitLayer::class, 'controller' => GeographicalUnitApiController::class, diff --git a/src/Bundle/ChillMainBundle/Entity/Gender.php b/src/Bundle/ChillMainBundle/Entity/Gender.php new file mode 100644 index 000000000..59c0bd134 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Entity/Gender.php @@ -0,0 +1,104 @@ + Gender::class])] +#[ORM\Entity(repositoryClass: GenderRepository::class)] +#[ORM\Table(name: 'chill_main_gender')] +class Gender +{ + #[Serializer\Groups(['read'])] + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] + private ?int $id = null; + + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] + private array $label = []; + + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] + private bool $active = true; + + #[Assert\NotNull(message: 'You must choose a gender translation')] + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, enumType: GenderEnum::class)] + private GenderEnum $genderTranslation; + + #[Serializer\Groups(['read'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, enumType: GenderIconEnum::class)] + private GenderIconEnum $icon; + + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT, name: 'ordering', nullable: true, options: ['default' => '0.0'])] + private float $order = 0; + + public function getId(): int + { + return $this->id; + } + + public function getLabel(): array + { + return $this->label; + } + + public function setLabel(array $label): void + { + $this->label = $label; + } + + public function isActive(): bool + { + return $this->active; + } + + public function setActive(bool $active): void + { + $this->active = $active; + } + + public function getGenderTranslation(): GenderEnum + { + return $this->genderTranslation; + } + + public function setGenderTranslation(GenderEnum $genderTranslation): void + { + $this->genderTranslation = $genderTranslation; + } + + public function getIcon(): GenderIconEnum + { + return $this->icon; + } + + public function setIcon(GenderIconEnum $icon): void + { + $this->icon = $icon; + } + + public function getOrder(): float + { + return $this->order; + } + + public function setOrder(float $order): void + { + $this->order = $order; + } +} diff --git a/src/Bundle/ChillMainBundle/Entity/GenderEnum.php b/src/Bundle/ChillMainBundle/Entity/GenderEnum.php new file mode 100644 index 000000000..c9fb3c2cf --- /dev/null +++ b/src/Bundle/ChillMainBundle/Entity/GenderEnum.php @@ -0,0 +1,20 @@ +add('label', TranslatableStringFormType::class, [ + 'required' => true, + ]) + ->add('icon', EnumType::class, [ + 'class' => GenderIconEnum::class, + 'choices' => GenderIconEnum::cases(), + 'expanded' => true, + 'multiple' => false, + 'mapped' => true, + 'choice_label' => fn (GenderIconEnum $enum) => '', + 'choice_value' => fn (?GenderIconEnum $enum) => null !== $enum ? $enum->value : null, + 'label' => 'gender.admin.Select Gender Icon', + 'label_html' => true, + ]) + ->add('genderTranslation', EnumType::class, [ + 'class' => GenderEnum::class, + 'choice_label' => fn (GenderEnum $enum) => $enum->value, + 'label' => 'gender.admin.Select Gender Translation', + ]) + ->add('active', ChoiceType::class, [ + 'choices' => [ + 'Active' => true, + 'Inactive' => false, + ], + ]) + ->add('order', NumberType::class); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => Gender::class, + ]); + } +} diff --git a/src/Bundle/ChillMainBundle/Repository/GenderRepository.php b/src/Bundle/ChillMainBundle/Repository/GenderRepository.php new file mode 100644 index 000000000..56dcd1a4b --- /dev/null +++ b/src/Bundle/ChillMainBundle/Repository/GenderRepository.php @@ -0,0 +1,47 @@ + + */ +class GenderRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Gender::class); + } + + public function findByActiveOrdered(): array + { + return $this->createQueryBuilder('g') + ->select('g') + ->where('g.active = True') + ->orderBy('g.order', 'ASC') + ->getQuery() + ->getResult(); + } + + public function findByGenderTranslation($gender): array + { + return $this->createQueryBuilder('g') + ->select('g') + ->where('g.genderTranslation = :gender') + ->setParameter('gender', $gender) + ->getQuery() + ->getResult(); + } +} diff --git a/src/Bundle/ChillMainBundle/Resources/public/module/bootstrap/index.js b/src/Bundle/ChillMainBundle/Resources/public/module/bootstrap/index.js index a9d34e01d..91d66416a 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/module/bootstrap/index.js +++ b/src/Bundle/ChillMainBundle/Resources/public/module/bootstrap/index.js @@ -10,6 +10,7 @@ import Modal from 'bootstrap/js/dist/modal'; import Collapse from 'bootstrap/js/src/collapse'; import Carousel from 'bootstrap/js/src/carousel'; import Popover from 'bootstrap/js/src/popover'; +import 'bootstrap-icons/font/bootstrap-icons.css'; // // Carousel: ACHeaderSlider is a small slider used in banner of AccompanyingCourse Section @@ -59,4 +60,4 @@ const popoverList = triggerList.map(function (el) { return new Popover(el, { html: true, }); -}); \ No newline at end of file +}); diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/_components/Entity/GenderIconRenderBox.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/_components/Entity/GenderIconRenderBox.vue new file mode 100644 index 000000000..2aeb123c7 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/_components/Entity/GenderIconRenderBox.vue @@ -0,0 +1,11 @@ + + + diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/_js/i18n.ts b/src/Bundle/ChillMainBundle/Resources/public/vuejs/_js/i18n.ts index f81699a7c..ae6f72dc5 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/_js/i18n.ts +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/_js/i18n.ts @@ -38,7 +38,9 @@ const messages = { person: "Usager", birthday: { man: "Né le", - woman: "Née le" + woman: "Née le", + neutral: "Né·e le", + unknown: "Né·e le", }, deathdate: "Date de décès", household_without_address: "Le ménage de l'usager est sans adresse", diff --git a/src/Bundle/ChillMainBundle/Resources/views/Gender/edit.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Gender/edit.html.twig new file mode 100644 index 000000000..39f01e519 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/Gender/edit.html.twig @@ -0,0 +1,75 @@ +{% extends '@ChillMain/CRUD/Admin/index.html.twig' %} + +{% block title %} + {% include('@ChillMain/CRUD/_edit_title.html.twig') %} +{% endblock %} + +{% form_theme form _self %} + +{% block _gender_icon_widget %} + {% for child in form %} +
+ + + +
+ {% endfor %} +{% endblock %} + +{% block admin_content %} + {% set formId = crudMainFormId|default('crud_main_form') %} + + {% block crud_content_header %} +

{{ ('crud.'~crud_name~'.title_edit')|trans }}

+ {% endblock crud_content_header %} + + {% block crud_content_form %} + {{ form_start(form, { 'attr' : { 'id': formId } }) }} + + {{ form_row(form.label) }} + {{ form_row(form.genderTranslation) }} + {{ form_row(form.icon) }} + {{ form_row(form.active) }} + {{ form_row(form.order) }} + + {{ form_end(form) }} + {% block crud_content_after_form %}{% endblock %} + + {% block crud_content_form_actions %} + + {% endblock %} + + {% endblock %} +{% endblock admin_content %} diff --git a/src/Bundle/ChillMainBundle/Resources/views/Gender/index.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Gender/index.html.twig new file mode 100644 index 000000000..8155e18ec --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/Gender/index.html.twig @@ -0,0 +1,46 @@ +{% extends '@ChillMain/CRUD/Admin/index.html.twig' %} + +{% block admin_content %} + {% embed '@ChillMain/CRUD/_index.html.twig' %} + {% block table_entities_thead_tr %} + id + {{ 'label'|trans }} + {{ 'icon'|trans }} + {{ 'gender.genderTranslation'|trans }} + {{ 'active'|trans }} + {{ 'ordering'|trans }} + + {% endblock %} + {% block table_entities_tbody %} + {% for entity in entities %} + + {{ entity.id }} + {{ entity.label|localize_translatable_string }} + {{ entity.icon|chill_entity_render_box }} + {{ entity.genderTranslation.value }} + + {%- if entity.active -%} + + {%- else -%} + + {%- endif -%} + + {{ entity.order }} + + + + + {% endfor %} + {% endblock %} + + {% block actions_before %} +
  • + {{'Back to the admin'|trans}} +
  • + {% endblock %} + {% endembed %} +{% endblock %} diff --git a/src/Bundle/ChillMainBundle/Resources/views/Gender/new.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Gender/new.html.twig new file mode 100644 index 000000000..a07ebfa9d --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/Gender/new.html.twig @@ -0,0 +1,79 @@ +{% extends '@ChillMain/CRUD/Admin/index.html.twig' %} + +{% block title %} + {% include('@ChillMain/CRUD/_new_title.html.twig') %} +{% endblock %} + +{% form_theme form _self %} + +{% block _gender_icon_widget %} + {% for child in form %} +
    + + + +
    + {% endfor %} +{% endblock %} + +{% block admin_content %} + {% set formId = crudMainFormId|default('crud_main_form') %} + + {% block crud_content_header %} +

    {{ ('crud.' ~ crud_name ~ '.title_new')|trans({'%crud_name%' : crud_name }) }}

    + {% endblock crud_content_header %} + + {% block crud_content_form %} + {{ form_start(form, { 'attr' : { 'id': formId } }) }} + {{ form_row(form.label) }} + {{ form_row(form.genderTranslation) }} + {{ form_row(form.icon) }} + {{ form_row(form.active) }} + {{ form_row(form.order) }} + {{ form_end(form) }} + + {% block crud_content_after_form %}{% endblock %} + + {% block crud_content_form_actions %} + + {% endblock %} + + {{ form_end(form) }} + {% endblock %} + +{% endblock admin_content %} diff --git a/src/Bundle/ChillMainBundle/Search/AbstractSearch.php b/src/Bundle/ChillMainBundle/Search/AbstractSearch.php index c4e0fecd9..a7c81d5bf 100644 --- a/src/Bundle/ChillMainBundle/Search/AbstractSearch.php +++ b/src/Bundle/ChillMainBundle/Search/AbstractSearch.php @@ -62,12 +62,12 @@ abstract class AbstractSearch implements SearchInterface $recomposed .= ' '.$term.':'; $containsSpace = str_contains((string) $terms[$term], ' '); - if ($containsSpace) { + if ($containsSpace || is_numeric($terms[$term])) { $recomposed .= '"'; } $recomposed .= (false === mb_stristr(' ', (string) $terms[$term])) ? $terms[$term] : '('.$terms[$term].')'; - if ($containsSpace) { + if ($containsSpace || is_numeric($terms[$term])) { $recomposed .= '"'; } } diff --git a/src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderInterface.php b/src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderInterface.php index 7a7a5e1fe..9eeb70c96 100644 --- a/src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderInterface.php +++ b/src/Bundle/ChillMainBundle/Templating/Entity/ChillEntityRenderInterface.php @@ -35,7 +35,7 @@ interface ChillEntityRenderInterface * * @phpstan-pure */ - public function renderBox($entity, array $options): string; + public function renderBox(mixed $entity, array $options): string; /** * Return the entity as a string. @@ -46,7 +46,7 @@ interface ChillEntityRenderInterface * * @phpstan-pure */ - public function renderString($entity, array $options): string; + public function renderString(mixed $entity, array $options): string; /** * Return true if the class support this object for the given options. diff --git a/src/Bundle/ChillMainBundle/Templating/Entity/ChillGenderIconRender.php b/src/Bundle/ChillMainBundle/Templating/Entity/ChillGenderIconRender.php new file mode 100644 index 000000000..383234bd3 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Templating/Entity/ChillGenderIconRender.php @@ -0,0 +1,35 @@ + + */ +final readonly class ChillGenderIconRender implements ChillEntityRenderInterface +{ + public function renderBox($icon, array $options): string + { + return ''; + } + + public function renderString($icon, array $options): string + { + return $icon->value; + } + + public function supports($icon, array $options): bool + { + return $icon instanceof GenderIconEnum; + } +} diff --git a/src/Bundle/ChillDocStoreBundle/Tests/Service/WorkflowStoredObjectPermissionHelperTest.php b/src/Bundle/ChillMainBundle/Tests/Workflow/Helper/WorkflowRelatedEntityPermissionHelperTest.php similarity index 68% rename from src/Bundle/ChillDocStoreBundle/Tests/Service/WorkflowStoredObjectPermissionHelperTest.php rename to src/Bundle/ChillMainBundle/Tests/Workflow/Helper/WorkflowRelatedEntityPermissionHelperTest.php index 9cfd55c57..3e4857d57 100644 --- a/src/Bundle/ChillDocStoreBundle/Tests/Service/WorkflowStoredObjectPermissionHelperTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Workflow/Helper/WorkflowRelatedEntityPermissionHelperTest.php @@ -9,9 +9,9 @@ declare(strict_types=1); * the LICENSE file that was distributed with this source code. */ -namespace Chill\DocStoreBundle\Tests\Service; +namespace Chill\MainBundle\Tests\Workflow\Helper; -use Chill\DocStoreBundle\Service\WorkflowStoredObjectPermissionHelper; +use Chill\MainBundle\Workflow\Helper\WorkflowRelatedEntityPermissionHelper; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\Workflow\EntityWorkflow; use Chill\MainBundle\Entity\Workflow\EntityWorkflowSignatureStateEnum; @@ -36,7 +36,7 @@ use Symfony\Component\Workflow\WorkflowInterface; * * @coversNothing */ -class WorkflowStoredObjectPermissionHelperTest extends TestCase +class WorkflowRelatedEntityPermissionHelperTest extends TestCase { use ProphecyTrait; @@ -53,6 +53,19 @@ class WorkflowStoredObjectPermissionHelperTest extends TestCase self::assertEquals($expected, $helper->notBlockedByWorkflow($entityWorkflow), $message); } + /** + * @dataProvider provideDataAllowedByWorkflow + */ + public function testAllowedByWorkflow(EntityWorkflow $entityWorkflow, User $user, bool $expected, string $message): void + { + // all entities must have this workflow name, so we are ok to set it here + $entityWorkflow->setWorkflowName('dummy'); + $object = new \stdClass(); + $helper = $this->buildHelper($object, $entityWorkflow, $user); + + self::assertEquals($expected, $helper->isAllowedByWorkflow($entityWorkflow), $message); + } + public function testNoWorkflow(): void { $object = new \stdClass(); @@ -60,7 +73,7 @@ class WorkflowStoredObjectPermissionHelperTest extends TestCase self::assertTrue($helper->notBlockedByWorkflow($object), "the user is not blocked by the user, as there aren't any user inside"); } - private function buildHelper(object $relatedEntity, ?EntityWorkflow $entityWorkflow, User $user): WorkflowStoredObjectPermissionHelper + private function buildHelper(object $relatedEntity, ?EntityWorkflow $entityWorkflow, User $user): WorkflowRelatedEntityPermissionHelper { $security = $this->prophesize(Security::class); $security->getUser()->willReturn($user); @@ -72,7 +85,55 @@ class WorkflowStoredObjectPermissionHelperTest extends TestCase $entityWorkflowManager->findByRelatedEntity(Argument::type('object'))->willReturn([]); } - return new WorkflowStoredObjectPermissionHelper($security->reveal(), $entityWorkflowManager->reveal(), $this->buildRegistry()); + return new WorkflowRelatedEntityPermissionHelper($security->reveal(), $entityWorkflowManager->reveal(), $this->buildRegistry()); + } + + public static function provideDataAllowedByWorkflow(): iterable + { + $entityWorkflow = new EntityWorkflow(); + $dto = new WorkflowTransitionContextDTO($entityWorkflow); + $entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User()); + + yield [$entityWorkflow, new User(), false, 'not allowed because the user is not present as a dest user']; + + $entityWorkflow = new EntityWorkflow(); + $dto = new WorkflowTransitionContextDTO($entityWorkflow); + $dto->futureDestUsers[] = $user = new User(); + $entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User()); + + yield [$entityWorkflow, $user, true, 'allowed because the user is a current user']; + + $entityWorkflow = new EntityWorkflow(); + $dto = new WorkflowTransitionContextDTO($entityWorkflow); + $dto->futureDestUsers[] = $user = new User(); + $entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User()); + + $dto = new WorkflowTransitionContextDTO($entityWorkflow); + $dto->futureDestUsers[] = new User(); + $entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User()); + + yield [$entityWorkflow, $user, true, 'allowed because the user was a previous user']; + + $entityWorkflow = new EntityWorkflow(); + $dto = new WorkflowTransitionContextDTO($entityWorkflow); + $dto->futureDestUsers[] = $user = new User(); + $entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User()); + $dto = new WorkflowTransitionContextDTO($entityWorkflow); + $entityWorkflow->setStep('final_positive', $dto, 'to_final_positive', new \DateTimeImmutable(), new User()); + $entityWorkflow->getCurrentStep()->setIsFinal(true); + + yield [$entityWorkflow, $user, false, 'not allowed because: user was a previous user, but it is finalized positive']; + + $entityWorkflow = new EntityWorkflow(); + $dto = new WorkflowTransitionContextDTO($entityWorkflow); + $dto->futureDestUsers[] = $user = new User(); + $entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable()); + $dto = new WorkflowTransitionContextDTO($entityWorkflow); + $entityWorkflow->setStep('final_negative', $dto, 'to_final_negative', new \DateTimeImmutable()); + $entityWorkflow->getCurrentStep()->setIsFinal(true); + + yield [$entityWorkflow, $user, true, 'allowed: user was a previous user, it is finalized, but finalized negative']; + } public static function provideDataNotBlockByWorkflow(): iterable diff --git a/src/Bundle/ChillDocStoreBundle/Service/WorkflowStoredObjectPermissionHelper.php b/src/Bundle/ChillMainBundle/Workflow/Helper/WorkflowRelatedEntityPermissionHelper.php similarity index 65% rename from src/Bundle/ChillDocStoreBundle/Service/WorkflowStoredObjectPermissionHelper.php rename to src/Bundle/ChillMainBundle/Workflow/Helper/WorkflowRelatedEntityPermissionHelper.php index 95cc77194..472ab93ee 100644 --- a/src/Bundle/ChillDocStoreBundle/Service/WorkflowStoredObjectPermissionHelper.php +++ b/src/Bundle/ChillMainBundle/Workflow/Helper/WorkflowRelatedEntityPermissionHelper.php @@ -9,7 +9,7 @@ declare(strict_types=1); * the LICENSE file that was distributed with this source code. */ -namespace Chill\DocStoreBundle\Service; +namespace Chill\MainBundle\Workflow\Helper; use Chill\MainBundle\Entity\Workflow\EntityWorkflowSignatureStateEnum; use Chill\MainBundle\Workflow\EntityWorkflowManager; @@ -19,7 +19,7 @@ use Symfony\Component\Workflow\Registry; /** * Check if an object, associated with a workflow, is blocked, or not, by this workflow. */ -class WorkflowStoredObjectPermissionHelper +class WorkflowRelatedEntityPermissionHelper { public function __construct( private readonly Security $security, @@ -27,6 +27,38 @@ class WorkflowStoredObjectPermissionHelper private readonly Registry $registry, ) {} + public function isAllowedByWorkflow(object $entity): bool + { + $entityWorkflows = $this->entityWorkflowManager->findByRelatedEntity($entity); + $currentUser = $this->security->getUser(); + + foreach ($entityWorkflows as $entityWorkflow) { + // if the user is finalized, we have to check if the workflow is finalPositive, or not + if ($entityWorkflow->isFinal()) { + $workflow = $this->registry->get($entityWorkflow, $entityWorkflow->getWorkflowName()); + $marking = $workflow->getMarkingStore()->getMarking($entityWorkflow); + foreach ($marking->getPlaces() as $place => $int) { + $placeMetadata = $workflow->getMetadataStore()->getPlaceMetadata($place); + if (true === ($placeMetadata['isFinalPositive'] ?? false)) { + // the workflow is final, and final positive, so we stop here. + return false; + } + } + } + } + + foreach ($entityWorkflows as $entityWorkflow) { + // so, the workflow is running... We return true if the current user is involved + foreach ($entityWorkflow->getSteps() as $step) { + if ($step->getAllDestUser()->contains($currentUser)) { + return true; + } + } + } + + return false; + } + /** * Return true if the user is allowed to update the given object. * diff --git a/src/Bundle/ChillMainBundle/config/services/templating.yaml b/src/Bundle/ChillMainBundle/config/services/templating.yaml index 04117bf16..56bc1ff75 100644 --- a/src/Bundle/ChillMainBundle/config/services/templating.yaml +++ b/src/Bundle/ChillMainBundle/config/services/templating.yaml @@ -54,6 +54,8 @@ services: Chill\MainBundle\Templating\Entity\NewsItemRender: ~ + Chill\MainBundle\Templating\Entity\ChillGenderIconRender: ~ + Chill\MainBundle\Templating\Entity\UserRender: ~ Chill\MainBundle\Templating\Entity\UserGroupRender: ~ diff --git a/src/Bundle/ChillMainBundle/migrations/Version20240926093955.php b/src/Bundle/ChillMainBundle/migrations/Version20240926093955.php new file mode 100644 index 000000000..9b891c319 --- /dev/null +++ b/src/Bundle/ChillMainBundle/migrations/Version20240926093955.php @@ -0,0 +1,69 @@ +addSql('CREATE SEQUENCE chill_main_gender_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE chill_main_gender (id INT NOT NULL, label JSON NOT NULL, active BOOLEAN NOT NULL, genderTranslation VARCHAR(255) NOT NULL, icon VARCHAR(255) NOT NULL, ordering DOUBLE PRECISION DEFAULT \'0.0\', PRIMARY KEY(id))'); + + // Insert the four gender records into the chill_main_gender table + $this->addSql(" + INSERT INTO chill_main_gender (id, label, active, genderTranslation, icon, ordering) + VALUES + (nextval('chill_main_gender_id_seq'), + '{\"fr\": \"homme\", \"nl\": \"man\"}', + true, + 'man', + 'bi bi-gender-male', + 1.0 + ), + (nextval('chill_main_gender_id_seq'), + '{\"fr\": \"femme\", \"nl\": \"vrouw\"}', + true, + 'woman', + 'bi bi-gender-female', + 1.1 + ), + (nextval('chill_main_gender_id_seq'), + '{\"fr\": \"neutre\", \"nl\": \"neutraal\"}', + true, + 'neutral', + 'bi bi-gender-neuter', + 1.1 + ), + (nextval('chill_main_gender_id_seq'), + '{\"fr\": \"inconnu\", \"nl\": \"ongekend\"}', + true, + 'unknown', + 'bi bi-question', + 1.2 + ) + "); + } + + public function down(Schema $schema): void + { + $this->addSql('DROP SEQUENCE chill_main_gender_id_seq CASCADE'); + $this->addSql('DROP TABLE chill_main_gender'); + } +} diff --git a/src/Bundle/ChillMainBundle/translations/messages.fr.yml b/src/Bundle/ChillMainBundle/translations/messages.fr.yml index 5344147d6..eeecfccb7 100644 --- a/src/Bundle/ChillMainBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillMainBundle/translations/messages.fr.yml @@ -43,6 +43,7 @@ lifecycleUpdate: Evenements de création et mise à jour address_fields: Données liées à l'adresse Datas: Données No title: Aucun titre +icon: icône user: profile: @@ -474,6 +475,12 @@ crud: title_delete: Supprimer une actualité button_delete: Supprimer confirm_message_delete: Êtes-vous sûr de vouloir supprimer l'actualité, "%as_string%" ? + main_gender: + index: + title: Liste des genres + add_new: Ajouter un genre + title_new: Nouveau genre + title_edit: Modifier un genre No entities: Aucun élément @@ -781,4 +788,9 @@ news: read_more: Lire la suite show_details: Voir l'actualité +gender: + genderTranslation: traduction grammaticale + not defined: Non défini + pick gender: Choisir une genre + diff --git a/src/Bundle/ChillPersonBundle/Actions/Remove/PersonMove.php b/src/Bundle/ChillPersonBundle/Actions/Remove/PersonMove.php index 2ebae0457..603825d35 100644 --- a/src/Bundle/ChillPersonBundle/Actions/Remove/PersonMove.php +++ b/src/Bundle/ChillPersonBundle/Actions/Remove/PersonMove.php @@ -201,7 +201,7 @@ class PersonMove private function getDeleteEntities(): array { return [ - AccompanyingPeriod\AccompanyingPeriodWork::class, + // AccompanyingPeriod\AccompanyingPeriodWork::class, Relationship::class, ]; } @@ -216,7 +216,7 @@ class PersonMove } /** - * get the full table name with schema if it does exists. + * get the full table name with schema if it exists. */ private function getTableName(ClassMetadata $metadata): string { diff --git a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php index d356cf9ad..f1be52959 100644 --- a/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php +++ b/src/Bundle/ChillPersonBundle/DataFixtures/ORM/LoadPeople.php @@ -15,11 +15,14 @@ use Chill\MainBundle\DataFixtures\ORM\LoadPostalCodes; use Chill\MainBundle\Entity\Address; use Chill\MainBundle\Entity\Center; use Chill\MainBundle\Entity\Country; +use Chill\MainBundle\Entity\Gender; +use Chill\MainBundle\Entity\GenderEnum; use Chill\MainBundle\Entity\PostalCode; use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Repository\CenterRepository; use Chill\MainBundle\Repository\CountryRepository; +use Chill\MainBundle\Repository\GenderRepository; use Chill\MainBundle\Repository\ScopeRepository; use Chill\MainBundle\Repository\UserRepository; use Chill\PersonBundle\Entity\AccompanyingPeriod; @@ -77,12 +80,15 @@ class LoadPeople extends AbstractFixture implements ContainerAwareInterface, Ord */ protected array $cacheUsers = []; + /** + * @var array|Gender[] + */ + protected array $cacheGenders = []; + protected Generator $faker; protected NativeLoader $loader; - private array $genders = [Person::MALE_GENDER, Person::FEMALE_GENDER, Person::BOTH_GENDER]; - private array $peoples = [ [ 'lastName' => 'Depardieu', @@ -90,7 +96,7 @@ class LoadPeople extends AbstractFixture implements ContainerAwareInterface, Ord 'birthdate' => '1948-12-27', 'placeOfBirth' => 'Châteauroux', 'nationality' => 'RU', - 'gender' => Person::MALE_GENDER, + 'gender' => GenderEnum::MALE, 'center' => 'Center A', 'accompanyingPeriods' => [ [ @@ -119,7 +125,7 @@ class LoadPeople extends AbstractFixture implements ContainerAwareInterface, Ord 'maritalStatus' => 'ms_divorce', ], [ - // to have a person with same birthdate of Gérard Depardieu + // to have a person with same birthdate as Gérard Depardieu 'lastName' => 'Van Snick', 'firstName' => 'Bart', 'birthdate' => '1948-12-27', @@ -131,7 +137,7 @@ class LoadPeople extends AbstractFixture implements ContainerAwareInterface, Ord 'lastName' => 'Depardieu', 'firstName' => 'Charline', 'birthdate' => '1970-10-15', - 'gender' => Person::FEMALE_GENDER, + 'gender' => GenderEnum::FEMALE, 'center' => 'Center A', 'maritalStatus' => 'ms_legalco', ], @@ -228,6 +234,7 @@ class LoadPeople extends AbstractFixture implements ContainerAwareInterface, Ord protected MaritalStatusRepository $maritalStatusRepository, protected ScopeRepository $scopeRepository, protected UserRepository $userRepository, + protected GenderRepository $genderRepository, ) { $this->faker = Factory::create('fr_FR'); $this->faker->addProvider($this); @@ -272,9 +279,17 @@ class LoadPeople extends AbstractFixture implements ContainerAwareInterface, Ord /** * @internal This method is public and called by faker as a custom generator */ - public function getRandomGender(): string + public function getRandomGender(int $nullPercentage = 50): ?Gender { - return $this->genders[array_rand($this->genders)]; + if (0 === \count($this->cacheGenders)) { + $this->cacheGenders = $this->genderRepository->findByActiveOrdered(); + } + + if (\random_int(0, 100) > $nullPercentage) { + return null; + } + + return $this->cacheGenders[array_rand($this->cacheGenders)]; } /** diff --git a/src/Bundle/ChillPersonBundle/Entity/Person.php b/src/Bundle/ChillPersonBundle/Entity/Person.php index 27a1a3f09..3bdfba767 100644 --- a/src/Bundle/ChillPersonBundle/Entity/Person.php +++ b/src/Bundle/ChillPersonBundle/Entity/Person.php @@ -21,6 +21,7 @@ use Chill\MainBundle\Entity\Center; use Chill\MainBundle\Entity\Civility; use Chill\MainBundle\Entity\Country; use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable; +use Chill\MainBundle\Entity\Gender; use Chill\MainBundle\Entity\HasCenterInterface; use Chill\MainBundle\Entity\Language; use Chill\MainBundle\Entity\User; @@ -62,19 +63,11 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface; #[HouseholdMembershipSequential(groups: ['household_memberships'])] class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateInterface, \Stringable { - final public const BOTH_GENDER = 'both'; - // have days in commun final public const ERROR_ADDIND_PERIOD_AFTER_AN_OPEN_PERIOD = 2; // where there exist final public const ERROR_PERIODS_ARE_COLLAPSING = 1; // when two different periods - final public const FEMALE_GENDER = 'woman'; - - final public const MALE_GENDER = 'man'; - - final public const NO_INFORMATION = 'unknown'; - /** * Accept receiving email. */ @@ -245,11 +238,11 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI private ?string $fullnameCanonical = ''; /** - * The person's gender. + * NEW column : The person's gender. */ #[Assert\NotNull(message: 'The gender must be set')] - #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 9, nullable: true)] - private ?string $gender = null; + #[ORM\ManyToOne(targetEntity: Gender::class)] + private ?Gender $gender = null; /** * Comment on gender. @@ -1041,7 +1034,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI return $this->fullnameCanonical; } - public function getGender(): ?string + public function getGender(): ?Gender { return $this->gender; } @@ -1051,24 +1044,6 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI return $this->genderComment; } - /** - * return gender as a Numeric form. - * This is used for translations. - * - * @return int - * - * @deprecated Keep for legacy. Used in Chill 1.5 for feminize before icu translations - */ - public function getGenderNumeric() - { - return match ($this->getGender()) { - self::FEMALE_GENDER => 1, - self::MALE_GENDER => 0, - self::BOTH_GENDER => 2, - default => -1, - }; - } - public function getHouseholdAddresses(): Collection { return $this->householdAddresses; @@ -1570,7 +1545,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI return $this; } - public function setGender(?string $gender): self + public function setGender(?Gender $gender): self { $this->gender = $gender; diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php index aec57c10a..c5f274cc4 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/AccompanyingCourseAggregators/ReferrerScopeAggregator.php @@ -55,7 +55,7 @@ readonly class ReferrerScopeAggregator implements AggregatorInterface, DataTrans $qb->expr()->gte('COALESCE(acp.closingDate, CURRENT_TIMESTAMP())', "{$p}_userHistory.startDate"), $qb->expr()->orX( $qb->expr()->isNull("{$p}_userHistory.endDate"), - $qb->expr()->lt('COALESCE(acp.closingDate, CURRENT_TIMESTAMP())', "{$p}_userHistory.endDate") + $qb->expr()->lt('COALESCE(acp.openingDate, CURRENT_TIMESTAMP())', "{$p}_userHistory.endDate") ) ), $qb->expr()->andX( diff --git a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GenderAggregator.php b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GenderAggregator.php index 0181c6e7b..f7ae26dca 100644 --- a/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GenderAggregator.php +++ b/src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/GenderAggregator.php @@ -12,7 +12,8 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Aggregator\PersonAggregators; use Chill\MainBundle\Export\AggregatorInterface; -use Chill\PersonBundle\Entity\Person; +use Chill\MainBundle\Repository\GenderRepository; +use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\PersonBundle\Export\Declarations; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\FormBuilderInterface; @@ -20,7 +21,7 @@ use Symfony\Contracts\Translation\TranslatorInterface; final readonly class GenderAggregator implements AggregatorInterface { - public function __construct(private TranslatorInterface $translator) {} + public function __construct(private TranslatorInterface $translator, private TranslatableStringHelperInterface $translatableStringHelper, private GenderRepository $repository) {} public function addRole(): ?string { @@ -29,7 +30,8 @@ final readonly class GenderAggregator implements AggregatorInterface public function alterQuery(QueryBuilder $qb, $data) { - $qb->addSelect('person.gender as gender'); + $qb->leftJoin('person.gender', 'g'); + $qb->addSelect('g.id as gender'); $qb->addGroupBy('gender'); } @@ -48,30 +50,20 @@ final readonly class GenderAggregator implements AggregatorInterface public function getLabels($key, array $values, $data) { - return function ($value) { - switch ($value) { - case Person::FEMALE_GENDER: - return $this->translator->trans('woman'); - - case Person::MALE_GENDER: - return $this->translator->trans('man'); - - case Person::BOTH_GENDER: - return $this->translator->trans('both'); - - case Person::NO_INFORMATION: - return $this->translator->trans('unknown'); - - case null: - case '': - return $this->translator->trans('Not given'); - - case '_header': - return $this->translator->trans('Gender'); - - default: - throw new \LogicException(sprintf('The value %s is not valid', $value)); + return function (int|string|null $value) { + if (null === $value || '' === $value) { + return ''; } + + if ('_header' === $value) { + return $this->translator->trans('Gender'); + } + + if (null === $gender = $this->repository->find((int) $value)) { + return ''; + } + + return (string) $this->translatableStringHelper->localize($gender->getLabel()); }; } diff --git a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/GenderFilter.php b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/GenderFilter.php index 5009e37d0..fc09e385a 100644 --- a/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/GenderFilter.php +++ b/src/Bundle/ChillPersonBundle/Export/Filter/PersonFilters/GenderFilter.php @@ -11,11 +11,13 @@ declare(strict_types=1); namespace Chill\PersonBundle\Export\Filter\PersonFilters; +use Chill\MainBundle\Entity\Gender; +use Chill\MainBundle\Export\DataTransformerInterface; use Chill\MainBundle\Export\ExportElementValidatedInterface; use Chill\MainBundle\Export\FilterInterface; -use Chill\PersonBundle\Entity\Person; +use Chill\MainBundle\Repository\GenderRepository; +use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\PersonBundle\Export\Declarations; -use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\FormBuilderInterface; @@ -24,17 +26,15 @@ use Symfony\Contracts\Translation\TranslatorInterface; class GenderFilter implements ExportElementValidatedInterface, - FilterInterface + FilterInterface, + DataTransformerInterface { - /** - * @var TranslatorInterface - */ - protected $translator; - - public function __construct(TranslatorInterface $translator) - { - $this->translator = $translator; - } + // inject gender repository and find the active genders so that you can pass them to the ChoiceType (ordered by ordering) + public function __construct( + private readonly TranslatorInterface $translator, + private readonly TranslatableStringHelperInterface $translatableStringHelper, + private readonly GenderRepository $genderRepository, + ) {} public function addRole(): ?string { @@ -46,23 +46,17 @@ class GenderFilter implements $where = $qb->getDQLPart('where'); $isIn = $qb->expr()->in('person.gender', ':person_gender'); - if (!\in_array('null', $data['accepted_genders'], true)) { + $acceptedGenders = $data['accepted_genders_entity']; + $nullIncluded = in_array(null, $acceptedGenders ?? [], true); + + if (!$nullIncluded) { $clause = $isIn; } else { $clause = $qb->expr()->orX($isIn, $qb->expr()->isNull('person.gender')); } - if ($where instanceof Expr\Andx) { - $where->add($clause); - } else { - $where = $qb->expr()->andX($clause); - } - - $qb->add('where', $where); - $qb->setParameter('person_gender', \array_filter( - $data['accepted_genders'], - static fn ($el) => 'null' !== $el - )); + $qb->andWhere($clause); + $qb->setParameter('person_gender', array_filter($acceptedGenders ?? [], fn ($gender) => null !== $gender)); } public function applyOn() @@ -72,19 +66,42 @@ class GenderFilter implements public function buildForm(FormBuilderInterface $builder) { - $builder->add('accepted_genders', ChoiceType::class, [ - 'choices' => [ - 'Woman' => Person::FEMALE_GENDER, - 'Man' => Person::MALE_GENDER, - 'Both' => Person::BOTH_GENDER, - 'Unknown' => Person::NO_INFORMATION, - 'Not given' => 'null', - ], + $genderChoices = $this->genderRepository->findByActiveOrdered(); + $choices = ['None' => null]; + + foreach ($genderChoices as $gender) { + $choices[$this->translatableStringHelper->localize($gender->getLabel())] = $gender->getId(); + } + + $builder->add('accepted_genders_entity', ChoiceType::class, [ + 'choices' => $choices, 'multiple' => true, 'expanded' => true, + 'placeholder' => 'Select gender', ]); } + public function transformData(?array $before): array + { + $transformedData = []; + $transformedData['accepted_genders_entity'] = $before['accepted_genders_entity'] ?? []; + + if (array_key_exists('accepted_genders', $before)) { + foreach ($before['accepted_genders'] as $genderBefore) { + foreach ($this->genderRepository->findByGenderTranslation( + match ($genderBefore) { + 'both' => 'neutral', + default => $genderBefore, + } + ) as $gender) { + $transformedData['accepted_genders_entity'][] = $gender; + } + } + } + + return $transformedData; + } + public function getFormDefaultData(): array { return []; @@ -94,11 +111,11 @@ class GenderFilter implements { $genders = []; - foreach ($data['accepted_genders'] as $g) { - if ('null' === $g) { - $genders[] = $this->translator->trans('Not given'); + foreach ($data['accepted_genders_entity'] as $g) { + if (null === $g) { + $genders[] = $this->translator->trans('export.filter.person.gender.no_gender'); } else { - $genders[] = $this->translator->trans($g); + $genders[] = $this->translatableStringHelper->localize($this->genderRepository->find($g)->getLabel()); } } @@ -120,7 +137,7 @@ class GenderFilter implements public function validateForm($data, ExecutionContextInterface $context) { - if (!\is_array($data['accepted_genders']) || 0 === \count($data['accepted_genders'])) { + if (!\is_iterable($data['accepted_genders_entity']) || 0 === \count($data['accepted_genders_entity'])) { $context->buildViolation('You should select an option') ->addViolation(); } diff --git a/src/Bundle/ChillPersonBundle/Export/Helper/ListPersonHelper.php b/src/Bundle/ChillPersonBundle/Export/Helper/ListPersonHelper.php index 393d246ea..0c270a7ca 100644 --- a/src/Bundle/ChillPersonBundle/Export/Helper/ListPersonHelper.php +++ b/src/Bundle/ChillPersonBundle/Export/Helper/ListPersonHelper.php @@ -16,6 +16,7 @@ use Chill\MainBundle\Export\Helper\ExportAddressHelper; use Chill\MainBundle\Repository\CenterRepositoryInterface; use Chill\MainBundle\Repository\CivilityRepositoryInterface; use Chill\MainBundle\Repository\CountryRepository; +use Chill\MainBundle\Repository\GenderRepository; use Chill\MainBundle\Repository\LanguageRepositoryInterface; use Chill\MainBundle\Repository\UserRepositoryInterface; use Chill\MainBundle\Templating\TranslatableStringHelper; @@ -80,6 +81,7 @@ final readonly class ListPersonHelper private TranslatableStringHelper $translatableStringHelper, private TranslatorInterface $translator, private UserRepositoryInterface $userRepository, + private GenderRepository $genderRepository, /** * @var iterable */ @@ -173,6 +175,11 @@ final readonly class ListPersonHelper break; + case 'gender': + $qb->addSelect('IDENTITY(person.gender) AS gender'); + + break; + case 'maritalStatus': $qb->addSelect('IDENTITY(person.maritalStatus) AS maritalStatus'); @@ -325,7 +332,13 @@ final readonly class ListPersonHelper return $this->translator->trans($key); } - return $this->translator->trans($value); + if (null === $value) { + return ''; + } + + $gender = $this->genderRepository->find($value); + + return $this->translatableStringHelper->localize($gender->getLabel()); }; case 'maritalStatus': diff --git a/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php b/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php index 9bfb75e31..bb40c6c35 100644 --- a/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php +++ b/src/Bundle/ChillPersonBundle/Form/CreationPersonType.php @@ -20,8 +20,8 @@ use Chill\MainBundle\Form\Type\PickCenterType; use Chill\MainBundle\Form\Type\PickCivilityType; use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper; use Chill\PersonBundle\Entity\Person; -use Chill\PersonBundle\Form\Type\GenderType; use Chill\PersonBundle\Form\Type\PersonAltNameType; +use Chill\PersonBundle\Form\Type\PickGenderType; use Chill\PersonBundle\Security\Authorization\PersonVoter; use libphonenumber\PhoneNumberType; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; @@ -60,7 +60,7 @@ final class CreationPersonType extends AbstractType 'label' => 'Civility', 'placeholder' => 'choose civility', ]) - ->add('gender', GenderType::class, [ + ->add('gender', PickGenderType::class, [ 'required' => true, 'placeholder' => null, ]) ->add('birthdate', ChillDateType::class, [ diff --git a/src/Bundle/ChillPersonBundle/Form/PersonType.php b/src/Bundle/ChillPersonBundle/Form/PersonType.php index 21717a25b..0f4fbd8e4 100644 --- a/src/Bundle/ChillPersonBundle/Form/PersonType.php +++ b/src/Bundle/ChillPersonBundle/Form/PersonType.php @@ -24,9 +24,9 @@ use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Entity\PersonPhone; -use Chill\PersonBundle\Form\Type\GenderType; use Chill\PersonBundle\Form\Type\PersonAltNameType; use Chill\PersonBundle\Form\Type\PersonPhoneType; +use Chill\PersonBundle\Form\Type\PickGenderType; use Chill\PersonBundle\Form\Type\Select2MaritalStatusType; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\CallbackTransformer; @@ -80,7 +80,7 @@ class PersonType extends AbstractType 'input' => 'datetime_immutable', 'widget' => 'single_text', ]) - ->add('gender', GenderType::class, [ + ->add('gender', PickGenderType::class, [ 'required' => true, ]) ->add('genderComment', CommentType::class, [ diff --git a/src/Bundle/ChillPersonBundle/Form/Type/GenderType.php b/src/Bundle/ChillPersonBundle/Form/Type/GenderType.php deleted file mode 100644 index 2989b3ec4..000000000 --- a/src/Bundle/ChillPersonBundle/Form/Type/GenderType.php +++ /dev/null @@ -1,44 +0,0 @@ - Person::MALE_GENDER, - Person::FEMALE_GENDER => Person::FEMALE_GENDER, - Person::BOTH_GENDER => Person::BOTH_GENDER, - ]; - - $resolver->setDefaults([ - 'choices' => $a, - 'expanded' => true, - 'multiple' => false, - 'placeholder' => null, - ]); - } - - public function getParent() - { - return ChoiceType::class; - } -} diff --git a/src/Bundle/ChillPersonBundle/Form/Type/PickGenderType.php b/src/Bundle/ChillPersonBundle/Form/Type/PickGenderType.php new file mode 100644 index 000000000..1e0c004d5 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Form/Type/PickGenderType.php @@ -0,0 +1,51 @@ +setDefault('label', 'Gender') + ->setDefault( + 'choice_label', + fn (Gender $gender): string => $this->translatableStringHelper->localize($gender->getLabel()) + ) + ->setDefault( + 'query_builder', + static fn (EntityRepository $er): QueryBuilder => $er->createQueryBuilder('g') + ->where('g.active = true') + ->orderBy('g.order'), + ) + ->setDefault('placeholder', 'choose gender') + ->setDefault('class', Gender::class); + } + + public function getParent() + { + return EntityType::class; + } +} diff --git a/src/Bundle/ChillPersonBundle/Menu/AdminPersonMenuBuilder.php b/src/Bundle/ChillPersonBundle/Menu/AdminPersonMenuBuilder.php index ee2dad9dc..c3d369f00 100644 --- a/src/Bundle/ChillPersonBundle/Menu/AdminPersonMenuBuilder.php +++ b/src/Bundle/ChillPersonBundle/Menu/AdminPersonMenuBuilder.php @@ -45,13 +45,17 @@ class AdminPersonMenuBuilder implements LocalMenuBuilderInterface 'route' => 'chill_crud_main_civility_index', ])->setExtras(['order' => 2010]); + $menu->addChild('Gender', [ + 'route' => 'chill_crud_main_gender_index', + ])->setExtras(['order' => 2020]); + $menu->addChild('Marital status', [ 'route' => 'chill_crud_person_marital-status_index', - ])->setExtras(['order' => 2020]); + ])->setExtras(['order' => 2030]); $menu->addChild('person_admin.person_resource_kind', [ 'route' => 'chill_crud_person_resource-kind_index', - ])->setExtras(['order' => 2030]); + ])->setExtras(['order' => 2040]); } public static function getMenuIds(): array diff --git a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php index 9e76dd374..686022ca3 100644 --- a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepository.php @@ -34,7 +34,7 @@ final readonly class PersonACLAwareRepository implements PersonACLAwareRepositor ?\DateTimeInterface $birthdate = null, ?\DateTimeInterface $birthdateBefore = null, ?\DateTimeInterface $birthdateAfter = null, - ?string $gender = null, + ?int $gender = null, ?string $countryCode = null, ?string $phonenumber = null, ?string $city = null, @@ -62,7 +62,7 @@ final readonly class PersonACLAwareRepository implements PersonACLAwareRepositor ?\DateTimeInterface $birthdate = null, ?\DateTimeInterface $birthdateBefore = null, ?\DateTimeInterface $birthdateAfter = null, - ?string $gender = null, + ?int $gender = null, ?string $countryCode = null, ?string $phonenumber = null, ?string $city = null, @@ -96,7 +96,7 @@ final readonly class PersonACLAwareRepository implements PersonACLAwareRepositor ?\DateTimeInterface $birthdate = null, ?\DateTimeInterface $birthdateBefore = null, ?\DateTimeInterface $birthdateAfter = null, - ?string $gender = null, + ?int $gender = null, ?string $countryCode = null, ?string $phonenumber = null, ?string $city = null, @@ -202,7 +202,7 @@ final readonly class PersonACLAwareRepository implements PersonACLAwareRepositor } if (null !== $gender) { - $query->andWhereClause('person.gender = ?', [$gender]); + $query->andWhereClause('person.gender_id = ?', [$gender]); } return $query; @@ -253,7 +253,7 @@ final readonly class PersonACLAwareRepository implements PersonACLAwareRepositor ?\DateTimeInterface $birthdate = null, ?\DateTimeInterface $birthdateBefore = null, ?\DateTimeInterface $birthdateAfter = null, - ?string $gender = null, + ?int $gender = null, ?string $countryCode = null, ?string $phonenumber = null, ?string $city = null, diff --git a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepositoryInterface.php b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepositoryInterface.php index 7a45d6648..50fdcd4b3 100644 --- a/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepositoryInterface.php +++ b/src/Bundle/ChillPersonBundle/Repository/PersonACLAwareRepositoryInterface.php @@ -23,7 +23,7 @@ interface PersonACLAwareRepositoryInterface ?\DateTimeInterface $birthdate = null, ?\DateTimeInterface $birthdateBefore = null, ?\DateTimeInterface $birthdateAfter = null, - ?string $gender = null, + ?int $gender = null, ?string $countryCode = null, ?string $phonenumber = null, ?string $city = null, @@ -36,7 +36,7 @@ interface PersonACLAwareRepositoryInterface ?\DateTimeInterface $birthdate = null, ?\DateTimeInterface $birthdateBefore = null, ?\DateTimeInterface $birthdateAfter = null, - ?string $gender = null, + ?int $gender = null, ?string $countryCode = null, ?string $phonenumber = null, ?string $city = null, @@ -55,7 +55,7 @@ interface PersonACLAwareRepositoryInterface ?\DateTimeInterface $birthdate = null, ?\DateTimeInterface $birthdateBefore = null, ?\DateTimeInterface $birthdateAfter = null, - ?string $gender = null, + ?int $gender = null, ?string $countryCode = null, ?string $phonenumber = null, ?string $city = null, diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/PersonsAssociated/ParticipationItem.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/PersonsAssociated/ParticipationItem.vue index 155fd6c46..a278d00c4 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/PersonsAssociated/ParticipationItem.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/PersonsAssociated/ParticipationItem.vue @@ -128,7 +128,7 @@ export default { body.mobilenumber = payload.data.mobilenumber; body.email = payload.data.email; body.altNames = payload.data.altNames; - body.gender = payload.data.gender; + body.gender = {id: payload.data.gender.id, type: payload.data.gender.type }; if (payload.data.civility !== null) { body.civility = {id: payload.data.civility.id, type: payload.data.civility.type }; } makeFetch('PATCH', `/api/1.0/person/person/${payload.data.id}.json`, body) diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Resources/ResourceItem.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Resources/ResourceItem.vue index c2368d9ab..920287b86 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Resources/ResourceItem.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/Resources/ResourceItem.vue @@ -153,7 +153,7 @@ export default { body.mobilenumber = payload.data.mobilenumber; body.email = payload.data.email; body.altNames = payload.data.altNames; - body.gender = payload.data.gender; + body.gender = {id: payload.data.gender.id, type: payload.data.gender.type }; if (payload.data.civility !== null) { body.civility = {id: payload.data.civility.id, type: payload.data.civility.type}; } makeFetch('PATCH', `/api/1.0/person/person/${payload.data.id}.json`, body) diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/HouseholdMembersEditor/components/MemberDetails.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/HouseholdMembersEditor/components/MemberDetails.vue index 2258d8b77..fd2ef7bdb 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/HouseholdMembersEditor/components/MemberDetails.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/HouseholdMembersEditor/components/MemberDetails.vue @@ -8,7 +8,7 @@ {{ $t('household_members_editor.holder') }} -
    {{ $t('person.born', {'gender': conc.person.gender} ) }}
    +
    {{ $t('person.born', {'gender': conc.person.gender.genderTranslation} ) }}

    - - +

    - + > + + +
    @@ -178,7 +177,7 @@