Merge remote-tracking branch 'origin/master' into testing-202505

This commit is contained in:
Julien Fastré 2025-05-30 14:58:45 +02:00
commit f3e04bd2bf
Signed by: julienfastre
GPG Key ID: BDE2190974723FCB
76 changed files with 809 additions and 925 deletions

View File

@ -0,0 +1,6 @@
kind: DX
body: Remove dead code for wopi-link module
time: 2025-04-30T14:45:50.406111606+02:00
custom:
Issue: "352"
SchemaChange: No schema change

View File

@ -0,0 +1,6 @@
kind: DX
body: Replace library node-sass by sass, and upgrade bootstrap to version 5.3 (yarn upgrade / install is required)
time: 2025-05-28T16:58:13.226870341+02:00
custom:
Issue: ""
SchemaChange: No schema change

View File

@ -0,0 +1,7 @@
kind: Feature
body: Add the document file name to the document title when a user upload a document,
unless there is already a document title.
time: 2025-04-24T14:22:11.800975422+02:00
custom:
Issue: "377"
SchemaChange: No schema change

View File

@ -0,0 +1,6 @@
kind: Feature
body: Add desactivation date for social action and issue csv export
time: 2025-05-20T09:56:28.108941934+02:00
custom:
Issue: ""
SchemaChange: No schema change

View File

@ -0,0 +1,6 @@
kind: Feature
body: Add Emoji and Fullscreen feature to ckeditor configuration
time: 2025-05-23T13:33:41.645095128+02:00
custom:
Issue: ""
SchemaChange: No schema change

View File

@ -0,0 +1,6 @@
kind: Feature
body: Create editor which allow us to toggle between rich and simple text editor
time: 2025-05-23T13:34:34.56795603+02:00
custom:
Issue: "321"
SchemaChange: No schema change

View File

@ -0,0 +1,7 @@
kind: Fixed
body: trying to prevent bug of typeerror in doc-history + improved display of document
history
time: 2025-04-24T13:39:43.878468232+02:00
custom:
Issue: "376"
SchemaChange: No schema change

View File

@ -0,0 +1,7 @@
kind: Fixed
body: Display previous participation in acc course work even if the person has left
the acc course
time: 2025-04-24T16:37:46.970203594+02:00
custom:
Issue: "381"
SchemaChange: No schema change

View File

@ -0,0 +1,6 @@
kind: Fixed
body: Fix display of text in calendar events
time: 2025-05-05T10:27:15.461493066+02:00
custom:
Issue: "372"
SchemaChange: No schema change

View File

@ -0,0 +1,6 @@
kind: Fixed
body: Add missing translation for user_group.no_user_groups
time: 2025-05-14T14:53:39.53927329+02:00
custom:
Issue: ""
SchemaChange: No schema change

View File

@ -0,0 +1,6 @@
kind: UX
body: Remove default filter in_progress for the page 'my tasks'; Allows for new tasks to be displayed upon opening of the page
time: 2025-04-23T17:26:24.45777387+02:00
custom:
Issue: "374"
SchemaChange: No schema change

View File

@ -1,52 +1,4 @@
[
{
"path": "assets/translator.js",
"line": 4,
"column": 3,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'getLocale' is defined but never used.",
"hash": "4de7bfba61e745c3cf5323aad048092c7c17ccf8"
},
{
"path": "assets/translator.js",
"line": 5,
"column": 3,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'setLocale' is defined but never used.",
"hash": "a7eabf4524aa4b2a7fd30de6d1ce61a3623c00db"
},
{
"path": "docs/source/development/user-interface/js-functions/show_hide.js",
"line": 12,
"column": 26,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'event' is defined but never used.",
"hash": "6d66a79b37a676e44177f5e22c83250315d23c96"
},
{
"path": "docs/source/development/user-interface/js-functions/show_hide.js",
"line": 29,
"column": 26,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'event' is defined but never used.",
"hash": "ecfe1d9da55e96316b21de60db959be5f9e20f59"
},
{
"path": "src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/SocialIssuesAcc.vue",
"line": 136,
"column": 39,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'reject' is defined but never used.",
"hash": "4faa92668b8548e3b747568ef9a3671708c0fbf9"
},
{
"path": "src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/components/SocialIssuesAcc.vue",
"line": 211,
"column": 47,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'reject' is defined but never used.",
"hash": "d1fd4d809f01ecad48418336edca270335fccff9"
},
{
"path": "src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/index.js",
"line": 18,
@ -63,14 +15,6 @@
"message": "'event' is defined but never used.",
"hash": "cf0cf378f71403f62a6425f384ccbbdec433d1f2"
},
{
"path": "src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/store.js",
"line": 90,
"column": 13,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'resources' is assigned a value but never used.",
"hash": "342d8aad3e080ba262239e5f5c6fc419f388ca33"
},
{
"path": "src/Bundle/ChillCalendarBundle/Resources/public/module/Invite/answer.js",
"line": 7,
@ -223,14 +167,6 @@
"message": "'changedEvent' is assigned a value but never used.",
"hash": "a7a81a6bf09d00c0364e3aa8207ffad853f0547b"
},
{
"path": "src/Bundle/ChillCalendarBundle/Resources/public/vuejs/MyCalendarRange/App2.vue",
"line": 444,
"column": 5,
"ruleId": "@typescript-eslint/ban-ts-comment",
"message": "Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.",
"hash": "1b8a1b6b081d3f14ed319619e6031039668cd736"
},
{
"path": "src/Bundle/ChillCalendarBundle/Resources/public/vuejs/MyCalendarRange/Components/EditLocation.vue",
"line": 77,
@ -279,30 +215,6 @@
"message": "'_' is defined but never used.",
"hash": "5bf7ba0b0200fb6788d50df669e6b7701f8a87bb"
},
{
"path": "src/Bundle/ChillCalendarBundle/Resources/public/vuejs/MyCalendarRange/store/modules/calendarRanges.ts",
"line": 259,
"column": 62,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'_' is defined but never used.",
"hash": "a06407a3b44a8e5865525e37e7620d20100c1e32"
},
{
"path": "src/Bundle/ChillCalendarBundle/Resources/public/vuejs/MyCalendarRange/store/modules/calendarRanges.ts",
"line": 350,
"column": 48,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'_' is defined but never used.",
"hash": "fabe51c847e3842b4a4fda0b581f10b466cbd098"
},
{
"path": "src/Bundle/ChillCalendarBundle/Resources/public/vuejs/MyCalendarRange/store/modules/calendarRanges.ts",
"line": 374,
"column": 48,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'_' is defined but never used.",
"hash": "7547f6801ac63196c32ffc61d2be7ad5bf113cc8"
},
{
"path": "src/Bundle/ChillCalendarBundle/Resources/public/vuejs/MyCalendarRange/store/modules/fullcalendar.ts",
"line": 57,
@ -639,54 +551,6 @@
"message": "'StoredObjectVersion' is defined but never used.",
"hash": "2fadbe9e331a66f44b54782acc1420c4b487e1f6"
},
{
"path": "src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentSignature/App.vue",
"line": 336,
"column": 20,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'reactive' is defined but never used.",
"hash": "433bed446eb37784c380d5c82bb364221af80969"
},
{
"path": "src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentSignature/App.vue",
"line": 354,
"column": 1,
"ruleId": "@typescript-eslint/ban-ts-comment",
"message": "Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.",
"hash": "b104a4e3ccf06c4a16fd83076e2b3f2dc27b2d91"
},
{
"path": "src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentSignature/App.vue",
"line": 363,
"column": 5,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'download_and_decrypt_doc' is defined but never used.",
"hash": "77340aab22ce01c7ed6518a96586f4219299dd36"
},
{
"path": "src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentSignature/App.vue",
"line": 757,
"column": 16,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'r' is defined but never used.",
"hash": "c4cc95fa4538bfd3a61bdc2d5ffcae8c96178af6"
},
{
"path": "src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentSignature/App.vue",
"line": 779,
"column": 5,
"ruleId": "@typescript-eslint/no-unused-expressions",
"message": "Expected an assignment or function call and instead saw an expression.",
"hash": "c5f5d0e73bd179d79b60b53a3dc1c6d676bee287"
},
{
"path": "src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentSignature/index.ts",
"line": 2,
"column": 1,
"ruleId": "@typescript-eslint/ban-ts-comment",
"message": "Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.",
"hash": "b60ce5d41e38f02a016f25170e065e86fd7863ec"
},
{
"path": "src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentSignature/index.ts",
"line": 34,
@ -919,46 +783,6 @@
"message": "'offset' is never reassigned. Use 'const' instead.",
"hash": "244b65de0ab0791ec89219058c5cb4f2e11622c7"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/lib/api/apiMethods.ts",
"line": 176,
"column": 25,
"ruleId": "@typescript-eslint/no-explicit-any",
"message": "Unexpected any. Specify a different type.",
"hash": "78974307acb7b584f0c2196fbb47fc914b5c7a32"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/lib/api/apiMethods.ts",
"line": 186,
"column": 9,
"ruleId": "prefer-const",
"message": "'promises' is never reassigned. Use 'const' instead.",
"hash": "2e178f566f5da9822a5dd46b29738829fbd1adf7"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/lib/api/apiMethods.ts",
"line": 232,
"column": 26,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'response' is defined but never used.",
"hash": "0a036a266bd7bba398df10163e9704e6ea6167f3"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/lib/api/apiMethods.ts",
"line": 240,
"column": 28,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'response' is defined but never used.",
"hash": "86c054fe1edcb6b24e6d0aefd64cd445e7614a52"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/lib/api/apiMethods.ts",
"line": 260,
"column": 5,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'response' is defined but never used.",
"hash": "a45a603d1877899ba33744991bc21cfa4bedb17d"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/lib/download-report/download-report.js",
"line": 18,
@ -1071,14 +895,6 @@
"message": "'popoverList' is assigned a value but never used.",
"hash": "2fd1da06ffc0a1025552cd02b7838cb5ee70006c"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/module/ckeditor5/index.ts",
"line": 7,
"column": 16,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'editor' is defined but never used.",
"hash": "a1ee37171b35396754af104e4815484e1bd2a5ec"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/module/collection/index.ts",
"line": 53,
@ -1135,38 +951,6 @@
"message": "Expected a `for-of` loop instead of a `for` loop with this simple iteration.",
"hash": "aac391029a9094c0024acd4748728d0345d43d62"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/module/notification/toggle_read.js",
"line": 4,
"column": 8,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'NotificationReadAllToggle' is defined but never used.",
"hash": "85b91b57af8f355c4da6175f0cd10543e8c21298"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/module/notification/toggle_read.js",
"line": 8,
"column": 55,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'e' is defined but never used.",
"hash": "07f4feb1fc536257245672cadc5e4a6eff3dfd11"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js",
"line": 26,
"column": 5,
"ruleId": "@typescript-eslint/no-unused-expressions",
"message": "Expected an assignment or function call and instead saw an expression.",
"hash": "ade0f5ef31462024600ac17130a26e0429e27039"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js",
"line": 176,
"column": 57,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'e' is defined but never used.",
"hash": "733b101d5fc60b4b4d0539d772cec69590baae19"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/module/pick-postal-code/index.js",
"line": 10,
@ -1753,19 +1537,19 @@
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CountrySelection.vue",
"line": 75,
"line": 76,
"column": 13,
"ruleId": "vue/no-mutating-props",
"message": "Unexpected mutation of \"entity\" prop.",
"hash": "f2e288dcddf773ed3a79b238327af8a48961e861"
"hash": "373a2e31f110d138c66d77f1faf5dc61545c55af"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CountrySelection.vue",
"line": 80,
"line": 81,
"column": 13,
"ruleId": "vue/no-mutating-props",
"message": "Unexpected mutation of \"entity\" prop.",
"hash": "836965dc8fa085f98d31f3ce261dcdf27d1ef6a4"
"hash": "421eb6a63224b4b1d81b216677a710c5c99ddee3"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/DatePane.vue",
@ -1871,30 +1655,6 @@
"message": "'props' is assigned a value but never used.",
"hash": "29fe0a5d52e46c479aa2e7bb23fb55c53df7b22e"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/_components/EntityWorkflow/ListWorkflow.vue",
"line": 142,
"column": 32,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'w' is defined but never used.",
"hash": "ad12fc3b08dbfc9c24ae65d2a59c7bd5cecb39f2"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/_components/EntityWorkflow/ListWorkflow.vue",
"line": 146,
"column": 33,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'w' is defined but never used.",
"hash": "d28435fe2f60f5d3c22ab2b4cb59a6bd2cd0f947"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/_components/EntityWorkflow/ListWorkflow.vue",
"line": 155,
"column": 15,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'popoverList' is assigned a value but never used.",
"hash": "933d1a8c7c3d9321347218a08588cdf4c352f422"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/_components/EntityWorkflow/PickWorkflow.vue",
"line": 114,
@ -1943,14 +1703,6 @@
"message": "The element inside `<transition>` is expected to have a `v-if` or `v-show` directive.",
"hash": "0594fb9d0984f4dd1612671aca21b571087ab8ee"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/_components/Modal.vue",
"line": 59,
"column": 22,
"ruleId": "vue/require-valid-default-prop",
"message": "Type of the default value for 'modalDialogClass' prop must be a function.",
"hash": "51033a0b54bc839ce532e609bc58a2686818c895"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/_js/i18n.ts",
"line": 60,
@ -1959,14 +1711,6 @@
"message": "Unexpected any. Specify a different type.",
"hash": "61fa9887fddae8f7c4fd60cd21827fb034d5bb7f"
},
{
"path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/_js/i18n.ts",
"line": 66,
"column": 9,
"ruleId": "@typescript-eslint/ban-ts-comment",
"message": "Use \"@ts-expect-error\" instead of \"@ts-ignore\", as \"@ts-ignore\" will do nothing if the following line is error-free.",
"hash": "370ce59576610d7a292501effe428366011585f4"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/page/accompanying_course_index/masonry.js",
"line": 4,
@ -2023,94 +1767,6 @@
"message": "'app' is assigned a value but never used.",
"hash": "aaaaa63e7a60443b8cbf8191feb9142852ebdf1c"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/App.vue",
"line": 436,
"column": 3,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'dateToISO' is defined but never used.",
"hash": "2ec2e571f3e30aa4c2be2d27bb2e8e0911f2b73f"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/App.vue",
"line": 437,
"column": 3,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'ISOToDate' is defined but never used.",
"hash": "e798ef13db37e7acb223e3df29da4ce8dbbd3ae6"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/App.vue",
"line": 438,
"column": 3,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'ISOToDatetime' is defined but never used.",
"hash": "76ca9c82007f9040643d2a8cf2689ebe1110823e"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/App.vue",
"line": 451,
"column": 10,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'buildLinkCreate' is defined but never used.",
"hash": "0dbad8bda4c2da8b4489288fdaf8e4e42583c399"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/App.vue",
"line": 512,
"column": 5,
"ruleId": "vue/no-unused-components",
"message": "The \"AddressRenderBox\" component has been registered but not used.",
"hash": "1fa5e8a5a2e917188fd4b5f5d215601e1be5ea9a"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/App.vue",
"line": 514,
"column": 5,
"ruleId": "vue/no-unused-components",
"message": "The \"PickTemplate\" component has been registered but not used.",
"hash": "b68269999f017d4125854ca86a09f355f046c5fb"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/App.vue",
"line": 699,
"column": 25,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'data' is defined but never used.",
"hash": "66ec68e084b27a818062ebf5d612bdd4598f1cc6"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/App.vue",
"line": 710,
"column": 25,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'data' is defined but never used.",
"hash": "fed92eac022439396e7c1a7dd5f00cf9b958c1e2"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/components/AddEvaluation.vue",
"line": 136,
"column": 26,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'e' is defined but never used.",
"hash": "d762b8ac0404258c3f69a602e838c141e7260af0"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/components/AddEvaluation.vue",
"line": 142,
"column": 28,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'event' is defined but never used.",
"hash": "49bc6a911e9dd1170d487d095920c519784a84bc"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/components/AddEvaluation.vue",
"line": 142,
"column": 35,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'link' is defined but never used.",
"hash": "537ba2743fe9b6894692e6a481d82557f533b75f"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/components/FormEvaluation.vue",
"line": 79,
@ -2119,46 +1775,6 @@
"message": "Elements in iteration expect to have 'v-bind:key' directives.",
"hash": "422f53925922e59655d0f71624c19af75d41628c"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/components/FormEvaluation.vue",
"line": 275,
"column": 3,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'dateToISO' is defined but never used.",
"hash": "1fb4dee6397e578ac9e4587fcf81b35ce1bfe3d9"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/components/FormEvaluation.vue",
"line": 276,
"column": 3,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'ISOToDate' is defined but never used.",
"hash": "ea360950c17604fe63003333c7a5a9c303887ca6"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/components/FormEvaluation.vue",
"line": 281,
"column": 10,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'mapGetters' is defined but never used.",
"hash": "ec02e9573e9ee7cc13e25fda951b748ba8ae8f93"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/components/FormEvaluation.vue",
"line": 600,
"column": 7,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'event' is defined but never used.",
"hash": "b7f25f6178570c873ffb8eefd349b967bb9afb17"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/components/FormEvaluation.vue",
"line": 601,
"column": 7,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'link' is defined but never used.",
"hash": "b60571c99af4afc2933bedef97fa6f745ce45a0f"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/index.js",
"line": 12,
@ -2223,14 +1839,6 @@
"message": "'app' is assigned a value but never used.",
"hash": "b025959acb471750c92952656e7a60ba28f5da0a"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/HouseholdMembersEditor/components/Positioning.vue",
"line": 82,
"column": 31,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'app' is defined but never used.",
"hash": "aad0b0d7e4bc2ea9f0a0dd7b6c696a82da14f25a"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/HouseholdMembersEditor/index.js",
"line": 13,
@ -2311,30 +1919,6 @@
"message": "'UserRenderBoxBadge' is defined but never used.",
"hash": "99eba0d8633b2c9497417f4f61ec4194dbb2a96b"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/OnTheFly/Person.vue",
"line": 430,
"column": 17,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'e' is defined but never used.",
"hash": "e48c11f9011de90dab15b426baf77030ffae7e22"
},
{
"path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/OnTheFly/Person.vue",
"line": 448,
"column": 33,
"ruleId": "@typescript-eslint/no-unused-vars",
"message": "'reject' is defined but never used.",
"hash": "dfd37ec320e99059374135a72bfd53978e7e66ae"
},
{
"path": "src/Bundle/ChillThirdPartyBundle/Resources/public/vuejs/_components/OnTheFly/ThirdParty.vue",
"line": 371,
"column": 21,
"ruleId": "@typescript-eslint/no-unused-expressions",
"message": "Expected an assignment or function call and instead saw an expression.",
"hash": "ed6f5ae90514bf9fc967f2eb7a3ce06344a5f8af"
},
{
"path": "src/Bundle/ChillWopiBundle/src/Resources/public/module/pending/index.ts",
"line": 4,
@ -2374,13 +1958,5 @@
"ruleId": "@typescript-eslint/no-explicit-any",
"message": "Unexpected any. Specify a different type.",
"hash": "7513ea552a0a649ce4ab93b6cf9d40bfef4f68d9"
},
{
"path": "webpack.config.js",
"line": 77,
"column": 28,
"ruleId": "@typescript-eslint/no-empty-function",
"message": "Unexpected empty arrow function.",
"hash": "a8e433351f1c8bc89a95c8570dd0781d59e26103"
}
]

View File

@ -17,9 +17,9 @@
"@types/eslint__js": "^8.42.3",
"@typescript-eslint/parser": "^8.12.2",
"bindings": "^1.5.0",
"bootstrap": "5.2.3",
"bootstrap": "^5.3.6",
"chokidar": "^3.5.1",
"ckeditor5": "^44.1.0",
"ckeditor5": "^45.1.0",
"dompurify": "^3.1.0",
"eslint": "^9.14.0",
"eslint-config-prettier": "^9.1.0",
@ -28,11 +28,11 @@
"fork-awesome": "^1.1.7",
"intl-messageformat": "^10.5.11",
"jquery": "^3.6.0",
"node-sass": "^8.0.0",
"popper.js": "^1.16.1",
"postcss-loader": "^7.0.2",
"prettier": "^3.3.3",
"raw-loader": "^4.0.2",
"sass": "^1.89.0",
"sass-loader": "^14.0.0",
"select2": "^4.0.13",
"select2-bootstrap-theme": "0.1.0-beta.10",

View File

@ -33,6 +33,7 @@
import { mapState, mapGetters } from "vuex";
import VueMultiselect from "vue-multiselect";
import NewLocation from "./Location/NewLocation.vue";
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
import {
trans,
ACTIVITY_LOCATION,
@ -77,15 +78,15 @@ export default {
},
methods: {
labelAccompanyingCourseLocation(value) {
return `${value.address.text} (${value.locationType.title.fr})`;
return `${value.address.text} (${localizeString(value.locationType.title)})`;
},
customLabel(value) {
return value.locationType
? value.name
? value.name === "__AccompanyingCourseLocation__"
? this.labelAccompanyingCourseLocation(value)
: `${value.name} (${value.locationType.title.fr})`
: value.locationType.title.fr
: `${value.name} (${localizeString(value.locationType.title)})`
: localizeString(value.locationType.title)
: "";
},
},

View File

@ -44,7 +44,7 @@
:value="t"
:key="t.id"
>
{{ t.title.fr }}
{{ localizeString(t.title) }}
</option>
</select>
<label>{{
@ -126,6 +126,7 @@ import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress.vue"
import { mapState } from "vuex";
import { getLocationTypes } from "../../api";
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
import {
SAVE,
ACTIVITY_LOCATION_FIELDS_EMAIL,
@ -270,6 +271,7 @@ export default {
this.getLocationTypesList();
},
methods: {
localizeString,
checkForm() {
let cond = true;
this.errors = [];

View File

@ -41,9 +41,7 @@ const i18nGendoc = _createI18n({});
document.querySelectorAll("div[data-docgen-template-picker]").forEach((el) => {
fetchTemplates(el.dataset.entityClass).then((templates) => {
const picker = {
template:
'<pick-template :templates="this.templates" :preventDefaultMoveToGenerate="true" ' +
':entityClass="faked" @go-to-generate-document="generateDoc"></pick-template>',
template: `<pick-template :templates="this.templates" :preventDefaultMoveToGenerate="true" @go-to-generate-document="generateDoc"></pick-template>`,
components: {
PickTemplate,
},
@ -54,7 +52,7 @@ document.querySelectorAll("div[data-docgen-template-picker]").forEach((el) => {
};
},
methods: {
generateDoc({ event, link, template }) {
generateDoc({ link, template }) {
console.log("generateDoc");
console.log("link", link);
console.log("template", template);

View File

@ -96,23 +96,23 @@
</div>
</div>
<FullCalendar :options="calendarOptions" ref="calendarRef">
<template v-slot:eventContent="{ arg }: { arg: { event: EventApi } }">
<span :class="eventClasses(arg.event)">
<b v-if="arg.event.extendedProps.is === 'remote'">{{
arg.event.title
<template v-slot:eventContent="{ event }: { event: EventApi }">
<span :class="eventClasses">
<b v-if="event.extendedProps.is === 'remote'">{{
event.title
}}</b>
<b v-else-if="arg.event.extendedProps.is === 'range'"
>{{ arg.event.startStr }} -
{{ arg.event.extendedProps.locationName }}</b
<b v-else-if="event.extendedProps.is === 'range'"
>{{ formatDate(event.startStr) }} -
{{ event.extendedProps.locationName }}</b
>
<b v-else-if="arg.event.extendedProps.is === 'local'">{{
arg.event.title
<b v-else-if="event.extendedProps.is === 'local'">{{
event.title
}}</b>
<b v-else>no 'is'</b>
<a
v-if="arg.event.extendedProps.is === 'range'"
v-if="event.extendedProps.is === 'range'"
class="fa fa-fw fa-times delete"
@click.prevent="onClickDelete(arg.event)"
@click.prevent="onClickDelete(event)"
>
</a>
</span>
@ -221,13 +221,12 @@ import type {
DatesSetArg,
EventInput,
} from "@fullcalendar/core";
import { reactive, computed, ref, onMounted } from "vue";
import { computed, ref, onMounted } from "vue";
import { useStore } from "vuex";
import { key } from "./store";
import FullCalendar from "@fullcalendar/vue3";
import frLocale from "@fullcalendar/core/locales/fr";
import interactionPlugin, {
DropArg,
EventResizeDoneArg,
} from "@fullcalendar/interaction";
import timeGridPlugin from "@fullcalendar/timegrid";
@ -237,19 +236,13 @@ import {
EventDropArg,
EventClickArg,
} from "@fullcalendar/core";
import {
dateToISO,
ISOToDate,
} from "../../../../../ChillMainBundle/Resources/public/chill/js/date";
import { dateToISO, ISOToDate } from "ChillMainAssets/chill/js/date";
import VueMultiselect from "vue-multiselect";
import { Location } from "../../../../../ChillMainBundle/Resources/public/types";
import { Location } from "ChillMainAssets/types";
import EditLocation from "./Components/EditLocation.vue";
import { useI18n } from "vue-i18n";
const store = useStore(key);
const { t } = useI18n();
const showWeekends = ref(false);
const slotDuration = ref("00:15:00");
const slotMinTime = ref("09:00:00");
@ -301,6 +294,11 @@ const nextWeeks = computed((): Weeks[] =>
}),
);
const formatDate = (datetime: string) => {
console.log(typeof datetime);
return ISOToDate(datetime);
};
const baseOptions = ref<CalendarOptions>({
locale: frLocale,
plugins: [interactionPlugin, timeGridPlugin],
@ -351,11 +349,8 @@ const pickedLocation = computed<Location | null>({
/**
* return the show classes for the event
* @param arg
*/
const eventClasses = function (arg: EventApi): object {
return { calendarRangeItems: true };
};
const eventClasses = { calendarRangeItems: true };
/*
// currently, all events are stored into calendarRanges, due to reactivity bug
@ -431,7 +426,6 @@ function onEventDropOrResize(payload: EventDropArg | EventResizeDoneArg) {
if (payload.event.extendedProps.is !== "range") {
return;
}
const changedEvent = payload.event;
store.dispatch("calendarRanges/patchRangeTime", {
calendarRangeId: payload.event.extendedProps.calendarRangeId,

View File

@ -20,7 +20,10 @@
</option>
<template v-for="t in templates" :key="t.id">
<option :value="t.id">
{{ t.name.fr || "Aucun nom défini" }}
{{
localizeString(t.name) ||
"Aucun nom défini"
}}
</option>
</template>
</select>

View File

@ -10,6 +10,9 @@ const startApp = (
collectionEntry: null | HTMLLIElement,
): void => {
console.log("app started", divElement);
const inputTitle = collectionEntry?.querySelector("input[type='text']");
const input_stored_object: HTMLInputElement | null =
divElement.querySelector("input[data-stored-object]");
if (null === input_stored_object) {
@ -26,9 +29,10 @@ const startApp = (
const app = createApp({
template:
'<drop-file-widget :existingDoc="this.$data.existingDoc" :allowRemove="true" @addDocument="this.addDocument" @removeDocument="removeDocument"></drop-file-widget>',
data(vm) {
data() {
return {
existingDoc: existingDoc,
inputTitle: inputTitle,
};
},
components: {
@ -38,10 +42,13 @@ const startApp = (
addDocument: function ({
stored_object,
stored_object_version,
file_name,
}: {
stored_object: StoredObject;
stored_object_version: StoredObjectVersion;
file_name: string;
}): void {
stored_object.title = file_name;
console.log("object added", stored_object);
console.log("version added", stored_object_version);
this.$data.existingDoc = stored_object;
@ -49,6 +56,11 @@ const startApp = (
input_stored_object.value = JSON.stringify(
this.$data.existingDoc,
);
if (this.$data.inputTitle) {
if (!this.$data.inputTitle?.value) {
this.$data.inputTitle.value = file_name;
}
}
},
removeDocument: function (object: StoredObject): void {
console.log("catch remove document", object);

View File

@ -41,7 +41,7 @@
>
<option value="" selected disabled>Zoom</option>
<option v-for="z in zoomLevels" :value="z.zoom" :key="z.id">
{{ z.label.fr }}
{{ localizeString(z.label) }}
</option>
</select>
<template v-if="pageCount > 1">
@ -173,7 +173,7 @@
>
<option value="" selected disabled>Zoom</option>
<option v-for="z in zoomLevels" :value="z.zoom" :key="z.id">
{{ z.label.fr }}
{{ localizeString(z.label) }}
</option>
</select>
<template v-if="pageCount > 1">
@ -395,6 +395,7 @@ import {
SIGNATURES_GO_TO_SIGNATURE_UNIQUE,
trans,
} from "translator";
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
// @ts-ignore incredible but the console.log is needed
import * as PdfWorker from "pdfjs-dist/build/pdf.worker.mjs";

View File

@ -23,6 +23,7 @@ const emit =
{
stored_object_version: StoredObjectVersionCreated,
stored_object: StoredObject,
file_name: string,
},
) => void
>();
@ -114,7 +115,21 @@ const handleFile = async (file: File): Promise<void> => {
persisted: false,
};
emit("addDocument", { stored_object, stored_object_version });
const fileName = file.name;
let file_name = "Nouveau document";
const file_name_split = fileName.split(".");
if (file_name_split.length > 1) {
const extension = file_name_split
? file_name_split[file_name_split.length - 1]
: "";
file_name = fileName.replace(extension, "").slice(0, -1);
}
emit("addDocument", {
stored_object,
stored_object_version,
file_name: file_name,
});
uploading.value = false;
};
</script>

View File

@ -20,6 +20,7 @@ const emit = defineEmits<{
{
stored_object: StoredObject,
stored_object_version: StoredObjectVersion,
file_name: string,
},
): void;
(e: "removeDocument"): void;
@ -42,14 +43,16 @@ const buttonState = computed<"add" | "replace">(() => {
function onAddDocument({
stored_object,
stored_object_version,
file_name,
}: {
stored_object: StoredObject;
stored_object_version: StoredObjectVersion;
file_name: string;
}): void {
const message =
buttonState.value === "add" ? "Document ajouté" : "Document remplacé";
$toast.success(message);
emit("addDocument", { stored_object_version, stored_object });
emit("addDocument", { stored_object_version, stored_object, file_name });
state.showModal = false;
}

View File

@ -19,6 +19,7 @@ const emit = defineEmits<{
{
stored_object: StoredObject,
stored_object_version: StoredObjectVersion,
file_name: string,
},
): void;
(e: "removeDocument"): void;
@ -53,11 +54,13 @@ const dav_link_href = computed<string | undefined>(() => {
const onAddDocument = ({
stored_object,
stored_object_version,
file_name,
}: {
stored_object: StoredObject;
stored_object_version: StoredObjectVersion;
file_name: string;
}): void => {
emit("addDocument", { stored_object, stored_object_version });
emit("addDocument", { stored_object, stored_object_version, file_name });
};
const onRemoveDocument = (e: Event): void => {

View File

@ -53,7 +53,7 @@ const onRestored = ({
<template>
<template v-if="props.versions.length > 0">
<div class="container">
<template v-for="v in props.versions">
<template v-for="v in props.versions" :key="v.id">
<history-button-list-item
:version="v"
:can-edit="canEdit"

View File

@ -32,13 +32,17 @@ const onRestore = ({
emit("restoreVersion", { newVersion });
};
const isKeptBeforeConversion = computed<boolean>(() =>
props.version["point-in-times"].reduce(
(accumulator: boolean, pit: StoredObjectPointInTime) =>
accumulator || "keep-before-conversion" === pit.reason,
false,
),
);
const isKeptBeforeConversion = computed<boolean>(() => {
if ("point-in-times" in props.version) {
return props.version["point-in-times"].reduce(
(accumulator: boolean, pit: StoredObjectPointInTime) =>
accumulator || "keep-before-conversion" === pit.reason,
false,
);
} else {
return false;
}
});
const isRestored = computed<boolean>(
() => props.version.version > 0 && null !== props.version["from-restored"],
@ -90,11 +94,11 @@ const classes = computed<{
<div class="col-12">
<file-icon :type="version.type"></file-icon>
<span
><strong>#{{ version.version + 1 }}</strong></span
><strong>&nbsp;#{{ version.version + 1 }}&nbsp;</strong></span
>
<template
v-if="version.createdBy !== null && version.createdAt !== null"
><strong v-if="version.version == 0">Créé par</strong
><strong v-if="version.version == 0">créé par</strong
><strong v-else>modifié par</strong>
<span class="badge-user"
><UserRenderBoxBadge

View File

@ -20,9 +20,11 @@
{{ mm.mimeIcon(document.object.type) }}
</div>
{% endif %}
<div>
<p>{{ document.category.name|localize_translatable_string }}</p>
</div>
{% if document.category %}
<div>
<p>{{ document.category.name|localize_translatable_string }}</p>
</div>
{% endif %}
{% if document.object.hasTemplate %}
<div>
<p>{{ document.object.template.name|localize_translatable_string }}</p>

View File

@ -0,0 +1,41 @@
import { TranslatableString } from "ChillMainAssets/types";
/**
* Localizes a translatable string object based on the current locale.
* A fallback logic is implemented in case no translation is available for the current locale.
*
* @param translatableString Object containing translations for different locales
* @param locale defaults to browser locale
* @returns The localized string or null if no translation is available
*/
export function localizeString(
translatableString: TranslatableString | null | undefined,
locale?: string,
): string {
if (!translatableString || Object.keys(translatableString).length === 0) {
return "";
}
const currentLocale = locale || navigator.language.split("-")[0] || "fr";
if (translatableString[currentLocale]) {
return translatableString[currentLocale];
}
// Define fallback locales
const fallbackLocales: string[] = ["fr", "en"];
for (const fallbackLocale of fallbackLocales) {
if (translatableString[fallbackLocale]) {
return translatableString[fallbackLocale];
}
}
// No fallback translation found, use the first available
const availableLocales = Object.keys(translatableString);
if (availableLocales.length > 0) {
return translatableString[availableLocales[0]];
}
return "";
}

View File

@ -11,15 +11,14 @@
// 3. Include remainder of required Bootstrap stylesheets
@import "bootstrap/scss/variables";
@import "bootstrap/scss/variables-dark";
// 4. Include any default map overrides here
@import "custom/_maps";
@import "bootstrap/scss/maps";
// 5. Include remainder of required parts
@import "bootstrap/scss/maps";
@import "bootstrap/scss/mixins";
@import "bootstrap/scss/utilities";
@import "bootstrap/scss/root";
@import "bootstrap/scss/utilities";

View File

@ -1,8 +1,8 @@
// Some Bootstrap variables and configuration files are shared with chill entrypoint
@import "shared";
// 6. Optionally include any other parts as needed
@import "bootstrap/scss/utilities";
// 6. Include any other optional stylesheet partials as desired; list below is not inclusive of all available stylesheets
@import "bootstrap/scss/root";
@import "bootstrap/scss/reboot";
@import "bootstrap/scss/type";
@import "bootstrap/scss/images";
@ -32,10 +32,12 @@
@import "bootstrap/scss/carousel";
@import "bootstrap/scss/spinners";
@import "bootstrap/scss/offcanvas";
@import "bootstrap/scss/helpers";
@import "bootstrap/scss/placeholders";
// 7. Optionally include utilities API last to generate classes based on the Sass map in
@import "bootstrap/scss/utilities/api";
// Helpers
@import "bootstrap/scss/helpers";
// 8. Add additional custom code here
@import "custom";

View File

@ -8,6 +8,9 @@ import {
Heading,
Link,
List,
Emoji,
Mention,
Fullscreen,
} from "ckeditor5";
import coreTranslations from "ckeditor5/translations/fr.js";
@ -26,6 +29,11 @@ export default {
Link,
List,
Paragraph,
// both Emoji and Mention are required for Emoji feature
Emoji,
Mention,
// to enable fullscreen
Fullscreen,
],
toolbar: {
items: [
@ -37,8 +45,13 @@ export default {
"bulletedList",
"numberedList",
"blockQuote",
"|",
"emoji",
"|",
"undo",
"redo",
"|",
"fullscreen",
],
},
translations: [coreTranslations],

View File

@ -1,12 +1,32 @@
import config from "./editor_config";
import { ClassicEditor } from "ckeditor5";
import { createApp } from "vue";
import CommentEditor from "ChillMainAssets/vuejs/_components/CommentEditor/CommentEditor.vue";
const ckeditorFields: NodeListOf<HTMLTextAreaElement> =
document.querySelectorAll("textarea[ckeditor]");
ckeditorFields.forEach((field: HTMLTextAreaElement): void => {
ClassicEditor.create(field, config).catch((error) => {
console.error(error.stack);
throw error;
});
const content = field.value;
const div = document.createElement("div");
if (field.parentNode !== null) {
field.parentNode.insertBefore(div, field);
} else {
throw "parent is null";
}
createApp({
components: { CommentEditor },
template: `<comment-editor v-model="content" @update:modelValue="handleInput"></comment-editor>`,
data() {
return {
content,
};
},
methods: {
handleInput() {
field.value = this.content;
},
},
}).mount(div);
field.style.display = "none";
});
//Fields.push.apply(Fields, document.querySelectorAll('.cf-fields textarea'));

View File

@ -1,45 +0,0 @@
import { createApp } from "vue";
import OpenWopiLink from "ChillMainAssets/vuejs/_components/OpenWopiLink";
import { _createI18n } from "ChillMainAssets/vuejs/_js/i18n";
const i18n = _createI18n({});
//TODO move to chillDocStore or ChillWopi
/*
tags to load module:
<span data-module="wopi-link"
data-wopi-url="{{ path('chill_wopi_file_edit', {'fileId': document.uuid}) }}"
data-doc-type="{{ document.type|e('html_attr') }}"
data-options="{{ options|json_encode }}"
></span>
*/
window.addEventListener("DOMContentLoaded", function (e) {
document
.querySelectorAll('span[data-module="wopi-link"]')
.forEach(function (el) {
createApp({
template:
'<open-wopi-link :wopiUrl="wopiUrl" :type="type" :options="options"></open-wopi-link>',
components: {
OpenWopiLink,
},
data() {
return {
wopiUrl: el.dataset.wopiUrl,
type: el.dataset.docType,
options:
el.dataset.options !== "null"
? JSON.parse(el.dataset.options)
: {},
};
},
})
.use(i18n)
.mount(el);
});
});

View File

@ -67,10 +67,7 @@ export interface UserAssociatedInterface {
id: number;
}
export interface TranslatableString {
fr?: string;
nl?: string;
}
export type TranslatableString = Record<string, string>;
export interface Postcode {
id: number;

View File

@ -22,6 +22,7 @@
<script>
import VueMultiselect from "vue-multiselect";
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
export default {
name: "CountrySelection",
@ -68,7 +69,7 @@ export default {
)[0];
},
transName({ name }) {
return name.fr; //TODO multilang
return localizeString(name);
},
selectCountry(value) {
//console.log('select country', value);

View File

@ -32,7 +32,7 @@
class="chill-entity entity-social-issue"
>
<span class="badge bg-chill-l-gray text-dark">
{{ i.title.fr }}
{{ localizeString(i.title) }}
</span>
</span>
</td>
@ -77,6 +77,7 @@
import { mapState, mapGetters } from "vuex";
import TabTable from "./TabTable";
import OnTheFly from "ChillMainAssets/vuejs/OnTheFly/components/OnTheFly";
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
export default {
name: "MyAccompanyingCourses",
@ -96,6 +97,7 @@ export default {
},
},
methods: {
localizeString,
getUrl(c) {
return `/fr/parcours/${c.id}`;
},

View File

@ -26,7 +26,7 @@
>
<td>{{ $d(e.maxDate.datetime, "short") }}</td>
<td>
{{ e.evaluation.title.fr }}
{{ localizeString(e.evaluation.title) }}
</td>
<td>
<span class="chill-entity entity-social-issue">
@ -97,6 +97,7 @@
import { mapState, mapGetters } from "vuex";
import TabTable from "./TabTable";
import OnTheFly from "ChillMainAssets/vuejs/OnTheFly/components/OnTheFly";
import { localizeString } from "../../lib/localizationHelper/localizationHelper";
export default {
name: "MyEvaluations",
@ -116,6 +117,7 @@ export default {
},
},
methods: {
localizeString,
getUrl(e) {
switch (e.type) {
case "accompanying_period_work_evaluation":

View File

@ -1,6 +1,6 @@
<template>
<template v-for="(container, index) in data.containers" :key="index">
<h4>{{ container.layer.name.fr }}</h4>
<h4>{{ localizeString(container.layer.name) }}</h4>
<ul>
<li v-for="(unit, index) in container.units" :key="index">
{{ unit.unitName }} ({{ unit.unitRefId }})
@ -20,6 +20,7 @@ import {
getAllGeographicalUnitLayers,
} from "../../../../lib/api/address";
import { onMounted, reactive } from "vue";
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
export interface AddressDetailsGeographicalLayersProp {
address: Address;

View File

@ -0,0 +1,122 @@
<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref } from "vue";
import { Ckeditor } from "@ckeditor/ckeditor5-vue";
import { ClassicEditor } from "ckeditor5";
import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config";
import {
trans,
EDITOR_SWITCH_TO_SIMPLE,
EDITOR_SWITCH_TO_COMPLEX,
} from "translator";
const EDITOR_MODE_KEY = "editorMode";
const kind = ref<"simple" | "rich">("simple");
const value = defineModel({ required: true });
const isSimple = computed(() => kind.value === "simple");
const toggleButtonClass = computed(() => {
return {
["toggle-button"]: true,
onEditor: !isSimple.value,
onSimple: isSimple.value,
};
});
const toggleEditor = () => {
let newValue;
newValue = kind.value === "simple" ? "rich" : "simple";
kind.value = "rich";
window.localStorage.setItem(EDITOR_MODE_KEY, newValue);
window.dispatchEvent(new Event("toggleEditorKind"));
};
const onKindChange = function (/* event: StorageEvent | Event */) {
const newValue = window.localStorage.getItem(EDITOR_MODE_KEY);
if (null === newValue || !(newValue === "rich" || newValue === "simple")) {
throw "invalid new value: " + newValue;
}
if (kind.value !== newValue) {
kind.value = newValue;
}
};
onMounted(function () {
const storage = window.localStorage;
const savedKind = storage.getItem(EDITOR_MODE_KEY);
if (
null !== kind.value &&
(savedKind === "simple" || savedKind === "rich")
) {
kind.value = savedKind;
}
window.addEventListener("storage", onKindChange);
window.addEventListener("toggleEditorKind", onKindChange);
});
onUnmounted(function () {
window.removeEventListener("storage", onKindChange);
window.removeEventListener("toggleEditorKind", onKindChange);
});
</script>
<template>
<div>
<div v-if="'rich' === kind">
<Ckeditor
:editor="ClassicEditor"
:config="classicEditorConfig"
v-model="value"
/>
</div>
<div v-else>
<textarea
v-model="value"
class="form-control simple-editor"
></textarea>
</div>
<button :class="toggleButtonClass" type="button" @click="toggleEditor">
{{
isSimple
? trans(EDITOR_SWITCH_TO_COMPLEX)
: trans(EDITOR_SWITCH_TO_SIMPLE)
}}
</button>
</div>
</template>
<style scoped lang="scss">
@import "ChillMainAssets/module/bootstrap/bootstrap";
.toggle-button {
background: white;
border: none;
padding: 0.15rem;
color: #069;
cursor: pointer;
@include media-breakpoint-up(md) {
&.onEditor {
position: relative;
left: 1rem;
top: -1.5rem;
}
&.onSimple {
position: relative;
top: -0.75rem;
left: 1rem;
}
}
}
.simple-editor {
min-height: 190px;
}
</style>

View File

@ -30,7 +30,7 @@
{{ address.postcode.name }}
</p>
<p v-if="null !== address.country" class="country">
{{ address.country.name.fr }}
{{ localizeString(address.country.name) }}
</p>
</div>
</template>
@ -84,9 +84,11 @@
import Confidential from "ChillMainAssets/vuejs/_components/Confidential.vue";
import AddressDetailsButton from "ChillMainAssets/vuejs/_components/AddressDetails/AddressDetailsButton.vue";
import { trans, ADDRESS_VALID_FROM, ADDRESS_VALID_TO } from "translator";
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
export default {
name: "AddressRenderBox",
methods: { localizeString },
components: {
Confidential,
AddressDetailsButton,

View File

@ -1,6 +1,7 @@
<script setup lang="ts">
import { UserGroup } from "../../../types";
import { computed } from "vue";
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
interface UserGroupRenderBoxProps {
userGroup: UserGroup;
@ -18,7 +19,7 @@ const styles = computed<{ color: string; "background-color": string }>(() => {
<template>
<span class="badge-user-group" :style="styles">{{
userGroup.label.fr
localizeString(userGroup.label)
}}</span>
</template>

View File

@ -2,10 +2,10 @@
<span class="chill-entity entity-user">
{{ user.label }}
<span class="user-job" v-if="user.user_job !== null"
>({{ user.user_job.label.fr }})</span
>({{ localizeString(user.user_job.label) }})</span
>
<span class="main-scope" v-if="user.main_scope !== null"
>({{ user.main_scope.name.fr }})</span
>({{ localizeString(user.main_scope.name) }})</span
>
<span
v-if="user.isAbsent"
@ -17,8 +17,15 @@
</template>
<script>
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
export default {
name: "UserRenderBoxBadge",
methods: {
localizeString() {
return localizeString;
},
},
props: ["user"],
};
</script>

View File

@ -1,214 +0,0 @@
<template>
<a
v-if="isOpenDocument"
class="btn"
:class="[
isChangeIcon ? 'change-icon' : '',
isChangeClass ? options.changeClass : 'btn-wopilink',
]"
@click="openModal"
>
<i v-if="isChangeIcon" class="fa me-2" :class="options.changeIcon"></i>
<span v-if="!noText">
{{ trans(WOPI_ONLINE_EDIT_DOCUMENT) }}
</span>
</a>
<teleport to="body">
<div class="wopi-frame" v-if="isOpenDocument">
<modal
v-if="modal.showModal"
:modalDialogClass="modal.modalDialogClass"
:hideFooter="true"
@close="modal.showModal = false"
>
<template #header>
<img class="logo" :src="logo" height="45" />
<span class="ms-auto me-3">
<span v-if="options.title">{{ options.title }}</span>
</span>
</template>
<template #body>
<div v-if="loading" class="loading">
<i
class="fa fa-circle-o-notch fa-spin fa-3x"
:title="trans(WOPI_LOADING)"
></i>
</div>
<iframe :src="this.wopiUrl" @load="loaded"></iframe>
</template>
</modal>
</div>
<div v-else>
<Modal
v-if="modal.showModal"
modalDialogClass="modal-sm"
@close="modal.showModal = false"
>
<template v-slot:header>
<h3>{{ trans(WOPI_INVALID_TITLE) }}</h3>
</template>
<template v-slot:body>
<div class="alert alert-warning">
{{ trans(WOPI_ONLINE_EDIT_DOCUMENT) }}
</div>
</template>
</Modal>
</div>
</teleport>
</template>
<script setup>
import { ref, computed } from "vue";
import {
trans,
WOPI_ONLINE_EDIT_DOCUMENT,
WOPI_INVALID_TITLE,
WOPI_LOADING,
} from "translator";
import Modal from "ChillMainAssets/vuejs/_components/Modal";
import logo from "ChillMainAssets/chill/img/logo-chill-sans-slogan_white.png";
// Props
const props = defineProps({
wopiUrl: {
type: String,
required: true,
},
type: {
type: String,
required: true,
},
options: {
type: Object,
required: false,
},
});
// data
const modal = ref({
showModal: false,
modalDialogClass: "modal-fullscreen",
});
const loading = ref(false);
// MIME types
const mime = [
// TODO temporary hardcoded. to be replaced by twig extension or a collabora server query
"application/clarisworks",
"application/coreldraw",
"application/macwriteii",
"application/msword",
"application/pdf",
"application/vnd.lotus-1-2-3",
"application/vnd.ms-excel",
"application/vnd.ms-excel.sheet.binary.macroEnabled.12",
"application/vnd.ms-excel.sheet.macroEnabled.12",
"application/vnd.ms-excel.template.macroEnabled.12",
"application/vnd.ms-powerpoint",
"application/vnd.ms-powerpoint.presentation.macroEnabled.12",
"application/vnd.ms-powerpoint.template.macroEnabled.12",
"application/vnd.ms-visio.drawing",
"application/vnd.ms-word.document.macroEnabled.12",
"application/vnd.ms-word.template.macroEnabled.12",
"application/vnd.ms-works",
"application/vnd.oasis.opendocument.chart",
"application/vnd.oasis.opendocument.formula",
"application/vnd.oasis.opendocument.graphics",
"application/vnd.oasis.opendocument.graphics-flat-xml",
"application/vnd.oasis.opendocument.graphics-template",
"application/vnd.oasis.opendocument.presentation",
"application/vnd.oasis.opendocument.presentation-flat-xml",
"application/vnd.oasis.opendocument.presentation-template",
"application/vnd.oasis.opendocument.spreadsheet",
"application/vnd.oasis.opendocument.spreadsheet-flat-xml",
"application/vnd.oasis.opendocument.spreadsheet-template",
"application/vnd.oasis.opendocument.text",
"application/vnd.oasis.opendocument.text-flat-xml",
"application/vnd.oasis.opendocument.text-master",
"application/vnd.oasis.opendocument.text-master-template",
"application/vnd.oasis.opendocument.text-template",
"application/vnd.oasis.opendocument.text-web",
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"application/vnd.openxmlformats-officedocument.presentationml.slideshow",
"application/vnd.openxmlformats-officedocument.presentationml.template",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/vnd.openxmlformats-officedocument.spreadsheetml.template",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.openxmlformats-officedocument.wordprocessingml.template",
"application/vnd.sun.xml.calc",
"application/vnd.sun.xml.calc.template",
"application/vnd.sun.xml.chart",
"application/vnd.sun.xml.draw",
"application/vnd.sun.xml.draw.template",
"application/vnd.sun.xml.impress",
"application/vnd.sun.xml.impress.template",
"application/vnd.sun.xml.math",
"application/vnd.sun.xml.writer",
"application/vnd.sun.xml.writer.global",
"application/vnd.sun.xml.writer.template",
"application/vnd.visio",
"application/vnd.visio2013",
"application/vnd.wordperfect",
"application/x-abiword",
"application/x-aportisdoc",
"application/x-dbase",
"application/x-dif-document",
"application/x-fictionbook+xml",
"application/x-gnumeric",
"application/x-hwp",
"application/x-iwork-keynote-sffkey",
"application/x-iwork-numbers-sffnumbers",
"application/x-iwork-pages-sffpages",
"application/x-mspublisher",
"application/x-mswrite",
"application/x-pagemaker",
"application/x-sony-bbeb",
"application/x-t602",
];
// Computed
const isOpenDocument = computed(() => mime.includes(props.type));
const noText = computed(() => props.options?.noText === true);
const isChangeIcon = computed(() => !!props.options?.changeIcon);
const isChangeClass = computed(() => !!props.options?.changeClass);
// Methods
const openModal = () => {
loading.value = true;
modal.value.showModal = true;
};
const loaded = () => {
loading.value = false;
};
</script>
<style lang="scss">
div.wopi-frame {
div.modal-header {
border-bottom: 0;
background-color: var(--bs-primary);
color: white;
}
div.modal-body {
padding: 0;
overflow-y: unset !important;
iframe {
height: 100%;
width: 100%;
}
div.loading {
position: absolute;
color: var(--bs-chill-gray);
top: calc(50% - 30px);
left: calc(50% - 30px);
}
}
}
</style>

View File

@ -9,7 +9,6 @@
{{ encore_entry_script_tags('mod_pickentity_type') }}
{{ encore_entry_script_tags('mod_entity_workflow_subscribe') }}
{{ encore_entry_script_tags('page_workflow_show') }}
{{ encore_entry_script_tags('mod_wopi_link') }}
{{ encore_entry_script_tags('mod_document_action_buttons_group') }}
{{ encore_entry_script_tags('mod_workflow_attachment') }}
{% endblock %}
@ -19,7 +18,6 @@
{{ encore_entry_link_tags('mod_pickentity_type') }}
{{ encore_entry_link_tags('mod_entity_workflow_subscribe') }}
{{ encore_entry_link_tags('page_workflow_show') }}
{{ encore_entry_link_tags('mod_wopi_link') }}
{{ encore_entry_link_tags('mod_document_action_buttons_group') }}
{{ encore_entry_link_tags('mod_workflow_attachment') }}
{% endblock %}

View File

@ -86,10 +86,6 @@ module.exports = function (encore, entries) {
"mod_entity_workflow_pick",
__dirname + "/Resources/public/module/entity-workflow-pick/index.js",
);
encore.addEntry(
"mod_wopi_link",
__dirname + "/Resources/public/module/wopi-link/index.js",
);
encore.addEntry(
"mod_pick_postal_code",
__dirname + "/Resources/public/module/pick-postal-code/index.js",

View File

@ -60,6 +60,7 @@ user_group:
inactive: Inactif
with_users: Membres
no_users: Aucun utilisateur associé
no_user_groups: Aucune groupe d'utilisateurs
no_admin_users: Aucun administrateur
Label: Nom du groupe
BackgroundColor: Couleur de fond du badge
@ -752,6 +753,7 @@ export:
id: Identifiant de l'action
social_issue_id: Identifiant de la problématique sociale
social_issue: Problématique sociale
desactivation_date: Date de désactivation
social_issue_ordering: Ordre de la problématique sociale
action_label: Action d'accompagnement
action_ordering: Ordre
@ -933,3 +935,7 @@ multiselect:
select_group_label: Appuyer sur "Entrée" pour sélectionner ce groupe
deselect_group_label: Appuyer sur "Entrée" pour désélectionner ce groupe
selected_label: Sélectionné'
editor:
switch_to_simple: Éditeur simple
switch_to_complex: Éditeur riche

View File

@ -207,7 +207,6 @@ final class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle
$works = $this->workRepository->findByAccompanyingPeriod(
$accompanyingCourse,
['startDate' => 'DESC', 'endDate' => 'DESC'],
3
);
$counters = [
@ -220,7 +219,7 @@ final class AccompanyingCourseController extends \Symfony\Bundle\FrameworkBundle
'accompanyingCourse' => $accompanyingCourse,
'withoutHousehold' => $withoutHousehold,
'participationsByHousehold' => $accompanyingCourse->actualParticipationsByHousehold(),
'works' => $works,
'works' => \array_slice($works, 0, 3),
'activities' => \array_slice($activities, 0, 3),
'counters' => $counters,
]);

View File

@ -11,46 +11,97 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Controller;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\MainBundle\Templating\Listing\FilterOrderHelperFactoryInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Repository\AccompanyingPeriodACLAwareRepository;
use Chill\PersonBundle\Repository\AccompanyingPeriodRepository;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\NoResultException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;
class UserAccompanyingPeriodController extends AbstractController
{
public function __construct(private readonly AccompanyingPeriodRepository $accompanyingPeriodRepository, private readonly PaginatorFactory $paginatorFactory) {}
public function __construct(
private readonly AccompanyingPeriodRepository $accompanyingPeriodRepository,
private readonly PaginatorFactory $paginatorFactory,
private readonly AccompanyingPeriodACLAwareRepository $accompanyingPeriodACLAwareRepository,
private readonly FilterOrderHelperFactoryInterface $filterOrderHelperFactory,
private readonly TranslatorInterface $translator,
) {}
/**
* @throws NonUniqueResultException
* @throws NoResultException
*/
#[Route(path: '/{_locale}/person/accompanying-periods/my', name: 'chill_person_accompanying_period_user')]
public function listAction(Request $request): Response
{
$active = $request->query->getBoolean('active', true);
$steps = match ($active) {
true => [
$filter = (int) $request->query->get('filter', 2);
$user = $this->getUser();
if (!$user instanceof User) {
throw new \LogicException('Expected an instance of Chill\MainBundle\Entity\User.');
}
$activeTab = match ($filter) {
2 => 'referrer',
4 => 'referrer_to_works',
6 => 'both',
8 => 'intervening',
default => 'referrer',
};
$statusAndDateFilter = $this->buildStatusAndDateFilter($filter);
$status = $statusAndDateFilter->getCheckboxData('statusFilter');
$from = null;
$to = null;
if ('intervening' === $activeTab) {
$interventionBetweenDates = $statusAndDateFilter->getDateRangeData('interventionBetweenDates');
$from = $interventionBetweenDates['from'];
$to = $interventionBetweenDates['to'];
}
$steps = [];
if (in_array('is_open', $status, true)) {
$steps[] = [
...$steps,
AccompanyingPeriod::STEP_CONFIRMED,
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_LONG,
AccompanyingPeriod::STEP_CONFIRMED_INACTIVE_SHORT,
],
false => [
AccompanyingPeriod::STEP_CLOSED,
],
};
];
}
$total = $this->accompanyingPeriodRepository->countBy(['user' => $this->getUser(), 'step' => $steps]);
$pagination = $this->paginatorFactory->create($total);
$accompanyingPeriods = $this->accompanyingPeriodRepository->findBy(
['user' => $this->getUser(), 'step' => $steps],
['openingDate' => 'DESC'],
$pagination->getItemsPerPage(),
$pagination->getCurrentPageFirstItemNumber()
if (in_array('is_closed', $status, true)) {
$steps[] = AccompanyingPeriod::STEP_CLOSED;
}
$total = $this->accompanyingPeriodACLAwareRepository->countByUserAssociation($user, $steps, $from, $to, $filter);
$paginator = $this->paginatorFactory->create($total);
$accompanyingPeriods = $this->accompanyingPeriodACLAwareRepository->findByUserAssociation(
$user,
$steps,
$from,
$to,
$filter,
$paginator->getCurrentPageFirstItemNumber(),
$paginator->getItemsPerPage(),
);
return $this->render('@ChillPerson/AccompanyingPeriod/user_periods_list.html.twig', [
'accompanyingPeriods' => $accompanyingPeriods,
'pagination' => $pagination,
'active' => $active,
'pagination' => $paginator,
'activeTab' => $activeTab,
'filter' => $filter,
'statusFilter' => $statusAndDateFilter,
]);
}
@ -71,4 +122,29 @@ class UserAccompanyingPeriodController extends AbstractController
'pagination' => $pagination,
]);
}
public function buildStatusAndDateFilter(int $filter)
{
$filterBuilder = $this->filterOrderHelperFactory
->create(self::class)
->addCheckbox(
'statusFilter',
['is_open', 'is_closed'],
['is_open'],
array_map(
static fn (string $s) => 'my_parcours_filters.'.$s,
['is_open', 'is_closed']
)
);
if (8 === $filter) {
$filterBuilder->addDateRange(
'interventionBetweenDates',
$this->translator->trans('Since'),
new \DateTimeImmutable('-6 months'),
);
}
return $filterBuilder->build();
}
}

View File

@ -22,7 +22,7 @@ use Doctrine\ORM\Mapping as ORM;
class MaritalStatus
{
#[ORM\Id]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 7)]
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 15)]
private ?string $id;
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)]

View File

@ -87,7 +87,7 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
], ])
->setExtras([
'order' => 40,
'counter' => count($period->getOpenWorks()) > 0 ? count($period->getOpenWorks()) : null,
'counter' => count($period->getWorks()) > 0 ? count($period->getWorks()) : null,
]);
}

View File

@ -365,4 +365,90 @@ final readonly class AccompanyingPeriodACLAwareRepository implements Accompanyin
return $qb;
}
public function findByUserAssociation(User $user, array $steps, ?\DateTimeImmutable $from, ?\DateTimeImmutable $to, int $filter, ?int $start = 0, ?int $limit = 1000): array
{
$qb = $this->buildQueryByUserAssociation($user, $steps, $from, $to, $filter);
$qb->addOrderBy('acp.openingDate', 'DESC');
if (null !== $start) {
$qb->setFirstResult($start);
}
if (null !== $limit) {
$qb->setMaxResults($limit);
}
return $qb->getQuery()->getResult();
}
public function countByUserAssociation(User $user, array $steps, ?\DateTimeImmutable $from, ?\DateTimeImmutable $to, int $filter): int
{
$qb = $this->buildQueryByUserAssociation($user, $steps, $from, $to, $filter);
$qb->select('COUNT(DISTINCT acp.id)');
return $qb->getQuery()->getSingleScalarResult();
}
public function buildQueryByUserAssociation(User $user, array $steps, ?\DateTimeImmutable $from, ?\DateTimeImmutable $to, int $filter): QueryBuilder
{
$qb = $this->accompanyingPeriodRepository->createQueryBuilder('acp');
// Create an andX expression to hold the user association conditions
$whereUserAssociation = $qb->expr()->andX();
if (($filter & self::USER_IS_REFERRER) > 0) {
$whereUserAssociation->add($qb->expr()->eq('acp.user', ':user'));
}
if (($filter & self::USER_IS_WORK_REFERRER) > 0) {
$whereUserAssociation->add(
$qb->expr()->exists(
'SELECT 1
FROM '.AccompanyingPeriod\AccompanyingPeriodWork::class.' subw
JOIN subw.referrersHistory subw_ref_history
WHERE subw.id = acpw.id
AND subw_ref_history.user = :user
AND subw_ref_history.endDate IS NULL'
)
);
$qb->innerJoin('acp.works', 'acpw');
}
if (($filter & self::USER_IS_INTERVENING) > 0) {
$expr = 'SELECT 1
FROM '.AccompanyingPeriod\AccompanyingPeriodInfo::class.' info
WHERE info.accompanyingPeriod = acp
AND info.user = :user';
if (null !== $from) {
$expr .= ' AND info.infoDate >= :from';
$qb->setParameter('from', $from);
}
if (null !== $to) {
$expr .= ' AND info.infoDate <= :to';
$qb->setParameter('to', $to);
}
$whereUserAssociation->add(
$qb->expr()->exists($expr)
);
}
// Apply the compound condition to the query builder
$qb->andWhere($whereUserAssociation);
// Apply the steps condition
$qb->andWhere($qb->expr()->in('acp.step', ':steps'));
// Set the remaining parameters
$qb->setParameter('user', $user)
->setParameter('steps', $steps);
return $qb;
}
}

View File

@ -21,6 +21,22 @@ use Chill\PersonBundle\Entity\Person;
interface AccompanyingPeriodACLAwareRepositoryInterface
{
public const USER_IS_REFERRER = 0b0010; // 2 in decimal
public const USER_IS_WORK_REFERRER = 0b0100; // 4 in decimal
public const USER_IS_INTERVENING = 0b1000; // 8 in decimal
/**
* Finds associations for a given user within a specific date range and step filters.
*
* @param \DateTimeImmutable|null $from the start date for filtering when intervention in accompanying period took place
* @param \DateTimeImmutable|null $to the end date for filtering when intervention in accompanying period took place
*
* @return array the list of user associations matching the given criteria
*/
public function findByUserAssociation(User $user, array $steps, ?\DateTimeImmutable $from, ?\DateTimeImmutable $to, int $filter, ?int $start = 0, ?int $limit = 1000): array;
public function countByUserAssociation(User $user, array $steps, ?\DateTimeImmutable $from, ?\DateTimeImmutable $to, int $filter): int;
/**
* @param array|UserJob[] $jobs
* @param array|Scope[] $services

View File

@ -62,6 +62,18 @@ final readonly class AccompanyingPeriodRepository implements ObjectRepository
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
}
public function findOneBy(array $criteria): ?AccompanyingPeriod
{
return $this->findOneBy($criteria);
}
public function getClassName()
{
return AccompanyingPeriod::class;
}
// CUSTOM FIND BY METHODS
/**
* @return array|AccompanyingPeriod[]
*/
@ -87,16 +99,6 @@ final readonly class AccompanyingPeriodRepository implements ObjectRepository
return $qb;
}
public function findOneBy(array $criteria): ?AccompanyingPeriod
{
return $this->findOneBy($criteria);
}
public function getClassName()
{
return AccompanyingPeriod::class;
}
private function buildQueryByRecentUserHistory(User $user, \DateTimeImmutable $since): QueryBuilder
{
$qb = $this->repository->createQueryBuilder('a');

View File

@ -13,14 +13,7 @@
$t("comment.label")
}}</label>
<ckeditor
name="content"
:placeholder="$t('comment.content')"
:editor="classicEditor"
:config="editorConfig"
v-model="content"
tag-name="textarea"
/>
<comment-editor v-model="content" />
<div class="sub-comment">
<div
@ -61,15 +54,13 @@
</template>
<script>
import { ClassicEditor } from "ckeditor5";
import { Ckeditor } from "@ckeditor/ckeditor5-vue";
import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config";
import CommentEditor from "ChillMainAssets/vuejs/_components/CommentEditor/CommentEditor.vue";
import { mapState } from "vuex";
export default {
name: "Comment",
components: {
ckeditor: Ckeditor,
CommentEditor,
},
data() {
return {

View File

@ -18,14 +18,7 @@
</h3>
</template>
<template #body>
<ckeditor
name="content"
:placeholder="$t('comment_placeholder')"
:editor="editor"
:config="editorConfig"
v-model="content"
tag-name="textarea"
/>
<comment-editor v-model="content" />
</template>
<template #footer>
<a class="btn btn-save" @click="saveAction">
@ -39,15 +32,13 @@
<script>
import Modal from "ChillMainAssets/vuejs/_components/Modal.vue";
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
import { Ckeditor } from "@ckeditor/ckeditor5-vue";
import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config";
import { ClassicEditor } from "ckeditor5";
import CommentEditor from "ChillMainAssets/vuejs/_components/CommentEditor/CommentEditor.vue";
export default {
name: "WriteComment",
components: {
Modal,
ckeditor: Ckeditor,
CommentEditor,
},
props: ["resource"],
emits: ["updateComment"],

View File

@ -11,7 +11,7 @@
:value="s"
/>
<label class="form-check-label">
{{ s.name.fr }}
{{ localizeString(s.name) }}
</label>
</div>
</div>
@ -24,6 +24,7 @@
<script>
import { mapState, mapGetters } from "vuex";
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
export default {
name: "Scopes",
@ -48,6 +49,7 @@ export default {
},
},
methods: {
localizeString,
restore() {
console.log("restore");
},

View File

@ -34,22 +34,12 @@
<div id="privateComment" class="action-row">
<label class="col-form-label">{{ $t("private_comment") }}</label>
<ckeditor
v-model="privateComment"
:editor="classicEditor"
:config="editorConfig"
tag-name="textarea"
></ckeditor>
<comment-editor v-model="privateComment"></comment-editor>
</div>
<div id="comment" class="action-row">
<label class="col-form-label">{{ $t("comments") }}</label>
<ckeditor
v-model="note"
:editor="classicEditor"
:config="editorConfig"
tag-name="textarea"
></ckeditor>
<comment-editor v-model="note"></comment-editor>
</div>
<div id="objectives" class="action-row">
@ -78,7 +68,7 @@
<!-- results which **are** attached to an objective -->
<div v-for="g in goalsPicked" :key="g.goal.id">
<div class="item-title" @click="removeGoal(g)">
<span class="removable">{{ g.goal.title.fr }}</span>
<span class="removable">{{ localizeString(g.goal.title) }}</span>
</div>
<div>
<add-result :goal="g.goal" destination="goal"></add-result>
@ -122,7 +112,7 @@
@click="addGoal(g)"
:key="g.id"
>
<span>{{ g.title.fr }}</span>
<span>{{ localizeString(g.title) }}</span>
</li>
</ul>
</template>
@ -167,7 +157,7 @@
@click="addEvaluation(e)"
:key="e.id"
>
<span>{{ e.title.fr }}</span>
<span>{{ localizeString(e.title) }}</span>
</li>
</ul>
</div>
@ -208,6 +198,29 @@
</label>
</div>
</li>
<li
v-for="p in getPreviousPersons"
:key="p.id"
class="alert alert-danger"
>
<div class="form-check">
<input
v-model="personsPicked"
:value="p.id"
type="checkbox"
class="me-2 form-check-input"
:id="'person_check' + p.id"
/>
<label :for="'person_check' + p.id" class="form-check-label">
<person-text :person="p"></person-text>
</label>
</div>
<span
><i class="fa fa-warning"></i>&nbsp;{{
$t("warning_previous_persons")
}}</span
>
</li>
</ul>
</div>
@ -438,9 +451,7 @@
<script>
import { mapState, mapGetters } from "vuex";
import { Ckeditor } from "@ckeditor/ckeditor5-vue";
import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config";
import { ClassicEditor } from "ckeditor5";
import CommentEditor from "ChillMainAssets/vuejs/_components/CommentEditor/CommentEditor.vue";
import AddResult from "./components/AddResult.vue";
import AddEvaluation from "./components/AddEvaluation.vue";
import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons.vue";
@ -449,6 +460,7 @@ import OnTheFly from "ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue";
import ListWorkflowModal from "ChillMainAssets/vuejs/_components/EntityWorkflow/ListWorkflowModal.vue";
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
const i18n = {
messages: {
@ -497,6 +509,8 @@ const i18n = {
notification_notify_referrer: "Notifier le référent",
notification_notify_any: "Notifier d'autres utilisateurs",
notification_send: "Envoyer une notification",
warning_previous_persons:
"Cet usager n'est désormais plus concerné par le parcours, bien qu'il ait été associé à l'action par le passé.",
},
},
};
@ -504,7 +518,7 @@ const i18n = {
export default {
name: "App",
components: {
ckeditor: Ckeditor,
CommentEditor,
AddResult,
AddEvaluation,
AddPersons,
@ -583,6 +597,7 @@ export default {
"hasHandlingThirdParty",
"hasThirdParties",
"hasReferrers",
"getPreviousPersons",
]),
classicEditor: () => ClassicEditor,
editorConfig: () => classicEditorConfig,
@ -647,6 +662,7 @@ export default {
},
},
methods: {
localizeString,
toggleSelect() {
this.isExpanded = !this.isExpanded;
},

View File

@ -2,7 +2,7 @@
<div>
<a id="evaluations"></a>
<div class="item-title" :title="evaluation.id || 'no id yet'">
<span>{{ evaluation.evaluation.title.fr }}</span>
<span>{{ localizeString(evaluation.evaluation.title) }}</span>
</div>
<div class="item-url mt-3 mb-4" v-if="evaluation.evaluation.url">
@ -69,6 +69,7 @@ import FormEvaluation from "./FormEvaluation.vue";
import Modal from "ChillMainAssets/vuejs/_components/Modal";
import ListWorkflowModal from "ChillMainAssets/vuejs/_components/EntityWorkflow/ListWorkflowModal.vue";
import { buildLinkCreate } from "ChillMainAssets/lib/entity-workflow/api";
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
const i18n = {
messages: {
@ -129,17 +130,18 @@ export default {
},
},
methods: {
localizeString,
removeEvaluation(e) {
this.$store.commit("removeEvaluation", e);
return;
},
toggleEditEvaluation(e) {
toggleEditEvaluation() {
this.$store.commit("toggleEvaluationEdit", { key: this.evaluation.key });
},
submitForm() {
this.toggleEditEvaluation();
},
goToGenerateWorkflow({ event, link, workflowName }) {
goToGenerateWorkflow({ workflowName }) {
const callback = (data) => {
let evaluationId = data.accompanyingPeriodWorkEvaluations.find(
(e) => e.key === this.evaluation.key,

View File

@ -7,7 +7,7 @@
<ul class="list-suggest remove-items">
<li v-for="r in pickedResults" @click="removeResult(r)" :key="r.id">
<span>
{{ r.title.fr }}
{{ localizeString(r.title) }}
</span>
</li>
</ul>
@ -50,7 +50,7 @@
@click="addResult(r)"
:key="r.id"
>
<span>{{ r.title.fr }}</span>
<span>{{ localizeString(r.title) }}</span>
</li>
</ul>
</template>
@ -66,6 +66,8 @@
</template>
<script>
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
const i18n = {
messages: {
fr: {
@ -124,6 +126,7 @@ export default {
},
},
methods: {
localizeString,
toggleSelect() {
this.isExpanded = !this.isExpanded;
},

View File

@ -88,13 +88,7 @@
$t("evaluation_public_comment")
}}</label>
<div class="col-sm-12">
<ckeditor
:editor="classicEditor"
:config="editorConfig"
:placeholder="$t('evaluation_comment_placeholder')"
v-model="comment"
tag-name="textarea"
></ckeditor>
<comment-editor v-model:value="comment"></comment-editor>
</div>
</div>
@ -273,9 +267,6 @@
<script>
import { ISOToDatetime } from "ChillMainAssets/chill/js/date";
import { Ckeditor } from "@ckeditor/ckeditor5-vue";
import { ClassicEditor } from "ckeditor5";
import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config";
import { mapState } from "vuex";
import PickTemplate from "ChillDocGeneratorAssets/vuejs/_components/PickTemplate.vue";
import { buildLink } from "ChillDocGeneratorAssets/lib/document-generator";
@ -284,6 +275,7 @@ import { buildLinkCreate } from "ChillMainAssets/lib/entity-workflow/api";
import { buildLinkCreate as buildLinkCreateNotification } from "ChillMainAssets/lib/entity-notification/api";
import DocumentActionButtonsGroup from "ChillDocStoreAssets/vuejs/DocumentActionButtonsGroup.vue";
import DropFileModal from "ChillDocStoreAssets/vuejs/DropFileWidget/DropFileModal.vue";
import CommentEditor from "ChillMainAssets/vuejs/_components/CommentEditor/CommentEditor.vue";
const i18n = {
messages: {
@ -322,8 +314,8 @@ export default {
name: "FormEvaluation",
props: ["evaluation", "docAnchorId"],
components: {
CommentEditor,
DropFileModal,
ckeditor: Ckeditor,
PickTemplate,
ListWorkflowModal,
DocumentActionButtonsGroup,
@ -371,8 +363,6 @@ export default {
},
computed: {
...mapState(["isPosting", "work", "me"]),
classicEditor: () => ClassicEditor,
editorConfig: () => classicEditorConfig,
AmIRefferer() {
return !(
this.$store.state.work.accompanyingPeriod.user &&
@ -535,11 +525,11 @@ export default {
title: title,
});
},
addDocument({ stored_object, stored_object_version }) {
addDocument({ stored_object, stored_object_version, file_name }) {
let document = {
type: "accompanying_period_work_evaluation_document",
storedObject: stored_object,
title: "Nouveau document",
title: file_name,
};
this.$store.commit("addDocument", {
key: this.evaluation.key,

View File

@ -87,6 +87,11 @@ const store = createStore({
return [];
},
getPreviousPersons(state) {
return state.personsPicked.filter(
(p) => !state.personsReachables.map((pr) => pr.id).includes(p.id),
);
},
buildPayload(state) {
return {
type: "accompanying_period_work",
@ -607,8 +612,7 @@ const store = createStore({
submit({ getters, state, commit }, callback) {
let payload = getters.buildPayload,
params = new URLSearchParams({ entity_version: state.version }),
url = `/api/1.0/person/accompanying-course/work/${state.work.id}.json?${params}`,
errors = [];
url = `/api/1.0/person/accompanying-course/work/${state.work.id}.json?${params}`;
commit("setIsPosting", true);
// console.log('the social action', payload);

View File

@ -28,7 +28,7 @@
:key="t.id"
:value="t.id"
>
{{ t.label.fr }}
{{ localizeString(t.label) }}
</option>
</select>
</div>
@ -83,9 +83,11 @@
<script>
import CurrentHousehold from "./CurrentHousehold";
import { mapGetters, mapState } from "vuex";
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
export default {
name: "Dates",
methods: { localizeString },
components: {
CurrentHousehold,
},

View File

@ -29,12 +29,7 @@
</div>
<div class="item-row comment">
<ckeditor
:editor="classicEditor"
:config="editorConfig"
v-model="comment"
tag-name="textarea"
/>
<comment-editor v-model="comment" />
</div>
<div class="item-row participation-details">
@ -103,15 +98,13 @@ div.participation-details {
<script>
import { mapGetters } from "vuex";
import PersonRenderBox from "ChillPersonAssets/vuejs/_components/Entity/PersonRenderBox.vue";
import { Ckeditor } from "@ckeditor/ckeditor5-vue";
import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config";
import { ClassicEditor } from "ckeditor5";
import CommentEditor from "ChillMainAssets/vuejs/_components/CommentEditor/CommentEditor.vue";
export default {
name: "MemberDetails",
components: {
PersonRenderBox,
ckeditor: Ckeditor,
CommentEditor,
},
props: ["conc"],
computed: {

View File

@ -1,30 +1,17 @@
<template>
<ckeditor
name="content"
:placeholder="
$t('household_members_editor.positioning.comment_placeholder')
"
:editor="editor"
:config="editorConfig"
v-model="content"
tag-name="textarea"
/>
<comment-editor v-model="content" />
</template>
<script>
import { Ckeditor } from "@ckeditor/ckeditor5-vue";
import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config";
import { ClassicEditor } from "ckeditor5";
import CommentEditor from "ChillMainAssets/vuejs/_components/CommentEditor/CommentEditor.vue";
export default {
name: "PersonComment.vue",
components: {
ckeditor: Ckeditor,
CommentEditor,
},
props: ["conc"],
computed: {
editor: () => ClassicEditor,
editorConfig: () => classicEditorConfig,
content: {
get() {
return this.$props.conc.comment || "";

View File

@ -38,7 +38,7 @@
}"
@click="moveToPosition(conc.person.id, position.id)"
>
{{ position.label.fr }}
{{ localizeString(position.label) }}
</button>
</div>
</div>
@ -57,6 +57,7 @@ import { mapGetters, mapState } from "vuex";
import CurrentHousehold from "./CurrentHousehold";
import PersonComment from "./PersonComment";
import PersonText from "../../_components/Entity/PersonText.vue";
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
export default {
name: "Positioning",
@ -79,7 +80,7 @@ export default {
this.$store.getters.concUnpositionned.length === 0
);
},
allowHolderForConcerned: (app) => (conc) => {
allowHolderForConcerned: () => (conc) => {
console.log("allow holder for concerned", conc);
if (conc.position === null) {
return false;
@ -89,6 +90,7 @@ export default {
},
},
methods: {
localizeString,
moveToPosition(person_id, position_id) {
this.$store.dispatch("markPosition", { person_id, position_id });
},

View File

@ -79,7 +79,7 @@
:value="personAltNamesLabels[i]"
@input="onAltNameInput"
/>
<label :for="a.key">{{ a.labels.fr }}</label>
<label :for="a.key">{{ localizeString(a.labels) }}</label>
</div>
<!-- TODO fix placeholder if undefined
@ -117,7 +117,7 @@
{{ $t("person.civility.placeholder") }}
</option>
<option v-for="c in config.civilities" :value="c.id" :key="c.id">
{{ c.name.fr }}
{{ localizeString(c.name) }}
</option>
</select>
<label>{{ $t("person.civility.title") }}</label>
@ -219,6 +219,7 @@ import {
} from "../../_api/OnTheFly";
import PersonRenderBox from "../Entity/PersonRenderBox.vue";
import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress.vue";
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
export default {
name: "OnTheFlyPerson",
@ -427,7 +428,8 @@ export default {
}
},
methods: {
checkErrors(e) {
localizeString,
checkErrors() {
this.errors = [];
if (this.person.lastName === "") {
this.errors.push("Le nom ne doit pas être vide.");
@ -445,7 +447,7 @@ export default {
loadData() {
getPerson(this.id).then(
(person) =>
new Promise((resolve, reject) => {
new Promise((resolve) => {
this.person = person;
//console.log('get person', this.person);
resolve();

View File

@ -211,7 +211,7 @@
<h3 class="chill-beige">Public</h3>
{% if w.note is not empty %}
<blockquote class="chill-user-quote">
{{ w.note }}
{{ w.note|chill_markdown_to_html }}
</blockquote>
{% else %}
<span class="chill-no-data-statement">{{ 'No comment associated'|trans }}</span>

View File

@ -8,7 +8,7 @@ L'usager {{ oldPersonLocation|chill_entity_render_string }} a déménagé.
Son adresse était utilisée pour localiser le parcours n°{{ period.id }}, dont vous êtes
le référent.
En conséquence de ce déménage, le parcours est toujours localisé à cette adresse, mais à l'aide d'une
En conséquence de ce déménagement, le parcours est toujours localisé à cette adresse, mais à l'aide d'une
adresse temporaire.
Si vous continuez à suivre le parcours, vous pouvez le localiser à nouveau auprès de l'adresse de

View File

@ -19,14 +19,38 @@
<ul class="nav nav-pills justify-content-center">
<li class="nav-item">
<a class="nav-link {% if active == true %}active{% endif %}" aria-current="page" href="{{ chill_path_forward_return_path('chill_person_accompanying_period_user', {'active': true}) }}">{{ ['Confirmed'|trans, 'course.inactive_short'|trans, 'course.inactive_long'|trans]|join(', ') }}</a>
<a class="nav-link {% if activeTab == 'referrer' %}active{% endif %}"
aria-current="page"
href="{{ chill_path_forward_return_path('chill_person_accompanying_period_user', {'active': true, 'filter': 2}) }}">
{{ 'my_parcours_filters.referrer_parcours'|trans }}
</a>
</li>
<li class="nav-item ">
<a class="nav-link {% if active == false %}active{% endif %}" href="{{ chill_path_forward_return_path('chill_person_accompanying_period_user', {'active': false}) }}">{{ 'course.closed'|trans }}</a>
<li class="nav-item">
<a class="nav-link {% if activeTab == 'referrer_to_works' %}active{% endif %}"
aria-current="page"
href="{{ chill_path_forward_return_path('chill_person_accompanying_period_user', {'active': true, 'filter': 4}) }}">
{{ 'my_parcours_filters.referrer_acpw'|trans }}
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if activeTab == 'both' %}active{% endif %}"
aria-current="page"
href="{{ chill_path_forward_return_path('chill_person_accompanying_period_user', {'active': true, 'filter': 6}) }}">
{{ 'my_parcours_filters.referrer_parcours_and_acpw'|trans }}
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if activeTab == 'intervening' %}active{% endif %}"
aria-current="page"
href="{{ chill_path_forward_return_path('chill_person_accompanying_period_user', {'active': true, 'filter': 8}) }}">
{{ 'my_parcours_filters.parcours_intervening'|trans }}
</a>
</li>
</ul>
<p>{{ 'Number of periods'|trans }}: <span class="badge rounded-pill bg-primary">{{ pagination.totalItems }}</span></p>
{{ statusFilter|chill_render_filter_order_helper }}
<p>{{ 'Number of periods'|trans }}: <span class="badge rounded-pill bg-primary mt-3">{{ pagination.totalItems }}</span></p>
<div class="flex-table accompanyingcourse-list">
{% for period in accompanyingPeriods %}

View File

@ -30,9 +30,6 @@ final readonly class SocialActionCSVExportService
private TranslatorInterface $translator,
) {}
/**
* @param list<SocialAction> $actions
*/
public function generateCsv(array $actions): Writer
{
// CSV headers
@ -84,7 +81,8 @@ final readonly class SocialActionCSVExportService
'action_id' => $action->getId(),
'social_issue_id' => $action->getIssue()?->getId(),
'problematique_label' => null !== $action->getIssue() ? $this->socialIssueRender->renderString($action->getIssue(), []) : null,
'social_issue_ordering' => null !== $action->getIssue() ? $action->getIssue()->getOrdering() : null,
'desactivation_date' => $action->getDesactivationDate()?->format('Y-m-d'),
'social_issue_ordering' => $action->getIssue()?->getOrdering(),
'action_label' => $this->socialActionRender->renderString($action, []),
'action_ordering' => $action->getOrdering(),
'goal_label' => null !== $goal ? $this->stringHelper->localize($goal->getTitle()) : null,

View File

@ -44,6 +44,7 @@ readonly class SocialIssueCSVExportService
'Id',
'Label',
'Social issue',
'export.social_action_list.desactivation_date',
'socialIssue.isParent?',
'socialIssue.Parent id',
]
@ -66,6 +67,7 @@ readonly class SocialIssueCSVExportService
'id' => $issue->getId(),
'label' => $this->stringHelper->localize($issue->getTitle()),
'title' => $this->socialIssueRender->renderString($issue, []),
'export.social_action_list.desactivation_date' => $issue->getDesactivationDate()?->format('Y-m-d'),
'isParent' => $issue->hasChildren() ? 'X' : '',
'parent_id' => null !== $issue->getParent() ? $issue->getParent()->getId() : '',
];

View File

@ -52,6 +52,7 @@ class SocialActionCsvExporterTest extends TestCase
// Création d'une instance réelle de SocialAction sans objectifs ni résultats
$actionWithoutGoalsOrResults = new SocialAction();
$actionWithoutGoalsOrResults->setIssue($socialIssue);
$actionWithoutGoalsOrResults->setDesactivationDate(new \DateTime('2025-05-21'));
$actionWithoutGoalsOrResults->setTitle(['fr' => 'Action without goals or results']);
// Création d'une instance réelle de SocialAction avec des objectifs et des résultats
@ -61,6 +62,7 @@ class SocialActionCsvExporterTest extends TestCase
$actionWithGoalsAndResults = new SocialAction();
$actionWithGoalsAndResults->setIssue($socialIssue);
$actionWithGoalsAndResults->setDesactivationDate(new \DateTime('2025-05-21'));
$actionWithGoalsAndResults->setTitle(['fr' => 'Action with goals and results']);
$actionWithGoalsAndResults->addGoal($goalWithResult);
@ -68,6 +70,7 @@ class SocialActionCsvExporterTest extends TestCase
$goalWithoutResult = new Goal();
$actionWithGoalsNoResults = new SocialAction();
$actionWithGoalsNoResults->setIssue($socialIssue);
$actionWithGoalsNoResults->setDesactivationDate(new \DateTime('2025-05-21'));
$actionWithGoalsNoResults->setTitle(['fr' => 'Action with goals and no results']);
$actionWithGoalsNoResults->addGoal($goalWithoutResult);
@ -76,6 +79,7 @@ class SocialActionCsvExporterTest extends TestCase
$resultWithNoAction->setTitle(['fr' => 'Result without objectives']);
$actionWithResultsNoGoals = new SocialAction();
$actionWithResultsNoGoals->setIssue($socialIssue);
$actionWithResultsNoGoals->setDesactivationDate(new \DateTime('2025-05-21'));
$actionWithResultsNoGoals->setTitle(['fr' => 'Action with results and no goals']);
$actionWithResultsNoGoals->addResult($resultWithNoAction);
@ -91,11 +95,11 @@ class SocialActionCsvExporterTest extends TestCase
$this->assertStringContainsString('Action with results and no goals', $content);
self::assertEquals(<<<'CSV'
export.social_action_list.action_id,export.social_action_list.social_issue_id,export.social_action_list.problematique_label,export.social_action_list.social_issue_ordering,export.social_action_list.action_label,export.social_action_list.action_ordering,export.social_action_list.goal_label,export.social_action_list.goal_id,export.social_action_list.goal_result_label,export.social_action_list.goal_result_id,export.social_action_list.result_without_goal_label,export.social_action_list.result_without_goal_id,export.social_action_list.evaluation_title,export.social_action_list.evaluation_id,export.social_action_list.evaluation_url,export.social_action_list.evaluation_delay_month,export.social_action_list.evaluation_delay_week,export.social_action_list.evaluation_delay_day
,,"Issue Title",0,"Action with goals and results",0,"not found",,"not found",,,,,,,,,
,,"Issue Title",0,"Action without goals or results",0,,,,,,,,,,,,
,,"Issue Title",0,"Action with goals and no results",0,"not found",,,,,,,,,,,
,,"Issue Title",0,"Action with results and no goals",0,,,,,"Result without objectives",,,,,,,
export.social_action_list.action_id,export.social_action_list.social_issue_id,export.social_action_list.problematique_label,export.social_action_list.desactivation_date,export.social_action_list.social_issue_ordering,export.social_action_list.action_label,export.social_action_list.action_ordering,export.social_action_list.goal_label,export.social_action_list.goal_id,export.social_action_list.goal_result_label,export.social_action_list.goal_result_id,export.social_action_list.result_without_goal_label,export.social_action_list.result_without_goal_id,export.social_action_list.evaluation_title,export.social_action_list.evaluation_id,export.social_action_list.evaluation_url,export.social_action_list.evaluation_delay_month,export.social_action_list.evaluation_delay_week,export.social_action_list.evaluation_delay_day
,,"Issue Title",2025-05-21,0,"Action with goals and results",0,"not found",,"not found",,,,,,,,,
,,"Issue Title",2025-05-21,0,"Action without goals or results",0,,,,,,,,,,,,
,,"Issue Title",2025-05-21,0,"Action with goals and no results",0,"not found",,,,,,,,,,,
,,"Issue Title",2025-05-21,0,"Action with results and no goals",0,,,,,"Result without objectives",,,,,,,
CSV, $content);
}

View File

@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\Migrations\Person;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version20250514115009 extends AbstractMigration
{
public function getDescription(): string
{
return 'Allow more characters for maritalstatus id';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE chill_person_marital_status ALTER id TYPE VARCHAR(15)
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE chill_person_person ALTER maritalstatus_id TYPE VARCHAR(15)
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
ALTER TABLE chill_person_person ALTER maritalStatus_id TYPE VARCHAR(7)
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE chill_person_marital_status ALTER id TYPE VARCHAR(7)
SQL);
}
}

View File

@ -1498,6 +1498,14 @@ entity_display_title:
Work (n°%w%): "Action d'accompagnement (n°%w%)"
Accompanying Course (n°%w%): "Parcours d'accompagnement (n°%w%)"
my_parcours_filters:
referrer_parcours_and_acpw: Agent traitant ou réferent
referrer_acpw: Agent traitant d'une action
referrer_parcours: Réferent
parcours_intervening: Intervenant
is_open: Parcours ouverts
is_closed: Parcours clôturés
acpw_duplicate:
title: Fusionner les actions d'accompagnement
description: Cette fusion conservera la date de début la plus ancienne, la date de fin la plus récente, toutes les évaluations, documents et workflows. Les agents traitants seront additionnés ainsi que les tiers intervenants. Les commentaires seront mis l'un à la suite de l'autre.

View File

@ -624,7 +624,7 @@ final class SingleTaskController extends AbstractController
->addCheckbox('status', $statuses, $statuses, $statusTrans);
$states = $this->singleTaskStateRepository->findAllExistingStates();
$checked = array_values(array_filter($states, fn (string $state) => !in_array($state, ['closed', 'canceled', 'validated'], true)));
$checked = array_values(array_filter($states, fn (string $state) => !in_array($state, ['in_progress', 'closed', 'canceled', 'validated'], true)));
if ([] !== $states) {
$filterBuilder

View File

@ -102,7 +102,7 @@
:key="civility.id"
:value="civility"
>
{{ civility.name.fr }}
{{ localizeString(civility.name) }}
</option>
</select>
</div>
@ -257,6 +257,7 @@ import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress";
import { getThirdparty } from "../../_api/OnTheFly";
import BadgeEntity from "ChillMainAssets/vuejs/_components/BadgeEntity.vue";
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
export default {
name: "OnTheFlyThirdParty",
@ -339,6 +340,7 @@ export default {
},
},
methods: {
localizeString,
loadData() {
return getThirdparty(this.id).then(
(thirdparty) =>

View File

@ -74,7 +74,12 @@ module.exports = (async () => {
// basic encore configuration
Encore.setOutputPath("public/build/")
.setPublicPath("/build")
.enableSassLoader()
.enableSassLoader(function (options) {
// If set to true, Sass wont print warnings that are caused by dependencies (like bootstrap):
// https://sass-lang.com/documentation/js-api/interfaces/options/#quietDeps
options.sassOptions.quietDeps = true;
options.sassOptions.silenceDeprecations = ['import'];
})
.enableVueLoader(() => {}, {
version: 3,
})