diff --git a/.eslint-baseline.json b/.eslint-baseline.json index 6483e47b3..a8bf01c0d 100644 --- a/.eslint-baseline.json +++ b/.eslint-baseline.json @@ -7,14 +7,6 @@ "message": "'app' is assigned a value but never used.", "hash": "f8c2979921289906e3baabae31ba101ead91504f" }, - { - "path": "src/Bundle/ChillActivityBundle/Resources/public/vuejs/Activity/index.js", - "line": 57, - "column": 23, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'event' is defined but never used.", - "hash": "cf0cf378f71403f62a6425f384ccbbdec433d1f2" - }, { "path": "src/Bundle/ChillCalendarBundle/Resources/public/module/Invite/answer.js", "line": 7, @@ -127,46 +119,6 @@ "message": "'payload' is defined but never used.", "hash": "66c545917093ba30f1d6ca10ddaa676140e749bd" }, - { - "path": "src/Bundle/ChillCalendarBundle/Resources/public/vuejs/MyCalendarRange/App2.vue", - "line": 224, - "column": 10, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'reactive' is defined but never used.", - "hash": "96ed76a9828138fb125fc36c4b55e900bbfe87c2" - }, - { - "path": "src/Bundle/ChillCalendarBundle/Resources/public/vuejs/MyCalendarRange/App2.vue", - "line": 230, - "column": 5, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'DropArg' is defined but never used.", - "hash": "bd405399a4091d65e8391404bfb0c4611816c8e0" - }, - { - "path": "src/Bundle/ChillCalendarBundle/Resources/public/vuejs/MyCalendarRange/App2.vue", - "line": 251, - "column": 9, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'t' is assigned a value but never used.", - "hash": "bc09207a496405f7a71c178e522b89aeb1f7ebd3" - }, - { - "path": "src/Bundle/ChillCalendarBundle/Resources/public/vuejs/MyCalendarRange/App2.vue", - "line": 356, - "column": 32, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'arg' is defined but never used.", - "hash": "aeae152f0669b946a1ad681dd52b0ef03393ae79" - }, - { - "path": "src/Bundle/ChillCalendarBundle/Resources/public/vuejs/MyCalendarRange/App2.vue", - "line": 434, - "column": 11, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'changedEvent' is assigned a value but never used.", - "hash": "a7a81a6bf09d00c0364e3aa8207ffad853f0547b" - }, { "path": "src/Bundle/ChillCalendarBundle/Resources/public/vuejs/MyCalendarRange/Components/EditLocation.vue", "line": 77, @@ -399,14 +351,6 @@ "message": "'error' is defined but never used.", "hash": "e26e5e101e90d2b7ee84d6f5de8c819e52129c17" }, - { - "path": "src/Bundle/ChillDocStoreBundle/Resources/public/module/async_upload/index.ts", - "line": 29, - "column": 14, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'vm' is defined but never used.", - "hash": "8e7f5e89dd72c54459cf82156389b88988f97d63" - }, { "path": "src/Bundle/ChillDocStoreBundle/Resources/public/module/async_upload/uploader.js", "line": 39, @@ -615,14 +559,6 @@ "message": "'ref' is defined but never used.", "hash": "2a27cd6d06a26e1326654c929068e3704137e24b" }, - { - "path": "src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/HistoryButton/HistoryButtonList.vue", - "line": 57, - "column": 17, - "ruleId": "vue/valid-v-for", - "message": "Custom elements in iteration require 'v-bind:key' directives.", - "hash": "cce787939524e83dd135869e13738ef332d7156c" - }, { "path": "src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/WopiEditButton.vue", "line": 15, @@ -983,22 +919,6 @@ "message": "'_e' is defined but never used.", "hash": "1d6448401778e8c56554020fe5abd47851ed33f3" }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/module/wopi-link/index.js", - "line": 21, - "column": 55, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'e' is defined but never used.", - "hash": "eae499e4f6e9f43a9d17f9cd917cb6d3d97be25c" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/page/export/download-export.js", - "line": 3, - "column": 55, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'e' is defined but never used.", - "hash": "088fd383e7807e484aefc9825209bc7c8942bd22" - }, { "path": "src/Bundle/ChillMainBundle/Resources/public/page/homepage_widget/index.js", "line": 9, @@ -1089,115 +1009,19 @@ }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue", - "line": 247, - "column": 5, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'postAddressToPerson' is defined but never used.", - "hash": "8a41c437cf2b5554cbbe1704cd51f3102b3d5994" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue", - "line": 248, - "column": 5, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'postAddressToHousehold' is defined but never used.", - "hash": "66dec84b2ece299daf21308e5e60d497ba442b27" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue", - "line": 490, + "line": 516, "column": 21, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"context\" prop.", - "hash": "0d3f40c47974a4371072b3b9ee04b197c830162d" + "hash": "984c4203f2ac1e1bb65f9ce76ecd03b763cfaa83" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue", - "line": 491, + "line": 517, "column": 21, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"context\" prop.", - "hash": "8e877b7e588c30e182f7b572bdb9685360f9cf99" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue", - "line": 508, - "column": 47, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'reject' is defined but never used.", - "hash": "5a3e3401bc3c765d91faaf4cfde57697af1262b7" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue", - "line": 525, - "column": 47, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'reject' is defined but never used.", - "hash": "35a741d90379574b9323279f5802193d0c98a9dc" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue", - "line": 553, - "column": 47, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'reject' is defined but never used.", - "hash": "c23d1ddf6c0d10ae97948e74aee9c14b9320b86c" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue", - "line": 572, - "column": 47, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'reject' is defined but never used.", - "hash": "4322e81c6ea9d9734c680633a724d5bd4fabacb2" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue", - "line": 803, - "column": 47, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'reject' is defined but never used.", - "hash": "7928a6461b9d394c7d97f048933553936f7d8963" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue", - "line": 852, - "column": 47, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'reject' is defined but never used.", - "hash": "e5afdb8efccb5470a08dde48f755b1268fa947b5" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressMore.vue", - "line": 93, - "column": 17, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "68f5e1cf5c03f9ada59c9e0afca0b74c7f3fca4b" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressMore.vue", - "line": 101, - "column": 17, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "50d730f6109092baff2db66adc44dc1315e2bda2" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressMore.vue", - "line": 109, - "column": 17, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "573e4c041ce663f28b933d7a675c2a525aba644c" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressMore.vue", - "line": 117, - "column": 17, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "293f845eeab515b1df4649d136c2d8219ed59c4d" + "hash": "c9fb019bc21bfa77d989ed596913b99dd653c594" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressMore.vue", @@ -1224,204 +1048,180 @@ "hash": "2d5a5e680ff207ad97c7e7b7d999064b561dfd8a" }, { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", - "line": 106, + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressMore.vue", + "line": 149, "column": 17, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"entity\" prop.", - "hash": "d52356f2af31d0167c02330ec22d09fbfa6b2b9f" + "hash": "e4c1ecd7ae77d46ac3625c5bbe92a24d6a964db9" }, { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", - "line": 114, + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressMore.vue", + "line": 157, "column": 17, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"entity\" prop.", - "hash": "c8e8e06f370f93bf05867e93b5f037dfa46937b1" + "hash": "4dece2db87c6ce1c04ae06c088ddfe916c1c0c61" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressMore.vue", + "line": 165, + "column": 17, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "facc7a0f17bdf19396fae3d0de3da82e60503c0d" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressMore.vue", + "line": 173, + "column": 17, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "19de32c76518387218264d7c4dab914d143a9cca" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", - "line": 128, - "column": 13, + "line": 130, + "column": 17, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"entity\" prop.", - "hash": "9abaf71ca4b4f292b3b01e724d0a7733365e71f1" + "hash": "239ac02a02694d5b20ab30d4c7ce5838c51d1515" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", - "line": 129, - "column": 13, + "line": 138, + "column": 17, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"entity\" prop.", - "hash": "0b0743959778a9e3d93089b132608816ee4e6646" + "hash": "a54f9bc6d1edfa4df93c7dd7d409cfef3fccf99e" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", - "line": 132, + "line": 152, "column": 13, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"entity\" prop.", - "hash": "9759da7b7859b8ee8efaf74876430658ac6b6fe2" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", - "line": 133, - "column": 13, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "dba8be9a27ab74ec743b7d9e07c05d857b407dd3" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", - "line": 134, - "column": 13, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "9b1f5bce779aafc46b19d7a5d266eaa29f8f9be9" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", - "line": 139, - "column": 13, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "fe6fc4aea0994ba9da15b7c09d308842b67958cb" + "hash": "74a5f664d18f3916ea908897fcd0291cb0128f29" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", "line": 153, - "column": 55, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'reject' is defined but never used.", - "hash": "bd0e024fcad2e3f4566f15293e3c25c840f6dd3e" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", - "line": 154, - "column": 37, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "596c4b180b926b7829f987384328bf5636cd367a" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", - "line": 171, - "column": 59, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'reject' is defined but never used.", - "hash": "5b41d5f9b45da074fb7bbbbd45e0da501da72071" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", - "line": 172, - "column": 41, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "d92b92a25043244cca809bd129633b7e024e26b4" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", - "line": 190, - "column": 17, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "dd9a85ea740742d620e864796f67c5bff834486d" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", - "line": 191, - "column": 17, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "e3e59960d0d50709a57b336f66b586710b774892" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", - "line": 192, - "column": 17, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "fe11b0e54396511e7b3b08615a78d22fc27e2fad" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", - "line": 222, "column": 13, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"entity\" prop.", - "hash": "63c14c2150c33ec701bc4a0ff94efde69537d490" + "hash": "740ea5d793c7a34c9f352d8b333f3aa04cc80ee8" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", + "line": 156, + "column": 13, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "af8aca18f0226a5988ed90d44d95e2d607bfb5e6" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", + "line": 157, + "column": 13, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "7bc2453017793ae20cd6c10005f941d384b59d84" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", + "line": 158, + "column": 13, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "571b4ee5f22358dd165ec59696bb3439b7c9ff6c" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", + "line": 163, + "column": 13, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "cfcb5946c86e289fc61623a794284a5a272d02e8" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", + "line": 178, + "column": 37, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "0ec402e43cb08bf129e0737c0d2c4f6d0c7af8bd" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", + "line": 196, + "column": 41, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "ec178d33e067aac892e015002afb6f3a2ff98762" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", + "line": 214, + "column": 17, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "c0f4e5454e672b6064eb9cf6c235c6810f7bfa80" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", + "line": 215, + "column": 17, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "e3dd840d2474f9865a45822872bf9ecfb15961d7" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", + "line": 216, + "column": 17, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "a32a60382b145cc7a4a7ebe01ec435b8e3103320" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressSelection.vue", + "line": 246, + "column": 13, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "082447e5c731012f3acc282943502775dfd24797" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", - "line": 96, + "line": 118, "column": 20, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"entity\" prop.", - "hash": "d2a9fdaeef0e2810f480022d4c6f99e4f76a818e" + "hash": "d4fba4fe09af3c0937c0dd164928c8930c1591b5" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", - "line": 96, + "line": 118, "column": 20, "ruleId": "vue/no-side-effects-in-computed-properties", "message": "Unexpected side effect in \"cities\" computed property.", - "hash": "dd92a60a9b1ebefeb9a90941d45326fbfa483733" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", - "line": 102, - "column": 17, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "04be01ab638ce01f568fb0216929e65e1175ca23" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", - "line": 110, - "column": 17, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "8619c8e0b63e87d09268832f90e4fba06b87e41f" + "hash": "1113a114d5aaf9f32f442916d25458541c5af35c" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", "line": 124, - "column": 13, + "column": 17, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"entity\" prop.", - "hash": "281f918da00635079501418b1e6b2c05b62eb4a7" + "hash": "fa56a7c93583f0a9d0c2ecac10228c4f4fc1bc3a" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", - "line": 125, - "column": 13, + "line": 132, + "column": 17, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"entity\" prop.", - "hash": "c131b09fa67ab1d069f1d04a54582d6b0f206153" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", - "line": 126, - "column": 13, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "3d3a2a4add64c291b8f5f1cddd90a173cd6a819d" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", - "line": 131, - "column": 21, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "ed48f4988914d7897018a2e06830a97e6740b3e8" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", - "line": 145, - "column": 13, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "744f3a7610d4d6015e50e25149bceffd6c6e2763" + "hash": "9fe87937ea67d1dae95fb3d44d4be0da2eba0905" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", @@ -1441,115 +1241,139 @@ }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", - "line": 149, - "column": 17, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "1e7b1ad55866f708baaca72dfa4ff26d6f8e5d21" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", - "line": 152, + "line": 148, "column": 13, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"entity\" prop.", - "hash": "84779331536ffceec8d4a8c5ca4307310b882549" + "hash": "ab4f478fbfbc954b8dff75176dcd432f9ff28cfc" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", - "line": 161, + "line": 153, + "column": 21, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "1d907d149f9ddb62e32140a90efe9a74b3e71fef" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", + "line": 167, "column": 13, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"entity\" prop.", - "hash": "0789999841be671a4d8ab080d6fdb679f843eb52" + "hash": "8aa37d2d4f011773e68838a2c88017875de563b5" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", - "line": 170, - "column": 51, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'reject' is defined but never used.", - "hash": "bbb17afa114f016e2058d90aa32d2a625804f0d1" + "line": 168, + "column": 13, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "a4827a357e52a51fa9262319114d81a130296acf" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", + "line": 169, + "column": 13, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "a4c9715664202949e3242b8d4aa4098288b46dc4" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", "line": 171, + "column": 17, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "f3e9e21e433e90ec7b615b8940d43c4177372b66" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", + "line": 174, + "column": 13, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "770b7a24cc24b380e88db47d62422c8e1ece2571" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", + "line": 183, + "column": 13, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "2aef3c519a9ec6abcfe7573989d3de19d5c4c752" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", + "line": 193, "column": 33, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"entity\" prop.", - "hash": "5fbe407ceceb37bff2ac800ceddd7942540132f1" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", - "line": 190, - "column": 55, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'reject' is defined but never used.", - "hash": "e2af91def877befbabef8e93deba4c58a3ee2ded" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", - "line": 191, - "column": 37, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "ee8544ee45681a650ed7d4918ae979685cdd8f0f" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", - "line": 210, - "column": 17, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "5d9d2217c8c7e6571bc9f72a98ea5b370edb4968" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", - "line": 211, - "column": 17, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "6e04619b373c23c91f6c36c2aad314ac16cdb697" - }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", - "line": 212, - "column": 17, - "ruleId": "vue/no-mutating-props", - "message": "Unexpected mutation of \"entity\" prop.", - "hash": "39df045639a62f64ccdb03a80e286bc3ad772587" + "hash": "5d1f97e4d7d9f47399d312e8b9f95ef9e3843b8c" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", "line": 213, - "column": 17, + "column": 37, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"entity\" prop.", - "hash": "c399a43fa797a8ce61c9d96a644a39cc84a387b7" + "hash": "c1df874f790ef0c036bf58ae8a8db1ee173685d4" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", - "line": 245, + "line": 232, + "column": 17, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "476e6588a28ac9382e8b9d2e63a8babecd23bad8" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", + "line": 233, + "column": 17, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "6a0c82ba72d6d87217bf33a6ad8e40a4b81bc802" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", + "line": 234, + "column": 17, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "741d5af6c7d90041c0dc1c1df2e8699b80fca69a" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", + "line": 235, + "column": 17, + "ruleId": "vue/no-mutating-props", + "message": "Unexpected mutation of \"entity\" prop.", + "hash": "c3ffd141f58d532663875cc5c7d338ed00db2a6d" + }, + { + "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CitySelection.vue", + "line": 267, "column": 13, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"entity\" prop.", - "hash": "04337a07944caaa4819cfebcf29e1a7cbfdf248b" + "hash": "2700f258396516a2fe971618fafbcdf72cdda3ab" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CountrySelection.vue", - "line": 76, + "line": 94, "column": 13, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"entity\" prop.", - "hash": "373a2e31f110d138c66d77f1faf5dc61545c55af" + "hash": "4be1b0592efa775092a91a1d744e16ce98bd216e" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/CountrySelection.vue", - "line": 81, + "line": 99, "column": 13, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"entity\" prop.", - "hash": "421eb6a63224b4b1d81b216677a710c5c99ddee3" + "hash": "19b54b6d76c30249d520a296f826eda9d6eb0668" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/DatePane.vue", @@ -1569,19 +1393,19 @@ }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/EditPane.vue", - "line": 155, + "line": 169, "column": 17, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"entity\" prop.", - "hash": "b3a822914fcb5e2fcf28efc331a45b9205002eeb" + "hash": "dcb7b34098062760ddbb849655a5bb3ca65c36d3" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/EditPane.vue", - "line": 164, + "line": 178, "column": 17, "ruleId": "vue/no-mutating-props", "message": "Unexpected mutation of \"entity\" prop.", - "hash": "72c7d850f6cdeaf65b373a33234222f9766ee30b" + "hash": "86b3ecf201025cac36878c5e4bf8850fb9d58cb5" }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/index.js", @@ -1631,14 +1455,6 @@ "message": "'app' is assigned a value but never used.", "hash": "9e6125f4fc387dc362c69cc6e3ce360eb2851f1b" }, - { - "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/PickEntity/PickEntity.vue", - "line": 60, - "column": 22, - "ruleId": "vue/require-valid-default-prop", - "message": "Type of the default value for 'suggested' prop must be a function.", - "hash": "d30212820bc2e97fa02d75dbc3a014558693f169" - }, { "path": "src/Bundle/ChillMainBundle/Resources/public/vuejs/_components/AddressDetails/Parts/AddressDetailsMap.vue", "line": 24, @@ -1727,14 +1543,6 @@ "message": "'tags' is assigned a value but never used.", "hash": "ae9bb2e0651c118ed9efd227e88b86cc83f5d80d" }, - { - "path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/components/StickyNav.vue", - "line": 116, - "column": 18, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'event' is defined but never used.", - "hash": "201f182769c6dfb87148b841e7d9b592be429669" - }, { "path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourse/index.js", "line": 19, @@ -1767,14 +1575,6 @@ "message": "'app' is assigned a value but never used.", "hash": "aaaaa63e7a60443b8cbf8191feb9142852ebdf1c" }, - { - "path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/components/FormEvaluation.vue", - "line": 79, - "column": 13, - "ruleId": "vue/require-v-for-key", - "message": "Elements in iteration expect to have 'v-bind:key' directives.", - "hash": "422f53925922e59655d0f71624c19af75d41628c" - }, { "path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/index.js", "line": 12, @@ -1815,22 +1615,6 @@ "message": "'evalFQDN' is assigned a value but never used.", "hash": "7fc32caafa23addddf44f3acbc5045b4523a0271" }, - { - "path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/store.js", - "line": 611, - "column": 9, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'errors' is assigned a value but never used.", - "hash": "c41cf979fc1626c38328dbf1028800c3395496bd" - }, - { - "path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/ExportFormActionGoalResult/App.vue", - "line": 282, - "column": 7, - "ruleId": "@typescript-eslint/no-unused-expressions", - "message": "Expected an assignment or function call and instead saw an expression.", - "hash": "de3a6e2bb10a80a2bacba665be74266c7efc7d64" - }, { "path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/ExportFormActionGoalResult/index.js", "line": 16, @@ -1847,38 +1631,6 @@ "message": "'app' is assigned a value but never used.", "hash": "2f161e663689e3e4dfe2c53b0d64c91a4d2b1a60" }, - { - "path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/VisGraph/App.vue", - "line": 263, - "column": 19, - "ruleId": "vue/return-in-computed-property", - "message": "Expected to return a value in \"refreshNetwork\" computed property.", - "hash": "2c1b08a49098c83b09058cedc0a962126e91e544" - }, - { - "path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/VisGraph/App.vue", - "line": 270, - "column": 7, - "ruleId": "vue/no-side-effects-in-computed-properties", - "message": "Unexpected side effect in \"legendLayers\" computed property.", - "hash": "760948d2187c853f17ac9a1bd7107e883092d4f4" - }, - { - "path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/VisGraph/App.vue", - "line": 281, - "column": 5, - "ruleId": "vue/no-dupe-keys", - "message": "Duplicate key 'checkedLayers'. May cause name collision in script or template tag.", - "hash": "447edb461e15e3ff5c60c8ecba88131e442539aa" - }, - { - "path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/VisGraph/App.vue", - "line": 353, - "column": 7, - "ruleId": "@typescript-eslint/no-unused-expressions", - "message": "Expected an assignment or function call and instead saw an expression.", - "hash": "9cf656cbf1eb3d7cc0082e63adcd320b6093d14f" - }, { "path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/VisGraph/index.js", "line": 20, @@ -1887,22 +1639,6 @@ "message": "'app' is assigned a value but never used.", "hash": "9e94e6412b8a44e47bfe8e66218cad09cff5bed4" }, - { - "path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/AccompanyingPeriod/SetReferrer.vue", - "line": 42, - "column": 16, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'response' is defined but never used.", - "hash": "62de07b13c662e32332bb062038acee23978ea70" - }, - { - "path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/AddPersons.vue", - "line": 356, - "column": 28, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'_response' is defined but never used.", - "hash": "097e7788a2b5dea500b80b8a3cf968e57063a66a" - }, { "path": "src/Bundle/ChillPersonBundle/Resources/public/vuejs/_components/AddPersons/TypeUserGroup.vue", "line": 6, @@ -1918,45 +1654,5 @@ "ruleId": "@typescript-eslint/no-unused-vars", "message": "'UserRenderBoxBadge' is defined but never used.", "hash": "99eba0d8633b2c9497417f4f61ec4194dbb2a96b" - }, - { - "path": "src/Bundle/ChillWopiBundle/src/Resources/public/module/pending/index.ts", - "line": 4, - "column": 3, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'StoredObjectStatus' is defined but never used.", - "hash": "63f8c4572293916850d6165647774b27d4b732c6" - }, - { - "path": "src/Bundle/ChillWopiBundle/src/Resources/public/module/pending/index.ts", - "line": 5, - "column": 3, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'StoredObjectStatusChange' is defined but never used.", - "hash": "a87c178e3eb5999bf0f46b3fa1c6da77e1be08b9" - }, - { - "path": "src/Bundle/ChillWopiBundle/src/Resources/public/module/pending/index.ts", - "line": 30, - "column": 61, - "ruleId": "@typescript-eslint/no-unused-vars", - "message": "'e' is defined but never used.", - "hash": "02953121583f4f73742a19adab099ab63df9076e" - }, - { - "path": "src/Bundle/ChillWopiBundle/src/Resources/public/module/pending/index.ts", - "line": 31, - "column": 32, - "ruleId": "@typescript-eslint/no-explicit-any", - "message": "Unexpected any. Specify a different type.", - "hash": "af48e21a1651b6017ede882dab249c00a818a44d" - }, - { - "path": "src/Bundle/ChillWopiBundle/src/Resources/public/module/pending/index.ts", - "line": 37, - "column": 16, - "ruleId": "@typescript-eslint/no-explicit-any", - "message": "Unexpected any. Specify a different type.", - "hash": "7513ea552a0a649ce4ab93b6cf9d40bfef4f68d9" } ] \ No newline at end of file diff --git a/src/Bundle/ChillEventBundle/Controller/Admin/EventBudgetKindController.php b/src/Bundle/ChillEventBundle/Controller/Admin/EventBudgetKindController.php new file mode 100644 index 000000000..063ca4c0d --- /dev/null +++ b/src/Bundle/ChillEventBundle/Controller/Admin/EventBudgetKindController.php @@ -0,0 +1,28 @@ +addOrderBy('e.type', 'ASC'); + + return parent::orderQuery($action, $query, $request, $paginator); + } +} diff --git a/src/Bundle/ChillEventBundle/Controller/EventController.php b/src/Bundle/ChillEventBundle/Controller/EventController.php index b4f099769..7bcc8dbe6 100644 --- a/src/Bundle/ChillEventBundle/Controller/EventController.php +++ b/src/Bundle/ChillEventBundle/Controller/EventController.php @@ -23,11 +23,11 @@ use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface; use Chill\PersonBundle\Entity\Person; use Chill\PersonBundle\Form\Type\PickPersonDynamicType; use Chill\PersonBundle\Privacy\PrivacyEvent; +use Doctrine\Persistence\ManagerRegistry; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Csv; use PhpOffice\PhpSpreadsheet\Writer\Ods; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -41,6 +41,8 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\Security\Core\Security; +use Symfony\Component\Serializer\Exception\ExceptionInterface; +use Symfony\Component\Serializer\Normalizer\NormalizerInterface; use Symfony\Contracts\Translation\TranslatorInterface; /** @@ -58,7 +60,8 @@ final class EventController extends AbstractController private readonly TranslatorInterface $translator, private readonly PaginatorFactory $paginator, private readonly Security $security, - private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry, + private readonly ManagerRegistry $managerRegistry, + private readonly NormalizerInterface $normalizer, ) {} #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/event/event/{event_id}/delete', name: 'chill_event__event_delete', requirements: ['event_id' => '\d+'], methods: ['GET', 'POST', 'DELETE'])] @@ -75,6 +78,7 @@ final class EventController extends AbstractController /** @var array $participations */ $participations = $event->getParticipations(); + $budgetElements = $event->getBudgetElements(); $form = $this->createDeleteForm($event_id); @@ -86,6 +90,10 @@ final class EventController extends AbstractController $em->remove($participation); } + foreach ($budgetElements as $e) { + $em->remove($e); + } + $em->remove($event); $em->flush(); @@ -103,7 +111,7 @@ final class EventController extends AbstractController } return $this->render('@ChillEvent/Event/confirm_delete.html.twig', [ - 'event_id' => $event->getId(), + 'id' => $event->getId(), 'delete_form' => $form->createView(), ]); } @@ -169,6 +177,8 @@ final class EventController extends AbstractController /** * Displays a form to create a new Event entity. + * + * @throws ExceptionInterface */ #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/event/event/new', name: 'chill_event__event_new', methods: ['GET', 'POST'])] public function newAction(?Center $center, Request $request): Response @@ -199,26 +209,23 @@ final class EventController extends AbstractController $this->addFlash('success', $this->translator ->trans('The event was created')); - return $this->redirectToRoute('chill_event__event_show', ['event_id' => $entity->getId()]); + return $this->redirectToRoute('chill_event__event_show', ['id' => $entity->getId()]); } + $entity_array = $this->normalizer->normalize($entity, 'json', ['groups' => 'read']); + return $this->render('@ChillEvent/Event/new.html.twig', [ 'entity' => $entity, 'form' => $form->createView(), + 'entity_json' => $entity_array, ]); } - /** - * First step of new Event form. - */ #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/event/event/new/pick-center', name: 'chill_event__event_new_pickcenter', options: [null])] public function newPickCenterAction(): Response { $role = 'CHILL_EVENT_CREATE'; - /** - * @var Center $centers - */ $centers = $this->authorizationHelper->getReachableCenters($this->getUser(), $role); if (1 === \count($centers)) { @@ -238,7 +245,7 @@ final class EventController extends AbstractController ->add('center_id', EntityType::class, [ 'class' => Center::class, 'choices' => $centers, - 'placeholder' => '', + 'placeholder' => $this->translator->trans('Pick a center'), 'label' => 'To which centre should the event be associated ?', ]) ->add('submit', SubmitType::class, [ @@ -251,16 +258,7 @@ final class EventController extends AbstractController ]); } - /** - * Finds and displays a Event entity. - * - * @ParamConverter("event", options={"id": "event_id"}) - * - * @return Response - * - * @throws \PhpOffice\PhpSpreadsheet\Exception - */ - #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/event/event/{event_id}/show', name: 'chill_event__event_show')] + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/event/event/{id}/show', name: 'chill_event__event_show')] public function showAction(Event $event, Request $request) { if (!$event) { @@ -317,7 +315,7 @@ final class EventController extends AbstractController $this->addFlash('success', $this->translator->trans('The event was updated')); - return $this->redirectToRoute('chill_event__event_show', ['event_id' => $event_id]); + return $this->redirectToRoute('chill_event__event_show', ['id' => $event_id]); } return $this->render('@ChillEvent/Event/edit.html.twig', [ diff --git a/src/Bundle/ChillEventBundle/Controller/EventListController.php b/src/Bundle/ChillEventBundle/Controller/EventListController.php index 692611adc..e88c28b35 100644 --- a/src/Bundle/ChillEventBundle/Controller/EventListController.php +++ b/src/Bundle/ChillEventBundle/Controller/EventListController.php @@ -15,11 +15,15 @@ use Chill\EventBundle\Entity\Event; use Chill\EventBundle\Entity\EventType; use Chill\EventBundle\Repository\EventACLAwareRepositoryInterface; use Chill\EventBundle\Repository\EventTypeRepository; +use Chill\EventBundle\Security\EventVoter; +use Chill\MainBundle\Entity\Center; use Chill\MainBundle\Pagination\PaginatorFactoryInterface; +use Chill\MainBundle\Security\Authorization\AuthorizationHelper; use Chill\MainBundle\Templating\Listing\FilterOrderHelper; use Chill\MainBundle\Templating\Listing\FilterOrderHelperFactory; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\PersonBundle\Form\Type\PickPersonDynamicType; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Form\Extension\Core\Type\FormType; use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\Form\FormFactoryInterface; @@ -29,17 +33,18 @@ use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Twig\Environment; -final readonly class EventListController +final class EventListController extends AbstractController { public function __construct( - private Environment $environment, - private EventACLAwareRepositoryInterface $eventACLAwareRepository, - private EventTypeRepository $eventTypeRepository, - private FilterOrderHelperFactory $filterOrderHelperFactory, - private FormFactoryInterface $formFactory, - private PaginatorFactoryInterface $paginatorFactory, - private TranslatableStringHelperInterface $translatableStringHelper, - private UrlGeneratorInterface $urlGenerator, + private readonly Environment $environment, + private readonly EventACLAwareRepositoryInterface $eventACLAwareRepository, + private readonly EventTypeRepository $eventTypeRepository, + private readonly FilterOrderHelperFactory $filterOrderHelperFactory, + private readonly FormFactoryInterface $formFactory, + private readonly PaginatorFactoryInterface $paginatorFactory, + private readonly TranslatableStringHelperInterface $translatableStringHelper, + private readonly UrlGeneratorInterface $urlGenerator, + private readonly AuthorizationHelper $authorizationHelper, ) {} #[Route(path: '{_locale}/event/event/list', name: 'chill_event_event_list')] @@ -50,6 +55,8 @@ final readonly class EventListController 'q' => (string) $filter->getQueryString(), 'dates' => $filter->getDateRangeData('dates'), 'event_types' => $filter->getEntityChoiceData('event_types'), + 'responsables' => $filter->getUserPickerData('responsables'), + 'centers' => $filter->getEntityChoiceData('centers'), ]; $total = $this->eventACLAwareRepository->countAllViewable($filterData); $pagination = $this->paginatorFactory->create($total); @@ -73,6 +80,7 @@ final readonly class EventListController private function buildFilterOrder(): FilterOrderHelper { $types = $this->eventTypeRepository->findAllActive(); + $centers = $this->authorizationHelper->getReachableCenters($this->getUser(), EventVoter::SEE); $builder = $this->filterOrderHelperFactory->create(__METHOD__); $builder @@ -80,6 +88,16 @@ final readonly class EventListController ->addSearchBox(['name']) ->addEntityChoice('event_types', 'event.filter.event_types', EventType::class, $types, [ 'choice_label' => fn (EventType $e) => $this->translatableStringHelper->localize($e->getName()), + 'expanded' => false, + 'required' => false, + 'attr' => ['class' => 'select2'], + ]) + ->addUserPicker('responsables', 'event.filter.pick_responsable', ['multiple' => true, 'required' => false]) + ->addEntityChoice('centers', 'event.filter.center', Center::class, $centers, [ + 'choice_label' => fn (Center $c) => $c->getName(), + 'expanded' => false, + 'required' => false, + 'attr' => ['class' => 'select2'], ]); return $builder->build(); diff --git a/src/Bundle/ChillEventBundle/Controller/EventThemeController.php b/src/Bundle/ChillEventBundle/Controller/EventThemeController.php new file mode 100644 index 000000000..027b99241 --- /dev/null +++ b/src/Bundle/ChillEventBundle/Controller/EventThemeController.php @@ -0,0 +1,44 @@ + 'create']); + } + + if ('edit' === $action) { + return parent::createFormFor($action, $entity, $formClass, ['step' => 'edit']); + } + + throw new \LogicException('action is not supported: '.$action); + } + + /** + * @param QueryBuilder|mixed $query + */ + protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator): QueryBuilder + { + /* @var QueryBuilder $query */ + return $query->orderBy('e.ordering', 'ASC') + ->addOrderBy('e.id', 'ASC'); + } +} diff --git a/src/Bundle/ChillEventBundle/Controller/ParticipationController.php b/src/Bundle/ChillEventBundle/Controller/ParticipationController.php index 2449528de..7fac83bf5 100644 --- a/src/Bundle/ChillEventBundle/Controller/ParticipationController.php +++ b/src/Bundle/ChillEventBundle/Controller/ParticipationController.php @@ -228,7 +228,7 @@ final class ParticipationController extends AbstractController } return $this->redirectToRoute('chill_event__event_show', [ - 'event_id' => $participation->getEvent()->getId(), + 'id' => $participation->getEvent()->getId(), ]); } @@ -242,7 +242,7 @@ final class ParticipationController extends AbstractController /** * @param int $participation_id */ - #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/event/participation/{participation_id}/delete', name: 'chill_event_participation_delete', requirements: ['participation_id' => '\d+'], methods: ['GET', 'DELETE'])] + #[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/event/participation/{participation_id}/delete', name: 'chill_event_participation_delete', requirements: ['participation_id' => '\d+'])] public function deleteAction($participation_id, Request $request): Response|\Symfony\Component\HttpFoundation\RedirectResponse { $em = $this->managerRegistry->getManager(); @@ -273,7 +273,7 @@ final class ParticipationController extends AbstractController ); return $this->redirectToRoute('chill_event__event_show', [ - 'event_id' => $event->getId(), + 'id' => $event->getId(), ]); } } @@ -442,7 +442,7 @@ final class ParticipationController extends AbstractController )); return $this->redirectToRoute('chill_event__event_show', [ - 'event_id' => $participation->getEvent()->getId(), + 'id' => $participation->getEvent()->getId(), ]); } diff --git a/src/Bundle/ChillEventBundle/DependencyInjection/ChillEventExtension.php b/src/Bundle/ChillEventBundle/DependencyInjection/ChillEventExtension.php index 0b30ca6c5..cb59bb390 100644 --- a/src/Bundle/ChillEventBundle/DependencyInjection/ChillEventExtension.php +++ b/src/Bundle/ChillEventBundle/DependencyInjection/ChillEventExtension.php @@ -11,6 +11,12 @@ declare(strict_types=1); namespace Chill\EventBundle\DependencyInjection; +use Chill\EventBundle\Controller\Admin\EventBudgetKindController; +use Chill\EventBundle\Controller\EventThemeController; +use Chill\EventBundle\Entity\EventBudgetKind; +use Chill\EventBundle\Entity\EventTheme; +use Chill\EventBundle\Form\EventBudgetKindType; +use Chill\EventBundle\Form\EventThemeType; use Chill\EventBundle\Security\EventVoter; use Chill\EventBundle\Security\ParticipationVoter; use Symfony\Component\Config\FileLocator; @@ -26,7 +32,10 @@ use Symfony\Component\HttpKernel\DependencyInjection\Extension; */ class ChillEventExtension extends Extension implements PrependExtensionInterface { - public function load(array $configs, ContainerBuilder $container) + /** + * @throws \Exception + */ + public function load(array $configs, ContainerBuilder $container): void { $configuration = new Configuration(); $config = $this->processConfiguration($configuration, $configs); @@ -45,16 +54,17 @@ class ChillEventExtension extends Extension implements PrependExtensionInterface /** (non-PHPdoc). * @see \Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface::prepend() */ - public function prepend(ContainerBuilder $container) + public function prepend(ContainerBuilder $container): void { $this->prependAuthorization($container); + $this->prependCruds($container); $this->prependRoute($container); } /** * add authorization hierarchy. */ - protected function prependAuthorization(ContainerBuilder $container) + protected function prependAuthorization(ContainerBuilder $container): void { $container->prependExtensionConfig('security', [ 'role_hierarchy' => [ @@ -70,7 +80,7 @@ class ChillEventExtension extends Extension implements PrependExtensionInterface /** * add route to route loader for chill. */ - protected function prependRoute(ContainerBuilder $container) + protected function prependRoute(ContainerBuilder $container): void { // add routes for custom bundle $container->prependExtensionConfig('chill_main', [ @@ -81,4 +91,54 @@ class ChillEventExtension extends Extension implements PrependExtensionInterface ], ]); } + + protected function prependCruds(ContainerBuilder $container): void + { + $container->prependExtensionConfig('chill_main', [ + 'cruds' => [ + [ + 'class' => EventTheme::class, + 'name' => 'event_theme', + 'base_path' => '/admin/event/theme', + 'form_class' => EventThemeType::class, + 'controller' => EventThemeController::class, + 'actions' => [ + 'index' => [ + 'template' => '@ChillEvent/Admin/EventTheme/index.html.twig', + 'role' => 'ROLE_ADMIN', + ], + 'new' => [ + 'role' => 'ROLE_ADMIN', + 'template' => '@ChillEvent/Admin/EventTheme/new.html.twig', + ], + 'edit' => [ + 'role' => 'ROLE_ADMIN', + 'template' => '@ChillEvent/Admin/EventTheme/edit.html.twig', + ], + ], + ], + [ + 'class' => EventBudgetKind::class, + 'name' => 'event_budget_kind', + 'base_path' => '/admin/event/budget', + 'form_class' => EventBudgetKindType::class, + 'controller' => EventBudgetKindController::class, + 'actions' => [ + 'index' => [ + 'template' => '@ChillEvent/Admin/BudgetKind/index.html.twig', + 'role' => 'ROLE_ADMIN', + ], + 'new' => [ + 'role' => 'ROLE_ADMIN', + 'template' => '@ChillEvent/Admin/BudgetKind/new.html.twig', + ], + 'edit' => [ + 'role' => 'ROLE_ADMIN', + 'template' => '@ChillEvent/Admin/BudgetKind/edit.html.twig', + ], + ], + ], + ], + ]); + } } diff --git a/src/Bundle/ChillEventBundle/Entity/BudgetTypeEnum.php b/src/Bundle/ChillEventBundle/Entity/BudgetTypeEnum.php new file mode 100644 index 000000000..a0a02455c --- /dev/null +++ b/src/Bundle/ChillEventBundle/Entity/BudgetTypeEnum.php @@ -0,0 +1,18 @@ + + */ + #[ORM\ManyToMany(targetEntity: User::class)] + #[Serializer\Groups(['read'])] + #[ORM\JoinTable('chill_event_animatorsintern')] + private Collection $animatorsIntern; + + /** + * @var Collection + */ + #[ORM\ManyToMany(targetEntity: ThirdParty::class)] + #[Serializer\Groups(['read'])] + #[ORM\JoinTable('chill_event_animatorsextern')] + private Collection $animatorsExtern; + #[Assert\NotBlank] - #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 150)] + #[Serializer\Groups(['read'])] + #[ORM\Column(type: Types::STRING, length: 150)] private ?string $name = null; /** * @var Collection */ #[ORM\OneToMany(mappedBy: 'event', targetEntity: Participation::class)] + #[Serializer\Groups(['read'])] private Collection $participations; #[Assert\NotNull] + #[Serializer\Groups(['read'])] #[ORM\ManyToOne(targetEntity: EventType::class)] private ?EventType $type = null; + /** + * @var Collection + */ + #[ORM\ManyToMany(targetEntity: EventTheme::class)] + #[Serializer\Groups(['read'])] + #[ORM\JoinTable('chill_event_eventtheme')] + private Collection $themes; + #[ORM\Embedded(class: CommentEmbeddable::class, columnPrefix: 'comment_')] private CommentEmbeddable $comment; #[ORM\ManyToOne(targetEntity: Location::class)] + #[Serializer\Groups(['read'])] #[ORM\JoinColumn(nullable: true)] private ?Location $location = null; @@ -85,7 +116,17 @@ class Event implements HasCenterInterface, HasScopeInterface, TrackCreationInter #[ORM\JoinTable('chill_event_event_documents')] private Collection $documents; - #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DECIMAL, precision: 10, scale: 4, nullable: true, options: ['default' => '0.0'])] + /** + * @var Collection + */ + #[ORM\OneToMany(mappedBy: 'event', targetEntity: EventBudgetElement::class, cascade: ['persist'])] + #[Serializer\Groups(['read'])] + private Collection $budgetElements; + + /** + * @deprecated use budgetElements instead + */ + #[ORM\Column(type: Types::DECIMAL, precision: 10, scale: 4, nullable: true, options: ['default' => '0.0'])] private string $organizationCost = '0.0'; /** @@ -96,6 +137,20 @@ class Event implements HasCenterInterface, HasScopeInterface, TrackCreationInter $this->participations = new ArrayCollection(); $this->documents = new ArrayCollection(); $this->comment = new CommentEmbeddable(); + $this->themes = new ArrayCollection(); + $this->budgetElements = new ArrayCollection(); + $this->animatorsIntern = new ArrayCollection(); + $this->animatorsExtern = new ArrayCollection(); + } + + public function addBudgetElement(EventBudgetElement $budgetElement) + { + if (!$this->budgetElements->contains($budgetElement)) { + $this->budgetElements[] = $budgetElement; + $budgetElement->setEvent($this); + } + + return $this; } /** @@ -126,38 +181,79 @@ class Event implements HasCenterInterface, HasScopeInterface, TrackCreationInter return $this; } - /** - * @return Center - */ - public function getCenter() + public function getThemes(): Collection + { + return $this->themes; + } + + public function addTheme(EventTheme $theme): self + { + $this->themes->add($theme); + + return $this; + } + + public function removeTheme(EventTheme $theme): void + { + $this->themes->removeElement($theme); + } + + public function getAnimatorsIntern(): Collection + { + return $this->animatorsIntern; + } + + public function getAnimatorsExtern(): Collection + { + return $this->animatorsExtern; + } + + public function addAnimatorsIntern(User $ai): self + { + $this->animatorsIntern->add($ai); + + return $this; + } + + public function removeAnimatorsIntern(User $ai): void + { + $this->animatorsIntern->removeElement($ai); + } + + public function addAnimatorsExtern(ThirdParty $ae): self + { + $this->animatorsExtern->add($ae); + + return $this; + } + + public function removeAnimatorsExtern(ThirdParty $ae): void + { + $this->animatorsExtern->removeElement($ae); + } + + public function getCenter(): Center { return $this->center; } - /** - * @return Scope - */ - public function getCircle() + public function getCircle(): ?Scope { return $this->circle; } /** * Get date. - * - * @return \DateTime */ - public function getDate() + public function getDate(): ?\DateTime { return $this->date; } /** * Get id. - * - * @return int */ - public function getId() + public function getId(): ?int { return $this->id; } @@ -169,14 +265,20 @@ class Event implements HasCenterInterface, HasScopeInterface, TrackCreationInter /** * Get label. - * - * @return string */ - public function getName() + public function getName(): ?string { return $this->name; } + /** + * @return Collection + */ + public function getBudgetElements(): Collection + { + return $this->budgetElements; + } + /** * @return Collection */ @@ -199,26 +301,26 @@ class Event implements HasCenterInterface, HasScopeInterface, TrackCreationInter /** * @deprecated - * - * @return Scope */ - public function getScope() + public function getScope(): Scope { return $this->getCircle(); } - /** - * @return EventType - */ - public function getType() + public function getType(): ?EventType { return $this->type; } + public function removeBudgetElement(EventBudgetElement $budgetElement): void + { + $this->budgetElements->removeElement($budgetElement); + } + /** * Remove participation. */ - public function removeParticipation(Participation $participation) + public function removeParticipation(Participation $participation): void { $this->participations->removeElement($participation); } @@ -314,11 +416,17 @@ class Event implements HasCenterInterface, HasScopeInterface, TrackCreationInter $this->documents = $documents; } + /** + * @deprecated + */ public function getOrganizationCost(): string { return $this->organizationCost; } + /** + * @deprecated + */ public function setOrganizationCost(string $organizationCost): void { $this->organizationCost = $organizationCost; diff --git a/src/Bundle/ChillEventBundle/Entity/EventBudgetElement.php b/src/Bundle/ChillEventBundle/Entity/EventBudgetElement.php new file mode 100644 index 000000000..ae2fcb1be --- /dev/null +++ b/src/Bundle/ChillEventBundle/Entity/EventBudgetElement.php @@ -0,0 +1,103 @@ +id; + } + + public function setId(?int $id): void + { + $this->id = $id; + } + + public function getAmount(): float + { + return (float) $this->amount; + } + + public function getComment(): ?CommentEmbeddable + { + return $this->comment; + } + + public function getEvent(): Event + { + return $this->event; + } + + public function getKind(): EventBudgetKind + { + return $this->kind; + } + + public function setAmount(string $amount): self + { + $this->amount = $amount; + + return $this; + } + + public function setComment(?CommentEmbeddable $comment = null): self + { + $this->comment = $comment; + + return $this; + } + + public function setEvent(Event $event): self + { + $this->event = $event; + + return $this; + } + + public function setKind(EventBudgetKind $kind): self + { + $this->kind = $kind; + + return $this; + } +} diff --git a/src/Bundle/ChillEventBundle/Entity/EventBudgetKind.php b/src/Bundle/ChillEventBundle/Entity/EventBudgetKind.php new file mode 100644 index 000000000..b668ff5cc --- /dev/null +++ b/src/Bundle/ChillEventBundle/Entity/EventBudgetKind.php @@ -0,0 +1,78 @@ + true])] + private bool $isActive = true; + + #[ORM\Column(enumType: BudgetTypeEnum::class)] + private BudgetTypeEnum $type; + + #[ORM\Column(type: Types::JSON, length: 255, options: ['default' => '{}', 'jsonb' => true])] + private array $name = []; + + public function getId(): ?int + { + return $this->id; + } + + public function getIsActive(): bool + { + return $this->isActive; + } + + public function getType(): BudgetTypeEnum + { + return $this->type; + } + + public function getName(): ?array + { + return $this->name; + } + + public function setIsActive(bool $isActive): self + { + $this->isActive = $isActive; + + return $this; + } + + public function setType(BudgetTypeEnum $type): self + { + $this->type = $type; + + return $this; + } + + public function setName(array $name): self + { + $this->name = $name; + + return $this; + } +} diff --git a/src/Bundle/ChillEventBundle/Entity/EventTheme.php b/src/Bundle/ChillEventBundle/Entity/EventTheme.php new file mode 100644 index 000000000..1a0461cbd --- /dev/null +++ b/src/Bundle/ChillEventBundle/Entity/EventTheme.php @@ -0,0 +1,158 @@ + + */ + #[ORM\OneToMany(mappedBy: 'parent', targetEntity: EventTheme::class)] + private Collection $children; + + #[ORM\ManyToOne(targetEntity: EventTheme::class, inversedBy: 'children')] + private ?EventTheme $parent = null; + + #[ORM\Column(name: 'ordering', type: Types::FLOAT, options: ['default' => '0.0'])] + private float $ordering = 0.0; + + /** + * Constructor. + */ + public function __construct() + { + $this->children = new ArrayCollection(); + } + + /** + * Get active. + */ + public function getIsActive(): bool + { + return $this->isActive; + } + + /** + * Get id. + */ + public function getId(): ?int + { + return $this->id; + } + + /** + * Get label. + */ + public function getName(): array + { + return $this->name; + } + + public function setIsActive(bool $active): self + { + $this->isActive = $active; + + return $this; + } + + public function setName(array $label): self + { + $this->name = $label; + + return $this; + } + + public function addChild(self $child): self + { + if (!$this->children->contains($child)) { + $this->children[] = $child; + } + + return $this; + } + + public function removeChild(self $child): self + { + if ($this->children->removeElement($child)) { + // set the owning side to null (unless already changed) + if ($child->getParent() === $this) { + $child->setParent(null); + } + } + + return $this; + } + + public function getChildren(): Collection + { + return $this->children; + } + + public function hasChildren(): bool + { + return 0 < $this->getChildren()->count(); + } + + public function hasParent(): bool + { + return null !== $this->parent; + } + + public function getOrdering(): float + { + return $this->ordering; + } + + public function setOrdering(float $ordering): EventTheme + { + $this->ordering = $ordering; + + return $this; + } + + public function getParent(): ?self + { + return $this->parent; + } + + public function setParent(?self $parent): self + { + $this->parent = $parent; + + $parent?->addChild($this); + + return $this; + } +} diff --git a/src/Bundle/ChillEventBundle/Export/Export/ListEvents.php b/src/Bundle/ChillEventBundle/Export/Export/ListEvents.php new file mode 100644 index 000000000..7065e87c7 --- /dev/null +++ b/src/Bundle/ChillEventBundle/Export/Export/ListEvents.php @@ -0,0 +1,377 @@ +filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center']; + } + + public function buildForm(FormBuilderInterface $builder): void + { + $builder + ->add('fields', ChoiceType::class, [ + 'multiple' => true, + 'expanded' => true, + 'choices' => array_combine($this->fields, $this->fields), + 'label' => 'Fields to include in export', + 'constraints' => [new Callback([ + 'callback' => static function ($selected, ExecutionContextInterface $context) { + if (0 === \count($selected)) { + $context->buildViolation('You must select at least one element') + ->atPath('fields') + ->addViolation(); + } + }, + ])], + ]); + + } + + public function getFormDefaultData(): array + { + return [ + 'fields' => $this->fields, + ]; + } + + public function getAllowedFormattersTypes(): array + { + return [FormatterInterface::TYPE_LIST]; + } + + public function getDescription(): string + { + return 'export.event.list.description'; + } + + public function getGroup(): string + { + return 'Exports of events'; + } + + public function getLabels($key, array $values, $data) + { + return match ($key) { + 'event_id' => fn ($value) => '_header' === $value ? $key : $value, + 'event_name' => fn ($value) => '_header' === $value ? $key : $value, + 'event_date' => function ($value) use ($key) { + if ('_header' === $value) { + return $key; + } + + if ($value instanceof \DateTime) { + return $value->format('Y-m-d'); + } + + $date = \DateTime::createFromFormat('Y-m-d H:i:s', $value); + + return $date ? $date->format('Y-m-d') : $value; + }, + 'event_type' => function ($value) use ($key) { + if ('_header' === $value) { + return 'export.event.list.'.$key; + } + + return $this->translatableStringHelper->localize(json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR)); + }, + 'event_center' => fn ($value) => '_header' === $value ? $key : $value, + 'event_moderator' => fn ($value) => '_header' === $value ? $key : $value, + 'event_participants_count' => fn ($value) => '_header' === $value ? $key : $value, + 'event_location' => fn ($value) => '_header' === $value ? $key : $value, + 'event_animators' => $this->labelThirdPartyHelper->getLabelMulti($key, $values, $key), + 'event_themes' => function ($value) use ($key) { + if ('_header' === $value) { + return $key; + } + + if (null === $value) { + return ''; + } + + return implode( + '|', + array_map( + fn ($t) => $this->eventThemeRender->renderString($this->eventThemeRepository->find($t), []), + json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR) + ) + ); + }, + 'event_budget_resources' => function ($value) use ($key) { + if ('_header' === $value) { + return $key; + } + + if (!$value) { + return ''; + } + + $ids = explode(',', $value); + $ids = json_decode($value, true, 512, JSON_THROW_ON_ERROR); + $elements = $this->eventBudgetElementRepository->findBy(['id' => $ids]); + + return implode('|', array_map(function ($element) { + $name = $this->translatableStringHelper->localize($element->getKind()->getName()); + $amount = number_format($element->getAmount(), 2, '.', ''); + + return $name.': '.$amount; + }, $elements)); + }, + + 'event_budget_charges' => function ($value) use ($key) { + if ('_header' === $value) { + return $key; + } + + if (!$value) { + return ''; + } + + $ids = explode(',', $value); + $ids = json_decode($value, true, 512, JSON_THROW_ON_ERROR); + + $elements = $this->eventBudgetElementRepository->findBy(['id' => $ids]); + + return implode('|', array_map(function ($element) { + $name = $this->translatableStringHelper->localize($element->getKind()->getName()); + $amount = number_format($element->getAmount(), 2, '.', ''); + + return $name.': '.$amount; + }, $elements)); + }, + + + default => fn ($value) => '_header' === $value ? $key : $value, + }; + } + + public function getQueryKeys(array $data): array + { + return $data['fields']; + } + + public function getResult($query, $data, ExportGenerationContext $context): array + { + return $query->getQuery()->getResult(Query::HYDRATE_SCALAR); + } + + public function getTitle(): string|TranslatableInterface + { + return 'export.event.list.title'; + } + + public function getType(): string + { + return Declarations::EVENT; + } + + public function initiateQuery(array $requiredModifiers, array $acl, array $data, ExportGenerationContext $context): NativeQuery|QueryBuilder + { + $centers = array_map(static fn ($el) => $el['center'], $acl); + + // Throw an error if no fields are present + if (!\array_key_exists('fields', $data)) { + throw new \InvalidArgumentException('No fields have been checked.'); + } + + $qb = $this->entityManager->createQueryBuilder() + ->from(Event::class, 'event'); + + if ($this->filterStatsByCenters) { + $qb + ->andWhere('event.center IN (:authorized_centers)') + ->setParameter('authorized_centers', $centers); + } + + // Add fields based on selection + foreach ($this->fields as $field) { + if (\in_array($field, $data['fields'], true)) { + switch ($field) { + case 'event_id': + $qb->addSelect('event.id AS event_id'); + break; + + case 'event_name': + $qb->addSelect('event.name AS event_name'); + break; + + case 'event_date': + $qb->addSelect('event.date AS event_date'); + break; + + case 'event_type': + if (!$this->hasJoin($qb, 'event.type')) { + $qb->leftJoin('event.type', 'type'); + } + $qb->addSelect('type.name AS event_type'); + break; + + case 'event_center': + if (!$this->hasJoin($qb, 'event.center')) { + $qb->leftJoin('event.center', 'center'); + } + $qb->addSelect('center.name AS event_center'); + break; + + case 'event_moderator': + if (!$this->hasJoin($qb, 'event.moderator')) { + $qb->leftJoin('event.moderator', 'user'); + } + $qb->addSelect('user.username AS event_moderator'); + break; + + case 'event_participants_count': + $qb->addSelect('(SELECT COUNT(p.id) FROM Chill\EventBundle\Entity\Participation p WHERE p.event = event.id) AS event_participants_count'); + break; + + case 'event_location': + if (!$this->hasJoin($qb, 'event.location')) { + $qb->leftJoin('event.location', 'location'); + } + $qb->addSelect('location.name AS event_location'); + break; + + case 'event_animators': + $qb->addSelect( + '(SELECT AGGREGATE(tp.id) FROM Chill\ThirdPartyBundle\Entity\ThirdParty tp WHERE tp MEMBER OF event.animators) AS event_animators' + ); + break; + + case 'event_themes': + $qb->addSelect( + '(SELECT AGGREGATE(t.id) FROM Chill\EventBundle\Entity\EventTheme t WHERE t MEMBER OF event.themes) AS event_themes' + ); + break; + + case 'event_budget_resources': + $qb->addSelect( + '(SELECT AGGREGATE(ebr.id) + FROM Chill\EventBundle\Entity\EventBudgetElement ebr + JOIN ebr.kind kr + WHERE ebr.event = event.id AND kr.type = :resource_type) AS event_budget_resources' + ); + $qb->setParameter('resource_type', BudgetTypeEnum::RESOURCE->value); + break; + + case 'event_budget_charges': + $qb->addSelect( + '(SELECT AGGREGATE(ebc.id) + FROM Chill\EventBundle\Entity\EventBudgetElement ebc + JOIN ebc.kind kc + WHERE ebc.event = event.id AND kc.type = :charge_type) AS event_budget_charges' + ); + $qb->setParameter('charge_type', BudgetTypeEnum::CHARGE->value); + break; + } + } + } + + return $qb; + } + + public function requiredRole(): string + { + return EventVoter::STATS; + } + + public function supportsModifiers() + { + return [Declarations::EVENT]; + } + + /** + * Helper method to check if a join already exists in the QueryBuilder. + */ + private function hasJoin($queryBuilder, $joinPath): bool + { + $joins = $queryBuilder->getDQLPart('join'); + if (!isset($joins['event'])) { + return false; + } + + foreach ($joins['event'] as $join) { + if ($join->getJoin() === $joinPath) { + return true; + } + } + + return false; + } + + public function normalizeFormData(array $formData): array + { + return ['fields' => $formData['fields']]; + } + + public function denormalizeFormData(array $formData, int $fromVersion): array + { + return ['fields' => $formData['fields']]; + } + + public function getNormalizationVersion(): int + { + return 1; + } +} diff --git a/src/Bundle/ChillEventBundle/Form/AddEventBudgetElementType.php b/src/Bundle/ChillEventBundle/Form/AddEventBudgetElementType.php new file mode 100644 index 000000000..a1942e4c1 --- /dev/null +++ b/src/Bundle/ChillEventBundle/Form/AddEventBudgetElementType.php @@ -0,0 +1,59 @@ +kindRepository->findByType(BudgetTypeEnum::CHARGE->value); + $resources = $this->kindRepository->findByType(BudgetTypeEnum::RESOURCE->value); + + $builder->add('kind', ChoiceType::class, [ + 'choices' => [ + 'event.budget.charges' => $charges, + 'event.budget.resources' => $resources, + ], + 'choice_label' => fn (EventBudgetKind $kind) => $this->translatableStringHelper->localize($kind->getName()), + 'choice_value' => fn (?EventBudgetKind $kind) => $kind?->getId(), + 'placeholder' => 'event.budget.Select a budget element kind', + ]) + ->add('amount', NumberType::class, [ + 'required' => true, + ]) + ->add('comment', CommentType::class, [ + 'label' => 'Comment', + 'required' => false, + ]); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => EventBudgetElement::class, + ]); + } +} diff --git a/src/Bundle/ChillEventBundle/Form/EventBudgetKindType.php b/src/Bundle/ChillEventBundle/Form/EventBudgetKindType.php new file mode 100644 index 000000000..571c4f942 --- /dev/null +++ b/src/Bundle/ChillEventBundle/Form/EventBudgetKindType.php @@ -0,0 +1,53 @@ +add('name', TranslatableStringFormType::class, [ + 'label' => 'Title', + ]) + ->add('type', EnumType::class, [ + 'class' => BudgetTypeEnum::class, + 'choice_label' => fn (BudgetTypeEnum $type): string => $this->translator->trans($type->value), + 'expanded' => true, + 'multiple' => false, + 'mapped' => true, + 'label' => 'event.admin.Select budget type', + ]) + ->add('isActive', CheckboxType::class, [ + 'label' => 'Actif ?', + 'required' => false, + ]); + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver + ->setDefault('class', EventBudgetKind::class); + } +} diff --git a/src/Bundle/ChillEventBundle/Form/EventThemeType.php b/src/Bundle/ChillEventBundle/Form/EventThemeType.php new file mode 100644 index 000000000..351bf5a59 --- /dev/null +++ b/src/Bundle/ChillEventBundle/Form/EventThemeType.php @@ -0,0 +1,67 @@ +add('name', TranslatableStringFormType::class, [ + 'label' => 'Nom', + ]); + + if ('create' === $options['step']) { + $builder + ->add('parent', EntityType::class, [ + 'class' => EventTheme::class, + 'required' => false, + 'choice_label' => fn (EventTheme $theme): ?string => $this->translatableStringHelper->localize($theme->getName()), + 'mapped' => 'create' == $options['step'], + ]); + } + + $builder + ->add('ordering', NumberType::class, [ + 'required' => true, + 'scale' => 6, + ]) + ->add('isActive', ChoiceType::class, [ + 'choices' => [ + 'Yes' => true, + 'No' => false, + ], + 'expanded' => true, + ]); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => EventTheme::class, + ]); + $resolver->setRequired('step') + ->setAllowedValues('step', ['create', 'edit']); + } +} diff --git a/src/Bundle/ChillEventBundle/Form/EventType.php b/src/Bundle/ChillEventBundle/Form/EventType.php index ebdf66010..a4048983e 100644 --- a/src/Bundle/ChillEventBundle/Form/EventType.php +++ b/src/Bundle/ChillEventBundle/Form/EventType.php @@ -13,25 +13,39 @@ namespace Chill\EventBundle\Form; use Chill\DocStoreBundle\Entity\StoredObject; use Chill\DocStoreBundle\Form\StoredObjectType; +use Chill\EventBundle\Entity\BudgetTypeEnum; use Chill\EventBundle\Entity\Event; +use Chill\EventBundle\Form\Type\PickEventThemeType; use Chill\EventBundle\Form\Type\PickEventTypeType; +use Chill\EventBundle\Repository\EventBudgetKindRepository; use Chill\MainBundle\Entity\Center; +use Chill\MainBundle\Form\DataTransformer\IdToLocationDataTransformer; use Chill\MainBundle\Form\Type\ChillCollectionType; use Chill\MainBundle\Form\Type\ChillDateTimeType; use Chill\MainBundle\Form\Type\CommentType; use Chill\MainBundle\Form\Type\PickUserDynamicType; -use Chill\MainBundle\Form\Type\PickUserLocationType; use Chill\MainBundle\Form\Type\ScopePickerType; +use Chill\ThirdPartyBundle\Form\Type\PickThirdpartyDynamicType; use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Extension\Core\Type\MoneyType; +use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Contracts\Translation\TranslatorInterface; class EventType extends AbstractType { - public function buildForm(FormBuilderInterface $builder, array $options) + public function __construct( + private readonly IdToLocationDataTransformer $idToLocationDataTransformer, + private readonly EventBudgetKindRepository $eventBudgetKindRepository, + private readonly TranslatorInterface $translator, + ) {} + + public function buildForm(FormBuilderInterface $builder, array $options): void { + $chargeKinds = $this->eventBudgetKindRepository->findByType(BudgetTypeEnum::CHARGE->value); + $resourceKinds = $this->eventBudgetKindRepository->findByType(BudgetTypeEnum::RESOURCE->value); + $builder ->add('name', TextType::class, [ 'required' => true, @@ -49,11 +63,28 @@ class EventType extends AbstractType 'class' => '', ], ]) + ->add('themes', PickEventThemeType::class, [ + 'multiple' => true, + ]) ->add('moderator', PickUserDynamicType::class, [ 'label' => 'Pick a moderator', ]) - ->add('location', PickUserLocationType::class, [ - 'label' => 'event.fields.location', + ->add('animatorsIntern', PickUserDynamicType::class, [ + 'multiple' => true, + 'label' => $this->translator->trans('event.fields.internal animators'), + 'required' => false, + ]) + ->add('animatorsExtern', PickThirdpartyDynamicType::class, [ + 'multiple' => true, + 'label' => $this->translator->trans('event.fields.external animators'), + 'required' => false, + ]) + ->add('budgetElements', ChillCollectionType::class, [ + 'entry_type' => AddEventBudgetElementType::class, + 'entry_options' => ['label' => false], + 'allow_add' => true, + 'allow_delete' => true, + 'by_reference' => false, ]) ->add('comment', CommentType::class, [ 'label' => 'Comment', @@ -69,11 +100,11 @@ class EventType extends AbstractType 'delete_empty' => fn (StoredObject $storedObject): bool => '' === $storedObject->getFilename(), 'button_remove_label' => 'event.form.remove_document', 'button_add_label' => 'event.form.add_document', - ]) - ->add('organizationCost', MoneyType::class, [ - 'label' => 'event.fields.organizationCost', - 'help' => 'event.form.organisationCost_help', ]); + + $builder->add('location', HiddenType::class) + ->get('location') + ->addModelTransformer($this->idToLocationDataTransformer); } public function configureOptions(OptionsResolver $resolver) @@ -87,11 +118,9 @@ class EventType extends AbstractType ->setAllowedTypes('role', 'string'); } - /** - * @return string - */ - public function getBlockPrefix() + public function getBlockPrefix(): string { - return 'chill_eventbundle_event'; + // as the js shares some hardcoded items from the activity bundle, we have to rewrite block prefix + return 'chill_activitybundle_activity'; } } diff --git a/src/Bundle/ChillEventBundle/Form/Type/PickEventThemeType.php b/src/Bundle/ChillEventBundle/Form/Type/PickEventThemeType.php new file mode 100644 index 000000000..3010df271 --- /dev/null +++ b/src/Bundle/ChillEventBundle/Form/Type/PickEventThemeType.php @@ -0,0 +1,45 @@ +setDefaults([ + 'class' => EventTheme::class, + 'choices' => $this->eventThemeRepository->findByActiveOrdered(), + 'choice_label' => fn (EventTheme $et) => $this->eventThemeRender->renderString($et, []), + 'placeholder' => 'event.form.Select one or more themes', + 'required' => true, + 'attr' => ['class' => 'select2'], + 'label' => 'event.theme.label', + 'multiple' => false, + ]) + ->setAllowedTypes('multiple', ['bool']); + } + + public function getParent(): string + { + return EntityType::class; + } +} diff --git a/src/Bundle/ChillEventBundle/Form/Type/PickEventTypeType.php b/src/Bundle/ChillEventBundle/Form/Type/PickEventTypeType.php index d027c05cf..7166893cc 100644 --- a/src/Bundle/ChillEventBundle/Form/Type/PickEventTypeType.php +++ b/src/Bundle/ChillEventBundle/Form/Type/PickEventTypeType.php @@ -23,15 +23,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver; */ class PickEventTypeType extends AbstractType { - /** - * @var TranslatableStringHelper - */ - protected $translatableStringHelper; - - public function __construct(TranslatableStringHelper $helper) - { - $this->translatableStringHelper = $helper; - } + public function __construct(protected TranslatableStringHelper $translatableStringHelper) {} public function configureOptions(OptionsResolver $resolver) { diff --git a/src/Bundle/ChillEventBundle/Menu/AdminMenuBuilder.php b/src/Bundle/ChillEventBundle/Menu/AdminMenuBuilder.php index 9db1713b6..b7930fbba 100644 --- a/src/Bundle/ChillEventBundle/Menu/AdminMenuBuilder.php +++ b/src/Bundle/ChillEventBundle/Menu/AdminMenuBuilder.php @@ -17,17 +17,9 @@ use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; class AdminMenuBuilder implements LocalMenuBuilderInterface { - /** - * @var AuthorizationCheckerInterface - */ - protected $authorizationChecker; + public function __construct(protected AuthorizationCheckerInterface $authorizationChecker) {} - public function __construct(AuthorizationCheckerInterface $authorizationChecker) - { - $this->authorizationChecker = $authorizationChecker; - } - - public function buildMenu($menuId, MenuItem $menu, array $parameters) + public function buildMenu($menuId, MenuItem $menu, array $parameters): void { if (!$this->authorizationChecker->isGranted('ROLE_ADMIN')) { return; @@ -52,6 +44,14 @@ class AdminMenuBuilder implements LocalMenuBuilderInterface $menu->addChild('Role', [ 'route' => 'chill_event_admin_role', ])->setExtras(['order' => 6530]); + + $menu->addChild('event.theme.label', [ + 'route' => 'chill_crud_event_theme_index', + ])->setExtras(['order' => 6540]); + + $menu->addChild('event.budget.label', [ + 'route' => 'chill_crud_event_budget_kind_index', + ])->setExtras(['order' => 6550]); } public static function getMenuIds(): array diff --git a/src/Bundle/ChillEventBundle/Repository/EventACLAwareRepository.php b/src/Bundle/ChillEventBundle/Repository/EventACLAwareRepository.php index 22141b536..2b8c7c01e 100644 --- a/src/Bundle/ChillEventBundle/Repository/EventACLAwareRepository.php +++ b/src/Bundle/ChillEventBundle/Repository/EventACLAwareRepository.php @@ -88,6 +88,16 @@ final readonly class EventACLAwareRepository implements EventACLAwareRepositoryI $qb->andWhere('event.type IN (:event_types)'); $qb->setParameter('event_types', $filters['event_types']); } + + if (0 < count($filters['centers'] ?? [])) { + $qb->andWhere('event.center IN (:centers)'); + $qb->setParameter('centers', $filters['centers']); + } + + if (0 < count($filters['responsables'] ?? [])) { + $qb->andWhere('event.moderator IN (:responsables)'); + $qb->setParameter('responsables', $filters['responsables']); + } } public function buildQueryByAllViewable(array $filters): QueryBuilder diff --git a/src/Bundle/ChillEventBundle/Repository/EventBudgetElementRepository.php b/src/Bundle/ChillEventBundle/Repository/EventBudgetElementRepository.php new file mode 100644 index 000000000..48b871dc2 --- /dev/null +++ b/src/Bundle/ChillEventBundle/Repository/EventBudgetElementRepository.php @@ -0,0 +1,27 @@ + + */ +class EventBudgetElementRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, EventBudgetElement::class); + } +} diff --git a/src/Bundle/ChillEventBundle/Repository/EventBudgetKindRepository.php b/src/Bundle/ChillEventBundle/Repository/EventBudgetKindRepository.php new file mode 100644 index 000000000..0c40fce7d --- /dev/null +++ b/src/Bundle/ChillEventBundle/Repository/EventBudgetKindRepository.php @@ -0,0 +1,46 @@ + + */ +class EventBudgetKindRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, EventBudgetKind::class); + } + + public function findByActive(): array + { + return $this->createQueryBuilder('e') + ->select('e') + ->where('e.active = True') + ->getQuery() + ->getResult(); + } + + public function findByType(string $type): array + { + return $this->createQueryBuilder('e') + ->select('e') + ->where('e.type = :type') + ->setParameter('type', $type) + ->getQuery() + ->getResult(); + } +} diff --git a/src/Bundle/ChillEventBundle/Repository/EventThemeRepository.php b/src/Bundle/ChillEventBundle/Repository/EventThemeRepository.php new file mode 100644 index 000000000..add79faeb --- /dev/null +++ b/src/Bundle/ChillEventBundle/Repository/EventThemeRepository.php @@ -0,0 +1,37 @@ + + */ +class EventThemeRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, EventTheme::class); + } + + public function findByActiveOrdered(): array + { + return $this->createQueryBuilder('t') + ->select('t') + ->where('t.isActive = True') + ->orderBy('t.ordering', 'ASC') + ->getQuery() + ->getResult(); + } +} diff --git a/src/Bundle/ChillEventBundle/Resources/public/chill/chillevent.scss b/src/Bundle/ChillEventBundle/Resources/public/chill/chillevent.scss index 6020d45dc..14f10b768 100644 --- a/src/Bundle/ChillEventBundle/Resources/public/chill/chillevent.scss +++ b/src/Bundle/ChillEventBundle/Resources/public/chill/chillevent.scss @@ -55,3 +55,13 @@ form#export_tableur { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out; } + +.participation-list { + flex-wrap: wrap; +} + +.participations-wrapper { + background-color: whitesmoke; + padding: 1rem; + margin-bottom: .5rem; +} diff --git a/src/Bundle/ChillEventBundle/Resources/public/vuejs/App.vue b/src/Bundle/ChillEventBundle/Resources/public/vuejs/App.vue new file mode 100644 index 000000000..89158d742 --- /dev/null +++ b/src/Bundle/ChillEventBundle/Resources/public/vuejs/App.vue @@ -0,0 +1,14 @@ + + + diff --git a/src/Bundle/ChillEventBundle/Resources/public/vuejs/index.js b/src/Bundle/ChillEventBundle/Resources/public/vuejs/index.js new file mode 100644 index 000000000..e0be75aaf --- /dev/null +++ b/src/Bundle/ChillEventBundle/Resources/public/vuejs/index.js @@ -0,0 +1,6 @@ +import { createApp } from "vue"; + +import App from "./App.vue"; +import store from "./store"; + +createApp(App).use(store).mount("#event"); diff --git a/src/Bundle/ChillEventBundle/Resources/public/vuejs/store.js b/src/Bundle/ChillEventBundle/Resources/public/vuejs/store.js new file mode 100644 index 000000000..4f4e194d8 --- /dev/null +++ b/src/Bundle/ChillEventBundle/Resources/public/vuejs/store.js @@ -0,0 +1,76 @@ +import "es6-promise/auto"; +import { createStore } from "vuex"; + +import prepareLocations from "ChillActivityAssets/vuejs/Activity/store.locations"; +import { whoami } from "ChillMainAssets/lib/api/user"; +import { postLocation } from "ChillActivityAssets/vuejs/Activity/api"; + +const debug = process.env.NODE_ENV !== "production"; + +const store = createStore({ + strict: debug, + state: { + activity: window.entity, // activity is the event entity in this case (re-using component from activity bundle) + currentEvent: null, + availableLocations: [], + me: null, + }, + getters: {}, + actions: { + addAvailableLocationGroup({ commit }, payload) { + commit("addAvailableLocationGroup", payload); + }, + updateLocation({ commit }, value) { + // console.log("### action: updateLocation", value); + let hiddenLocation = document.getElementById( + "chill_activitybundle_activity_location", + ); + if (value.onthefly) { + const body = { + type: "location", + name: + value.name === "__AccompanyingCourseLocation__" ? null : value.name, + locationType: { + id: value.locationType.id, + type: "location-type", + }, + }; + if (value.address.id) { + Object.assign(body, { + address: { + id: value.address.id, + }, + }); + } + postLocation(body) + .then((location) => (hiddenLocation.value = location.id)) + .catch((err) => { + console.log(err.message); + }); + } else { + hiddenLocation.value = value.id; + } + commit("updateLocation", value); + }, + }, + mutations: { + setWhoAmiI(state, me) { + state.me = me; + }, + addAvailableLocationGroup(state, group) { + state.availableLocations.push(group); + }, + updateLocation(state, value) { + // console.log("### mutation: updateLocation", value); + state.activity.location = value; + }, + }, +}); + +whoami().then((me) => { + store.commit("setWhoAmiI", me); +}); + +prepareLocations(store); + +export default store; diff --git a/src/Bundle/ChillEventBundle/Resources/views/Admin/BudgetKind/edit.html.twig b/src/Bundle/ChillEventBundle/Resources/views/Admin/BudgetKind/edit.html.twig new file mode 100644 index 000000000..3a60d3e9c --- /dev/null +++ b/src/Bundle/ChillEventBundle/Resources/views/Admin/BudgetKind/edit.html.twig @@ -0,0 +1,12 @@ +{% extends '@ChillMain/CRUD/Admin/index.html.twig' %} + +{% block title %} + {% include('@ChillMain/CRUD/_edit_title.html.twig') %} +{% endblock %} + +{% block admin_content %} + {% embed '@ChillMain/CRUD/_edit_content.html.twig' %} + {% block content_form_actions_view %}{% endblock %} + {% block content_form_actions_save_and_show %}{% endblock %} + {% endembed %} +{% endblock %} diff --git a/src/Bundle/ChillEventBundle/Resources/views/Admin/BudgetKind/index.html.twig b/src/Bundle/ChillEventBundle/Resources/views/Admin/BudgetKind/index.html.twig new file mode 100644 index 000000000..f55ec4f17 --- /dev/null +++ b/src/Bundle/ChillEventBundle/Resources/views/Admin/BudgetKind/index.html.twig @@ -0,0 +1,51 @@ +{% extends '@ChillMain/Admin/layoutWithVerticalMenu.html.twig' %} + +{% block title %}{{ 'event.admin.title.Event budget element list'|trans }}{% endblock title %} + +{% block admin_content %} + +

{{ 'event.admin.title.Event budget element list'|trans }}

+ + + + + + + + + + + + {% for entity in entities %} + + + + + + + {% endfor %} + +
{{ 'Name'|trans }}{{ 'Type'|trans }}{{ 'Active'|trans }} 
{{ entity.name|localize_translatable_string }}{{ entity.type.value|trans }} + {%- if entity.isActive -%} + + {%- else -%} + + {%- endif -%} + +
    +
  • + +
  • +
+
+ + {{ chill_pagination(paginator) }} + + +{% endblock %} diff --git a/src/Bundle/ChillEventBundle/Resources/views/Admin/BudgetKind/new.html.twig b/src/Bundle/ChillEventBundle/Resources/views/Admin/BudgetKind/new.html.twig new file mode 100644 index 000000000..00ebd2938 --- /dev/null +++ b/src/Bundle/ChillEventBundle/Resources/views/Admin/BudgetKind/new.html.twig @@ -0,0 +1,11 @@ +{% extends '@ChillMain/CRUD/Admin/index.html.twig' %} + +{% block title %} + {% include('@ChillMain/CRUD/_new_title.html.twig') %} +{% endblock %} + +{% block admin_content %} + {% embed '@ChillMain/CRUD/_new_content.html.twig' %} + {% block content_form_actions_save_and_show %}{% endblock %} + {% endembed %} +{% endblock %} diff --git a/src/Bundle/ChillEventBundle/Resources/views/Admin/EventTheme/edit.html.twig b/src/Bundle/ChillEventBundle/Resources/views/Admin/EventTheme/edit.html.twig new file mode 100644 index 000000000..a63d81c99 --- /dev/null +++ b/src/Bundle/ChillEventBundle/Resources/views/Admin/EventTheme/edit.html.twig @@ -0,0 +1,26 @@ +{% extends '@ChillMain/CRUD/Admin/index.html.twig' %} + +{% block title %} + {% include('@ChillMain/CRUD/_edit_title.html.twig') %} +{% endblock %} + +{% block admin_content %} + {% embed '@ChillMain/CRUD/_edit_content.html.twig' %} + + {% block crud_content_form_rows %} + {{ form_row(form.name) }} +
+ +
+ {{ entity.parent|chill_entity_render_box }} +
+
+ {{ form_row(form.ordering) }} + {{ form_row(form.isActive) }} + {% endblock crud_content_form_rows %} + + {% block content_form_actions_save_and_show %}{% endblock %} + {% endembed %} +{% endblock admin_content %} diff --git a/src/Bundle/ChillEventBundle/Resources/views/Admin/EventTheme/index.html.twig b/src/Bundle/ChillEventBundle/Resources/views/Admin/EventTheme/index.html.twig new file mode 100644 index 000000000..d518ea625 --- /dev/null +++ b/src/Bundle/ChillEventBundle/Resources/views/Admin/EventTheme/index.html.twig @@ -0,0 +1,45 @@ +{% extends '@ChillMain/CRUD/Admin/index.html.twig' %} + +{% block admin_content %} + {% embed '@ChillMain/CRUD/_index.html.twig' %} + {% block table_entities_thead_tr %} + {{ 'Id'|trans }} + {{ 'Title'|trans }} + {{ 'Ordering'|trans }} + {{ 'active'|trans }} +   + {% endblock %} + + {% block table_entities_tbody %} + {% for entity in entities %} + + {{ entity.id }} + + {{ entity|chill_entity_render_box }} + + {{ entity.ordering }} + + {%- if entity.isActive -%} + + {%- else -%} + + {%- endif -%} + + +
    +
  • + +
  • +
+ + + {% endfor %} + {% endblock %} + + {% block actions_before %} +
  • + {{'Back to the admin'|trans}} +
  • + {% endblock %} + {% endembed %} +{% endblock %} diff --git a/src/Bundle/ChillEventBundle/Resources/views/Admin/EventTheme/new.html.twig b/src/Bundle/ChillEventBundle/Resources/views/Admin/EventTheme/new.html.twig new file mode 100644 index 000000000..7c204dddd --- /dev/null +++ b/src/Bundle/ChillEventBundle/Resources/views/Admin/EventTheme/new.html.twig @@ -0,0 +1,11 @@ +{% extends '@ChillMain/CRUD/Admin/index.html.twig' %} + +{% block title %} + {% include('@ChillMain/CRUD/_new_title.html.twig') %} +{% endblock %} + +{% block admin_content %} + {% embed '@ChillMain/CRUD/_new_content.html.twig' %} + {% block content_form_actions_save_and_show %}{% endblock %} + {% endembed %} +{% endblock admin_content %} diff --git a/src/Bundle/ChillEventBundle/Resources/views/Entity/event_theme.html.twig b/src/Bundle/ChillEventBundle/Resources/views/Entity/event_theme.html.twig new file mode 100644 index 000000000..08796d7b2 --- /dev/null +++ b/src/Bundle/ChillEventBundle/Resources/views/Entity/event_theme.html.twig @@ -0,0 +1,13 @@ +{% set reversed_parents = parents|reverse %} + + + {%- for p in reversed_parents %} + + {{ p.name|localize_translatable_string }}{{ options['default.separator'] }} + + {%- endfor -%} + + {{ eventTheme.name|localize_translatable_string }} + + + diff --git a/src/Bundle/ChillEventBundle/Resources/views/Event/confirm_delete.html.twig b/src/Bundle/ChillEventBundle/Resources/views/Event/confirm_delete.html.twig index c3a13b55a..a7666f149 100644 --- a/src/Bundle/ChillEventBundle/Resources/views/Event/confirm_delete.html.twig +++ b/src/Bundle/ChillEventBundle/Resources/views/Event/confirm_delete.html.twig @@ -12,7 +12,7 @@ 'title' : 'Delete event'|trans, 'confirm_question' : 'Are you sure you want to remove that event ?'|trans, 'cancel_route' : activeRouteKey, - 'cancel_parameters' : { 'event_id' : event_id }, + 'cancel_parameters' : { 'id' : id }, 'form' : delete_form } ) }} diff --git a/src/Bundle/ChillEventBundle/Resources/views/Event/edit.html.twig b/src/Bundle/ChillEventBundle/Resources/views/Event/edit.html.twig index b6b11878b..55c2fc21f 100644 --- a/src/Bundle/ChillEventBundle/Resources/views/Event/edit.html.twig +++ b/src/Bundle/ChillEventBundle/Resources/views/Event/edit.html.twig @@ -17,10 +17,12 @@ {{ form_row(edit_form.date) }} {{ form_row(edit_form.type, { label: "Event type" }) }} + {{ form_row(edit_form.themes) }} {{ form_row(edit_form.moderator) }} + {{ form_row(edit_form.animatorsIntern) }} + {{ form_row(edit_form.animatorsExtern) }} {{ form_row(edit_form.location) }} - {{ form_row(edit_form.organizationCost) }} - + {{ form_row(edit_form.budgetElements) }} {{ form_row(edit_form.comment) }} {{ form_row(edit_form.documents) }} diff --git a/src/Bundle/ChillEventBundle/Resources/views/Event/list.html.twig b/src/Bundle/ChillEventBundle/Resources/views/Event/list.html.twig index 4bdb1f0f8..b376050b4 100644 --- a/src/Bundle/ChillEventBundle/Resources/views/Event/list.html.twig +++ b/src/Bundle/ChillEventBundle/Resources/views/Event/list.html.twig @@ -34,7 +34,7 @@
    • {# {% if is_granted('CHILL_EVENT_SEE_DETAILS', event) %} #} - + {{ 'See'|trans }} {# {% endif %} #} diff --git a/src/Bundle/ChillEventBundle/Resources/views/Event/new.html.twig b/src/Bundle/ChillEventBundle/Resources/views/Event/new.html.twig index 0fb69a4ea..2f5a82c8d 100644 --- a/src/Bundle/ChillEventBundle/Resources/views/Event/new.html.twig +++ b/src/Bundle/ChillEventBundle/Resources/views/Event/new.html.twig @@ -1,25 +1,30 @@ -{% extends '@ChillEvent/layout.html.twig' %} {% block js %} -{{ encore_entry_script_tags("mod_async_upload") }} -{{ encore_entry_script_tags("mod_pickentity_type") }} +{% extends '@ChillEvent/layout.html.twig' %} -{% endblock %} {% block css %} +{% block css %} {{ encore_entry_link_tags("mod_async_upload") }} {{ encore_entry_link_tags("mod_pickentity_type") }} +{{ encore_entry_link_tags('vue_event') }} +{% endblock %} -{% endblock %} {% block title 'Event creation'|trans %} {% block event_content --%} +{% block title 'Event creation'|trans %} + +{% block event_content -%}

      {{ "Event creation" | trans }}

      {{ form_start(form) }} {{ form_errors(form) }} - {{ form_row(form.circle) }} {{ form_row(form.name) }} + {{ form_row(form.circle) }} {{ form_row(form.date) }} {{ form_row(form.type, { label: "Event type" }) }} + {{ form_row(form.themes) }} {{ form_row(form.moderator) }} + {{ form_row(form.animatorsIntern) }} + {{ form_row(form.animatorsExtern) }} {{ form_row(form.location) }} - {{ form_row(form.organizationCost) }} +
      + {{ form_row(form.budgetElements) }} {{ form_row(form.comment) }} {{ form_row(form.documents) }} @@ -40,5 +45,18 @@
    {{ form_end(form) }} + +
    + {% endblock %} + +{% block js %} + {{ encore_entry_script_tags("mod_async_upload") }} + {{ encore_entry_script_tags("mod_pickentity_type") }} + {{ encore_entry_script_tags('vue_event') }} + +{% endblock %} diff --git a/src/Bundle/ChillEventBundle/Resources/views/Event/page_list.html.twig b/src/Bundle/ChillEventBundle/Resources/views/Event/page_list.html.twig index 4d887d3c5..888c698e7 100644 --- a/src/Bundle/ChillEventBundle/Resources/views/Event/page_list.html.twig +++ b/src/Bundle/ChillEventBundle/Resources/views/Event/page_list.html.twig @@ -11,7 +11,7 @@ block js %} {{ filter | chill_render_filter_order_helper }} - {# {% if is_granted('CHILL_EVENT_CREATE') %} #} + {% if is_granted('CHILL_EVENT_CREATE') %} - {# {% endif %} #} {% if events|length > 0 %} + {% endif %} + + {% if events|length > 0 %}
    {% for e in events %}
    @@ -41,6 +43,12 @@ block js %} {{ e.moderator | chill_entity_render_box }}

    {% endif %} + +
    + {% for t in e.themes %} + {{ t|chill_entity_render_box }} + {% endfor %} +
    @@ -48,11 +56,12 @@ block js %}

    {{ 'count participations to this event'|trans({'count': e.participations|length}) }}

    +

    {{ "center"|trans }}: {{ e.center.name }}

    {% if e.participations|length > 0 %} -
    +
    {{ "Participations" | trans }} : {% for part in e.participations|slice(0, 5) %} {% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with { @@ -106,7 +115,7 @@ block js %} href="{{ chill_path_add_return_path( 'chill_event__event_show', - { event_id: e.id } + { id: e.id } ) }}" class="btn btn-show" diff --git a/src/Bundle/ChillEventBundle/Resources/views/Event/show.html.twig b/src/Bundle/ChillEventBundle/Resources/views/Event/show.html.twig index 7d8bf1fc0..1f6f2d4b9 100644 --- a/src/Bundle/ChillEventBundle/Resources/views/Event/show.html.twig +++ b/src/Bundle/ChillEventBundle/Resources/views/Event/show.html.twig @@ -16,6 +16,16 @@ {{ encore_entry_link_tags('mod_document_action_buttons_group') }} {% endblock %} +{% macro insert_onthefly(type, entity, parent = null) %} + {% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with { + action: 'show', displayBadge: true, + targetEntity: { name: type, id: entity.id }, + buttonText: entity|chill_entity_render_string, + isDead: entity.deathdate is defined and entity.deathdate is not null, + parent: parent + } %} +{% endmacro %} + {% block event_content -%}

    {{ 'Details of an event'|trans }}

    @@ -26,6 +36,10 @@ {{ 'Circle'|trans }} {{ event.circle.name|localize_translatable_string }} + + {{ 'Center'|trans }} + {{ event.center.name }} + {{ 'Name'|trans }} {{ event.name }} @@ -39,12 +53,32 @@ {{ event.type.name|localize_translatable_string }} - {{ 'Moderator'|trans }} - {{ event.moderator|trans|default('-') }} + {{ 'event.theme.label'|trans }} + + {% for t in event.themes %} + {{ t|chill_entity_render_box }} + {% endfor %} + - {{ 'event.fields.organizationCost'|trans }} - {{ event.organizationCost|format_currency('EUR') }} + {{ 'Moderator'|trans }} + {{ event.moderator|chill_entity_render_string }} + + + {{ 'event.animators.intern'|trans }} + + {% for a in event.animatorsIntern %} + {{ _self.insert_onthefly('user', a) }} + {% endfor %} + + + + {{ 'event.animators.extern'|trans }} + + {% for a in event.animatorsExtern %} + {{ _self.insert_onthefly('thirdparty', a) }} + {% endfor %} + {{ 'event.fields.location'|trans }} @@ -60,6 +94,77 @@ +
    + {% set resources = event.budgetElements|filter(e => e.kind.type.value == 'Resource') %} + {% set charges = event.budgetElements|filter(e => e.kind.type.value == 'Charge') %} + +

    Budget de l'événement

    + +

    Ressources

    + {% if resources is not empty %} + + + + + + + + + + {% set totalResources = 0 %} + {% for res in resources %} + + + + + + {% set totalResources = totalResources + res.amount %} + {% endfor %} + + + + + + + +
    {{ 'event.budget.resource type'|trans }}{{ 'event.budget.amount'|trans }}{{ 'event.budget.comment'|trans }}
    {{ res.kind.name|localize_translatable_string }}{{ res.amount|format_currency('EUR') }}{{ res.comment.comment|chill_print_or_message(null, 'blockquote') }}
    Total{{ totalResources|format_currency('EUR') }}
    + {% else %} +

    {{ 'event.budget.no elements'|trans }}

    + {% endif %} + +

    Charges

    + {% if charges is not empty %} + + + + + + + + + + {% set totalCharges = 0 %} + {% for chg in charges %} + + + + + + {% set totalCharges = totalCharges + chg.amount %} + {% endfor %} + + + + + + + +
    {{ 'event.budget.charge type'|trans }}{{ 'event.budget.amount'|trans }}{{ 'event.budget.comment'|trans }}
    {{ chg.kind.name|localize_translatable_string }}{{ chg.amount|format_currency('EUR') }}{{ chg.comment.comment|chill_print_or_message(null, 'blockquote') }}
    Total{{ totalCharges|format_currency('EUR') }}
    + {% else %} +

    {{ 'event.budget.no elements'|trans }}

    + {% endif %} +
    + {% if event.documents|length > 0 %}

    {{ 'event.fields.documents'|trans }}

    @@ -80,6 +185,97 @@
    {% endif %} +
    +

    {{ 'Participations'|trans }}

    + {% set count = event.participations|length %} +

    {{ 'count participations to this event'|trans({'count': count}) }}

    + + {% if count > 0 %} + + + + + + + + + + + + {% for participation in event.participations %} + + + + + + + + {% endfor %} + +
    {{ 'Person'|trans }}{{ 'Role'|trans }}{{ 'Status'|trans }}{{ 'Last update'|trans }} 
    + {% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with { + targetEntity: { name: 'person', id: participation.person.id }, + action: 'show', + displayBadge: true, + buttonText: participation.person|chill_entity_render_string, + isDead: participation.person.deathdate is not null + } %} + {{ participation.role.name|localize_translatable_string }}{{ participation.status.name|localize_translatable_string }}{{ participation.lastUpdate|ago }} {# sf4 check: filter 'time_diff' is abandoned, + alternative: knplabs/knp-time-bundle provide filter 'ago' #} + + +
      + {% if is_granted('CHILL_EVENT_PARTICIPATION_UPDATE', participation) %} +
    • + +
    • +
    • + +
    • + {% endif %} +
    +
    + + + {% endif %} + +
    +
    + {{ form_start(form_add_participation_by_person) }} +
    + {{ form_widget(form_add_participation_by_person.person_id, { 'attr' : { + 'class' : 'custom-select', + 'style': 'min-width: 15em; max-width: 18em; display: inline-block;' + }} ) }} +
    + + {{ form_end(form_add_participation_by_person) }} +
    +
    + +
    +
    +
    + {{ chill_delegated_block('block_footer_show', { 'event': event }) }} +
      @@ -100,97 +296,5 @@
    - -

    {{ 'Participations'|trans }}

    - {% set count = event.participations|length %} -

    {{ 'count participations to this event'|trans({'count': count}) }}

    - - {% if count > 0 %} - - - - - - - - - - - - {% for participation in event.participations %} - - - - - - - - {% endfor %} - -
    {{ 'Person'|trans }}{{ 'Role'|trans }}{{ 'Status'|trans }}{{ 'Last update'|trans }} 
    - {% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with { - targetEntity: { name: 'person', id: participation.person.id }, - action: 'show', - displayBadge: true, - buttonText: participation.person|chill_entity_render_string, - isDead: participation.person.deathdate is not null - } %} - {{ participation.role.name|localize_translatable_string }}{{ participation.status.name|localize_translatable_string }}{{ participation.lastUpdate|ago }} {# sf4 check: filter 'time_diff' is abandoned, - alternative: knplabs/knp-time-bundle provide filter 'ago' #} - - -
      - {% if is_granted('CHILL_EVENT_PARTICIPATION_UPDATE', participation) %} -
    • - -
    • -
    • - -
    • - {% endif %} -
    -
    - - - {% endif %} - - - -
    -
    - {{ form_start(form_add_participation_by_person) }} -
    - {{ form_widget(form_add_participation_by_person.person_id, { 'attr' : { - 'class' : 'custom-select', - 'style': 'min-width: 15em; max-width: 18em; display: inline-block;' - }} ) }} -
    - - {{ form_end(form_add_participation_by_person) }} -
    - -
    - {{ form_start(form_export, {'attr': {'id': 'export_tableur'}}) }} -
    - {{ form_widget(form_export.format, { 'attr' : { 'class': 'custom-select' } }) }} -
    - {{ form_widget(form_export.submit, { 'attr' : { 'class': 'btn btn-save' } }) }} -
    - -
    - {{ form_rest(form_export) }} - {{ form_end(form_export) }} -
    -
    - -
    - {{ chill_delegated_block('block_footer_show', { 'event': event }) }} -
    {% endblock %} diff --git a/src/Bundle/ChillEventBundle/Resources/views/Participation/confirm_delete.html.twig b/src/Bundle/ChillEventBundle/Resources/views/Participation/confirm_delete.html.twig index 0d993b075..4d88caf59 100644 --- a/src/Bundle/ChillEventBundle/Resources/views/Participation/confirm_delete.html.twig +++ b/src/Bundle/ChillEventBundle/Resources/views/Participation/confirm_delete.html.twig @@ -11,7 +11,7 @@ 'title' : 'Remove participation'|trans, 'confirm_question' : 'Are you sure you want to remove that participation ?'|trans, 'cancel_route' : activeRouteKey, - 'cancel_parameters' : { 'event_id' : event_id }, + 'cancel_parameters' : { 'id' : event_id }, 'form' : delete_form } ) }} diff --git a/src/Bundle/ChillEventBundle/Resources/views/Participation/edit.html.twig b/src/Bundle/ChillEventBundle/Resources/views/Participation/edit.html.twig index d1995b625..ab6bbdb37 100644 --- a/src/Bundle/ChillEventBundle/Resources/views/Participation/edit.html.twig +++ b/src/Bundle/ChillEventBundle/Resources/views/Participation/edit.html.twig @@ -33,7 +33,7 @@ {% set returnPath = app.request.get('return_path') %} {% set returnLabel = app.request.get('return_label') %} - + {{ returnLabel |default('Back to the event'|trans) }} diff --git a/src/Bundle/ChillEventBundle/Resources/views/Participation/new.html.twig b/src/Bundle/ChillEventBundle/Resources/views/Participation/new.html.twig index 620bc7995..180b16c59 100644 --- a/src/Bundle/ChillEventBundle/Resources/views/Participation/new.html.twig +++ b/src/Bundle/ChillEventBundle/Resources/views/Participation/new.html.twig @@ -34,7 +34,7 @@
    • - + {{ 'Back to the event'|trans }}
    • diff --git a/src/Bundle/ChillEventBundle/Security/EventVoter.php b/src/Bundle/ChillEventBundle/Security/EventVoter.php index 29fcb6e9d..0c1f58bd2 100644 --- a/src/Bundle/ChillEventBundle/Security/EventVoter.php +++ b/src/Bundle/ChillEventBundle/Security/EventVoter.php @@ -54,9 +54,9 @@ class EventVoter extends AbstractChillVoter implements ProvideRoleHierarchyInter ) { $this->voterHelper = $voterHelperFactory ->generate(self::class) - ->addCheckFor(null, [self::SEE]) + ->addCheckFor(null, [self::SEE, self::CREATE]) ->addCheckFor(Event::class, [...self::ROLES]) - ->addCheckFor(Person::class, [self::SEE, self::CREATE]) + ->addCheckFor(Person::class, [self::SEE]) ->addCheckFor(Center::class, [self::STATS]) ->build(); } diff --git a/src/Bundle/ChillEventBundle/Templating/Entity/EventThemeRender.php b/src/Bundle/ChillEventBundle/Templating/Entity/EventThemeRender.php new file mode 100644 index 000000000..6a10b61f7 --- /dev/null +++ b/src/Bundle/ChillEventBundle/Templating/Entity/EventThemeRender.php @@ -0,0 +1,109 @@ + + */ +class EventThemeRender implements ChillEntityRenderInterface +{ + public const AND_CHILDREN_MENTION = 'show_and_children_mention'; + + public const DEFAULT_ARGS = [ + self::SEPARATOR_KEY => ' > ', + self::SHOW_AND_CHILDREN => false, + self::AND_CHILDREN_MENTION => 'event_theme.and children', + ]; + + public const SEPARATOR_KEY = 'default.separator'; + + /** + * Show a mention "and children" on each EventTheme, if the event theme + * has at least one child. + */ + public const SHOW_AND_CHILDREN = 'show_and_children'; + + public function __construct(private readonly TranslatableStringHelper $translatableStringHelper, private readonly \Twig\Environment $engine, private readonly TranslatorInterface $translator) {} + + /** + * @throws RuntimeError + * @throws SyntaxError + * @throws LoaderError + */ + public function renderBox($entity, array $options): string + { + $options = array_merge(self::DEFAULT_ARGS, $options); + // give some help to twig: an array of parents + $parents = $this->buildParents($entity); + + return $this + ->engine + ->render( + '@ChillEvent/Entity/event_theme.html.twig', + [ + 'eventTheme' => $entity, + 'parents' => $parents, + 'options' => $options, + ] + ); + } + + public function renderString($entity, array $options): string + { + /** @var EventTheme $entity */ + $options = array_merge(self::DEFAULT_ARGS, $options); + + $titles = [$this->translatableStringHelper->localize($entity->getName())]; + + // loop to parent, until root + while ($entity->hasParent()) { + $entity = $entity->getParent(); + $titles[] = $this->translatableStringHelper->localize( + $entity->getName() + ); + } + + $titles = \array_reverse($titles); + + $title = \implode($options[self::SEPARATOR_KEY], $titles); + + if ($options[self::SHOW_AND_CHILDREN] && $entity->hasChildren()) { + $title .= ' ('.$this->translator->trans($options[self::AND_CHILDREN_MENTION]).')'; + } + + return $title; + } + + public function supports($entity, array $options): bool + { + return $entity instanceof EventTheme; + } + + private function buildParents(EventTheme $entity): array + { + $parents = []; + + while ($entity->hasParent()) { + $entity = $parents[] = $entity->getParent(); + } + + return $parents; + } +} diff --git a/src/Bundle/ChillEventBundle/chill.webpack.config.js b/src/Bundle/ChillEventBundle/chill.webpack.config.js index e2c1e14bc..3f13a7773 100644 --- a/src/Bundle/ChillEventBundle/chill.webpack.config.js +++ b/src/Bundle/ChillEventBundle/chill.webpack.config.js @@ -1,3 +1,10 @@ module.exports = function (encore, entries) { entries.push(__dirname + "/Resources/public/chill/index.js"); + + encore.addEntry( + "vue_event", + __dirname + "/Resources/public/vuejs/index.js", + ); }; + + diff --git a/src/Bundle/ChillEventBundle/config/services.yaml b/src/Bundle/ChillEventBundle/config/services.yaml index cee12a024..b117528a8 100644 --- a/src/Bundle/ChillEventBundle/config/services.yaml +++ b/src/Bundle/ChillEventBundle/config/services.yaml @@ -1,6 +1,7 @@ services: Chill\EventBundle\Controller\: autowire: true + autoconfigure: true resource: '../Controller' tags: ['controller.service_arguments'] @@ -8,4 +9,11 @@ services: autowire: true autoconfigure: true resource: '../Menu/' - tags: ['chill.menu_builder'] \ No newline at end of file + tags: ['chill.menu_builder'] + + Chill\EventBundle\Templating\Entity\: + autowire: true + autoconfigure: true + resource: '../Templating/Entity' + tags: + - 'chill.render_entity' diff --git a/src/Bundle/ChillEventBundle/config/services/controller.yaml b/src/Bundle/ChillEventBundle/config/services/controller.yaml index e69de29bb..2dda648c9 100644 --- a/src/Bundle/ChillEventBundle/config/services/controller.yaml +++ b/src/Bundle/ChillEventBundle/config/services/controller.yaml @@ -0,0 +1,4 @@ +services: + _defaults: + autowire: true + autoconfigure: true diff --git a/src/Bundle/ChillEventBundle/config/services/export.yaml b/src/Bundle/ChillEventBundle/config/services/export.yaml index 8f8399e31..529c14893 100644 --- a/src/Bundle/ChillEventBundle/config/services/export.yaml +++ b/src/Bundle/ChillEventBundle/config/services/export.yaml @@ -8,6 +8,9 @@ services: Chill\EventBundle\Export\Export\CountEvents: tags: - { name: chill.export, alias: 'count_events' } + Chill\EventBundle\Export\Export\ListEvents: + tags: + - { name: chill.export, alias: 'list_events' } Chill\EventBundle\Export\Export\CountEventParticipations: tags: - { name: chill.export, alias: 'count_event_participants' } diff --git a/src/Bundle/ChillEventBundle/config/services/forms.yaml b/src/Bundle/ChillEventBundle/config/services/forms.yaml index 8c81c3e63..ab5d788f8 100644 --- a/src/Bundle/ChillEventBundle/config/services/forms.yaml +++ b/src/Bundle/ChillEventBundle/config/services/forms.yaml @@ -31,3 +31,29 @@ services: Chill\EventBundle\Form\Type\PickEventType: tags: - { name: form.type } + + Chill\EventBundle\Form\EventThemeType: + tags: + - { name: form.type } + + Chill\EventBundle\Form\Type\PickEventThemeType: + tags: + - { name: form.type } + + Chill\EventBundle\Form\EventType: + tags: + - { name: form.type } + + Chill\EventBundle\Form\EventBudgetKindType: + tags: + - { name: form.type } + + Chill\EventBundle\Form\AddEventBudgetElementType: + tags: + - { name: form.type } + + Chill\EventBundle\Form\Type\PickAnimatorType: + tags: + - { name: form.type } + + diff --git a/src/Bundle/ChillEventBundle/migrations/Version20250428092611.php b/src/Bundle/ChillEventBundle/migrations/Version20250428092611.php new file mode 100644 index 000000000..811a368ad --- /dev/null +++ b/src/Bundle/ChillEventBundle/migrations/Version20250428092611.php @@ -0,0 +1,40 @@ +addSql('CREATE SEQUENCE chill_event_event_theme_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE chill_event_event_theme (id INT NOT NULL, parent_id INT DEFAULT NULL, isActive BOOLEAN NOT NULL, name JSON NOT NULL, ordering DOUBLE PRECISION DEFAULT \'0.0\' NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_80D7C6B0727ACA70 ON chill_event_event_theme (parent_id)'); + $this->addSql('ALTER TABLE chill_event_event_theme ADD CONSTRAINT FK_80D7C6B0727ACA70 FOREIGN KEY (parent_id) REFERENCES chill_event_event_theme (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_event_event_theme DROP CONSTRAINT FK_80D7C6B0727ACA70'); + $this->addSql('DROP TABLE chill_event_event_theme'); + } +} diff --git a/src/Bundle/ChillEventBundle/migrations/Version20250429062911.php b/src/Bundle/ChillEventBundle/migrations/Version20250429062911.php new file mode 100644 index 000000000..967442601 --- /dev/null +++ b/src/Bundle/ChillEventBundle/migrations/Version20250429062911.php @@ -0,0 +1,42 @@ +addSql('CREATE TABLE chill_event_eventtheme (event_id INT NOT NULL, eventtheme_id INT NOT NULL, PRIMARY KEY(event_id, eventtheme_id))'); + $this->addSql('CREATE INDEX IDX_8D75029771F7E88B ON chill_event_eventtheme (event_id)'); + $this->addSql('CREATE INDEX IDX_8D750297A81D3C55 ON chill_event_eventtheme (eventtheme_id)'); + $this->addSql('ALTER TABLE chill_event_eventtheme ADD CONSTRAINT FK_8D75029771F7E88B FOREIGN KEY (event_id) REFERENCES chill_event_event (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_event_eventtheme ADD CONSTRAINT FK_8D750297A81D3C55 FOREIGN KEY (eventtheme_id) REFERENCES chill_event_event_theme (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_event_eventtheme DROP CONSTRAINT FK_8D75029771F7E88B'); + $this->addSql('ALTER TABLE chill_event_eventtheme DROP CONSTRAINT FK_8D750297A81D3C55'); + $this->addSql('DROP TABLE chill_event_eventtheme'); + } +} diff --git a/src/Bundle/ChillEventBundle/migrations/Version20250505120818.php b/src/Bundle/ChillEventBundle/migrations/Version20250505120818.php new file mode 100644 index 000000000..3c5f45651 --- /dev/null +++ b/src/Bundle/ChillEventBundle/migrations/Version20250505120818.php @@ -0,0 +1,43 @@ +addSql(<<<'SQL' + CREATE SEQUENCE chill_event_budget_kind_id_seq INCREMENT BY 1 MINVALUE 1 START 1 + SQL); + $this->addSql(<<<'SQL' + CREATE TABLE chill_event_budget_kind (id INT NOT NULL, isActive BOOLEAN DEFAULT true NOT NULL, type VARCHAR(255) NOT NULL, name JSONB DEFAULT '{}' NOT NULL, PRIMARY KEY(id)) + SQL); + } + + public function down(Schema $schema): void + { + $this->addSql(<<<'SQL' + DROP SEQUENCE chill_event_budget_kind_id_seq CASCADE + SQL); + $this->addSql(<<<'SQL' + DROP TABLE chill_event_budget_kind + SQL); + } +} diff --git a/src/Bundle/ChillEventBundle/migrations/Version20250506114531.php b/src/Bundle/ChillEventBundle/migrations/Version20250506114531.php new file mode 100644 index 000000000..e349f50a7 --- /dev/null +++ b/src/Bundle/ChillEventBundle/migrations/Version20250506114531.php @@ -0,0 +1,61 @@ +addSql(<<<'SQL' + CREATE SEQUENCE chill_event_budget_element_id_seq INCREMENT BY 1 MINVALUE 1 START 1 + SQL); + $this->addSql(<<<'SQL' + CREATE TABLE chill_event_budget_element (id INT NOT NULL, event_id INT DEFAULT NULL, kind_id INT DEFAULT NULL, amount NUMERIC(10, 2) NOT NULL, comment_budget_element_comment TEXT DEFAULT NULL, comment_budget_element_date TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, comment_budget_element_userId INT DEFAULT NULL, PRIMARY KEY(id)) + SQL); + $this->addSql(<<<'SQL' + CREATE INDEX IDX_BA25859071F7E88B ON chill_event_budget_element (event_id) + SQL); + $this->addSql(<<<'SQL' + CREATE INDEX IDX_BA25859030602CA9 ON chill_event_budget_element (kind_id) + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE chill_event_budget_element ADD CONSTRAINT FK_BA25859071F7E88B FOREIGN KEY (event_id) REFERENCES chill_event_event (id) NOT DEFERRABLE INITIALLY IMMEDIATE + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE chill_event_budget_element ADD CONSTRAINT FK_BA25859030602CA9 FOREIGN KEY (kind_id) REFERENCES chill_event_budget_kind (id) NOT DEFERRABLE INITIALLY IMMEDIATE + SQL); + } + + public function down(Schema $schema): void + { + $this->addSql(<<<'SQL' + DROP SEQUENCE chill_event_budget_element_id_seq CASCADE + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE chill_event_budget_element DROP CONSTRAINT FK_BA25859071F7E88B + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE chill_event_budget_element DROP CONSTRAINT FK_BA25859030602CA9 + SQL); + $this->addSql(<<<'SQL' + DROP TABLE chill_event_budget_element + SQL); + } +} diff --git a/src/Bundle/ChillEventBundle/migrations/Version20250507073301.php b/src/Bundle/ChillEventBundle/migrations/Version20250507073301.php new file mode 100644 index 000000000..e5d7f0e52 --- /dev/null +++ b/src/Bundle/ChillEventBundle/migrations/Version20250507073301.php @@ -0,0 +1,55 @@ +addSql(<<<'SQL' + CREATE TABLE chill_event_thirdparty (event_id INT NOT NULL, thirdparty_id INT NOT NULL, PRIMARY KEY(event_id, thirdparty_id)) + SQL); + $this->addSql(<<<'SQL' + CREATE INDEX IDX_9946573E71F7E88B ON chill_event_thirdparty (event_id) + SQL); + $this->addSql(<<<'SQL' + CREATE INDEX IDX_9946573EC7D3A8E6 ON chill_event_thirdparty (thirdparty_id) + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE chill_event_thirdparty ADD CONSTRAINT FK_9946573E71F7E88B FOREIGN KEY (event_id) REFERENCES chill_event_event (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE chill_event_thirdparty ADD CONSTRAINT FK_9946573EC7D3A8E6 FOREIGN KEY (thirdparty_id) REFERENCES chill_3party.third_party (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE + SQL); + } + + public function down(Schema $schema): void + { + $this->addSql(<<<'SQL' + ALTER TABLE chill_event_thirdparty DROP CONSTRAINT FK_9946573E71F7E88B + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE chill_event_thirdparty DROP CONSTRAINT FK_9946573EC7D3A8E6 + SQL); + $this->addSql(<<<'SQL' + DROP TABLE chill_event_thirdparty + SQL); + } +} diff --git a/src/Bundle/ChillEventBundle/migrations/Version20250702144312.php b/src/Bundle/ChillEventBundle/migrations/Version20250702144312.php new file mode 100644 index 000000000..afb072ae9 --- /dev/null +++ b/src/Bundle/ChillEventBundle/migrations/Version20250702144312.php @@ -0,0 +1,79 @@ +addSql(<<<'SQL' + CREATE TABLE chill_event_animatorsintern (event_id INT NOT NULL, user_id INT NOT NULL, PRIMARY KEY(event_id, user_id)) + SQL); + $this->addSql(<<<'SQL' + CREATE INDEX IDX_E699558771F7E88B ON chill_event_animatorsintern (event_id) + SQL); + $this->addSql(<<<'SQL' + CREATE INDEX IDX_E6995587A76ED395 ON chill_event_animatorsintern (user_id) + SQL); + $this->addSql(<<<'SQL' + CREATE TABLE chill_event_animatorsextern (event_id INT NOT NULL, thirdparty_id INT NOT NULL, PRIMARY KEY(event_id, thirdparty_id)) + SQL); + $this->addSql(<<<'SQL' + CREATE INDEX IDX_7EFBF7DE71F7E88B ON chill_event_animatorsextern (event_id) + SQL); + $this->addSql(<<<'SQL' + CREATE INDEX IDX_7EFBF7DEC7D3A8E6 ON chill_event_animatorsextern (thirdparty_id) + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE chill_event_animatorsintern ADD CONSTRAINT FK_E699558771F7E88B FOREIGN KEY (event_id) REFERENCES chill_event_event (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE chill_event_animatorsintern ADD CONSTRAINT FK_E6995587A76ED395 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE chill_event_animatorsextern ADD CONSTRAINT FK_7EFBF7DE71F7E88B FOREIGN KEY (event_id) REFERENCES chill_event_event (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE chill_event_animatorsextern ADD CONSTRAINT FK_7EFBF7DEC7D3A8E6 FOREIGN KEY (thirdparty_id) REFERENCES chill_3party.third_party (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE + SQL); + } + + public function down(Schema $schema): void + { + $this->addSql(<<<'SQL' + ALTER TABLE chill_event_animatorsintern DROP CONSTRAINT FK_E699558771F7E88B + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE chill_event_animatorsintern DROP CONSTRAINT FK_E6995587A76ED395 + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE chill_event_animatorsextern DROP CONSTRAINT FK_7EFBF7DE71F7E88B + SQL); + $this->addSql(<<<'SQL' + ALTER TABLE chill_event_animatorsextern DROP CONSTRAINT FK_7EFBF7DEC7D3A8E6 + SQL); + $this->addSql(<<<'SQL' + DROP TABLE chill_event_animatorsintern + SQL); + $this->addSql(<<<'SQL' + DROP TABLE chill_event_animatorsextern + SQL); + } +} diff --git a/src/Bundle/ChillEventBundle/translations/messages.fr.yml b/src/Bundle/ChillEventBundle/translations/messages.fr.yml index 6319a0765..2251dbd6c 100644 --- a/src/Bundle/ChillEventBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillEventBundle/translations/messages.fr.yml @@ -7,7 +7,8 @@ Participation: Participation Participations: Participations Status: Statut Last update: Dernière mise à jour -Moderator: Animateur +Moderator: Responsable +Animators: Animateurs #CRUD event Details of an event: Détails d'un événement @@ -74,7 +75,7 @@ Show the event: Voir l'événement Subscribe an event: Ajouter un événement Pick an event: Choisir un événement Pick a type of event: Choisir un type d'événement -Pick a moderator: Choisir un animateur +Pick a moderator: Choisir un responsable # exports Select a format: Choisir un format @@ -128,15 +129,70 @@ Create a new type: Créer un nouveau type Create a new status: Créer un nouveau statut event: + admin: + title: + Event budget element list: Liste des elements du budget pour un évenement + Select budget type: Selectionner le type d'element du budget + new: + Create a new budget kind: Créér un nouveau element de budget + theme: + label: Thématiques fields: organizationCost: Coût d'organisation location: Localisation documents: Documents + internal animators: Animateurs internes + external animators: Animateurs externes form: organisationCost_help: Coût d'organisation pour la structure. Utile pour les statistiques. add_document: Ajouter un document remove_document: Supprimer le document + Select one or more themes: Selectionnez une ou plusieurs thématiques filter: event_types: Par types d'événement event_dates: Par date d'événement + center: Par centre + by_responsable: Par responsable + pick_responsable: Filtrer par responsables + budget: + resources: Ressources + charges: Charges + label: Elements de budget d'un évenement + Select a budget element kind: Selectionner un element de budget + no elements: Il y a aucun element + resource type: Ressource + charge type: Charge + amount: Montant + comment: Commentaire + animators: + intern: Animateurs internes + extern: Animateurs externes +crud: + event_theme: + title_new: Créér une nouvelle thématique + title_edit: Modifier la thématique + index: + title: Liste des thématiques + add_new: Créér une nouvelle thématique + event_budget_kind: + title_new: Créér un nouveau element de budget + +export: + event: + list: + title: Liste des évenements + description: Crée la liste des évenements en fonction de différents paramètres. + +event_id: Identifiant +event_name: Nom +event_date: Date +event_type: Type d'évenement +event_center: Centre +event_moderator: Responsable +event_participants_count: Nombre de participants +event_location: Localisation +event_budget_resources: Ressources +event_budget_charges: Charges +event_animators: Animateurs +event_themes: Thématiques diff --git a/src/Bundle/ChillMainBundle/Resources/public/chill/scss/chill_variables.scss b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/chill_variables.scss index 2f113f45b..dce2b4a34 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/chill/scss/chill_variables.scss +++ b/src/Bundle/ChillMainBundle/Resources/public/chill/scss/chill_variables.scss @@ -10,8 +10,9 @@ $chill-household-context: #929d69; // Badges colors $social-issue-color: #4bafe8; $social-action-color: $orange; +$event-theme-color: #ecc546; $activity-color: yellowgreen; // budget colors $budget-resource-color: #6d9e63; -$budget-charge-color: #e03851; \ No newline at end of file +$budget-charge-color: #e03851; diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue index 103849e3a..ffe7f0bc1 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue @@ -21,10 +21,12 @@ > @@ -43,7 +45,7 @@ @@ -62,13 +64,13 @@ > @@ -85,10 +87,12 @@ > @@ -108,17 +112,17 @@ @@ -139,7 +143,7 @@ > @@ -171,10 +175,12 @@ > @@ -193,10 +199,10 @@ @@ -216,13 +222,13 @@ @@ -244,9 +250,16 @@ import { postPostalCode, } from "../api"; import { - postAddressToPerson, - postAddressToHousehold, -} from "ChillPersonAssets/vuejs/_api/AddAddress.js"; + CREATE_A_NEW_ADDRESS, + ADDRESS_LOADING, + ACTIVITY_CREATE_ADDRESS, + ACTIVITY_EDIT_ADDRESS, + CANCEL, + SAVE, + PREVIOUS, + NEXT, + trans, +} from "translator"; import ShowPane from "./ShowPane.vue"; import SuggestPane from "./SuggestPane.vue"; import EditPane from "./EditPane.vue"; @@ -254,6 +267,17 @@ import DatePane from "./DatePane.vue"; export default { name: "AddAddress", + setup() { + return { + trans, + CREATE_A_NEW_ADDRESS, + ADDRESS_LOADING, + CANCEL, + SAVE, + PREVIOUS, + NEXT, + }; + }, props: ["context", "options", "addressChangedCallback"], components: { Modal, @@ -373,9 +397,11 @@ export default { (this.options.title.edit !== null || this.options.title.create !== null) ) { + console.log("this.options.title", this.options.title); + return this.context.edit - ? this.options.title.edit - : this.options.title.create; + ? ACTIVITY_EDIT_ADDRESS + : ACTIVITY_CREATE_ADDRESS; } return this.context.edit ? this.defaultz.title.edit @@ -505,7 +531,7 @@ export default { getAddress(id) .then( (address) => - new Promise((resolve, reject) => { + new Promise((resolve) => { this.entity.address = address; this.flag.loading = false; resolve(); @@ -522,7 +548,7 @@ export default { fetchCountries() .then( (countries) => - new Promise((resolve, reject) => { + new Promise((resolve) => { this.entity.loaded.countries = countries.results; if (this.flag.showPane === true) { this.closeShowPane(); @@ -550,7 +576,7 @@ export default { fetchCities(country) .then( (cities) => - new Promise((resolve, reject) => { + new Promise((resolve) => { this.entity.loaded.cities = cities.results.filter( (c) => c.origin !== 3, ); // filter out user-defined cities @@ -569,7 +595,7 @@ export default { fetchReferenceAddresses(city) .then( (addresses) => - new Promise((resolve, reject) => { + new Promise((resolve) => { this.entity.loaded.addresses = addresses.results; this.flag.loading = false; resolve(); @@ -800,7 +826,7 @@ export default { return postAddress(payload) .then( (address) => - new Promise((resolve, reject) => { + new Promise((resolve) => { this.entity.address = address; this.flag.loading = false; this.flag.success = true; @@ -849,7 +875,7 @@ export default { return patchAddress(payload.addressId, payload.newAddress) .then( (address) => - new Promise((resolve, reject) => { + new Promise((resolve) => { this.entity.address = address; this.flag.loading = false; this.flag.success = true; diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressMore.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressMore.vue index 4b59efbc6..9a6ffda10 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressMore.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress/AddressMore.vue @@ -1,6 +1,6 @@