mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-10 08:44:58 +00:00
Compare commits
1118 Commits
deploy/qui
...
optimize_a
Author | SHA1 | Date | |
---|---|---|---|
|
2d39fdb8ea | ||
|
cae3defedb | ||
|
78f66d4f14 | ||
ddbd6a9f23 | |||
b5eaea0e88 | |||
ed8a569fea | |||
c41bc7bef9 | |||
27dea97bc6 | |||
27125b838e | |||
4c55631297 | |||
cd6dec5082 | |||
152a7de1dc | |||
da19f68440 | |||
e895125d12 | |||
fe9b76a1fb | |||
baf9251000 | |||
665b38d166 | |||
9450d34af0 | |||
42301c9df7 | |||
eb1a7b2374 | |||
7f661f9022 | |||
178ffdf6bf | |||
5f0238f614 | |||
cfaa64884d | |||
faba2b67eb | |||
a981661ea5 | |||
3a3baa79c8 | |||
e35f002f2b | |||
fbd17a1de6 | |||
77d86d3836 | |||
eb11597f9c | |||
daa8b03c8b | |||
9ee679a3b3 | |||
8791c78426 | |||
abd60f7ddf | |||
75348f6ba7 | |||
75a06d6896 | |||
65782d3a6b | |||
1dc01fa8e2 | |||
db9a203df0 | |||
2a7e3c0334 | |||
ad72904aa9 | |||
0b57b3c74d | |||
8c0abbc5cd | |||
c42b7c014b | |||
0d5d4b3f05 | |||
a3e43fcaaa | |||
4047399b76 | |||
4c9d352c46 | |||
a316cb9568 | |||
14539f6f88 | |||
92e6506ecb | |||
59fed905e9 | |||
577d665f09 | |||
decc3c7463 | |||
1eb8d04a32 | |||
2f60ab4d17 | |||
3cf9920718 | |||
|
f1f13996f9 | ||
29838a4d8e | |||
e9b1f442bc | |||
e2feea15f9 | |||
14a13c7bd5 | |||
5a37bfd1a0 | |||
bd7f2d997e | |||
309fe40564 | |||
|
f8f019cfe6 | ||
460f0daf0a | |||
5de05c0ee9 | |||
|
7f721da08a | ||
|
9a34aa59bb | ||
|
00259dae20 | ||
|
fb8b8b354f | ||
d8c34c3089 | |||
74b649fb2c | |||
bac8e8d0b8 | |||
008a10dab8 | |||
a2df3c8144 | |||
d8444455c0 | |||
c793159593 | |||
26140de7de | |||
2c1d3d08c3 | |||
|
86c2a5c3e8 | ||
9420c34f58 | |||
d94fec3352 | |||
ba98283348 | |||
bfd95bff39 | |||
|
664fcd07ef | ||
a8df0070e8 | |||
440e21a83b | |||
8c2d211661 | |||
f2ebb1f33c | |||
c53636c40b | |||
0ec095b59a | |||
86c5376cc2 | |||
0e54b8cdf0 | |||
53e82f1b2a | |||
f4999548ac | |||
302f60e722 | |||
5b7484b1ce | |||
fc1dd499c4 | |||
3824a380ff | |||
315253589e | |||
af24637dc4 | |||
0fe248320d | |||
a26d278510 | |||
9641fd3fcc | |||
2b3c4b7af9 | |||
8853359405 | |||
704ec76ca4 | |||
|
6020ee2cb2 | ||
|
ba53ce40fa | ||
|
ab845d4569 | ||
|
dcb92b1378 | ||
|
59fcd1e96b | ||
|
0aec2fc1d1 | ||
|
e43ae56e73 | ||
3040ed9483 | |||
adc94aaeea | |||
c5fa1b883c | |||
644d0420ce | |||
e2230409b8 | |||
472866ce91 | |||
d5d12c4a17 | |||
e72ba4c940 | |||
|
ca7ba90717 | ||
f3ba3aeed9 | |||
c791c48248 | |||
5da332a06e | |||
eb89fa2cd4 | |||
82db55cfec | |||
349a0e69f1 | |||
4de106ec30 | |||
9851efa804 | |||
327fcbef8b | |||
d60b6aa3c4 | |||
f0d0f16d3c | |||
832c7bab9f | |||
78b56dc32d | |||
6301c4c10b | |||
b87c995d22 | |||
960db6aefc | |||
62f8d2c01d | |||
388db459bf | |||
d1e28b1afc | |||
d3bf64a00c | |||
84223316c4 | |||
9f07e6a272 | |||
47d6270b7f | |||
1d4b1d852f | |||
430177f0c7 | |||
72b1916da8 | |||
b5c2dd7bd2 | |||
a9ce72034b | |||
f93c2d8d32 | |||
463b615595 | |||
95e0198952 | |||
f93c13234a | |||
ee3776288b | |||
694213e79a | |||
a28c996164 | |||
05c5eaa925 | |||
d4116a4659 | |||
6b91808987 | |||
d5f1de1fbc | |||
fa9b571d6b | |||
|
d172ae9682 | ||
|
1a6c37e5a6 | ||
|
99f2692684 | ||
|
c6bbe46bae | ||
|
17036e83ba | ||
|
e8d8a57b4b | ||
|
3385cb2dda | ||
|
5b81bffcf6 | ||
|
27674985bd | ||
3c3baed1ce | |||
efd9380d13 | |||
0808f5a6f3 | |||
1c568a75ec | |||
e7676c5c2e | |||
a8024ba38f | |||
d994612987 | |||
3ee0f4bf20 | |||
15897b4f33 | |||
ca86eb3c56 | |||
14fdeac4fd | |||
98f1f19e9a | |||
4630e2b80c | |||
5d99e261e1 | |||
f7ec87e012 | |||
0ed2dc8b13 | |||
d52ab2188c | |||
4768785bb5 | |||
47d0043462 | |||
aa1f02ebd4 | |||
1672e873a3 | |||
f8d5dcf937 | |||
544af59009 | |||
851fa663ca | |||
019a66c915 | |||
dfc6ed9bf3 | |||
dbb9e6a663 | |||
d6f6f49090 | |||
7c2422743e | |||
e336990b16 | |||
dee27ee01f | |||
f1c29a8bd3 | |||
7df923c669 | |||
b06e726ad1 | |||
c62254caec | |||
c382008b4d | |||
f5348daddf | |||
e13b7bf195 | |||
edc528ff92 | |||
62e70c0c36 | |||
f2e945dc0f | |||
d2ce4865c0 | |||
7fe0f08300 | |||
7d2e82d69b | |||
3f3dd83132 | |||
f3b755e46e | |||
8ba74f8de8 | |||
690f649dd1 | |||
75a240a2d6 | |||
717cd03d95 | |||
1e829707be | |||
e7928c222d | |||
120f7d8026 | |||
b6c58a5c31 | |||
74598ee926 | |||
cf40f38463 | |||
ebb2f5d243 | |||
50b7554aea | |||
f63d4fcfba | |||
6bc83edfe9 | |||
f87f03b5c0 | |||
addcf72ae6 | |||
b4e78a948b | |||
9b38e486df | |||
960bac8c37 | |||
dc09c9424a | |||
5b70fb2ee5 | |||
2450655452 | |||
41d76542b4 | |||
7faddbe3fe | |||
eec798cfd3 | |||
03e8624528 | |||
501ffe7829 | |||
a842229d5e | |||
4b87e16f6d | |||
2788170f03 | |||
1b4e5c4956 | |||
601c16ac27 | |||
bde9e44f87 | |||
4855ec2065 | |||
c440d8a2bd | |||
210d819125 | |||
8204107ceb | |||
3f3b7af42b | |||
331dd286e7 | |||
f048395a89 | |||
6a60758c0d | |||
782f0bc332 | |||
4bafa83b65 | |||
6e42b08627 | |||
3c5f0ce15e | |||
7ab57eba9a | |||
3279db85de | |||
6ab1391bd8 | |||
ce40814aa9 | |||
c58d1eccc5 | |||
f66df3b77c | |||
2aa0bbf371 | |||
0bb0b24c21 | |||
aae2ee32f6 | |||
8dbdc28df1 | |||
9ff58fe0c3 | |||
da32afeb3f | |||
a5ceb551eb | |||
17a3f45247 | |||
9ef91eabfb | |||
310e9f5a82 | |||
9725970c56 | |||
546a2e4fa1 | |||
c2f75654dd | |||
683eac91d8 | |||
6e31e01e51 | |||
e94790b8ab | |||
92fae5cba2 | |||
df28494f16 | |||
4046a7ca9b | |||
910016f722 | |||
a4f446c6b9 | |||
d7a4e6c037 | |||
e03f41ffbc | |||
2e5c2de363 | |||
|
951d686366 | ||
|
fe533bc716 | ||
|
6c47ce53e7 | ||
4448547fcd | |||
b80d109d8e | |||
dd0e695ac2 | |||
6a21bcc520 | |||
f7cb93fdac | |||
7dc85b8474 | |||
ee01020ae6 | |||
dcbac34b96 | |||
6fe78b7177 | |||
6fa0d229af | |||
e4cfb4804b | |||
6c61b2da30 | |||
dc2f094ca2 | |||
4525f01d5f | |||
3fe7e131a2 | |||
db92531257 | |||
5512e25cdf | |||
a0df8d8c61 | |||
a6826623bc | |||
267c3bae6e | |||
a131510ea8 | |||
eca00d155f | |||
6680ba19ce | |||
|
813da1f9e0 | ||
337a6eb974 | |||
ed31dc3157 | |||
98729af065 | |||
75aa600a20 | |||
caca9ad71f | |||
5a4cb31ea5 | |||
|
c82efc4fd5 | ||
6ab0007f02 | |||
672133fb5e | |||
|
503c97d8c6 | ||
|
5dc430ed31 | ||
|
855686c0ba | ||
da9d81dc05 | |||
fa938471aa | |||
c89e2662b1 | |||
|
f6f24d0beb | ||
|
29c148f924 | ||
|
0ab53f4659 | ||
|
c42ec1d493 | ||
|
82e76d7d5a | ||
|
0a274eb2a4 | ||
|
6bfc180951 | ||
|
e1ccc8aba5 | ||
|
25b85fcc68 | ||
|
bcb36ddc11 | ||
|
6d607e3939 | ||
|
0fe6d7d00b | ||
|
329d3cc3d8 | ||
|
ee4d23ff82 | ||
|
54ea954a5a | ||
|
864f84fede | ||
|
68538f0e85 | ||
|
74957154b1 | ||
ff7cb6ca79 | |||
753e6c1105 | |||
88c192c22e | |||
05aaa32881 | |||
5211fb2fe9 | |||
3a6a0da1dd | |||
e99a371f3a | |||
dba3ede9e1 | |||
a94a757ae6 | |||
cf78c59e76 | |||
6e57d16ebf | |||
f4ce634061 | |||
f9402ec981 | |||
98b0b3beeb | |||
1a95b44577 | |||
93c08f7e18 | |||
1262d8cc16 | |||
e5690b7575 | |||
406426111a | |||
374ac652d4 | |||
2208518ca0 | |||
d51752fa41 | |||
3ccc82147b | |||
81f97980fc | |||
8b945dc38b | |||
b11592fb6d | |||
d575b48e76 | |||
3fefaf1e4d | |||
9b8b60ed75 | |||
f2f39d0922 | |||
eb067fe59b | |||
aad0d295ef | |||
46560da67d | |||
3bb0e470bc | |||
81b7e769e1 | |||
7c37a5f583 | |||
c51b129a5e | |||
21630a37af | |||
f2248a1e9c | |||
d8b2d3cd90 | |||
b14b27c110 | |||
f6e65dddbe | |||
b940348452 | |||
90faa27461 | |||
a4118b1235 | |||
903d57ea9d | |||
820def6294 | |||
19a4542e2b | |||
9961c38b3c | |||
f41997e6da | |||
3927fd738c | |||
b69fdd459a | |||
1a2cb22b5b | |||
3fa4f1b28b | |||
c0d2454473 | |||
2cffd61b86 | |||
b9602aa720 | |||
219a41e034 | |||
983bca97ac | |||
c1d19640a9 | |||
5fd7d869bf | |||
4f6011348d | |||
d4430246f7 | |||
8182e35c9c | |||
c258179017 | |||
2333b5c6b4 | |||
a302f0fdbf | |||
52a0c0e95b | |||
c5f40c53ea | |||
5194cad354 | |||
34df295801 | |||
ccb302ad28 | |||
a0fd3cd481 | |||
25f43bc758 | |||
e369e43b00 | |||
88362bd284 | |||
5884fbaffc | |||
ddd1eb5d10 | |||
7d6def733c | |||
bfed062910 | |||
d3e52e81f1 | |||
647bdb2749 | |||
8fb4a7110e | |||
cd6aeefb07 | |||
668b3e182e | |||
a0b914380b | |||
bbc3399e19 | |||
52fa4b5549 | |||
3894c7a56d | |||
4933edaa94 | |||
9fd455b622 | |||
3451bcaab1 | |||
d1344d6d54 | |||
73a1d42ee7 | |||
3ceb3d4b2b | |||
10b1edda11 | |||
a0f0e4e9ad | |||
b79c1f02da | |||
c798b1290c | |||
af0905c6e0 | |||
bd528c9025 | |||
4fed96f988 | |||
3bffde6123 | |||
9fa82fc44c | |||
4001bb0996 | |||
d6135641c5 | |||
075f22e79c | |||
09e5cc1545 | |||
37b73931c4 | |||
4ad6786bf2 | |||
d11c493e2d | |||
9795704532 | |||
883cb858a9 | |||
b301c1d405 | |||
6959de4e39 | |||
9c25132216 | |||
87a917d11c | |||
026562c32f | |||
b37de4cd4f | |||
14cbb1dd28 | |||
4d65c54996 | |||
2a3f869882 | |||
d198c33f9c | |||
949a453b48 | |||
4f1a9c205f | |||
638af4728f | |||
742445e7b3 | |||
4ee67869bd | |||
|
223efba655 | ||
|
fec8fa50ed | ||
8bcd69c5ec | |||
badf632a8a | |||
7363092d51 | |||
d2b0b9d7da | |||
|
de8478f3e5 | ||
bf0a24b38e | |||
|
026ac91e69 | ||
|
6a6b1760f5 | ||
698514ef12 | |||
38dcca7397 | |||
176b68417a | |||
1d2299e143 | |||
20ef04683d | |||
b9674d7d28 | |||
ffec80c5fd | |||
7f28effc1e | |||
28f69d8dec | |||
55c34c2583 | |||
80672a038c | |||
3e27589cca | |||
|
9fc7ed0fb6 | ||
|
975f27f780 | ||
|
043e865eb0 | ||
|
0479ddb42b | ||
f2b5cd7636 | |||
d100de4fcd | |||
e711ac1feb | |||
5b8439e13c | |||
06abefd576 | |||
|
3799627bf1 | ||
8295788d7f | |||
52469d995a | |||
b4234ddc58 | |||
71e6b356c3 | |||
bbcf9cc4ca | |||
07030922e8 | |||
c16c517e97 | |||
a0afaa568d | |||
75d3dfb830 | |||
a797143511 | |||
bb471fd4af | |||
fdd08905a8 | |||
|
4ae9b29924 | ||
|
364346d0aa | ||
|
1a025ead1b | ||
|
73c90f8c6a | ||
|
772388298d | ||
|
4184a74e7e | ||
|
237476dc28 | ||
|
e6f5ef91ec | ||
755812ae3c | |||
|
c9cc0dd2a9 | ||
|
10c9526b49 | ||
3602b0d097 | |||
|
53cad32910 | ||
|
2a40645604 | ||
|
da505ed106 | ||
|
fe4b9647b9 | ||
|
1d7ef9300c | ||
|
bb9e175849 | ||
|
5a3fd2712c | ||
5dc92ed5bd | |||
|
7e64ec0a45 | ||
|
0a183c8cfc | ||
|
60328032d8 | ||
|
cf4f25aaff | ||
|
71900010f6 | ||
|
3599508a3b | ||
|
b1c15ec8ce | ||
d61dbaed91 | |||
|
6a609eb1ab | ||
9ac72a21d1 | |||
fd8f4a98c0 | |||
|
96ade5bd36 | ||
|
6383c1ca7b | ||
|
8be99bfe50 | ||
13ff55c967 | |||
8c0d8692b0 | |||
|
65bce1aacb | ||
2394895ccb | |||
60f7bdc926 | |||
6ca35d5a18 | |||
6253927e2e | |||
|
4f39676e97 | ||
|
84a460c4e7 | ||
|
494573e5b4 | ||
|
c16fc77d01 | ||
|
282539ae6b | ||
|
50f1d3cd10 | ||
|
4e04714a42 | ||
|
8992b99d56 | ||
|
62536ab2ff | ||
|
b189726380 | ||
|
a63c26482e | ||
|
c208797daf | ||
|
0366d0cb17 | ||
|
2b7fa630fc | ||
|
a41b959fbd | ||
|
e4d9129af2 | ||
|
72fc6e05cc | ||
|
47a2af6f19 | ||
|
1bd01aefae | ||
|
c6b6fa5bf6 | ||
|
36d582c8ab | ||
|
df544bdfa4 | ||
|
12e17fac82 | ||
|
b2d84a7677 | ||
|
ebb679dbbb | ||
|
61bb595bba | ||
|
c7aafc6730 | ||
|
24b675ce97 | ||
|
3c888238c5 | ||
|
1bd00535ce | ||
|
d616e00660 | ||
|
5d5ad9e4f7 | ||
|
28af73db19 | ||
0f87d77896 | |||
8b50e5bd62 | |||
f490fdd37c | |||
7ffdf4cb1f | |||
801e897a38 | |||
21db8674e7 | |||
de7322464b | |||
90cfcd0569 | |||
4a0ffd2cba | |||
3e9d96368d | |||
227d627ad5 | |||
c7a2bbfc1d | |||
|
d8ca9cf082 | ||
|
0457ee2b8d | ||
bab06796f1 | |||
|
7c4f976230 | ||
1aa77bd1c4 | |||
39e8af48b4 | |||
9447516694 | |||
9a1f56a820 | |||
|
dbf72774c2 | ||
|
a70d5cc263 | ||
|
07eb5c797a | ||
|
a54434a677 | ||
|
ca9738b55a | ||
|
b40c25595a | ||
|
e6deb6bc7a | ||
|
e499ebdf8b | ||
|
07f086dd61 | ||
|
f2d79919f0 | ||
|
02a9e21f62 | ||
|
323434f34e | ||
|
afad23eb0f | ||
|
981c819f56 | ||
|
9907b59379 | ||
|
dc3c8a4032 | ||
|
95b50f2b99 | ||
|
b106a03534 | ||
|
b7c5a459f7 | ||
|
4a6914be22 | ||
|
5181098339 | ||
|
cc3e7f54a7 | ||
df7e76a2e7 | |||
ccd5ac74fd | |||
29c2ed3ce8 | |||
4c17ce7926 | |||
d49fd9738b | |||
892e43d195 | |||
|
fe3cbdadab | ||
|
c54290a265 | ||
|
de6df983a0 | ||
|
0585455bbe | ||
|
f508971b6a | ||
|
5c8b247f40 | ||
|
9c7c890943 | ||
|
7e02b284ca | ||
|
d4ec5d137e | ||
|
d542f582e6 | ||
|
3c37802821 | ||
|
227be0b482 | ||
|
4b8736ae57 | ||
|
206347de91 | ||
|
516c286519 | ||
|
adc462b735 | ||
|
43d6dc835f | ||
|
1557b8f80a | ||
|
20d113b1db | ||
|
114df16e0f | ||
|
b01eba2533 | ||
|
75caf3fa14 | ||
|
fdccdfe7b1 | ||
|
38ec2b5de9 | ||
|
3010df2016 | ||
|
3e7a9522b6 | ||
d652771af0 | |||
9d655d92f2 | |||
9e51717984 | |||
a6b360c193 | |||
42b9e25403 | |||
403922c631 | |||
53fe90adc3 | |||
41fe95c80f | |||
28435940f1 | |||
34e1a9b748 | |||
097ad3a364 | |||
816d860f4a | |||
c7cc2c7596 | |||
6ad8a73fc0 | |||
4cf676858e | |||
b87046dcd6 | |||
76eea2a4eb | |||
7ba3e0287a | |||
54ac122863 | |||
eac4c48d8f | |||
160383e3a3 | |||
7af85bc401 | |||
cdc6cf211a | |||
|
f12dc97d57 | ||
|
a58bdb466c | ||
1a6c0529cc | |||
|
23366d5582 | ||
|
f58be46466 | ||
65e72b05c5 | |||
|
069b3d1839 | ||
|
cbdf976885 | ||
|
8df4c93c97 | ||
|
5ce6d37a69 | ||
|
7dc501cbda | ||
|
8207db4b45 | ||
f5c5038fda | |||
436d583f65 | |||
533865c41a | |||
14c0c9763f | |||
a54e70f9e0 | |||
63b820784f | |||
71b54622e2 | |||
190549180b | |||
375326fc32 | |||
a1435314a0 | |||
8d98a144fd | |||
d0fa28db2a | |||
9ac14ff5e3 | |||
d67483fd9a | |||
3156706c2b | |||
44e85361e6 | |||
320f16a121 | |||
5635d19252 | |||
6544566c34 | |||
9f7c0dcd09 | |||
0e2e7155fb | |||
8a962a4f1c | |||
2f699d32b0 | |||
72a1ac02eb | |||
c420d2bfd7 | |||
8d2b1fbe13 | |||
a3a5d5cfd0 | |||
3302d69373 | |||
f188cc2d27 | |||
8f9c8bc1a6 | |||
43f9e50100 | |||
aa0ff37479 | |||
20cdec20d2 | |||
0abb4983f7 | |||
5a716a3523 | |||
29b5e700f6 | |||
e8e2607076 | |||
107699ec31 | |||
25465b1121 | |||
|
8834f200df | ||
|
cc84c067c5 | ||
|
d8ee42b0a5 | ||
|
a948d9e2da | ||
|
c9a5d0548c | ||
|
c37ba5db6a | ||
54c4524b27 | |||
966292cdd5 | |||
9d1166d8fc | |||
1b3904f8e3 | |||
77fe497994 | |||
b89a66b20c | |||
2d2bb117ca | |||
17dd52c3dc | |||
d6e41e5ac7 | |||
b0187d0594 | |||
ea691d9b32 | |||
1d2cbc4f62 | |||
5e0c930087 | |||
f535e794a7 | |||
2f28e02f65 | |||
438134690f | |||
166144e57e | |||
1600d3d271 | |||
4b69f97e2f | |||
64433b420d | |||
8f9d4a1765 | |||
c302452e01 | |||
6bb5440220 | |||
c48586cd0e | |||
205c48f58a | |||
368bbcf9b2 | |||
76a4b24aa1 | |||
21fd69488f | |||
f6376118a0 | |||
a6001c195a | |||
8829d234ec | |||
6ee0acfa0f | |||
7d97889cbf | |||
|
364aff36a4 | ||
|
3f1b5b2319 | ||
fc6a9ad64f | |||
4c7129a3b2 | |||
bbb69bcfe0 | |||
a1ed0d3ce4 | |||
fb43980a2a | |||
da98b42c8c | |||
840ffe42a6 | |||
1f8c343a89 | |||
f6a02e157d | |||
21957846b0 | |||
1c7e1b55f8 | |||
ea391d18e9 | |||
72cd9f452e | |||
44313b507a | |||
46bd70881e | |||
fbf343dd19 | |||
028af50dbc | |||
0075fed9a5 | |||
62dc94bb14 | |||
c075ff199d | |||
e178183cef | |||
63fbf4b249 | |||
9f77b84e48 | |||
fae196d3eb | |||
ca4d542604 | |||
75be8aa557 | |||
9e94cea9d5 | |||
6d58bf152b | |||
47d704b521 | |||
cdbd97e595 | |||
24714227b8 | |||
da09e10fb1 | |||
b74f9cf5dc | |||
b62597426c | |||
6c0ab6f25e | |||
9f3ceb94f0 | |||
|
6b4e27a531 | ||
|
3be024bf6b | ||
|
88847cb19c | ||
|
ad5eed4c26 | ||
|
25eee88693 | ||
|
c32ca59c76 | ||
|
94b0432bb9 | ||
9ee140a7d8 | |||
5d598bf46b | |||
8649d49d98 | |||
d67b99b269 | |||
01cc230136 | |||
ac999a4f17 | |||
794c7d0c4a | |||
07ffc86ced | |||
718933af75 | |||
884de5c19e | |||
d948ba0cd5 | |||
0072f4c676 | |||
72b43e9a99 | |||
7a56ff7d29 | |||
51f4d2ab0e | |||
4716ab3e3c | |||
3d630eeedf | |||
61d8e06975 | |||
eec913375e | |||
7f3b266209 | |||
85b7e4add8 | |||
fadf2d62b0 | |||
3e498c34e5 | |||
81de17594d | |||
e42a5217be | |||
a0154331de | |||
3d2cc340a6 | |||
82841f47c8 | |||
b571620e6c | |||
357b87dadb | |||
a5948259d9 | |||
0bc894836f | |||
23bc71a38c | |||
3082634323 | |||
4cd2dc63c5 | |||
ff58816ee0 | |||
7b8a067002 | |||
c13f63b3ba | |||
94d743c5b6 | |||
2290da6f3b | |||
f9195aa881 | |||
84dc5bd881 | |||
1edcb399c4 | |||
9ac31d2d8b | |||
ccf5b90951 | |||
ee8e9f1ebc | |||
4fa1820d8d | |||
e72a8fe5a0 | |||
|
9b756ffb2f | ||
7ee91afae2 | |||
7665181d44 | |||
a8047fd89b | |||
61f6e95281 | |||
ad55cc0477 | |||
714d8b841c | |||
e2e38a9ce8 | |||
d916b575da | |||
982c704f6c | |||
9f5086e9c1 | |||
ee819e7767 | |||
d34a00b2c0 | |||
a096266ca5 | |||
96e979f92d | |||
48873d15c9 | |||
4be4cd7279 | |||
c4a8b85be5 | |||
4c47105de1 | |||
1c404e5cb3 | |||
6dae4785e6 | |||
360322bdbf | |||
8c06014ea5 | |||
98dd31dffc | |||
1325355ca7 | |||
9764ee1794 | |||
a48d7f5e94 | |||
4eef8492b1 | |||
949366cf7b | |||
65fe9ab784 | |||
532d4aa164 | |||
02bea40cc4 | |||
51216b90c5 | |||
f9735823c7 | |||
b683e60cf7 | |||
e8e4dbef1f | |||
7e4afc826b | |||
31c5c8b52a | |||
f734210db5 | |||
014fe19b45 | |||
08cd6c81f2 | |||
175d6892ec | |||
4cac5f9a4a | |||
6dac130844 | |||
886924a7e5 | |||
55ac730c18 | |||
87a7e0de00 | |||
39f6f14467 | |||
5ef5b65d90 | |||
ad3fe7cf91 | |||
4e9916534f | |||
3637ae6aee | |||
2893b9c726 | |||
42784cf584 | |||
3169da20ad | |||
81752befcf | |||
3c7b67604c | |||
4e8dd3b189 | |||
50e9a06e49 | |||
57a8b49f49 | |||
df3d32c653 | |||
4cca148f69 | |||
34f22d237e | |||
|
d0b51f3573 | ||
|
53d3a0921b | ||
|
cc824faf54 | ||
|
b33cb4946c | ||
|
ef6c5870b5 | ||
|
e1f8aa5a5e | ||
|
d208a79764 | ||
|
b41b1346e5 | ||
|
d50d3e0e4b | ||
|
401659748c | ||
|
c25c302466 | ||
|
c37b98cecd | ||
|
979ea5841d | ||
|
9e9a459a20 | ||
89dfea74b3 | |||
4b3f4edcc1 | |||
376d8df55e | |||
5d1d6c83a9 | |||
a6266c5317 | |||
b0ef9b6612 | |||
8384508c1a | |||
d20a3cf9d4 | |||
e0dbe9cf9d | |||
|
5c2c509805 | ||
|
9d478c0f01 | ||
|
4646795c2c | ||
d8d66aeeb6 | |||
7ac61002b0 | |||
c9562ebdf7 | |||
|
18369a6c0a | ||
|
0fd9485de5 | ||
c8f139528a | |||
8030792eb6 | |||
|
50a4df3d0f | ||
|
0907ae1602 | ||
|
673a4761e9 | ||
|
282db51f06 | ||
|
bdf691a063 | ||
|
18ab10dd45 | ||
0cd9dc6028 | |||
65198937c0 | |||
2699d48533 | |||
a559589883 | |||
d81f5bafe3 | |||
c6a3f59d87 | |||
ff671ded9c | |||
678c7d18b4 | |||
f73f515fb3 | |||
afd4ac27ea | |||
ea734e2a9e | |||
587da94645 | |||
3f9e215ea5 | |||
732390f704 | |||
25b00296ca | |||
1e626d573f | |||
3ee676600e | |||
d2c631ae20 | |||
8462538123 | |||
645252fd85 | |||
08e396195c | |||
ab0863a275 | |||
82c79a17dd | |||
d35553a1e2 | |||
030e71d276 | |||
4fc3d813c4 | |||
5f012165d1 | |||
61bd5d8ae8 | |||
07c464c112 | |||
70a4c34865 | |||
5a47ebed42 | |||
80eb5519bc | |||
50f3ec9064 | |||
bdf0ec63d2 | |||
15f439b43d | |||
30af99f4f0 | |||
c413166866 | |||
3c4c5e29a3 | |||
0224224744 | |||
a9a59895b4 | |||
8a859f7885 | |||
2244c58ec2 | |||
c1ede921ff | |||
17ff80c39c | |||
f4f747d8d1 | |||
a740ad29ea | |||
ccee105efb | |||
b10012f4da | |||
4937fd00fc | |||
0b329a9c9b | |||
4cfc43aaa6 | |||
1c45770929 | |||
198c815052 | |||
a995adcf0d | |||
bccda15307 | |||
75c3df50e0 | |||
ce8207ea65 | |||
0f6ad3670a | |||
02a752f20b | |||
1bbce2bb81 | |||
ca43933163 | |||
1392365257 | |||
3653d7e0b8 | |||
3970bb2644 | |||
ea2d6eac7b | |||
9a1272d350 | |||
e7c76734a6 | |||
8389afb4a8 | |||
36419cf5f0 | |||
fc074c2f1a | |||
eff1d6e797 | |||
10de2d7966 | |||
c96f407e6a | |||
690688f5e1 | |||
4668f657ab | |||
49253abfb8 | |||
c2122d62c6 | |||
ca17ca4984 | |||
a5d749b882 | |||
53c021b06e | |||
b6e8c64211 | |||
342fd3e297 | |||
05a1f7d041 | |||
2e2eeae4f2 | |||
c27268443c | |||
|
842dfcc69f | ||
|
67c31e781d | ||
f32ffc572d | |||
a44b26da6c | |||
d016f9be86 | |||
c36aa22ab2 | |||
e77c886e3f | |||
4ca1618480 | |||
8e8cdfce0a | |||
3694eb5bf2 | |||
e44342ab87 | |||
a236873919 | |||
a13766e7d7 | |||
bc240a6754 | |||
50727fc4b0 | |||
b327a3fbfa | |||
2916babe1c | |||
fe2f107ddc | |||
3da8f89d3c | |||
19326ee750 | |||
e0ae5d56f0 | |||
0878767c17 | |||
f0232228a3 | |||
fc63955205 | |||
a78de0f96c | |||
270c0accc5 | |||
fd94f27eee | |||
f7e3be38a7 | |||
5861a86289 | |||
68c0f9b7d7 | |||
52288f7260 | |||
2fe1605385 | |||
d8256b0ac5 | |||
b5760e82ea | |||
d3ac8d8ceb | |||
196f709065 | |||
6a8c96cdae | |||
3e83891744 | |||
|
d71c3f310e | ||
|
4a2ada784a | ||
|
3b5ef53b9b | ||
|
18d0ad67d6 | ||
|
ea1c12da64 | ||
|
141aabcddc | ||
|
6e37e7feac | ||
|
df1f44d814 | ||
|
dc26ca7e77 | ||
|
2667867bd0 | ||
|
5ddc0e7a53 |
@@ -7,6 +7,7 @@ charset = utf-8
|
||||
end_of_line = LF
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
indent_size = 4
|
||||
|
||||
[*.{php,html,twig}]
|
||||
indent_style = space
|
||||
|
@@ -5,11 +5,13 @@ image: registry.gitlab.com/chill-projet/chill-app/php-base-image:7.4
|
||||
cache:
|
||||
paths:
|
||||
- tests/app/vendor/
|
||||
- .composer
|
||||
|
||||
before_script:
|
||||
# add extensions to postgres
|
||||
- PGPASSWORD=$POSTGRES_PASSWORD psql -U $POSTGRES_USER -h db -c "CREATE EXTENSION IF NOT EXISTS unaccent; CREATE EXTENSION IF NOT EXISTS pg_trgm;"
|
||||
# Install and run Composer
|
||||
- mkdir -p $COMPOSER_HOME
|
||||
- curl -sS https://getcomposer.org/installer | php
|
||||
- php -d memory_limit=2G composer.phar install
|
||||
- php tests/app/bin/console doctrine:migrations:migrate -n
|
||||
@@ -34,6 +36,10 @@ variables:
|
||||
REDIS_HOST: redis
|
||||
REDIS_PORT: 6379
|
||||
REDIS_URL: redis://redis:6379
|
||||
# change vendor dir to make the app install into tests/apps
|
||||
COMPOSER_VENDOR_DIR: tests/app/vendor
|
||||
# cache some composer data
|
||||
COMPOSER_HOME: .composer
|
||||
|
||||
|
||||
# Run our tests
|
||||
|
45
CHANGELOG.md
Normal file
45
CHANGELOG.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to
|
||||
|
||||
* [Semantic Versioning](https://semver.org/spec/v2.0.0.html) for stable releases;
|
||||
* date versioning for test releases
|
||||
|
||||
## Unreleased
|
||||
|
||||
* Address: zoom on postal code geometry + fix origin of manually entered postal code
|
||||
|
||||
* [Aside activity] Fixes for aside activity
|
||||
|
||||
* categories with child
|
||||
* fast creation buttons
|
||||
* add ordering for types
|
||||
|
||||
|
||||
## Test releases
|
||||
|
||||
### test release 2021-10-04
|
||||
|
||||
* [Household editor][UI] Update how household suggestion and addresses are picked;
|
||||
* [AddAddress] Handle address suggestion;
|
||||
* [CenterType][Create a person] when overriding the ACL rules, allow to show a PickCenterType
|
||||
when no centers are reachable by the default ACL.
|
||||
* [Household] Show comment event if no address are associated with the household;
|
||||
* [Person results] Add requestor into search results:
|
||||
|
||||
* a badge "requestor" is shown into search results;
|
||||
* periods where the person is only requestor (without participating) are also shown;
|
||||
|
||||
Issues:
|
||||
|
||||
* https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/13
|
||||
* https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/199
|
||||
* [Person form] "accept sms" not required:
|
||||
|
||||
https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/37
|
||||
https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/221
|
||||
* On-The-Fly modale works for showing, editing and creating person and thirdparty ;
|
||||
* AccompanyingCourse Resume page: list associated persons by household, see household when hover, and show on-the-fly modale when clicking on person ;
|
134
composer.json
134
composer.json
@@ -1,9 +1,72 @@
|
||||
{
|
||||
"name": "chill-project/chill-bundles",
|
||||
"license": "AGPL-3.0-only",
|
||||
"type": "library",
|
||||
"description": "Most used bundles for chill-project",
|
||||
"keywords": ["chill", "social worker"],
|
||||
"keywords": [
|
||||
"chill",
|
||||
"social worker"
|
||||
],
|
||||
"license": "AGPL-3.0-only",
|
||||
"require": {
|
||||
"champs-libres/async-uploader-bundle": "dev-sf4",
|
||||
"champs-libres/wopi-bundle": "dev-master",
|
||||
"composer/package-versions-deprecated": "^1.10",
|
||||
"doctrine/doctrine-bundle": "^2.1",
|
||||
"doctrine/doctrine-migrations-bundle": "^3.0",
|
||||
"doctrine/orm": "^2.7",
|
||||
"erusev/parsedown": "^1.7",
|
||||
"graylog2/gelf-php": "^1.5",
|
||||
"knplabs/knp-menu": "^3.1",
|
||||
"knplabs/knp-menu-bundle": "^3.0",
|
||||
"knplabs/knp-time-bundle": "^1.12",
|
||||
"league/csv": "^9.7.1",
|
||||
"nyholm/psr7": "^1.4",
|
||||
"phpoffice/phpspreadsheet": "^1.16",
|
||||
"ramsey/uuid-doctrine": "^1.7",
|
||||
"sensio/framework-extra-bundle": "^5.5",
|
||||
"symfony/asset": "4.*",
|
||||
"symfony/browser-kit": "^5.2",
|
||||
"symfony/css-selector": "^5.2",
|
||||
"symfony/expression-language": "4.*",
|
||||
"symfony/form": "4.*",
|
||||
"symfony/intl": "4.*",
|
||||
"symfony/mime": "^4 || ^5",
|
||||
"symfony/monolog-bundle": "^3.5",
|
||||
"symfony/security-bundle": "4.*",
|
||||
"symfony/serializer": "^5.2",
|
||||
"symfony/swiftmailer-bundle": "^3.5",
|
||||
"symfony/templating": "4.*",
|
||||
"symfony/translation": "4.*",
|
||||
"symfony/twig-bundle": "^4.4",
|
||||
"symfony/validator": "4.*",
|
||||
"symfony/webpack-encore-bundle": "^1.11",
|
||||
"symfony/workflow": "4.*",
|
||||
"symfony/yaml": "4.*",
|
||||
"twig/extra-bundle": "^2.12 || ^3.0",
|
||||
"twig/intl-extra": "^3.0",
|
||||
"twig/markdown-extra": "^3.3",
|
||||
"twig/twig": "^2.12 || ^3.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/symfony": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/doctrine-fixtures-bundle": "^3.3",
|
||||
"fakerphp/faker": "^1.13",
|
||||
"nelmio/alice": "^3.8",
|
||||
"phpunit/phpunit": "^7.0",
|
||||
"symfony/debug-bundle": "^5.1",
|
||||
"symfony/dotenv": "^5.1",
|
||||
"symfony/maker-bundle": "^1.20",
|
||||
"symfony/phpunit-bridge": "^5.2",
|
||||
"symfony/stopwatch": "^5.1",
|
||||
"symfony/var-dumper": "4.*",
|
||||
"symfony/web-profiler-bundle": "^5.0"
|
||||
},
|
||||
"config": {
|
||||
"bin-dir": "bin",
|
||||
"vendor-dir": "tests/app/vendor"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Chill\\ActivityBundle\\": "src/Bundle/ChillActivityBundle",
|
||||
@@ -16,75 +79,24 @@
|
||||
"Chill\\PersonBundle\\": "src/Bundle/ChillPersonBundle",
|
||||
"Chill\\ReportBundle\\": "src/Bundle/ChillReportBundle",
|
||||
"Chill\\TaskBundle\\": "src/Bundle/ChillTaskBundle",
|
||||
"Chill\\ThirdPartyBundle\\": "src/Bundle/ChillThirdPartyBundle"
|
||||
"Chill\\ThirdPartyBundle\\": "src/Bundle/ChillThirdPartyBundle",
|
||||
"Chill\\AsideActivityBundle\\": "src/Bundle/ChillAsideActivityBundle/src",
|
||||
"Chill\\DocGeneratorBundle\\": "src/Bundle/ChillDocGeneratorBundle",
|
||||
"Chill\\CalendarBundle\\": "src/Bundle/ChillCalendarBundle",
|
||||
"Chill\\WopiBundle\\": "src/Bundle/ChillWopiBundle/src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"App\\": "tests/app/src/"
|
||||
"App\\": "tests/app/src/"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"champs-libres/async-uploader-bundle": "dev-sf4",
|
||||
"graylog2/gelf-php": "^1.5",
|
||||
"symfony/form": "4.*",
|
||||
"symfony/twig-bundle": "^4.4",
|
||||
"twig/extra-bundle": "^2.12|^3.0",
|
||||
"twig/twig": "^2.12|^3.0",
|
||||
"composer/package-versions-deprecated": "^1.10",
|
||||
"doctrine/doctrine-bundle": "^2.1",
|
||||
"doctrine/doctrine-migrations-bundle": "^3.0",
|
||||
"doctrine/orm": "^2.7",
|
||||
"symfony/asset": "4.*",
|
||||
"symfony/monolog-bundle": "^3.5",
|
||||
"symfony/security-bundle": "4.*",
|
||||
"symfony/translation": "4.*",
|
||||
"symfony/validator": "4.*",
|
||||
"sensio/framework-extra-bundle": "^5.5",
|
||||
"symfony/yaml": "4.*",
|
||||
"symfony/webpack-encore-bundle": "^1.11",
|
||||
"knplabs/knp-menu": "^3.1",
|
||||
"knplabs/knp-menu-bundle": "^3.0",
|
||||
"symfony/templating": "4.*",
|
||||
"twig/intl-extra": "^3.0",
|
||||
"symfony/workflow": "4.*",
|
||||
"symfony/expression-language": "4.*",
|
||||
"knplabs/knp-time-bundle": "^1.12",
|
||||
"symfony/intl": "4.*",
|
||||
"symfony/swiftmailer-bundle": "^3.5",
|
||||
"league/csv": "^9.6",
|
||||
"phpoffice/phpspreadsheet": "^1.16",
|
||||
"symfony/browser-kit": "^5.2",
|
||||
"symfony/css-selector": "^5.2",
|
||||
"twig/markdown-extra": "^3.3",
|
||||
"erusev/parsedown": "^1.7",
|
||||
"symfony/serializer": "^5.2",
|
||||
"symfony/webpack-encore-bundle": "^1.11"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/symfony": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.13",
|
||||
"phpunit/phpunit": "^7.0",
|
||||
"symfony/dotenv": "^5.1",
|
||||
"symfony/maker-bundle": "^1.20",
|
||||
"doctrine/doctrine-fixtures-bundle": "^3.3",
|
||||
"symfony/stopwatch": "^5.1",
|
||||
"symfony/web-profiler-bundle": "^5.0",
|
||||
"symfony/var-dumper": "4.*",
|
||||
"symfony/debug-bundle": "^5.1",
|
||||
"symfony/phpunit-bridge": "^5.2",
|
||||
"nelmio/alice": "^3.8"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"scripts": {
|
||||
"auto-scripts": {
|
||||
"cache:clear": "symfony-cmd",
|
||||
"assets:install %PUBLIC_DIR%": "symfony-cmd"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"vendor-dir": "tests/app/vendor",
|
||||
"bin-dir": "bin"
|
||||
}
|
||||
}
|
||||
|
@@ -28,7 +28,7 @@ Then, render the pagination using the dedicated twig function.
|
||||
|
||||
.. code-block:: html+twig
|
||||
|
||||
{% extends "ChillPersonBundle::layout.html.twig" %}
|
||||
{% extends "@ChillPerson/Person/layout.html.twig" %}
|
||||
|
||||
{% block title 'Item list'|trans %}
|
||||
|
||||
|
@@ -149,7 +149,7 @@ It proposes a new block :
|
||||
|
||||
* where to display the admin content
|
||||
|
||||
ChillPersonBundle::layout.html.twig
|
||||
@ChillPersonBundle/Person/layout.html.twig
|
||||
-----------------------------------
|
||||
|
||||
This layout extend `ChillMainBundle::layoutWithVerticalMenu.html.twig` add the person details in the block `top_banner`, set the menu `person` as the vertical menu.
|
||||
|
3
package.json.txt
Normal file
3
package.json.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
add npm/yarn dependency in package.json :
|
||||
|
||||
"select2-bootstrap-theme": "0.1.0-beta.10",
|
@@ -10,7 +10,7 @@
|
||||
<php>
|
||||
<ini name="error_reporting" value="-1" />
|
||||
<server name="APP_ENV" value="test" force="true" />
|
||||
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
|
||||
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
|
||||
<server name="SHELL_VERBOSITY" value="-1" />
|
||||
</php>
|
||||
|
||||
@@ -31,6 +31,12 @@
|
||||
<!-- temporarily removed, the time to find a fix -->
|
||||
<exclude>src/Bundle/ChillPersonBundle/Tests/Controller/PersonDuplicateControllerViewTest.php</exclude>
|
||||
</testsuite>
|
||||
<testsuite name="AsideActivityBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillAsideActivityBundle/src/Tests/</directory>
|
||||
</testsuite>
|
||||
<testsuite name="CalendarBundle">
|
||||
<directory suffix="Test.php">src/Bundle/ChillCalendarBundle/Tests/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<listeners>
|
||||
|
@@ -22,6 +22,9 @@
|
||||
|
||||
namespace Chill\ActivityBundle\Controller;
|
||||
|
||||
use Chill\ActivityBundle\Repository\ActivityACLAwareRepository;
|
||||
use Chill\ActivityBundle\Repository\ActivityACLAwareRepositoryInterface;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
@@ -36,6 +39,7 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Form\ActivityType;
|
||||
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
|
||||
/**
|
||||
@@ -53,12 +57,16 @@ class ActivityController extends AbstractController
|
||||
|
||||
protected SerializerInterface $serializer;
|
||||
|
||||
protected ActivityACLAwareRepositoryInterface $activityACLAwareRepository;
|
||||
|
||||
public function __construct(
|
||||
ActivityACLAwareRepositoryInterface $activityACLAwareRepository,
|
||||
EventDispatcherInterface $eventDispatcher,
|
||||
AuthorizationHelper $authorizationHelper,
|
||||
LoggerInterface $logger,
|
||||
SerializerInterface $serializer
|
||||
) {
|
||||
$this->activityACLAwareRepository = $activityACLAwareRepository;
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->authorizationHelper = $authorizationHelper;
|
||||
$this->logger = $logger;
|
||||
@@ -77,13 +85,9 @@ class ActivityController extends AbstractController
|
||||
[$person, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
if ($person instanceof Person) {
|
||||
$reachableScopes = $this->authorizationHelper
|
||||
->getReachableCircles($this->getUser(), new Role('CHILL_ACTIVITY_SEE'),
|
||||
$person->getCenter());
|
||||
|
||||
$activities = $em->getRepository(Activity::class)
|
||||
->findByPersonImplied($person, $reachableScopes)
|
||||
;
|
||||
$this->denyAccessUnlessGranted(ActivityVoter::SEE, $person);
|
||||
$activities = $this->activityACLAwareRepository
|
||||
->findByPerson($person, ActivityVoter::SEE, 0, null);
|
||||
|
||||
$event = new PrivacyEvent($person, array(
|
||||
'element_class' => Activity::class,
|
||||
@@ -93,10 +97,10 @@ class ActivityController extends AbstractController
|
||||
|
||||
$view = 'ChillActivityBundle:Activity:listPerson.html.twig';
|
||||
} elseif ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$activities = $em->getRepository('ChillActivityBundle:Activity')->findBy(
|
||||
['accompanyingPeriod' => $accompanyingPeriod],
|
||||
['date' => 'DESC'],
|
||||
);
|
||||
$this->denyAccessUnlessGranted(ActivityVoter::SEE, $accompanyingPeriod);
|
||||
|
||||
$activities = $this->activityACLAwareRepository
|
||||
->findByAccompanyingPeriod($accompanyingPeriod, ActivityVoter::SEE);
|
||||
|
||||
$view = 'ChillActivityBundle:Activity:listAccompanyingCourse.html.twig';
|
||||
}
|
||||
@@ -136,6 +140,12 @@ class ActivityController extends AbstractController
|
||||
];
|
||||
}
|
||||
|
||||
if ($request->query->has('activityData')) {
|
||||
$activityData = $request->query->get('activityData');
|
||||
} else {
|
||||
$activityData = [];
|
||||
}
|
||||
|
||||
if ($view === null) {
|
||||
throw $this->createNotFoundException('Template not found');
|
||||
}
|
||||
@@ -144,6 +154,7 @@ class ActivityController extends AbstractController
|
||||
'person' => $person,
|
||||
'accompanyingCourse' => $accompanyingPeriod,
|
||||
'data' => $data,
|
||||
'activityData' => $activityData
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -163,10 +174,19 @@ class ActivityController extends AbstractController
|
||||
$activityType = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityType::class)
|
||||
->find($activityType_id);
|
||||
|
||||
$activityData = null;
|
||||
if ($request->query->has('activityData')) {
|
||||
$activityData = $request->query->get('activityData');
|
||||
}
|
||||
|
||||
if (!$activityType instanceof \Chill\ActivityBundle\Entity\ActivityType ||
|
||||
!$activityType->isActive()) {
|
||||
|
||||
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
|
||||
|
||||
if (null !== $activityData) {
|
||||
$params['activityData'] = $activityData;
|
||||
}
|
||||
return $this->redirectToRoute('chill_activity_activity_select_type', $params);
|
||||
}
|
||||
|
||||
@@ -184,6 +204,50 @@ class ActivityController extends AbstractController
|
||||
$entity->setType($activityType);
|
||||
$entity->setDate(new \DateTime('now'));
|
||||
|
||||
if ($request->query->has('activityData')) {
|
||||
$activityData = $request->query->get('activityData');
|
||||
|
||||
if (array_key_exists('durationTime', $activityData)) {
|
||||
$durationTimeInMinutes = $activityData['durationTime'];
|
||||
$hours = floor($durationTimeInMinutes / 60);
|
||||
$minutes = $durationTimeInMinutes % 60;
|
||||
$duration = \DateTime::createFromFormat("H:i", $hours.':'.$minutes);
|
||||
if ($duration) {
|
||||
$entity->setDurationTime($duration);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('date', $activityData)) {
|
||||
$date = \DateTime::createFromFormat('Y-m-d', $activityData['date']);
|
||||
if ($date) {
|
||||
$entity->setDate($date);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('personsId', $activityData)) {
|
||||
foreach($activityData['personsId'] as $personId){
|
||||
$concernedPerson = $em->getRepository(\Chill\PersonBundle\Entity\Person::class)->find($personId);
|
||||
$entity->addPerson($concernedPerson);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('professionalsId', $activityData)) {
|
||||
foreach($activityData['professionalsId'] as $professionalsId){
|
||||
$professional = $em->getRepository(\Chill\ThirdPartyBundle\Entity\ThirdParty::class)->find($professionalsId);
|
||||
$entity->addThirdParty($professional);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('comment', $activityData)) {
|
||||
$comment = new CommentEmbeddable();
|
||||
$comment->setComment($activityData['comment']);
|
||||
$comment->setUserId($this->getUser()->getid());
|
||||
$comment->setDate(new \DateTime('now'));
|
||||
$entity->setComment($comment);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO revoir le Voter de Activity pour tenir compte qu'une activité peut appartenir a une période
|
||||
// $this->denyAccessUnlessGranted('CHILL_ACTIVITY_CREATE', $entity);
|
||||
|
||||
@@ -201,6 +265,7 @@ class ActivityController extends AbstractController
|
||||
$this->addFlash('success', $this->get('translator')->trans('Success : activity created!'));
|
||||
|
||||
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
|
||||
|
||||
$params['id'] = $entity->getId();
|
||||
|
||||
return $this->redirectToRoute('chill_activity_activity_show', $params);
|
||||
@@ -238,7 +303,7 @@ class ActivityController extends AbstractController
|
||||
if (!$entity) {
|
||||
throw $this->createNotFoundException('Unable to find Activity entity.');
|
||||
}
|
||||
|
||||
|
||||
if (null !== $accompanyingPeriod) {
|
||||
$entity->personsAssociated = $entity->getPersonsAssociated();
|
||||
$entity->personsNotAssociated = $entity->getPersonsNotAssociated();
|
||||
|
@@ -22,6 +22,7 @@ class LoadActivityNotifications extends AbstractFixture implements DependentFixt
|
||||
'entityRef' => 'activity_gerard depardieu',
|
||||
'sender' => 'center a_social',
|
||||
'addressees' => [
|
||||
'center a_social',
|
||||
'center a_administrative',
|
||||
'center a_direction',
|
||||
'multi_center'
|
||||
|
@@ -55,6 +55,7 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf
|
||||
$loader->load('services/controller.yaml');
|
||||
$loader->load('services/form.yaml');
|
||||
$loader->load('services/templating.yaml');
|
||||
$loader->load('services/accompanyingPeriodConsistency.yaml');
|
||||
}
|
||||
|
||||
public function prepend(ContainerBuilder $container)
|
||||
|
@@ -23,6 +23,7 @@ namespace Chill\ActivityBundle\Entity;
|
||||
use Chill\DocStoreBundle\Entity\Document;
|
||||
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
|
||||
use Chill\PersonBundle\AccompanyingPeriod\SocialIssueConsistency\AccompanyingPeriodLinkedWithSocialIssuesEntityInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
|
||||
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
|
||||
@@ -60,7 +61,7 @@ use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||
* path="scope")
|
||||
*/
|
||||
|
||||
class Activity implements HasCenterInterface, HasScopeInterface
|
||||
class Activity implements HasCenterInterface, HasScopeInterface, AccompanyingPeriodLinkedWithSocialIssuesEntityInterface
|
||||
{
|
||||
const SENTRECEIVED_SENT = 'sent';
|
||||
const SENTRECEIVED_RECEIVED = 'received';
|
||||
@@ -282,7 +283,7 @@ class Activity implements HasCenterInterface, HasScopeInterface
|
||||
return $this->socialIssues;
|
||||
}
|
||||
|
||||
public function addSocialIssue(?SocialIssue $socialIssue): self
|
||||
public function addSocialIssue(SocialIssue $socialIssue): self
|
||||
{
|
||||
if (!$this->socialIssues->contains($socialIssue)) {
|
||||
$this->socialIssues[] = $socialIssue;
|
||||
@@ -303,7 +304,7 @@ class Activity implements HasCenterInterface, HasScopeInterface
|
||||
return $this->socialActions;
|
||||
}
|
||||
|
||||
public function addSocialAction(?SocialAction $socialAction): self
|
||||
public function addSocialAction(SocialAction $socialAction): self
|
||||
{
|
||||
if (!$this->socialActions->contains($socialAction)) {
|
||||
$this->socialActions[] = $socialAction;
|
||||
@@ -417,7 +418,7 @@ class Activity implements HasCenterInterface, HasScopeInterface
|
||||
return $this->persons;
|
||||
}
|
||||
|
||||
public function getPersonsAssociated(): array
|
||||
public function getPersonsAssociated(): array
|
||||
{
|
||||
if (null !== $this->accompanyingPeriod) {
|
||||
$personsAssociated = [];
|
||||
@@ -426,11 +427,11 @@ class Activity implements HasCenterInterface, HasScopeInterface
|
||||
$personsAssociated[] = $participation->getPerson();
|
||||
}
|
||||
}
|
||||
return $personsAssociated;
|
||||
return $personsAssociated;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
public function getPersonsNotAssociated(): array
|
||||
{
|
||||
if (null !== $this->accompanyingPeriod) {
|
||||
@@ -443,7 +444,7 @@ class Activity implements HasCenterInterface, HasScopeInterface
|
||||
return $personsNotAssociated;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public function setPersons(?Collection $persons): self
|
||||
{
|
||||
|
@@ -36,7 +36,7 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
|
||||
$period = $parameters['accompanyingCourse'];
|
||||
|
||||
if (AccompanyingPeriod::STEP_DRAFT !== $period->getStep()) {
|
||||
$menu->addChild($this->translator->trans('Activity list'), [
|
||||
$menu->addChild($this->translator->trans('Activity'), [
|
||||
'route' => 'chill_activity_activity_list',
|
||||
'routeParameters' => [
|
||||
'accompanying_period_id' => $period->getId(),
|
||||
|
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\ActivityBundle\Notification;
|
||||
|
||||
use Chill\MainBundle\Entity\Notification;
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
|
||||
final class ActivityNotificationRenderer
|
||||
{
|
||||
public function supports(Notification $notification, array $options = []): bool
|
||||
{
|
||||
return $notification->getRelatedEntityClass() == Activity::class;
|
||||
}
|
||||
|
||||
public function getTemplate()
|
||||
{
|
||||
return '@ChillActivity/Activity/showInNotification.html.twig';
|
||||
}
|
||||
|
||||
public function getTemplateData(Notification $notification)
|
||||
{
|
||||
return ['notification' => $notification];
|
||||
}
|
||||
}
|
@@ -23,6 +23,8 @@
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\ActivityBundle\Repository\ActivityRepository;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
|
||||
@@ -33,9 +35,10 @@ use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
|
||||
final class ActivityACLAwareRepository
|
||||
final class ActivityACLAwareRepository implements ActivityACLAwareRepositoryInterface
|
||||
{
|
||||
private AuthorizationHelper $authorizationHelper;
|
||||
|
||||
@@ -45,16 +48,63 @@ final class ActivityACLAwareRepository
|
||||
|
||||
private EntityManagerInterface $em;
|
||||
|
||||
private Security $security;
|
||||
|
||||
private CenterResolverDispatcher $centerResolverDispatcher;
|
||||
|
||||
public function __construct(
|
||||
AuthorizationHelper $authorizationHelper,
|
||||
CenterResolverDispatcher $centerResolverDispatcher,
|
||||
TokenStorageInterface $tokenStorage,
|
||||
ActivityRepository $repository,
|
||||
EntityManagerInterface $em
|
||||
EntityManagerInterface $em,
|
||||
Security $security
|
||||
) {
|
||||
$this->authorizationHelper = $authorizationHelper;
|
||||
$this->centerResolverDispatcher = $centerResolverDispatcher;
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->repository = $repository;
|
||||
$this->em = $em;
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Person $person
|
||||
* @param string $role
|
||||
* @param int|null $start
|
||||
* @param int|null $limit
|
||||
* @param array $orderBy
|
||||
* @return array|Activity[]
|
||||
*/
|
||||
public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array
|
||||
{
|
||||
$user = $this->security->getUser();
|
||||
$center = $this->centerResolverDispatcher->resolveCenter($person);
|
||||
if (0 === count($orderBy)) {
|
||||
$orderBy = ['date' => 'DESC'];
|
||||
}
|
||||
|
||||
$reachableScopes = $this->authorizationHelper
|
||||
->getReachableCircles($user, $role, $center);
|
||||
|
||||
return $this->em->getRepository(Activity::class)
|
||||
->findByPersonImplied($person, $reachableScopes, $orderBy, $limit, $start);
|
||||
;
|
||||
}
|
||||
|
||||
public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array
|
||||
{
|
||||
$user = $this->security->getUser();
|
||||
$center = $this->centerResolverDispatcher->resolveCenter($period);
|
||||
if (0 === count($orderBy)) {
|
||||
$orderBy = ['date' => 'DESC'];
|
||||
}
|
||||
|
||||
$scopes = $this->authorizationHelper
|
||||
->getReachableCircles($user, $role, $center);
|
||||
|
||||
return $this->em->getRepository(Activity::class)
|
||||
->findByAccompanyingPeriod($period, $scopes, true, $limit, $start, $orderBy);
|
||||
}
|
||||
|
||||
public function queryTimelineIndexer(string $context, array $args = []): array
|
||||
@@ -81,7 +131,7 @@ final class ActivityACLAwareRepository
|
||||
$metadataActivity = $this->em->getClassMetadata(Activity::class);
|
||||
$metadataPerson = $this->em->getClassMetadata(Person::class);
|
||||
$associationMapping = $metadataActivity->getAssociationMapping('person');
|
||||
|
||||
|
||||
return $metadataActivity->getTableName().' JOIN '
|
||||
.$metadataPerson->getTableName().' ON '
|
||||
.$metadataPerson->getTableName().'.'.
|
||||
@@ -95,7 +145,7 @@ final class ActivityACLAwareRepository
|
||||
{
|
||||
$where = '';
|
||||
$parameters = [];
|
||||
|
||||
|
||||
$metadataActivity = $this->em->getClassMetadata(Activity::class);
|
||||
$metadataPerson = $this->em->getClassMetadata(Person::class);
|
||||
$activityToPerson = $metadataActivity->getAssociationMapping('person')['joinColumns'][0]['name'];
|
||||
@@ -105,20 +155,20 @@ final class ActivityACLAwareRepository
|
||||
|
||||
// acls:
|
||||
$role = new Role(ActivityVoter::SEE);
|
||||
$reachableCenters = $this->authorizationHelper->getReachableCenters($this->tokenStorage->getToken()->getUser(),
|
||||
$reachableCenters = $this->authorizationHelper->getReachableCenters($this->tokenStorage->getToken()->getUser(),
|
||||
$role);
|
||||
|
||||
|
||||
if (count($reachableCenters) === 0) {
|
||||
// insert a dummy condition
|
||||
return 'FALSE = TRUE';
|
||||
}
|
||||
|
||||
if ($context === 'person') {
|
||||
// we start with activities having the person_id linked to person
|
||||
if ($context === 'person') {
|
||||
// we start with activities having the person_id linked to person
|
||||
$where .= sprintf('%s = ? AND ', $activityToPerson);
|
||||
$parameters[] = $person->getId();
|
||||
}
|
||||
|
||||
|
||||
// we add acl (reachable center and scopes)
|
||||
$where .= '('; // first loop for the for centers
|
||||
$centersI = 0; // like centers#i
|
||||
@@ -131,7 +181,7 @@ final class ActivityACLAwareRepository
|
||||
$reachableScopes = $this->authorizationHelper->getReachableScopes($this->tokenStorage->getToken()->getUser(), $role, $center);
|
||||
// we get the ids for those scopes
|
||||
$reachablesScopesId = array_map(
|
||||
function(Scope $scope) { return $scope->getId(); },
|
||||
function(Scope $scope) { return $scope->getId(); },
|
||||
$reachableScopes
|
||||
);
|
||||
|
||||
@@ -162,7 +212,7 @@ final class ActivityACLAwareRepository
|
||||
}
|
||||
// close loop for centers
|
||||
$where .= ')';
|
||||
|
||||
|
||||
return [$where, $parameters];
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
|
||||
interface ActivityACLAwareRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* @return array|Activity[]
|
||||
*/
|
||||
public function findByPerson(Person $person, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array;
|
||||
|
||||
/**
|
||||
* @return array|Activity[]
|
||||
*/
|
||||
public function findByAccompanyingPeriod(AccompanyingPeriod $period, string $role, ?int $start = 0, ?int $limit = 1000, ?array $orderBy = []): array;
|
||||
}
|
@@ -23,6 +23,8 @@
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
@@ -39,15 +41,22 @@ class ActivityRepository extends ServiceEntityRepository
|
||||
parent::__construct($registry, Activity::class);
|
||||
}
|
||||
|
||||
public function findByPersonImplied($person, array $scopes, $orderBy = [ 'date' => 'DESC'], $limit = 100, $offset = 0)
|
||||
/**
|
||||
* @param $person
|
||||
* @param array $scopes
|
||||
* @param string[] $orderBy
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return array|Activity[]
|
||||
*/
|
||||
public function findByPersonImplied(Person $person, array $scopes, ?array $orderBy = [ 'date' => 'DESC'], ?int $limit = 100, ?int $offset = 0): array
|
||||
{
|
||||
$qb = $this->createQueryBuilder('a');
|
||||
$qb->select('a');
|
||||
|
||||
$qb
|
||||
// TODO add acl
|
||||
//->where($qb->expr()->in('a.scope', ':scopes'))
|
||||
//->setParameter('scopes', $scopes)
|
||||
->where($qb->expr()->in('a.scope', ':scopes'))
|
||||
->setParameter('scopes', $scopes)
|
||||
->andWhere(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->eq('a.person', ':person'),
|
||||
@@ -61,7 +70,56 @@ class ActivityRepository extends ServiceEntityRepository
|
||||
$qb->addOrderBy('a.'.$k, $dir);
|
||||
}
|
||||
|
||||
$qb->setMaxResults($limit)->setFirstResult($offset);
|
||||
|
||||
return $qb->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccompanyingPeriod $period
|
||||
* @param array $scopes
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @param array|string[] $orderBy
|
||||
* @return array|Activity[]
|
||||
*/
|
||||
public function findByAccompanyingPeriod(AccompanyingPeriod $period, array $scopes, ?bool $allowNullScope = false, ?int $limit = 100, ?int $offset = 0, array $orderBy = ['date' => 'desc']): array
|
||||
{
|
||||
$qb = $this->createQueryBuilder('a');
|
||||
$qb->select('a');
|
||||
|
||||
if (!$allowNullScope) {
|
||||
$qb
|
||||
->where($qb->expr()->in('a.scope', ':scopes'))
|
||||
->setParameter('scopes', $scopes)
|
||||
;
|
||||
} else {
|
||||
$qb
|
||||
->where(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->in('a.scope', ':scopes'),
|
||||
$qb->expr()->isNull('a.scope')
|
||||
)
|
||||
)
|
||||
->setParameter('scopes', $scopes)
|
||||
;
|
||||
}
|
||||
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->eq('a.accompanyingPeriod', ':period')
|
||||
)
|
||||
->setParameter('period', $period)
|
||||
;
|
||||
|
||||
foreach ($orderBy as $k => $dir) {
|
||||
$qb->addOrderBy('a.'.$k, $dir);
|
||||
}
|
||||
|
||||
$qb->setMaxResults($limit)->setFirstResult($offset);
|
||||
|
||||
return $qb->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,142 @@
|
||||
// Access to Bootstrap variables and mixins
|
||||
@import '~ChillMainAssets/module/bootstrap/shared';
|
||||
|
||||
// activity creation first step: select type page
|
||||
div.new-activity-select-type {
|
||||
div.activity-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
|
||||
div.bloc {
|
||||
width: 200px;
|
||||
align-self: flex-end;
|
||||
height: 140px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// exceptions for flex-table in list-records
|
||||
div.activity-list {
|
||||
div.flex-table {
|
||||
div.item-bloc {
|
||||
div.item-row.main {
|
||||
div.item-col {
|
||||
&:first-child {
|
||||
flex-basis: 15%;
|
||||
}
|
||||
ul.list-content {
|
||||
li.social-issues, li.social-actions {
|
||||
.badge-primary {
|
||||
font-variant: small-caps;
|
||||
font-weight: bold;
|
||||
font-size: 88%;
|
||||
margin-bottom: 0.2em;
|
||||
}
|
||||
}
|
||||
li.social-issues .badge-primary {
|
||||
background-color: $orange;
|
||||
}
|
||||
li.social-actions .badge-primary {
|
||||
background-color: $green;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
div.item-row.comment {
|
||||
margin-left: 15%;
|
||||
blockquote.chill-user-quote {
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
}
|
||||
div.item-row.details {
|
||||
margin-left: 15%;
|
||||
|
||||
// override flex-bloc to adapt in list
|
||||
// TODO refund this
|
||||
div.accompanyingCourse.flex-bloc.concerned-groups {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
justify-content: space-around;
|
||||
div.item-bloc {
|
||||
box-shadow: unset;
|
||||
padding: 0;
|
||||
flex-basis: 25%;
|
||||
div.item-row {
|
||||
flex-direction: column;
|
||||
div.item-col {
|
||||
&:first-child {
|
||||
width: unset;
|
||||
}
|
||||
&:last-child {
|
||||
border-top: 0;
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
ul.list-content {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
ul.list-content {
|
||||
list-style-type: none;
|
||||
padding-left: 1em;
|
||||
margin: 0 0;
|
||||
li {
|
||||
margin-bottom: 0.2em;
|
||||
}
|
||||
}
|
||||
}
|
||||
div.duration {
|
||||
font-size: smaller;
|
||||
padding-left: 1em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// exceptions for flex-bloc in concerned-groups
|
||||
div.flex-bloc.concerned-groups {
|
||||
margin-top: 1em;
|
||||
div.item-bloc {
|
||||
flex-grow: 0; flex-shrink: 0; flex-basis: 25%; //4 blocs
|
||||
ul.list-content {
|
||||
list-style-type: none;
|
||||
padding-left: 0;
|
||||
li {
|
||||
margin-bottom: 0.2em;
|
||||
a {
|
||||
color: $white;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: #ffffffab;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&.person div.item-bloc {
|
||||
flex-basis: 33%; //3 blocs
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// CHILL ENTITY RENDER BOX
|
||||
.chill-entity {
|
||||
|
||||
/// ACTIVITY-REASON
|
||||
&.entity-activity-reason {
|
||||
margin-right: 0.3em;
|
||||
font-size: 120%;
|
||||
}
|
||||
}
|
@@ -0,0 +1 @@
|
||||
require('./chillactivity.scss');
|
@@ -1 +0,0 @@
|
||||
require('./scss/chillactivity.scss');
|
@@ -1,130 +0,0 @@
|
||||
@import '~ChillMainSass/custom/config/colors';
|
||||
@import '~ChillMainSass/custom/mixins/entity';
|
||||
|
||||
.chill-entity.chill-entity__activity-reason {
|
||||
@include entity($chill-pink, white);
|
||||
}
|
||||
|
||||
.activity {
|
||||
color: $chill-green;
|
||||
}
|
||||
|
||||
// exceptions for flex-bloc in concerned-groups
|
||||
div.flex-bloc.concerned-groups {
|
||||
margin-top: 1em;
|
||||
div.item-bloc {
|
||||
flex-grow: 0; flex-shrink: 0; flex-basis: 25%; //4 blocs
|
||||
ul.list-content {
|
||||
list-style-type: none;
|
||||
padding-left: 0;
|
||||
li {
|
||||
margin-bottom: 0.2em;
|
||||
a {
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: #ffffffab;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&.person div.item-bloc {
|
||||
flex-basis: 33%; //3 blocs
|
||||
}
|
||||
}
|
||||
|
||||
// exceptions for flex-table in list-records
|
||||
div.flex-table.list-records {
|
||||
div.item-bloc {
|
||||
div.item-row.main {
|
||||
div.item-col {
|
||||
&:first-child {
|
||||
flex-basis: 27%;
|
||||
}
|
||||
ul.list-content {
|
||||
li.social-issues, li.social-actions {
|
||||
.badge-primary {
|
||||
font-variant: small-caps;
|
||||
font-weight: bold;
|
||||
font-size: 88%;
|
||||
margin-bottom: 0.2em;
|
||||
}
|
||||
}
|
||||
li.social-issues .badge-primary {
|
||||
background-color: var(--chill-orange);
|
||||
}
|
||||
li.social-actions .badge-primary {
|
||||
background-color: var(--chill-green);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
div.item-row.details {
|
||||
flex-direction: row;
|
||||
& > div.item-col {
|
||||
justify-content: flex-start;
|
||||
align-self: center;
|
||||
&:nth-child(1) {
|
||||
flex-grow: 1; flex-shrink: 0; flex-basis: 30%;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
flex-grow: 0; flex-shrink: 1; flex-basis: 70%;
|
||||
}
|
||||
|
||||
&:only-child {
|
||||
flex-grow: 0; flex-shrink: 0; flex-basis: 100%;
|
||||
& > div.concerned-groups {
|
||||
flex-grow: 0; flex-shrink: 0; flex-basis: 100%;
|
||||
display: flex;
|
||||
flex-direction: column; // TODO pas fini
|
||||
div.group {
|
||||
flex-grow: 1; flex-shrink: 0; flex-basis: 30%;
|
||||
h4 {}
|
||||
ul.list-content {
|
||||
li {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
div.concerned-groups {
|
||||
font-size: 85%;
|
||||
h4 {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
}
|
||||
ul.list-content {
|
||||
list-style-type: none;
|
||||
padding-left: 1em;
|
||||
margin: 0 0;
|
||||
li {
|
||||
margin-bottom: 0.2em;
|
||||
}
|
||||
}
|
||||
}
|
||||
div.duration {
|
||||
font-size: smaller;
|
||||
padding-left: 1em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
div.activity-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
div.bloc {
|
||||
width: 200px;
|
||||
align-self: flex-end;
|
||||
height: 140px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
@@ -2,7 +2,7 @@
|
||||
<teleport to="#add-persons">
|
||||
|
||||
<div class="flex-bloc concerned-groups" :class="getContext">
|
||||
<persons-bloc
|
||||
<persons-bloc
|
||||
v-for="bloc in contextPersonsBlocs"
|
||||
v-bind:key="bloc.key"
|
||||
v-bind:bloc="bloc"
|
||||
@@ -10,7 +10,15 @@
|
||||
</persons-bloc>
|
||||
</div>
|
||||
|
||||
<add-persons
|
||||
<div v-if="getContext === 'accompanyingCourse' && filterSuggestedPersons.length > 0">
|
||||
<ul>
|
||||
<li v-for="p in filterSuggestedPersons" @click="addNewPerson(p)">
|
||||
{{ p.text }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<add-persons
|
||||
buttonTitle="activity.add_persons"
|
||||
modalTitle="activity.add_persons"
|
||||
v-bind:key="addPersons.key"
|
||||
@@ -18,12 +26,12 @@
|
||||
@addNewPersons="addNewPersons"
|
||||
ref="addPersons">
|
||||
</add-persons>
|
||||
|
||||
</teleport>
|
||||
|
||||
</teleport>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
import { mapState, mapGetters } from 'vuex';
|
||||
import AddPersons from 'ChillPersonAssets/vuejs/_components/AddPersons.vue';
|
||||
import PersonsBloc from './ConcernedGroups/PersonsBloc.vue';
|
||||
|
||||
@@ -36,36 +44,36 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
personsBlocs: [
|
||||
{ key: 'persons',
|
||||
title: 'activity.bloc_persons',
|
||||
persons: [],
|
||||
included: false
|
||||
{ key: 'persons',
|
||||
title: 'activity.bloc_persons',
|
||||
persons: [],
|
||||
included: false
|
||||
},
|
||||
{ key: 'personsAssociated',
|
||||
title: 'activity.bloc_persons_associated',
|
||||
persons: [],
|
||||
included: false
|
||||
{ key: 'personsAssociated',
|
||||
title: 'activity.bloc_persons_associated',
|
||||
persons: [],
|
||||
included: false
|
||||
},
|
||||
{ key: 'personsNotAssociated',
|
||||
title: 'activity.bloc_persons_not_associated',
|
||||
persons: [],
|
||||
included: false
|
||||
{ key: 'personsNotAssociated',
|
||||
title: 'activity.bloc_persons_not_associated',
|
||||
persons: [],
|
||||
included: false
|
||||
},
|
||||
{ key: 'thirdparty',
|
||||
title: 'activity.bloc_thirdparty',
|
||||
persons: [],
|
||||
{ key: 'thirdparty',
|
||||
title: 'activity.bloc_thirdparty',
|
||||
persons: [],
|
||||
included: true
|
||||
},
|
||||
{ key: 'users',
|
||||
title: 'activity.bloc_users',
|
||||
persons: [],
|
||||
{ key: 'users',
|
||||
title: 'activity.bloc_users',
|
||||
persons: [],
|
||||
included: true
|
||||
},
|
||||
],
|
||||
addPersons: {
|
||||
key: 'activity',
|
||||
options: {
|
||||
type: ['person', 'thirdparty'], // TODO add 'user'
|
||||
type: ['person', 'thirdparty', 'user'], // TODO add 'user'
|
||||
priority: null,
|
||||
uniq: false,
|
||||
}
|
||||
@@ -79,6 +87,9 @@ export default {
|
||||
users: state => state.activity.users,
|
||||
accompanyingCourse: state => state.activity.accompanyingPeriod
|
||||
}),
|
||||
...mapGetters([
|
||||
'filterSuggestedPersons'
|
||||
]),
|
||||
getContext() {
|
||||
return (this.accompanyingCourse) ? "accompanyingCourse" : "person";
|
||||
},
|
||||
@@ -91,10 +102,10 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
setPersonsInBloc() {
|
||||
let groups;
|
||||
let groups;
|
||||
if (this.accompanyingCourse) {
|
||||
groups = this.splitPersonsInGroups();
|
||||
}
|
||||
}
|
||||
this.personsBlocs.forEach(bloc => {
|
||||
if (this.accompanyingCourse) {
|
||||
switch (bloc.key) {
|
||||
@@ -109,7 +120,7 @@ export default {
|
||||
}
|
||||
} else {
|
||||
switch (bloc.key) {
|
||||
case 'persons':
|
||||
case 'persons':
|
||||
bloc.persons = this.persons;
|
||||
bloc.included = true;
|
||||
break;
|
||||
@@ -128,7 +139,7 @@ export default {
|
||||
splitPersonsInGroups() {
|
||||
let personsAssociated = [];
|
||||
let personsNotAssociated = this.persons;
|
||||
let participations = this.getCourseParticipations();
|
||||
let participations = this.getCourseParticipations();
|
||||
this.persons.forEach(person => {
|
||||
participations.forEach(participation => {
|
||||
if (person.id === participation.id) {
|
||||
@@ -138,9 +149,9 @@ export default {
|
||||
}
|
||||
});
|
||||
});
|
||||
return {
|
||||
'personsAssociated': personsAssociated,
|
||||
'personsNotAssociated': personsNotAssociated
|
||||
return {
|
||||
'personsAssociated': personsAssociated,
|
||||
'personsNotAssociated': personsNotAssociated
|
||||
};
|
||||
},
|
||||
getCourseParticipations() {
|
||||
@@ -161,7 +172,11 @@ export default {
|
||||
this.$refs.addPersons.resetSearch(); // to cast child method
|
||||
modal.showModal = false;
|
||||
this.setPersonsInBloc();
|
||||
}
|
||||
},
|
||||
addNewPerson(person) {
|
||||
this.$store.dispatch('addPersonsInvolved', { result: person, type: 'person' });
|
||||
this.setPersonsInBloc();
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<li>
|
||||
<span class="badge badge-primary" :title="person.text">
|
||||
<span class="badge bg-primary" :title="person.text">
|
||||
<span class="chill_denomination">
|
||||
{{ textCutted }}
|
||||
</span>
|
||||
|
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<teleport to="#social-issues-acc">
|
||||
|
||||
<div class="container">
|
||||
<div class="grid-4 clear">
|
||||
<label>{{ $t('activity.social_issues') }}</label>
|
||||
<div class="mb-3 row">
|
||||
<div class="col-4">
|
||||
<label class="col-form-label">{{ $t('activity.social_issues') }}</label>
|
||||
</div>
|
||||
<div class="grid-8">
|
||||
<div class="col-8">
|
||||
|
||||
<check-social-issue
|
||||
v-for="issue in socialIssuesList"
|
||||
@@ -41,11 +41,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="grid-4 clear">
|
||||
<label>{{ $t('activity.social_actions') }}</label>
|
||||
<div class="mb-3 row">
|
||||
<div class="col-4">
|
||||
<label class="col-form-label">{{ $t('activity.social_actions') }}</label>
|
||||
</div>
|
||||
<div class="grid-8">
|
||||
<div class="col-8">
|
||||
|
||||
<div v-if="actionIsLoading === true">
|
||||
<i class="chill-green fa fa-circle-o-notch fa-spin fa-lg"></i>
|
||||
|
@@ -1,18 +1,20 @@
|
||||
<template>
|
||||
<span class="inline-choice">
|
||||
|
||||
<input
|
||||
type="checkbox"
|
||||
v-model="selected"
|
||||
name="action"
|
||||
v-bind:id="action.id"
|
||||
v-bind:value="action"
|
||||
/>
|
||||
<label class="inline" v-bind:for="action.id">
|
||||
{{ action.text }}
|
||||
</label>
|
||||
|
||||
</span><br>
|
||||
<div class="form-check">
|
||||
|
||||
<input class="form-check-input"
|
||||
type="checkbox"
|
||||
v-model="selected"
|
||||
name="action"
|
||||
v-bind:id="action.id"
|
||||
v-bind:value="action"
|
||||
/>
|
||||
<label class="form-check-label" v-bind:for="action.id">
|
||||
{{ action.text }}
|
||||
</label>
|
||||
|
||||
</div>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@@ -1,18 +1,20 @@
|
||||
<template>
|
||||
<span class="inline-choice">
|
||||
<div class="form-check">
|
||||
|
||||
<input
|
||||
type="checkbox"
|
||||
v-model="selected"
|
||||
name="issue"
|
||||
v-bind:id="issue.id"
|
||||
v-bind:value="issue"
|
||||
/>
|
||||
<label class="inline" v-bind:for="issue.id">
|
||||
{{ issue.text }}
|
||||
</label>
|
||||
|
||||
</span><br>
|
||||
<input class="form-check-input"
|
||||
type="checkbox"
|
||||
v-model="selected"
|
||||
name="issue"
|
||||
v-bind:id="issue.id"
|
||||
v-bind:value="issue"
|
||||
/>
|
||||
<label class="form-check-label" v-bind:for="issue.id">
|
||||
{{ issue.text }}
|
||||
</label>
|
||||
|
||||
</div>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@@ -5,165 +5,175 @@ const debug = process.env.NODE_ENV !== 'production';
|
||||
//console.log('window.activity', window.activity);
|
||||
|
||||
const addIdToValue = (string, id) => {
|
||||
let array = string ? string.split(',') : [];
|
||||
array.push(id.toString());
|
||||
let str = array.join();
|
||||
return str;
|
||||
let array = string ? string.split(',') : [];
|
||||
array.push(id.toString());
|
||||
let str = array.join();
|
||||
return str;
|
||||
};
|
||||
|
||||
const removeIdFromValue = (string, id) => {
|
||||
let array = string.split(',');
|
||||
array = array.filter(el => el !== id.toString());
|
||||
let str = array.join();
|
||||
return str;
|
||||
let array = string.split(',');
|
||||
array = array.filter(el => el !== id.toString());
|
||||
let str = array.join();
|
||||
return str;
|
||||
};
|
||||
|
||||
const store = createStore({
|
||||
strict: debug,
|
||||
state: {
|
||||
activity: window.activity,
|
||||
socialIssuesOther: [],
|
||||
socialActionsList: [],
|
||||
},
|
||||
mutations: {
|
||||
|
||||
// SocialIssueAcc
|
||||
addIssueInList(state, issue) {
|
||||
//console.log('add issue list', issue.id);
|
||||
state.activity.accompanyingPeriod.socialIssues.push(issue);
|
||||
},
|
||||
addIssueSelected(state, issue) {
|
||||
//console.log('add issue selected', issue.id);
|
||||
state.activity.socialIssues.push(issue);
|
||||
},
|
||||
updateIssuesSelected(state, issues) {
|
||||
//console.log('update issues selected', issues);
|
||||
state.activity.socialIssues = issues;
|
||||
},
|
||||
updateIssuesOther(state, payload) {
|
||||
//console.log('update issues other');
|
||||
state.socialIssuesOther = payload;
|
||||
},
|
||||
removeIssueInOther(state, issue) {
|
||||
//console.log('remove issue other', issue.id);
|
||||
state.socialIssuesOther = state.socialIssuesOther.filter(i => i.id !== issue.id);
|
||||
},
|
||||
resetActionsList(state) {
|
||||
//console.log('reset list actions');
|
||||
state.socialActionsList = [];
|
||||
},
|
||||
addActionInList(state, action) {
|
||||
//console.log('add action list', action.id);
|
||||
state.socialActionsList.push(action);
|
||||
},
|
||||
updateActionsSelected(state, actions) {
|
||||
//console.log('update actions selected', actions);
|
||||
state.activity.socialActions = actions;
|
||||
},
|
||||
filterList(state, list) {
|
||||
const filterList = (list) => {
|
||||
// remove duplicates entries
|
||||
list = list.filter((value, index) => list.findIndex(array => array.id === value.id) === index);
|
||||
// alpha sort
|
||||
list.sort((a,b) => (a.text > b.text) ? 1 : ((b.text > a.text) ? -1 : 0));
|
||||
return list;
|
||||
};
|
||||
if (list === 'issues') {
|
||||
state.activity.accompanyingPeriod.socialIssues = filterList(state.activity.accompanyingPeriod.socialIssues);
|
||||
}
|
||||
if (list === 'actions') {
|
||||
state.socialActionsList = filterList(state.socialActionsList);
|
||||
}
|
||||
},
|
||||
|
||||
// ConcernedGroups
|
||||
addPersonsInvolved(state, payload) {
|
||||
//console.log('### mutation addPersonsInvolved', payload.result.type);
|
||||
switch (payload.result.type) {
|
||||
case 'person':
|
||||
state.activity.persons.push(payload.result);
|
||||
break;
|
||||
case 'thirdparty':
|
||||
state.activity.thirdParties.push(payload.result);
|
||||
break;
|
||||
case 'user':
|
||||
state.activity.users.push(payload.result);
|
||||
break;
|
||||
};
|
||||
},
|
||||
removePersonInvolved(state, payload) {
|
||||
//console.log('### mutation removePersonInvolved', payload.type);
|
||||
switch (payload.type) {
|
||||
case 'person':
|
||||
state.activity.persons = state.activity.persons.filter(person => person !== payload);
|
||||
break;
|
||||
case 'thirdparty':
|
||||
state.activity.thirdParties = state.activity.thirdParties.filter(thirdparty => thirdparty !== payload);
|
||||
break;
|
||||
case 'user':
|
||||
state.activity.users = state.activity.users.filter(user => user !== payload);
|
||||
break;
|
||||
};
|
||||
strict: debug,
|
||||
state: {
|
||||
activity: window.activity,
|
||||
socialIssuesOther: [],
|
||||
socialActionsList: [],
|
||||
},
|
||||
getters: {
|
||||
filterSuggestedPersons(state) {
|
||||
if (typeof(state.activity.accompanyingPeriod) === 'undefined') {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
addIssueSelected({ commit }, issue) {
|
||||
let aSocialIssues = document.getElementById("chill_activitybundle_activity_socialIssues");
|
||||
aSocialIssues.value = addIdToValue(aSocialIssues.value, issue.id);
|
||||
commit('addIssueSelected', issue);
|
||||
},
|
||||
updateIssuesSelected({ commit }, payload) {
|
||||
let aSocialIssues = document.getElementById("chill_activitybundle_activity_socialIssues");
|
||||
aSocialIssues.value = '';
|
||||
payload.forEach(item => {
|
||||
aSocialIssues.value = addIdToValue(aSocialIssues.value, item.id);
|
||||
});
|
||||
commit('updateIssuesSelected', payload);
|
||||
},
|
||||
updateActionsSelected({ commit }, payload) {
|
||||
let aSocialActions = document.getElementById("chill_activitybundle_activity_socialActions");
|
||||
aSocialActions.value = '';
|
||||
payload.forEach(item => {
|
||||
aSocialActions.value = addIdToValue(aSocialActions.value, item.id);
|
||||
});
|
||||
commit('updateActionsSelected', payload);
|
||||
},
|
||||
addPersonsInvolved({ commit }, payload) {
|
||||
//console.log('### action addPersonsInvolved', payload.result.type);
|
||||
switch (payload.result.type) {
|
||||
case 'person':
|
||||
let aPersons = document.getElementById("chill_activitybundle_activity_persons");
|
||||
aPersons.value = addIdToValue(aPersons.value, payload.result.id);
|
||||
break;
|
||||
case 'thirdparty':
|
||||
let aThirdParties = document.getElementById("chill_activitybundle_activity_thirdParties");
|
||||
aThirdParties.value = addIdToValue(aThirdParties.value, payload.result.id);
|
||||
break;
|
||||
case 'user':
|
||||
let aUsers = document.getElementById("chill_activitybundle_activity_users");
|
||||
aUsers.value = addIdToValue(aUsers.value, payload.result.id);
|
||||
break;
|
||||
};
|
||||
commit('addPersonsInvolved', payload);
|
||||
},
|
||||
removePersonInvolved({ commit }, payload) {
|
||||
//console.log('### action removePersonInvolved', payload);
|
||||
switch (payload.type) {
|
||||
case 'person':
|
||||
let aPersons = document.getElementById("chill_activitybundle_activity_persons");
|
||||
aPersons.value = removeIdFromValue(aPersons.value, payload.id);
|
||||
break;
|
||||
case 'thirdparty':
|
||||
let aThirdParties = document.getElementById("chill_activitybundle_activity_thirdParties");
|
||||
aThirdParties.value = removeIdFromValue(aThirdParties.value, payload.id);
|
||||
break;
|
||||
case 'user':
|
||||
let aUsers = document.getElementById("chill_activitybundle_activity_users");
|
||||
aUsers.value = removeIdFromValue(aUsers.value, payload.id);
|
||||
break;
|
||||
};
|
||||
commit('removePersonInvolved', payload);
|
||||
let existingPersonIds = state.activity.persons.map(p => p.id);
|
||||
return state.activity.accompanyingPeriod.participations.filter(p => p.endDate === null)
|
||||
.map(p => p.person)
|
||||
.filter(p => !existingPersonIds.includes(p.id))
|
||||
}
|
||||
},
|
||||
mutations: {
|
||||
// SocialIssueAcc
|
||||
addIssueInList(state, issue) {
|
||||
//console.log('add issue list', issue.id);
|
||||
state.activity.accompanyingPeriod.socialIssues.push(issue);
|
||||
},
|
||||
addIssueSelected(state, issue) {
|
||||
//console.log('add issue selected', issue.id);
|
||||
state.activity.socialIssues.push(issue);
|
||||
},
|
||||
updateIssuesSelected(state, issues) {
|
||||
//console.log('update issues selected', issues);
|
||||
state.activity.socialIssues = issues;
|
||||
},
|
||||
updateIssuesOther(state, payload) {
|
||||
//console.log('update issues other');
|
||||
state.socialIssuesOther = payload;
|
||||
},
|
||||
removeIssueInOther(state, issue) {
|
||||
//console.log('remove issue other', issue.id);
|
||||
state.socialIssuesOther = state.socialIssuesOther.filter(i => i.id !== issue.id);
|
||||
},
|
||||
resetActionsList(state) {
|
||||
//console.log('reset list actions');
|
||||
state.socialActionsList = [];
|
||||
},
|
||||
addActionInList(state, action) {
|
||||
//console.log('add action list', action.id);
|
||||
state.socialActionsList.push(action);
|
||||
},
|
||||
updateActionsSelected(state, actions) {
|
||||
//console.log('update actions selected', actions);
|
||||
state.activity.socialActions = actions;
|
||||
},
|
||||
filterList(state, list) {
|
||||
const filterList = (list) => {
|
||||
// remove duplicates entries
|
||||
list = list.filter((value, index) => list.findIndex(array => array.id === value.id) === index);
|
||||
// alpha sort
|
||||
list.sort((a,b) => (a.text > b.text) ? 1 : ((b.text > a.text) ? -1 : 0));
|
||||
return list;
|
||||
};
|
||||
if (list === 'issues') {
|
||||
state.activity.accompanyingPeriod.socialIssues = filterList(state.activity.accompanyingPeriod.socialIssues);
|
||||
}
|
||||
if (list === 'actions') {
|
||||
state.socialActionsList = filterList(state.socialActionsList);
|
||||
}
|
||||
},
|
||||
|
||||
// ConcernedGroups
|
||||
addPersonsInvolved(state, payload) {
|
||||
//console.log('### mutation addPersonsInvolved', payload.result.type);
|
||||
switch (payload.result.type) {
|
||||
case 'person':
|
||||
state.activity.persons.push(payload.result);
|
||||
break;
|
||||
case 'thirdparty':
|
||||
state.activity.thirdParties.push(payload.result);
|
||||
break;
|
||||
case 'user':
|
||||
state.activity.users.push(payload.result);
|
||||
break;
|
||||
};
|
||||
},
|
||||
removePersonInvolved(state, payload) {
|
||||
//console.log('### mutation removePersonInvolved', payload.type);
|
||||
switch (payload.type) {
|
||||
case 'person':
|
||||
state.activity.persons = state.activity.persons.filter(person => person !== payload);
|
||||
break;
|
||||
case 'thirdparty':
|
||||
state.activity.thirdParties = state.activity.thirdParties.filter(thirdparty => thirdparty !== payload);
|
||||
break;
|
||||
case 'user':
|
||||
state.activity.users = state.activity.users.filter(user => user !== payload);
|
||||
break;
|
||||
};
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
addIssueSelected({ commit }, issue) {
|
||||
let aSocialIssues = document.getElementById("chill_activitybundle_activity_socialIssues");
|
||||
aSocialIssues.value = addIdToValue(aSocialIssues.value, issue.id);
|
||||
commit('addIssueSelected', issue);
|
||||
},
|
||||
updateIssuesSelected({ commit }, payload) {
|
||||
let aSocialIssues = document.getElementById("chill_activitybundle_activity_socialIssues");
|
||||
aSocialIssues.value = '';
|
||||
payload.forEach(item => {
|
||||
aSocialIssues.value = addIdToValue(aSocialIssues.value, item.id);
|
||||
});
|
||||
commit('updateIssuesSelected', payload);
|
||||
},
|
||||
updateActionsSelected({ commit }, payload) {
|
||||
let aSocialActions = document.getElementById("chill_activitybundle_activity_socialActions");
|
||||
aSocialActions.value = '';
|
||||
payload.forEach(item => {
|
||||
aSocialActions.value = addIdToValue(aSocialActions.value, item.id);
|
||||
});
|
||||
commit('updateActionsSelected', payload);
|
||||
},
|
||||
addPersonsInvolved({ commit }, payload) {
|
||||
//console.log('### action addPersonsInvolved', payload.result.type);
|
||||
switch (payload.result.type) {
|
||||
case 'person':
|
||||
let aPersons = document.getElementById("chill_activitybundle_activity_persons");
|
||||
aPersons.value = addIdToValue(aPersons.value, payload.result.id);
|
||||
break;
|
||||
case 'thirdparty':
|
||||
let aThirdParties = document.getElementById("chill_activitybundle_activity_thirdParties");
|
||||
aThirdParties.value = addIdToValue(aThirdParties.value, payload.result.id);
|
||||
break;
|
||||
case 'user':
|
||||
let aUsers = document.getElementById("chill_activitybundle_activity_users");
|
||||
aUsers.value = addIdToValue(aUsers.value, payload.result.id);
|
||||
break;
|
||||
};
|
||||
commit('addPersonsInvolved', payload);
|
||||
},
|
||||
removePersonInvolved({ commit }, payload) {
|
||||
//console.log('### action removePersonInvolved', payload);
|
||||
switch (payload.type) {
|
||||
case 'person':
|
||||
let aPersons = document.getElementById("chill_activitybundle_activity_persons");
|
||||
aPersons.value = removeIdFromValue(aPersons.value, payload.id);
|
||||
break;
|
||||
case 'thirdparty':
|
||||
let aThirdParties = document.getElementById("chill_activitybundle_activity_thirdParties");
|
||||
aThirdParties.value = removeIdFromValue(aThirdParties.value, payload.id);
|
||||
break;
|
||||
case 'user':
|
||||
let aUsers = document.getElementById("chill_activitybundle_activity_users");
|
||||
aUsers.value = removeIdFromValue(aUsers.value, payload.id);
|
||||
break;
|
||||
};
|
||||
commit('removePersonInvolved', payload);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
Binary file not shown.
@@ -59,8 +59,11 @@
|
||||
{% for item in bloc.items %}
|
||||
<li>
|
||||
<a href="{{ _self.href(bloc.path, bloc.key, item.id) }}">
|
||||
<span class="badge badge-primary">
|
||||
{{ item|chill_entity_render_box({'only_denomination': true}) }}
|
||||
<span class="{% if (badge_person is defined and badge_person == true) %}badge-person{% else %}badge bg-primary{% endif %}">
|
||||
{{ item|chill_entity_render_box({
|
||||
'render': 'raw',
|
||||
'addAltNames': false
|
||||
}) }}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -72,7 +75,7 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if (with_display == 'row') %}
|
||||
<div class="concerned-groups">
|
||||
{% for bloc in blocs %}
|
||||
@@ -83,8 +86,11 @@
|
||||
{% for item in bloc.items %}
|
||||
<li>
|
||||
<a href="{{ _self.href(bloc.path, bloc.key, item.id) }}">
|
||||
<span class="badge badge-primary">
|
||||
{{ item|chill_entity_render_box({'only_denomination': true}) }}
|
||||
<span class="{% if (badge_person is defined and badge_person == true) %}badge-person{% else %}badge bg-primary{% endif %}">
|
||||
{{ item|chill_entity_render_box({
|
||||
'render': 'raw',
|
||||
'addAltNames': false
|
||||
}) }}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
{% extends "@ChillPerson/layout.html.twig" %}
|
||||
{% extends "@ChillPerson/Person/layout.html.twig" %}
|
||||
|
||||
{% set activeRouteKey = 'chill_activity_activity_list' %}
|
||||
{% set person = activity.person %}
|
||||
|
@@ -1,8 +1,5 @@
|
||||
<h1>{{ "Update activity"|trans ~ ' :' }}
|
||||
<span style="font-size: 70%; text-transform: lowercase; margin-left: 1em;">
|
||||
{{ entity.type.name|localize_translatable_string }}
|
||||
</span>
|
||||
</h1>
|
||||
<h1>{{ "Update activity"|trans }}</h1>
|
||||
<h2 class="chill-green mb-4">{{ entity.type.name|localize_translatable_string }}</h2>
|
||||
|
||||
{{ form_start(edit_form) }}
|
||||
{{ form_errors(edit_form) }}
|
||||
@@ -57,7 +54,7 @@
|
||||
{{ form_row(edit_form.date) }}
|
||||
{% endif %}
|
||||
|
||||
.. location
|
||||
{# TODO .. location #}
|
||||
|
||||
{%- if edit_form.durationTime is defined -%}
|
||||
{{ form_row(edit_form.durationTime) }}
|
||||
@@ -68,7 +65,7 @@
|
||||
{% endif %}
|
||||
|
||||
{%- if edit_form.comment is defined -%}
|
||||
.. public and private
|
||||
{# TODO .. public and private #}
|
||||
{{ form_row(edit_form.comment) }}
|
||||
{% endif %}
|
||||
|
||||
@@ -80,7 +77,7 @@
|
||||
{{ form_row(edit_form.attendee) }}
|
||||
{% endif %}
|
||||
|
||||
.. status
|
||||
{# TODO .. status #}
|
||||
|
||||
{% set person_id = null %}
|
||||
{% if entity.person %}
|
||||
@@ -94,12 +91,12 @@
|
||||
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li class="cancel">
|
||||
<a href="{{ path('chill_activity_activity_show', { 'id': entity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id } ) }}" class="sc-button bt-cancel">
|
||||
<a href="{{ path('chill_activity_activity_show', { 'id': entity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id } ) }}" class="btn btn-cancel">
|
||||
{{ 'Cancel'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<button class="sc-button bt-update" type="submit">{{ 'Save'|trans }}</button>
|
||||
<button class="btn btn-update" type="submit">{{ 'Save'|trans }}</button>
|
||||
</li>
|
||||
</ul>
|
||||
{{ form_end(edit_form) }}
|
||||
|
@@ -5,13 +5,17 @@
|
||||
{% block title 'Update activity'|trans %}
|
||||
|
||||
{% block content %}
|
||||
<div id="activity"></div> {# <=== vue component #}
|
||||
{% include 'ChillActivityBundle:Activity:edit.html.twig' %}
|
||||
<div class="activity-edit">
|
||||
|
||||
<div id="activity"></div> {# <=== vue component #}
|
||||
{% include 'ChillActivityBundle:Activity:edit.html.twig' %}
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_link_tags('async_upload') }}
|
||||
{{ encore_entry_link_tags('mod_async_upload') }}
|
||||
<script type="text/javascript">
|
||||
window.addEventListener('DOMContentLoaded', function (e) {
|
||||
chill.displayAlertWhenLeavingModifiedForm('form[name="{{ edit_form.vars.form.vars.name }}"]',
|
||||
@@ -24,6 +28,6 @@
|
||||
|
||||
{% block css %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_link_tags('async_upload') }}
|
||||
{{ encore_entry_link_tags('mod_async_upload') }}
|
||||
{{ encore_entry_link_tags('vue_activity') }}
|
||||
{% endblock %}
|
||||
|
@@ -14,19 +14,23 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#}
|
||||
{% extends "@ChillPerson/layout.html.twig" %}
|
||||
{% extends "@ChillPerson/Person/layout.html.twig" %}
|
||||
|
||||
{% set activeRouteKey = 'chill_activity_activity_list' %}
|
||||
|
||||
{% block title 'Update activity'|trans %}
|
||||
|
||||
{% block personcontent %}
|
||||
<div id="activity"></div> {# <=== vue component #}
|
||||
{% include 'ChillActivityBundle:Activity:edit.html.twig' %}
|
||||
<div class="activity-edit">
|
||||
|
||||
<div id="activity"></div> {# <=== vue component #}
|
||||
{% include 'ChillActivityBundle:Activity:edit.html.twig' %}
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ encore_entry_link_tags('async_upload') }}
|
||||
{{ encore_entry_link_tags('mod_async_upload') }}
|
||||
<script type="text/javascript">
|
||||
window.addEventListener('DOMContentLoaded', function (e) {
|
||||
chill.displayAlertWhenLeavingModifiedForm('form[name="{{ edit_form.vars.form.vars.name }}"]',
|
||||
@@ -38,6 +42,6 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ encore_entry_link_tags('async_upload') }}
|
||||
{{ encore_entry_link_tags('mod_async_upload') }}
|
||||
{{ encore_entry_link_tags('vue_activity') }}
|
||||
{% endblock %}
|
||||
|
@@ -1,197 +1,186 @@
|
||||
{% set person_id = null %}
|
||||
{% if person %}
|
||||
{% set person_id = person.id %}
|
||||
{% endif %}
|
||||
<div class="activity-list context-{{ context }}">
|
||||
|
||||
{% set accompanying_course_id = null %}
|
||||
{% if accompanyingCourse %}
|
||||
{% set accompanying_course_id = accompanyingCourse.id %}
|
||||
{% endif %}
|
||||
{% if activities|length == 0 %}
|
||||
<p class="chill-no-data-statement">
|
||||
{{ "There isn't any activities."|trans }}
|
||||
<a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'accompanying_period_id': accompanying_course_id}) }}" class="btn btn-sm btn-create"></a>
|
||||
</p>
|
||||
|
||||
<h2>{{ 'Activity list' |trans }}</h2>
|
||||
{% else %}
|
||||
<div class="flex-table">
|
||||
{% for activity in activities %}
|
||||
{% set t = activity.type %}
|
||||
<div class="item-bloc">
|
||||
<div class="item-row main">
|
||||
<div class="item-col">
|
||||
|
||||
{% if activities|length == 0 %}
|
||||
<p class="chill-no-data-statement">
|
||||
{{ "There isn't any activities."|trans }}
|
||||
<a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'accompanying_period_id': accompanying_course_id}) }}" class="sc-button bt-create button-small"></a>
|
||||
</p>
|
||||
{% else %}
|
||||
{% if activity.date %}
|
||||
<h3>{{ activity.date|format_date('long') }}</h3>
|
||||
{% endif %}
|
||||
|
||||
<div class="flex-table list-records context-{{ context }}">
|
||||
<!--
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="chill-red">{{'Date' | trans }}</th>
|
||||
<th class="chill-green">{{'Duration Time' | trans }}</th>
|
||||
<th class="chill-orange">{{'Reasons' | trans}}</th>
|
||||
<th>{{'Type' | trans}}</th>
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
-->
|
||||
{% for activity in activities %}
|
||||
{% set t = activity.type %}
|
||||
<div class="item-bloc">
|
||||
<div class="item-row main">
|
||||
<div class="item-col">
|
||||
|
||||
{% if activity.date %}
|
||||
<h3>{{ activity.date|format_date('long') }}</h3>
|
||||
{% endif %}
|
||||
|
||||
<div class="duration">
|
||||
{% if t.durationTimeVisible > 0 %}
|
||||
<p>
|
||||
<i class="fa fa-fw fa-hourglass-end"></i>
|
||||
{{ activity.durationTime|date('H:i') }}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if activity.travelTime and t.travelTimeVisible %}
|
||||
<p>
|
||||
<i class="fa fa-fw fa-car"></i>
|
||||
{{ activity.travelTime|date('H:i') }}
|
||||
</p>
|
||||
{% endif %}
|
||||
<div class="duration">
|
||||
{% if activity.durationTime and t.durationTimeVisible %}
|
||||
<p>
|
||||
<i class="fa fa-fw fa-hourglass-end"></i>
|
||||
{{ activity.durationTime|date('H:i') }}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if activity.travelTime and t.travelTimeVisible %}
|
||||
<p>
|
||||
<i class="fa fa-fw fa-car"></i>
|
||||
{{ activity.travelTime|date('H:i') }}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if context == 'person' and activity.accompanyingPeriod is not empty %}
|
||||
<div class="mt-3">
|
||||
<a class="btn btn-sm btn-outline-primary"
|
||||
title="{{ 'Period number %number%'|trans({'%number%': activity.accompanyingPeriod.id}) }}"
|
||||
href="{{ chill_path_add_return_path(
|
||||
"chill_person_accompanying_course_index",
|
||||
{ 'accompanying_period_id': activity.accompanyingPeriod.id }
|
||||
) }}"><i class="fa fa-random"></i>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
<div class="item-col">
|
||||
|
||||
<div class="float-button top">
|
||||
<div class="box">
|
||||
|
||||
<div class="action">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_show', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"
|
||||
class="btn btn-sm btn-show "></a>
|
||||
</li>
|
||||
{% if no_action is not defined or no_action == false %}
|
||||
{# TODO
|
||||
{% if is_granted('CHILL_ACTIVITY_UPDATE', activity) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_edit', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"
|
||||
class="btn btn-sm btn-update "></a>
|
||||
</li>
|
||||
{# TODO
|
||||
{% endif %}
|
||||
{% if is_granted('CHILL_ACTIVITY_DELETE', activity) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_delete', { 'id': activity.id, 'person_id' : person_id, 'accompanying_period_id': accompanying_course_id } ) }}"
|
||||
class="btn btn-sm btn-delete "></a>
|
||||
</li>
|
||||
{# TODO
|
||||
{% endif %}
|
||||
#}
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<ul class="list-content">
|
||||
|
||||
{% if activity.user and t.userVisible %}
|
||||
<li>
|
||||
<abbr class="referrer" title="{{ 'Referrer'|trans }}">ref:</abbr>
|
||||
<b>{{ activity.user.usernameCanonical }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li>
|
||||
<b>{{ activity.type.name | localize_translatable_string }}</b>
|
||||
|
||||
{% if activity.attendee is not null and t.attendeeVisible %}
|
||||
{% if activity.attendee %}
|
||||
{{ '→ ' ~ 'present'|trans|capitalize }}
|
||||
{% else %}
|
||||
{{ '→ ' ~ 'not present'|trans|capitalize }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<b>{{ 'location'|trans ~ ': ' }}</b>
|
||||
Domicile de l'usager
|
||||
|
||||
{# TODO {% if activity.location %}{{ activity.location }}{% endif %}
|
||||
#}
|
||||
|
||||
</li>
|
||||
|
||||
{%- if t.reasonsVisible -%}
|
||||
<li>
|
||||
{%- if activity.reasons is not empty -%}
|
||||
{% for r in activity.reasons %}
|
||||
{{ r|chill_entity_render_box }}
|
||||
{% endfor %}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{%- if t.socialIssuesVisible %}
|
||||
<li class="social-issues">
|
||||
{%- if activity.socialIssues is not empty -%}
|
||||
{% for r in activity.socialIssues %}
|
||||
{{ r|chill_entity_render_box }}
|
||||
{% endfor %}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{%- if t.socialActionsVisible -%}
|
||||
<li class="social-actions">
|
||||
{%- if activity.socialActions is not empty -%}
|
||||
{% for r in activity.socialActions %}
|
||||
{{ r|chill_entity_render_box }}
|
||||
{% endfor %}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if context == 'person' and activity.accompanyingPeriod is not empty %}
|
||||
<div class="accompanyingPeriodLink" style="margin-top: 1rem">
|
||||
<a
|
||||
href="{{ chill_path_add_return_path(
|
||||
"chill_person_accompanying_course_index",
|
||||
{ 'accompanying_period_id': activity.accompanyingPeriod.id }
|
||||
) }}"
|
||||
>
|
||||
<i class="fa fa-random"></i>
|
||||
{{ activity.accompanyingPeriod.id }}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
<div class="item-col">
|
||||
<ul class="list-content">
|
||||
{% if activity.user and t.userVisible %}
|
||||
<li>
|
||||
<b>{{ 'by'|trans }}{{ activity.user.usernameCanonical }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li>
|
||||
<b>{{ activity.type.name | localize_translatable_string }}</b>
|
||||
|
||||
{% if activity.attendee is not null and t.attendeeVisible %}
|
||||
{% if activity.attendee %}
|
||||
{{ '→ ' ~ 'present'|trans|capitalize }}
|
||||
{% else %}
|
||||
{{ '→ ' ~ 'not present'|trans|capitalize }}
|
||||
{% endif %}
|
||||
|
||||
{% if activity.comment.comment is not empty
|
||||
or activity.persons|length > 0
|
||||
or activity.thirdParties|length > 0
|
||||
or activity.users|length > 0
|
||||
%}
|
||||
<div class="item-row comment separator">
|
||||
{% if activity.comment.comment is not empty %}
|
||||
{{ activity.comment|chill_entity_render_box({
|
||||
'disable_markdown': false,
|
||||
'limit_lines': 3,
|
||||
'metadata': false,
|
||||
}) }}
|
||||
{% endif %}
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<b>{{ 'location'|trans ~ ': ' }}</b>
|
||||
Domicile de l'usager
|
||||
{#
|
||||
{% if activity.location %}{{ activity.location }}{% endif %}
|
||||
#}
|
||||
</li>
|
||||
|
||||
{%- if t.reasonsVisible -%}
|
||||
<li>
|
||||
{%- if activity.reasons is empty -%}
|
||||
<span class="chill-no-data-statement">{{ 'No reason associated'|trans }}</span>
|
||||
{%- else -%}
|
||||
{% for r in activity.reasons %}
|
||||
{{ r|chill_entity_render_box }}
|
||||
{% endfor %}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="item-row details">
|
||||
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {
|
||||
'context': context,
|
||||
'with_display': 'bloc',
|
||||
'entity': activity,
|
||||
'badge_person': true
|
||||
} %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{%- if t.socialIssuesVisible %}
|
||||
<li class="social-issues">
|
||||
{%- if activity.socialIssues is empty -%}
|
||||
<span class="chill-no-data-statement">{{ 'No social issues associated'|trans }}</span>
|
||||
{%- else -%}
|
||||
{% for r in activity.socialIssues %}
|
||||
{{ r|chill_entity_render_box }}
|
||||
{% endfor %}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{%- if t.socialActionsVisible -%}
|
||||
<li class="social-actions">
|
||||
{%- if activity.socialActions is empty -%}
|
||||
<span class="chill-no-data-statement">{{ 'No social actions associated'|trans }}</span>
|
||||
{%- else -%}
|
||||
{% for r in activity.socialActions %}
|
||||
<span class="badge badge-primary">{{ r.title|localize_translatable_string }}</span>
|
||||
{% endfor %}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</ul>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_show', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}" class="sc-button bt-show "></a>
|
||||
</li>
|
||||
{# TOOD
|
||||
{% if is_granted('CHILL_ACTIVITY_UPDATE', activity) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_edit', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}" class="sc-button bt-update "></a>
|
||||
</li>
|
||||
{# TOOD
|
||||
{% endif %}
|
||||
{% if is_granted('CHILL_ACTIVITY_DELETE', activity) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_delete', { 'id': activity.id, 'person_id' : person_id, 'accompanying_period_id': accompanying_course_id } ) }}" class="sc-button bt-delete "></a>
|
||||
</li>
|
||||
{#
|
||||
{% endif %}
|
||||
#}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{%
|
||||
if activity.comment.comment is not empty
|
||||
or activity.persons|length > 0
|
||||
or activity.thirdParties|length > 0
|
||||
or activity.users|length > 0
|
||||
%}
|
||||
<div class="item-row details">
|
||||
<div class="item-col">
|
||||
|
||||
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {'context': context, 'with_display': 'row', 'entity': activity } %}
|
||||
</div>
|
||||
|
||||
{% if activity.comment.comment is not empty %}
|
||||
<div class="item-col comment">
|
||||
{{ activity.comment|chill_entity_render_box( { 'limit_lines': 3, 'metadata': false } ) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if context != 'person' %}
|
||||
{# TODO set this condition in configuration #}
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'accompanying_period_id': accompanying_course_id}) }}" class="sc-button bt-create">
|
||||
{{ 'Add a new activity' | trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
@@ -5,5 +5,27 @@
|
||||
{% block title %}{{ 'Activity list' |trans }}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% set person_id = null %}
|
||||
{% if person %}
|
||||
{% set person_id = person.id %}
|
||||
{% endif %}
|
||||
|
||||
{% set accompanying_course_id = null %}
|
||||
{% if accompanyingCourse %}
|
||||
{% set accompanying_course_id = accompanyingCourse.id %}
|
||||
{% endif %}
|
||||
|
||||
<h1>{{ 'Activity list' |trans }}</h1>
|
||||
|
||||
{% include 'ChillActivityBundle:Activity:list.html.twig' with {'context': 'accompanyingCourse'} %}
|
||||
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'accompanying_period_id': accompanying_course_id}) }}" class="btn btn-create">
|
||||
{{ 'Add a new activity' | trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{% endblock %}
|
||||
|
@@ -14,12 +14,34 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#}
|
||||
{% extends "@ChillPerson/layout.html.twig" %}
|
||||
{% extends "@ChillPerson/Person/layout.html.twig" %}
|
||||
|
||||
{% set activeRouteKey = 'chill_activity_activity_list' %}
|
||||
|
||||
{% block title %}{{ 'Activity list' |trans }}{% endblock title %}
|
||||
|
||||
{% block personcontent %}
|
||||
|
||||
{% set person_id = null %}
|
||||
{% if person %}
|
||||
{% set person_id = person.id %}
|
||||
{% endif %}
|
||||
|
||||
{% set accompanying_course_id = null %}
|
||||
{% if accompanyingCourse %}
|
||||
{% set accompanying_course_id = accompanyingCourse.id %}
|
||||
{% endif %}
|
||||
|
||||
<h1>{{ 'Activity list' |trans }}</h1>
|
||||
|
||||
{% include 'ChillActivityBundle:Activity:list.html.twig' with {'context': 'person'} %}
|
||||
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'accompanying_period_id': accompanying_course_id}) }}"
|
||||
class="btn btn-create disabled" tabindex="-1" role="button" aria-disabled="true">{{ 'Add a new activity' | trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{% endblock %}
|
||||
|
@@ -1,8 +1,5 @@
|
||||
<h1>{{ "Activity creation"|trans ~ ' :' }}
|
||||
<span style="font-size: 70%; text-transform: lowercase; margin-left: 1em;">
|
||||
{{ entity.type.name|localize_translatable_string }}
|
||||
</span>
|
||||
</h1>
|
||||
<h1>{{ "Activity creation"|trans ~ ' :' }}</h1>
|
||||
<h2 class="chill-green mb-4">{{ entity.type.name|localize_translatable_string }}</h2>
|
||||
|
||||
{{ form_start(form) }}
|
||||
{{ form_errors(form) }}
|
||||
@@ -58,7 +55,7 @@
|
||||
{{ form_row(form.date) }}
|
||||
{% endif %}
|
||||
|
||||
.. location
|
||||
{# TODO .. location #}
|
||||
|
||||
{%- if form.durationTime is defined -%}
|
||||
{{ form_row(form.durationTime) }}
|
||||
@@ -69,7 +66,7 @@
|
||||
{% endif %}
|
||||
|
||||
{%- if form.comment is defined -%}
|
||||
.. public and private
|
||||
{# TODO .. public and private #}
|
||||
{{ form_row(form.comment) }}
|
||||
{% endif %}
|
||||
|
||||
@@ -81,13 +78,13 @@
|
||||
{{ form_row(form.attendee) }}
|
||||
{% endif %}
|
||||
|
||||
.. status
|
||||
{# TODO .. status #}
|
||||
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li class="cancel">
|
||||
<a
|
||||
class="sc-button bt-cancel"
|
||||
{%- if context == 'person' -%}
|
||||
<a
|
||||
class="btn btn-cancel"
|
||||
{%- if context == 'person' -%}
|
||||
href="{{ chill_return_path_or('chill_activity_activity_list', { 'person_id': person.id } )}}"
|
||||
{%- else -%}
|
||||
href="{{ chill_return_path_or('chill_activity_activity_list', { 'accompanying_period_id': accompanyingCourse.id } )}}"
|
||||
@@ -97,7 +94,7 @@
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<button class="sc-button bt-create" type="submit">
|
||||
<button class="btn btn-create" type="submit">
|
||||
{{ 'Create'|trans }}
|
||||
</button>
|
||||
</li>
|
||||
|
@@ -5,25 +5,29 @@
|
||||
{% block title 'Activity creation' |trans %}
|
||||
|
||||
{% block content %}
|
||||
<div class="activity-new">
|
||||
|
||||
<div id="activity"></div> {# <=== vue component #}
|
||||
{% include 'ChillActivityBundle:Activity:new.html.twig' with {'context': 'accompanyingCourse'} %}
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_script_tags('async_upload') }}
|
||||
{{ encore_entry_script_tags('mod_async_upload') }}
|
||||
<script type="text/javascript">
|
||||
window.addEventListener('DOMContentLoaded', function (e) {
|
||||
chill.displayAlertWhenLeavingUnsubmittedForm('form[name="{{ form.vars.form.vars.name }}"]',
|
||||
chill.displayAlertWhenLeavingUnsubmittedForm('form[name="{{ form.vars.form.vars.name }}"]',
|
||||
'{{ "You are going to leave a page with unsubmitted data. Are you sure you want to leave ?"|trans }}');
|
||||
});
|
||||
window.activity = {{ activity_json|json_encode|raw }};
|
||||
window.activity = {{ activity_json|json_encode|raw }};
|
||||
</script>
|
||||
{{ encore_entry_script_tags('vue_activity') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ parent() }}
|
||||
<link rel="stylesheet" href="{{ asset('build/async_upload.css') }}"/>
|
||||
{{ encore_entry_link_tags('mod_async_upload') }}
|
||||
{{ encore_entry_link_tags('vue_activity') }}
|
||||
{% endblock %}
|
||||
|
@@ -1,16 +1,20 @@
|
||||
{% extends "@ChillPerson/layout.html.twig" %}
|
||||
{% extends "@ChillPerson/Person/layout.html.twig" %}
|
||||
|
||||
{% set activeRouteKey = 'chill_activity_activity_new' %}
|
||||
|
||||
{% block title 'Activity creation' |trans %}
|
||||
|
||||
{% block personcontent %}
|
||||
<div id="activity"></div> {# <=== vue component #}
|
||||
{% include 'ChillActivityBundle:Activity:new.html.twig' with {'context': 'person'} %}
|
||||
<div class="activity-new">
|
||||
|
||||
<div id="activity"></div> {# <=== vue component #}
|
||||
{% include 'ChillActivityBundle:Activity:new.html.twig' with {'context': 'person'} %}
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ encore_entry_link_tags('async_upload') }}
|
||||
{{ encore_entry_link_tags('mod_async_upload') }}
|
||||
<script type="text/javascript">
|
||||
window.addEventListener('DOMContentLoaded', function (e) {
|
||||
chill.displayAlertWhenLeavingUnsubmittedForm('form[name="{{ form.vars.form.vars.name }}"]',
|
||||
@@ -22,6 +26,6 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ encore_entry_link_tags('async_upload') }}
|
||||
{{ encore_entry_link_tags('mod_async_upload') }}
|
||||
{{ encore_entry_link_tags('vue_activity') }}
|
||||
{% endblock %}
|
||||
|
@@ -1,28 +1,35 @@
|
||||
<h2 class="chill-red">{{ "Activity creation"|trans }}</h2>
|
||||
<div class="new-activity-select-type">
|
||||
<h2 class="chill-red">{{ "Activity creation"|trans }}</h2>
|
||||
|
||||
{# TODO: refaire l'html css des tuilles #}
|
||||
{# TODO: refaire l'html css des tuilles #}
|
||||
|
||||
{% for row in data %}
|
||||
<h3>{{ row.activityTypeCategory.name|localize_translatable_string }}</h3>
|
||||
<div class="activity-row">
|
||||
{% for activityType in row.activityTypes %}
|
||||
{% for row in data %}
|
||||
<h3>{{ row.activityTypeCategory.name|localize_translatable_string }}</h3>
|
||||
<div class="activity-row">
|
||||
{% for activityType in row.activityTypes %}
|
||||
|
||||
{% set person_id = null %}
|
||||
{% if person %}
|
||||
{% set person_id = person.id %}
|
||||
{% endif %}
|
||||
{% set person_id = null %}
|
||||
{% if person %}
|
||||
{% set person_id = person.id %}
|
||||
{% endif %}
|
||||
|
||||
{% set accompanying_course_id = null %}
|
||||
{% if accompanyingCourse %}
|
||||
{% set accompanying_course_id = accompanyingCourse.id %}
|
||||
{% endif %}
|
||||
{% set accompanying_course_id = null %}
|
||||
{% if accompanyingCourse %}
|
||||
{% set accompanying_course_id = accompanyingCourse.id %}
|
||||
{% endif %}
|
||||
|
||||
<a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'activityType_id': activityType.id, 'accompanying_period_id': accompanying_course_id }) }}">
|
||||
<a href="{{ path('chill_activity_activity_new', {
|
||||
'person_id': person_id,
|
||||
'activityType_id': activityType.id,
|
||||
'accompanying_period_id': accompanying_course_id,
|
||||
'activityData': activityData
|
||||
}) }}">
|
||||
|
||||
<div class="bloc btn btn-primary btn-lg btn-block">
|
||||
{{ activityType.name|localize_translatable_string }}
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="bloc btn btn-primary btn-lg btn-block">
|
||||
{{ activityType.name|localize_translatable_string }}
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
{% extends "@ChillPerson/layout.html.twig" %}
|
||||
{% extends "@ChillPerson/Person/layout.html.twig" %}
|
||||
|
||||
{% set activeRouteKey = 'chill_activity_activity_new' %}
|
||||
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<h1>
|
||||
{{ "Activity"|trans }}
|
||||
{%- if t.emergencyVisible and entity.emergency -%}
|
||||
<span class="badge badge-secondary">
|
||||
<span class="badge bg-secondary">
|
||||
{{- 'Emergency'|trans -}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
@@ -64,16 +64,26 @@
|
||||
|
||||
{% if t.durationTimeVisible %}
|
||||
<dt class="inline">{{ 'Duration Time'|trans }}</dt>
|
||||
<dd>{{ entity.durationTime|date('H:i') }}</dd>
|
||||
<dd>{% if entity.durationTime is not null %}
|
||||
{{ entity.durationTime|date('H:i') }}
|
||||
{% else %}
|
||||
{{ 'None'|trans|capitalize }}
|
||||
{% endif %}
|
||||
</dd>
|
||||
{% endif %}
|
||||
|
||||
{% if t.travelTimeVisible %}
|
||||
<dt class="inline">{{ 'Travel Time'|trans }}</dt>
|
||||
<dd>{{ entity.travelTime|date('H:i') }}</dd>
|
||||
<dd>{% if entity.travelTime is not null %}
|
||||
{{ entity.travelTime|date('H:i') }}
|
||||
{% else %}
|
||||
{{ 'None'|trans|capitalize }}
|
||||
{% endif %}
|
||||
</dd>
|
||||
{% endif %}
|
||||
|
||||
{% if t.commentVisible %}
|
||||
<dt class="inline">{{ 'Comment'|trans }}</dt>
|
||||
<dt class="inline">{{ 'activity.comment'|trans }}</dt>
|
||||
{%- if entity.comment.empty -%}
|
||||
<dd><span class="chill-no-data-statement">{{ 'No comment associated'|trans }}</span></dd>
|
||||
{%- else -%}
|
||||
@@ -109,25 +119,28 @@
|
||||
{% set accompanying_course_id = accompanyingCourse.id %}
|
||||
{% endif %}
|
||||
|
||||
<ul class="record_actions">
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li class="cancel">
|
||||
<a class="sc-button bt-cancel" href="{{ path('chill_activity_activity_list', { 'person_id': person_id, 'accompanying_period_id': accompanying_course_id } ) }}">
|
||||
<a class="btn btn-cancel" href="{{ path('chill_activity_activity_list', { 'person_id': person_id, 'accompanying_period_id': accompanying_course_id } ) }}">
|
||||
{{ 'Back to the list'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="sc-button bt-update" href="{{ path('chill_activity_activity_edit', { 'id': entity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}">
|
||||
{{ 'Edit'|trans }}
|
||||
</a>
|
||||
<a class="btn btn-update" href="{{ path('chill_activity_activity_edit', { 'id': entity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}">
|
||||
{{ 'Edit'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
{# TODO
|
||||
{% if is_granted('CHILL_ACTIVITY_DELETE', entity) %}
|
||||
#}
|
||||
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_delete', { 'id': entity.id, 'person_id' : person_id, 'accompanying_period_id': accompanying_course_id } ) }}" class="sc-button bt-delete">
|
||||
<a href="{{ path('chill_activity_activity_delete', { 'id': entity.id, 'person_id' : person_id, 'accompanying_period_id': accompanying_course_id } ) }}" class="btn btn-delete">
|
||||
{{ 'Delete'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
{#
|
||||
{% endif %}
|
||||
#}
|
||||
|
@@ -2,10 +2,14 @@
|
||||
|
||||
{% set activeRouteKey = 'chill_activity_activity_list' %}
|
||||
|
||||
{% block title 'Activity'|trans %}
|
||||
{% block title 'Show the activity'|trans %}
|
||||
|
||||
{% import 'ChillActivityBundle:ActivityReason:macro.html.twig' as m %}
|
||||
|
||||
{% block content -%}
|
||||
{% include 'ChillActivityBundle:Activity:show.html.twig' with {'context': 'accompanyingCourse'} %}
|
||||
<div class="activity-show">
|
||||
|
||||
{% include 'ChillActivityBundle:Activity:show.html.twig' with {'context': 'accompanyingCourse'} %}
|
||||
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
@@ -0,0 +1,4 @@
|
||||
|
||||
{{ dump(notification) }}
|
||||
|
||||
<a href="{{ path('chill_activity_activity_show', {'id': notification.relatedEntityId }) }}">Go to Activity</a>
|
@@ -1,11 +1,15 @@
|
||||
{% extends "@ChillPerson/layout.html.twig" %}
|
||||
{% extends "@ChillPerson/Person/layout.html.twig" %}
|
||||
|
||||
{% set activeRouteKey = 'chill_activity_activity_list' %}
|
||||
|
||||
{% block title 'Activity'|trans %}
|
||||
{% block title 'Show the activity'|trans %}
|
||||
|
||||
{% import 'ChillActivityBundle:ActivityReason:macro.html.twig' as m %}
|
||||
|
||||
{% block personcontent -%}
|
||||
{% include 'ChillActivityBundle:Activity:show.html.twig' with {'context': 'person'} %}
|
||||
<div class="activity-show">
|
||||
|
||||
{% include 'ChillActivityBundle:Activity:show.html.twig' with {'context': 'person'} %}
|
||||
|
||||
</div>
|
||||
{% endblock personcontent %}
|
||||
|
@@ -25,7 +25,7 @@
|
||||
<td>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_crud_activity_presence_edit', { 'id': entity.id }) }}" class="sc-button bt-edit" title="{{ 'edit'|trans }}"></a>
|
||||
<a href="{{ path('chill_crud_activity_presence_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_crud_activity_presence_new') }}" class="sc-button bt-create">
|
||||
<a href="{{ path('chill_crud_activity_presence_new') }}" class="btn btn-create">
|
||||
{{ 'Create a new activity presence'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
|
@@ -26,10 +26,10 @@
|
||||
|
||||
<ul class="record_actions">
|
||||
<li class="cancel">
|
||||
<a href="{{ path('chill_activity_activityreason') }}" class="sc-button bt-cancel">{{ 'Back to the list'|trans }}</a>
|
||||
<a href="{{ path('chill_activity_activityreason') }}" class="btn btn-cancel">{{ 'Back to the list'|trans }}</a>
|
||||
</li>
|
||||
<li>
|
||||
{{ form_row(edit_form.submit, { 'attr': { 'class' : 'sc-button orange' } } ) }}
|
||||
{{ form_row(edit_form.submit, { 'attr': { 'class' : 'btn btn-chill-orange' } } ) }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
@@ -33,10 +33,10 @@
|
||||
<td>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activityreason_show', { 'id': entity.id }) }}" class="sc-button bt-show" title="{{ 'show'|trans }}"></a>
|
||||
<a href="{{ path('chill_activity_activityreason_show', { 'id': entity.id }) }}" class="btn btn-show" title="{{ 'show'|trans }}"></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activityreason_edit', { 'id': entity.id }) }}" class="sc-button bt-edit" title="{{ 'edit'|trans }}"></a>
|
||||
<a href="{{ path('chill_activity_activityreason_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activityreason_new') }}" class="sc-button bt-new">
|
||||
<a href="{{ path('chill_activity_activityreason_new') }}" class="btn btn-new">
|
||||
{{ 'Create a new activity reason'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
|
@@ -26,10 +26,10 @@
|
||||
|
||||
<ul class="record_actions">
|
||||
<li class="cancel">
|
||||
<a href="{{ path('chill_activity_activityreason') }}" class="sc-button bt-cancel">{{ 'Back to the list'|trans }}</a>
|
||||
<a href="{{ path('chill_activity_activityreason') }}" class="btn btn-cancel">{{ 'Back to the list'|trans }}</a>
|
||||
</li>
|
||||
<li>
|
||||
{{ form_row(form.submit, { 'attr': { 'class' : 'sc-button bt-new' } } ) }}
|
||||
{{ form_row(form.submit, { 'attr': { 'class' : 'btn btn-new' } } ) }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
@@ -40,12 +40,12 @@
|
||||
|
||||
<ul class="record_actions">
|
||||
<li class="cancel">
|
||||
<a href="{{ path('chill_activity_activityreason') }}" class="sc-button bt-cancel">
|
||||
<a href="{{ path('chill_activity_activityreason') }}" class="btn btn-cancel">
|
||||
{{ 'Back to the list'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activityreason_edit', { 'id': entity.id }) }}" class="sc-button bt-edit">
|
||||
<a href="{{ path('chill_activity_activityreason_edit', { 'id': entity.id }) }}" class="btn btn-edit">
|
||||
{{ 'Edit'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
|
@@ -25,12 +25,12 @@
|
||||
|
||||
<ul class="record_actions">
|
||||
<li class="cancel">
|
||||
<a href="{{ path('chill_activity_activityreasoncategory') }}" class="sc-button bt-cancel">
|
||||
<a href="{{ path('chill_activity_activityreasoncategory') }}" class="btn btn-cancel">
|
||||
{{ 'Back to the list'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
{{ form_row(edit_form.submit, { 'attr': { 'class': 'sc-button bt-edit' } } ) }}
|
||||
{{ form_row(edit_form.submit, { 'attr': { 'class': 'btn btn-edit' } } ) }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
@@ -34,10 +34,10 @@
|
||||
<td>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activityreasoncategory_show', { 'id': entity.id }) }}" class="sc-button bt-show" title="{{ 'show'|trans }}"></a>
|
||||
<a href="{{ path('chill_activity_activityreasoncategory_show', { 'id': entity.id }) }}" class="btn btn-show" title="{{ 'show'|trans }}"></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activityreasoncategory_edit', { 'id': entity.id }) }}" class="sc-button bt-edit" title="{{ 'edit'|trans }}"></a>
|
||||
<a href="{{ path('chill_activity_activityreasoncategory_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
@@ -48,7 +48,7 @@
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activityreasoncategory_new') }}" class="sc-button bt-new">
|
||||
<a href="{{ path('chill_activity_activityreasoncategory_new') }}" class="btn btn-new">
|
||||
{{ 'Create a new activity category reason'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
|
@@ -25,10 +25,10 @@
|
||||
|
||||
<ul class="record_actions">
|
||||
<li class="cancel">
|
||||
<a href="{{ path('chill_activity_activityreasoncategory') }}" class="sc-button bt-cancel">{{ 'Back to the list'|trans }}</a>
|
||||
<a href="{{ path('chill_activity_activityreasoncategory') }}" class="btn btn-cancel">{{ 'Back to the list'|trans }}</a>
|
||||
</li>
|
||||
<li>
|
||||
{{ form_widget(form.submit, { 'attr': { 'class' : 'sc-button bt-new' } } ) }}
|
||||
{{ form_widget(form.submit, { 'attr': { 'class' : 'btn btn-new' } } ) }}
|
||||
</li>
|
||||
</ul>
|
||||
{{ form_end(form) }}
|
||||
|
@@ -39,12 +39,12 @@
|
||||
</table>
|
||||
<ul class="record_actions">
|
||||
<li class="cancel">
|
||||
<a href="{{ path('chill_activity_activityreasoncategory') }}" class="sc-button bt-cancel">
|
||||
<a href="{{ path('chill_activity_activityreasoncategory') }}" class="btn btn-cancel">
|
||||
{{ 'Back to the list'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activityreasoncategory_edit', { 'id': entity.id }) }}" class="sc-button bt-edit">
|
||||
<a href="{{ path('chill_activity_activityreasoncategory_edit', { 'id': entity.id }) }}" class="btn btn-edit">
|
||||
{{ 'Edit'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
|
@@ -41,7 +41,7 @@
|
||||
<td>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_crud_activity_type_edit', { 'id': entity.id }) }}" class="sc-button bt-edit" title="{{ 'edit'|trans }}"></a>
|
||||
<a href="{{ path('chill_crud_activity_type_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_crud_activity_type_new') }}" class="sc-button bt-create">
|
||||
<a href="{{ path('chill_crud_activity_type_new') }}" class="btn btn-create">
|
||||
{{ 'Create a new activity type'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
|
@@ -25,7 +25,7 @@
|
||||
<td>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_crud_activity_type_category_edit', { 'id': entity.id }) }}" class="sc-button bt-edit" title="{{ 'edit'|trans }}"></a>
|
||||
<a href="{{ path('chill_crud_activity_type_category_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_crud_activity_type_category_new') }}" class="sc-button bt-create">
|
||||
<a href="{{ path('chill_crud_activity_type_category_new') }}" class="btn btn-create">
|
||||
{{ 'Create a new activity type category'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
|
@@ -29,13 +29,13 @@
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_show', { 'person_id': activity.person.id, 'id': activity.id} ) }}" class="sc-button bt-view">
|
||||
<a href="{{ path('chill_activity_activity_show', { 'person_id': activity.person.id, 'id': activity.id} ) }}" class="btn btn-view">
|
||||
{{ 'Show the activity'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
{% if is_granted('CHILL_ACTIVITY_UPDATE', activity) %}
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_edit', { 'person_id': activity.person.id, 'id': activity.id} ) }}" class="sc-button bt-edit">
|
||||
<a href="{{ path('chill_activity_activity_edit', { 'person_id': activity.person.id, 'id': activity.id} ) }}" class="btn btn-edit">
|
||||
{{ 'Edit the activity'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
|
@@ -19,6 +19,11 @@
|
||||
|
||||
namespace Chill\ActivityBundle\Security\Authorization;
|
||||
|
||||
use Chill\MainBundle\Security\Authorization\VoterHelperFactoryInterface;
|
||||
use Chill\MainBundle\Security\Authorization\VoterHelperInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
|
||||
use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
|
||||
@@ -28,11 +33,10 @@ use Chill\MainBundle\Entity\User;
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
* Voter for Activity class
|
||||
*/
|
||||
class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
|
||||
{
|
||||
@@ -41,30 +45,37 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
|
||||
const SEE_DETAILS = 'CHILL_ACTIVITY_SEE_DETAILS';
|
||||
const UPDATE = 'CHILL_ACTIVITY_UPDATE';
|
||||
const DELETE = 'CHILL_ACTIVITY_DELETE';
|
||||
const FULL = 'CHILL_ACTIVITY_FULL';
|
||||
|
||||
/**
|
||||
*
|
||||
* @var AuthorizationHelper
|
||||
*/
|
||||
protected $helper;
|
||||
private const ALL = [
|
||||
self::CREATE,
|
||||
self::SEE,
|
||||
self::UPDATE,
|
||||
self::DELETE,
|
||||
self::SEE_DETAILS,
|
||||
self::FULL
|
||||
];
|
||||
|
||||
public function __construct(AuthorizationHelper $helper)
|
||||
{
|
||||
$this->helper = $helper;
|
||||
protected VoterHelperInterface $voterHelper;
|
||||
|
||||
protected Security $security;
|
||||
|
||||
public function __construct(
|
||||
Security $security,
|
||||
VoterHelperFactoryInterface $voterHelperFactory
|
||||
) {
|
||||
$this->security = $security;
|
||||
$this->voterHelper = $voterHelperFactory->generate(self::class)
|
||||
->addCheckFor(Person::class, [self::SEE, self::CREATE])
|
||||
->addCheckFor(AccompanyingPeriod::class, [self::SEE, self::CREATE])
|
||||
->addCheckFor(Activity::class, self::ALL)
|
||||
->build();
|
||||
}
|
||||
|
||||
|
||||
protected function supports($attribute, $subject)
|
||||
{
|
||||
if ($subject instanceof Activity) {
|
||||
return \in_array($attribute, $this->getAttributes());
|
||||
} elseif ($subject instanceof Person) {
|
||||
return $attribute === self::SEE
|
||||
||
|
||||
$attribute === self::CREATE;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return $this->voterHelper->supports($attribute, $subject);
|
||||
}
|
||||
|
||||
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
|
||||
@@ -72,32 +83,34 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
|
||||
if (!$token->getUser() instanceof User) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($subject instanceof Person) {
|
||||
$centers = $this->helper->getReachableCenters($token->getUser(), new Role($attribute));
|
||||
|
||||
return \in_array($subject->getCenter(), $centers);
|
||||
|
||||
if ($subject instanceof Activity) {
|
||||
if ($subject->getPerson() instanceof Person) {
|
||||
// the context is person: we must have the right to see the person
|
||||
if (!$this->security->isGranted(PersonVoter::SEE, $subject->getPerson())) {
|
||||
return false;
|
||||
}
|
||||
} elseif ($subject->getAccompanyingPeriod() instanceof AccompanyingPeriod) {
|
||||
if (!$this->security->isGranted(AccompanyingPeriodVoter::SEE, $subject->getAccompanyingPeriod())) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
throw new \RuntimeException("could not determine context of activity");
|
||||
}
|
||||
}
|
||||
|
||||
/* @var $subject Activity */
|
||||
return $this->helper->userHasAccess($token->getUser(), $subject, $attribute);
|
||||
}
|
||||
|
||||
private function getAttributes()
|
||||
{
|
||||
return [ self::CREATE, self::SEE, self::UPDATE, self::DELETE,
|
||||
self::SEE_DETAILS ];
|
||||
|
||||
return $this->voterHelper->voteOnAttribute($attribute, $subject, $token);
|
||||
}
|
||||
|
||||
|
||||
public function getRoles()
|
||||
{
|
||||
return $this->getAttributes();
|
||||
return self::ALL;
|
||||
}
|
||||
|
||||
public function getRolesWithoutScope()
|
||||
{
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
|
@@ -35,35 +35,37 @@ class ActivityReasonRender extends AbstractChillEntityRender
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
protected $translatableStringHelper;
|
||||
|
||||
|
||||
public function __construct(TranslatableStringHelper $translatableStringHelper)
|
||||
{
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function renderBox($entity, array $options): string
|
||||
{
|
||||
return
|
||||
$this->getDefaultOpeningBox('activity-reason').
|
||||
'<span class="badge bg-chill-pink">'.
|
||||
'<i class="fa fa-question-circle"></i> '.
|
||||
'<span class="activity-reason__category">'.
|
||||
'<span class="category">'.
|
||||
$this->translatableStringHelper->localize(
|
||||
$entity->getCategory()->getName()
|
||||
).
|
||||
'</span>'.
|
||||
'<span class="activity-reason__separator"> > </span>'.
|
||||
'<span class="activity-reason__reason">'.
|
||||
'<span class="separator"> > </span>'.
|
||||
'<span class="reason">'.
|
||||
$this->translatableStringHelper->localize(
|
||||
$entity->getName()
|
||||
).
|
||||
'</span>'.
|
||||
'</span>'.
|
||||
$this->getDefaultClosingBox()
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param ActivityReason $entity
|
||||
* @param array $options
|
||||
* @return string
|
||||
@@ -71,12 +73,12 @@ class ActivityReasonRender extends AbstractChillEntityRender
|
||||
public function renderString($entity, array $options): string
|
||||
{
|
||||
$category = '';
|
||||
|
||||
|
||||
if (null !== $entity->getCategory()) {
|
||||
$category = $this->translatableStringHelper->localize(
|
||||
$entity->getCategory()->getName()). ' > ';
|
||||
}
|
||||
|
||||
|
||||
return $category .
|
||||
$this->translatableStringHelper->localize(
|
||||
$entity->getName()
|
||||
|
@@ -1,10 +1,11 @@
|
||||
// this file loads all assets from the Chill person bundle
|
||||
module.exports = function(encore, entries) {
|
||||
entries.push(__dirname + '/Resources/public/index.js');
|
||||
|
||||
module.exports = function(encore, entries)
|
||||
{
|
||||
entries.push(__dirname + '/Resources/public/chill/index.js');
|
||||
|
||||
encore.addAliases({
|
||||
ChillActivityAssets: __dirname + '/Resources/public'
|
||||
});
|
||||
|
||||
|
||||
encore.addEntry('vue_activity', __dirname + '/Resources/public/vuejs/Activity/index.js');
|
||||
};
|
||||
|
@@ -1,21 +1,5 @@
|
||||
services:
|
||||
chill.activity.security.authorization.activity_voter:
|
||||
class: Chill\ActivityBundle\Security\Authorization\ActivityVoter
|
||||
arguments:
|
||||
- "@chill.main.security.authorization.helper"
|
||||
tags:
|
||||
- { name: security.voter }
|
||||
- { name: chill.role }
|
||||
|
||||
chill.activity.security.authorization.activity_stats_voter:
|
||||
class: Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter
|
||||
arguments:
|
||||
- "@chill.main.security.authorization.helper"
|
||||
tags:
|
||||
- { name: security.voter }
|
||||
- { name: chill.role }
|
||||
|
||||
|
||||
services:
|
||||
|
||||
chill.activity.timeline:
|
||||
class: Chill\ActivityBundle\Timeline\TimelineActivityProvider
|
||||
arguments:
|
||||
@@ -33,3 +17,13 @@ services:
|
||||
autoconfigure: true
|
||||
resource: '../Menu/'
|
||||
tags: ['chill.menu_builder']
|
||||
|
||||
Chill\ActivityBundle\Notification\:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
resource: '../Notification'
|
||||
|
||||
Chill\ActivityBundle\Security\Authorization\:
|
||||
resource: '../Security/Authorization/'
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
@@ -0,0 +1,14 @@
|
||||
services:
|
||||
accompanying_period_social_issue_consistency_for_activity:
|
||||
class: 'Chill\PersonBundle\AccompanyingPeriod\SocialIssueConsistency\AccompanyingPeriodSocialIssueConsistencyEntityListener'
|
||||
tags:
|
||||
-
|
||||
name: 'doctrine.orm.entity_listener'
|
||||
event: 'prePersist'
|
||||
entity: 'Chill\ActivityBundle\Entity\Activity'
|
||||
lazy: true
|
||||
-
|
||||
name: 'doctrine.orm.entity_listener'
|
||||
event: 'preUpdate'
|
||||
entity: 'Chill\ActivityBundle\Entity\Activity'
|
||||
lazy: true
|
@@ -1,8 +1,4 @@
|
||||
services:
|
||||
Chill\ActivityBundle\Controller\ActivityController:
|
||||
arguments:
|
||||
$eventDispatcher: '@Symfony\Component\EventDispatcher\EventDispatcherInterface'
|
||||
$authorizationHelper: '@Chill\MainBundle\Security\Authorization\AuthorizationHelper'
|
||||
$logger: '@chill.main.logger'
|
||||
$serializer: '@Symfony\Component\Serializer\SerializerInterface'
|
||||
autowire: true
|
||||
tags: ['controller.service_arguments']
|
||||
|
@@ -24,9 +24,7 @@ services:
|
||||
- '@Doctrine\Persistence\ManagerRegistry'
|
||||
|
||||
Chill\ActivityBundle\Repository\ActivityACLAwareRepository:
|
||||
arguments:
|
||||
$tokenStorage: '@Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface'
|
||||
$authorizationHelper: '@Chill\MainBundle\Security\Authorization\AuthorizationHelper'
|
||||
$repository: '@Chill\ActivityBundle\Repository\ActivityRepository'
|
||||
$em: '@Doctrine\ORM\EntityManagerInterface'
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
Chill\ActivityBundle\Repository\ActivityACLAwareRepositoryInterface: '@Chill\ActivityBundle\Repository\ActivityACLAwareRepository'
|
||||
|
||||
|
@@ -81,9 +81,9 @@ activity:
|
||||
'%user% has done an %activity_type%': '%user% a effectué une activité de type "%activity_type%"'
|
||||
|
||||
#controller
|
||||
'Success : activity created!': Bravo ! L'activité a été créée.
|
||||
'Success : activity created!': L'activité a été créée.
|
||||
'The form is not valid. The activity has not been created !': Le formulaire est invalide. L'activité n'a pas été créée.
|
||||
'Success : activity updated!': Bravo ! L'activité a été mise à jour.
|
||||
'Success : activity updated!': L'activité a été mise à jour.
|
||||
'The form is not valid. The activity has not been updated !': Le formulaire est invalide. L'activité n'a pas été mise à jour.
|
||||
|
||||
# ROLES
|
||||
|
661
src/Bundle/ChillAsideActivityBundle/LICENSE
Normal file
661
src/Bundle/ChillAsideActivityBundle/LICENSE
Normal file
@@ -0,0 +1,661 @@
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU Affero General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
3
src/Bundle/ChillAsideActivityBundle/README.md
Normal file
3
src/Bundle/ChillAsideActivityBundle/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Aside activities module
|
||||
|
||||
This module offers the possibility to add extra curricular activities per user (eg. administrative tasks, formation, meetings) not immediately related to client support.
|
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\AsideActivityBundle;
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
|
||||
class ChillAsideActivityBundle extends Bundle
|
||||
{
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\Controller;
|
||||
|
||||
use Chill\MainBundle\CRUD\Controller\CRUDController;
|
||||
use Chill\MainBundle\Pagination\PaginatorInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
|
||||
/**
|
||||
* Class AsideActivityBundle
|
||||
*/
|
||||
class AsideActivityCategoryController extends CRUDController
|
||||
{
|
||||
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
|
||||
{
|
||||
/** @var QueryBuilder $query */
|
||||
$query->addOrderBy('e.ordering', 'ASC');
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\AsideActivityBundle\Controller;
|
||||
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivity;
|
||||
use Chill\AsideActivityBundle\Repository\AsideActivityCategoryRepository;
|
||||
use Chill\MainBundle\CRUD\Controller\CRUDController;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Chill\MainBundle\Pagination\PaginatorInterface;
|
||||
use Doctrine\Common\Collections\Criteria;
|
||||
|
||||
final class AsideActivityController extends CRUDController
|
||||
{
|
||||
|
||||
private $categoryRepository;
|
||||
|
||||
public function __construct(AsideActivityCategoryRepository $categoryRepository)
|
||||
{
|
||||
$this->categoryRepository = $categoryRepository;
|
||||
}
|
||||
|
||||
protected function buildQueryEntities(string $action, Request $request)
|
||||
{
|
||||
$qb = parent::buildQueryEntities($action, $request);
|
||||
|
||||
if ('index' === $action) {
|
||||
$qb->where($qb->expr()->eq('e.agent', ':user'));
|
||||
$qb->orWhere($qb->expr()->eq('e.createdBy', ':user'));
|
||||
$qb->setParameter('user', $this->getUser());
|
||||
}
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
protected function orderQuery(
|
||||
string $action,
|
||||
$query,
|
||||
Request $request,
|
||||
PaginatorInterface $paginator
|
||||
) {
|
||||
if ('index' === $action) {
|
||||
return $query->orderBy('e.date', 'DESC');
|
||||
}
|
||||
|
||||
return parent::orderQuery($action, $query, $request, $paginator);
|
||||
}
|
||||
|
||||
public function createEntity(string $action, Request $request): object
|
||||
{
|
||||
$asideActivity = new AsideActivity();
|
||||
|
||||
$duration = $request->query->get('duration', '300');
|
||||
$duration = \DateTime::createFromFormat('U', $duration);
|
||||
$asideActivity->setDuration($duration);
|
||||
|
||||
$categoryId = $request->query->get('type', 7);
|
||||
if($categoryId === null){
|
||||
return $this->createNotFoundException('You must give a valid category id');
|
||||
}
|
||||
$category = $this->categoryRepository->find($categoryId);
|
||||
$asideActivity->setType($category);
|
||||
|
||||
$note = $request->query->get('note', null);
|
||||
$asideActivity->setNote($note);
|
||||
|
||||
return $asideActivity;
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\DataFixtures\ORM;
|
||||
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivity;
|
||||
use Chill\MainBundle\DataFixtures\ORM\LoadUsers;
|
||||
use Chill\MainBundle\Repository\UserRepository;
|
||||
use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
class LoadAsideActivity extends Fixture implements DependentFixtureInterface
|
||||
{
|
||||
private UserRepository $userRepository;
|
||||
|
||||
public function __construct(UserRepository $userRepository)
|
||||
{
|
||||
$this->userRepository = $userRepository;
|
||||
}
|
||||
|
||||
public function getDependencies(): array
|
||||
{
|
||||
return [
|
||||
LoadUsers::class,
|
||||
LoadAsideActivityCategory::class
|
||||
];
|
||||
}
|
||||
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
$user = $this->userRepository->findOneBy(['username' => 'center a_social']);
|
||||
|
||||
for ($i = 0; $i < 50; $i++) {
|
||||
$activity = new AsideActivity();
|
||||
$activity
|
||||
->setAgent($user)
|
||||
->setCreatedAt(new \DateTimeImmutable('now'))
|
||||
->setCreatedBy($user)
|
||||
->setUpdatedAt(new \DateTimeImmutable('now'))
|
||||
->setUpdatedBy($user)
|
||||
->setType(
|
||||
$this->getReference('aside_activity_category_0')
|
||||
)
|
||||
->setDate((new \DateTimeImmutable('today'))
|
||||
->sub(new \DateInterval('P'.\random_int(1, 100).'D')))
|
||||
;
|
||||
|
||||
$manager->persist($activity);
|
||||
}
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\DataFixtures\ORM;
|
||||
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivityCategory;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
class LoadAsideActivityCategory extends \Doctrine\Bundle\FixturesBundle\Fixture
|
||||
{
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
foreach ([
|
||||
'Appel téléphonique',
|
||||
'Formation'
|
||||
] as $key => $label) {
|
||||
$category = new AsideActivityCategory();
|
||||
$category->setTitle(['fr' => $label]);
|
||||
$manager->persist($category);
|
||||
$this->setReference('aside_activity_category_'.$key, $category);
|
||||
}
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
}
|
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\AsideActivityBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\Config\FileLocator;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Extension\Extension;
|
||||
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
|
||||
use Symfony\Component\DependencyInjection\Loader;
|
||||
|
||||
final class ChillAsideActivityExtension extends Extension implements PrependExtensionInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
public function load(array $configs, ContainerBuilder $container): void
|
||||
{
|
||||
|
||||
$configuration = $this->getConfiguration($configs, $container);
|
||||
$config = $this->processConfiguration($configuration, $configs);
|
||||
|
||||
$container->setParameter('chill_aside_activity.form.time_duration', $config['form']['time_duration']);
|
||||
|
||||
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config'));
|
||||
$loader->load('services.yaml');
|
||||
$loader->load('services/form.yaml');
|
||||
$loader->load('services/menu.yaml');
|
||||
}
|
||||
|
||||
public function prepend(ContainerBuilder $container)
|
||||
{
|
||||
$this->prependRoute($container);
|
||||
$this->prependCruds($container);
|
||||
}
|
||||
|
||||
protected function prependRoute(ContainerBuilder $container)
|
||||
{
|
||||
//declare routes for task bundle
|
||||
$container->prependExtensionConfig('chill_main', array(
|
||||
'routing' => array(
|
||||
'resources' => array(
|
||||
'@ChillAsideActivityBundle/config/routes.yaml',
|
||||
)
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
protected function prependCruds(ContainerBuilder $container)
|
||||
{
|
||||
$container->prependExtensionConfig('chill_main', [
|
||||
'cruds' => [
|
||||
[
|
||||
'class' => \Chill\AsideActivityBundle\Entity\AsideActivityCategory::class,
|
||||
'name' => 'aside_activity_category',
|
||||
'base_path' => '/admin/asideactivity/category',
|
||||
'form_class' => \Chill\AsideActivityBundle\Form\AsideActivityCategoryType::class,
|
||||
'controller' => \Chill\AsideActivityBundle\Controller\AsideActivityCategoryController::class,
|
||||
'actions' => [
|
||||
'index' => [
|
||||
'template' => '@ChillAsideActivity/asideActivityCategory/index.html.twig',
|
||||
'role' => 'ROLE_ADMIN'
|
||||
],
|
||||
'new' => [
|
||||
'role' => 'ROLE_ADMIN',
|
||||
'template' => '@ChillAsideActivity/asideActivityCategory/new.html.twig',
|
||||
],
|
||||
'edit' => [
|
||||
'role' => 'ROLE_ADMIN',
|
||||
'template' => '@ChillAsideActivity/asideActivityCategory/edit.html.twig',
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'class' => \Chill\AsideActivityBundle\Entity\AsideActivity::class,
|
||||
'name' => 'aside_activity',
|
||||
'base_path' => '/asideactivity',
|
||||
'form_class' => \Chill\AsideActivityBundle\Form\AsideActivityFormType::class,
|
||||
'controller' => \Chill\AsideActivityBundle\Controller\AsideActivityController::class,
|
||||
'actions' => [
|
||||
'index' => [
|
||||
'template' => '@ChillAsideActivity/asideActivity/index.html.twig',
|
||||
'role' => 'ROLE_USER'
|
||||
],
|
||||
'new' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillAsideActivity/asideActivity/new.html.twig',
|
||||
],
|
||||
'view' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillAsideActivity/asideActivity/view.html.twig',
|
||||
],
|
||||
'edit' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillAsideActivity/asideActivity/edit.html.twig',
|
||||
],
|
||||
'delete' => [
|
||||
'role' => 'ROLE_USER',
|
||||
'template' => '@ChillAsideActivity/asideActivity/delete.html.twig',
|
||||
]
|
||||
]
|
||||
],
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
|
||||
class Configuration implements ConfigurationInterface
|
||||
{
|
||||
public function getConfigTreeBuilder()
|
||||
{
|
||||
$treeBuilder = new TreeBuilder('chill_aside_activity');
|
||||
|
||||
$treeBuilder->getRootNode('chill_aside_activity')
|
||||
->children()
|
||||
->arrayNode('form')
|
||||
->canBeEnabled()
|
||||
->children()
|
||||
->arrayNode('time_duration')
|
||||
->isRequired()
|
||||
->defaultValue(
|
||||
[
|
||||
[ 'label' => '5 minutes', 'seconds' => 300],
|
||||
[ 'label' => '10 minutes', 'seconds' => 600],
|
||||
[ 'label' => '15 minutes', 'seconds' => 900],
|
||||
[ 'label' => '20 minutes', 'seconds' => 1200],
|
||||
[ 'label' => '25 minutes', 'seconds' => 1500],
|
||||
[ 'label' => '30 minutes', 'seconds' => 1800],
|
||||
[ 'label' => '45 minutes', 'seconds' => 2700],
|
||||
[ 'label' => '1 hour', 'seconds' => 3600],
|
||||
[ 'label' => '1 hour 15', 'seconds' => 4500],
|
||||
[ 'label' => '1 hour 30', 'seconds' => 5400],
|
||||
[ 'label' => '1 hour 45', 'seconds' => 6300],
|
||||
[ 'label' => '2 hours', 'seconds' => 7200],
|
||||
[ 'label' => '2 hours 30', 'seconds' => 9000],
|
||||
[ 'label' => '3 hours', 'seconds' => 10800],
|
||||
[ 'label' => '3 hours 30', 'seconds' => 12600],
|
||||
[ 'label' => '4 hours', 'seconds' => 14400],
|
||||
[ 'label' => '4 hours 30', 'seconds' => 16200],
|
||||
[ 'label' => '5 hours', 'seconds' => 18000],
|
||||
[ 'label' => '5 hours 30', 'seconds' => 19800],
|
||||
[ 'label' => '6 hours', 'seconds' => 21600],
|
||||
[ 'label' => '6 hours 30', 'seconds' => 23400],
|
||||
[ 'label' => '7 hours', 'seconds' => 25200],
|
||||
[ 'label' => '7 hours 30', 'seconds' => 27000],
|
||||
[ 'label' => '8 hours', 'seconds' => 28800],
|
||||
[ 'label' => '8 hours 30', 'seconds' => 30600],
|
||||
[ 'label' => '9 hours', 'seconds' => 32400],
|
||||
[ 'label' => '9 hours 30', 'seconds' => 34200],
|
||||
[ 'label' => '10 hours', 'seconds' => 36000],
|
||||
[ 'label' => '1/2 day', 'seconds' => 14040],
|
||||
[ 'label' => '1 day', 'seconds' => 28080],
|
||||
[ 'label' => '1 1/2 days', 'seconds' => 42120],
|
||||
[ 'label' => '2 days', 'seconds' => 56160],
|
||||
[ 'label' => '2 1/2 days', 'seconds' => 70200],
|
||||
[ 'label' => '3 days', 'seconds' => 84240],
|
||||
[ 'label' => '3 1/2 days', 'seconds' => 98280],
|
||||
[ 'label' => '4 days', 'seconds' => 112320],
|
||||
[ 'label' => '4 1/2 days', 'seconds' => 126360],
|
||||
[ 'label' => '5 days', 'seconds' => 140400],
|
||||
[ 'label' => '5 1/2 days', 'seconds' => 154440],
|
||||
[ 'label' => '6 days', 'seconds' => 168480],
|
||||
[ 'label' => '6 1/2 days', 'seconds' => 182520],
|
||||
[ 'label' => '7 days', 'seconds' => 196560],
|
||||
[ 'label' => '7 1/2 days', 'seconds' => 210600],
|
||||
[ 'label' => '8 days', 'seconds' => 224640],
|
||||
[ 'label' => '8 1/2 days', 'seconds' => 238680],
|
||||
[ 'label' => '9 days', 'seconds' => 252720],
|
||||
[ 'label' => '9 1/2 days', 'seconds' => 266760],
|
||||
[ 'label' => '10 days', 'seconds' => 280800],
|
||||
[ 'label' => '10 1/2days', 'seconds' => 294840],
|
||||
[ 'label' => '11 days', 'seconds' => 308880],
|
||||
[ 'label' => '11 1/2 days', 'seconds' => 322920],
|
||||
[ 'label' => '12 days', 'seconds' => 336960],
|
||||
[ 'label' => '12 1/2 days', 'seconds' => 351000],
|
||||
[ 'label' => '13 days', 'seconds' => 365040],
|
||||
[ 'label' => '13 1/2 days', 'seconds' => 379080],
|
||||
[ 'label' => '14 days', 'seconds' => 393120],
|
||||
[ 'label' => '14 1/2 days', 'seconds' => 407160],
|
||||
[ 'label' => '15 days', 'seconds' => 421200],
|
||||
[ 'label' => '15 1/2 days', 'seconds' => 435240],
|
||||
[ 'label' => '16 days', 'seconds' => 449280],
|
||||
[ 'label' => '16 1/2 days', 'seconds' => 463320],
|
||||
[ 'label' => '17 days', 'seconds' => 477360],
|
||||
[ 'label' => '17 1/2 days', 'seconds' => 491400],
|
||||
[ 'label' => '18 days', 'seconds' => 505440],
|
||||
[ 'label' => '18 1/2 days', 'seconds' => 519480],
|
||||
[ 'label' => '19 days', 'seconds' => 533520],
|
||||
[ 'label' => '19 1/2 days', 'seconds' => 547560],
|
||||
[ 'label' => '20 days', 'seconds' => 561600],
|
||||
[ 'label' => '20 1/2 days', 'seconds' => 575640],
|
||||
[ 'label' => '21 days', 'seconds' => 580680],
|
||||
[ 'label' => '21 1/2 days', 'seconds' => 603720],
|
||||
[ 'label' => '22 days', 'seconds' => 617760],
|
||||
[ 'label' => '22 1/2 days', 'seconds' => 631800],
|
||||
[ 'label' => '23 days', 'seconds' => 645840],
|
||||
[ 'label' => '23 1/2 days', 'seconds' => 659880],
|
||||
[ 'label' => '24 days', 'seconds' => 673920],
|
||||
[ 'label' => '24 1/2 days', 'seconds' => 687960],
|
||||
[ 'label' => '25 days', 'seconds' => 702000],
|
||||
[ 'label' => '25 1/2 days', 'seconds' => 716040],
|
||||
[ 'label' => '26 days', 'seconds' => 730080],
|
||||
[ 'label' => '26 1/2 days', 'seconds' => 744120],
|
||||
[ 'label' => '27 days', 'seconds' => 758160],
|
||||
[ 'label' => '27 1/2 days', 'seconds' => 772200],
|
||||
[ 'label' => '28 days', 'seconds' => 786240],
|
||||
[ 'label' => '28 1/2 days', 'seconds' => 800280],
|
||||
[ 'label' => '29 days', 'seconds' => 814320],
|
||||
[ 'label' => '29 1/2 days', 'seconds' => 828360],
|
||||
[ 'label' => '30 days', 'seconds' => 842400],
|
||||
]
|
||||
)
|
||||
->info('The intervals of time to show in activity form')
|
||||
|
||||
->prototype('array')
|
||||
->children()
|
||||
->scalarNode('seconds')
|
||||
->info("The number of seconds of this duration. Must be an integer.")
|
||||
->cannotBeEmpty()
|
||||
->validate()
|
||||
->ifTrue(function($data) {
|
||||
return !is_int($data);
|
||||
})->thenInvalid("The value %s is not a valid integer")
|
||||
->end()
|
||||
->end()
|
||||
->scalarNode('label')
|
||||
->cannotBeEmpty()
|
||||
->info("The label to show into fields")
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end();
|
||||
|
||||
return $treeBuilder;
|
||||
}
|
||||
}
|
203
src/Bundle/ChillAsideActivityBundle/src/Entity/AsideActivity.php
Normal file
203
src/Bundle/ChillAsideActivityBundle/src/Entity/AsideActivity.php
Normal file
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\AsideActivityBundle\Entity;
|
||||
|
||||
use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
/**
|
||||
* @ORM\Entity
|
||||
* @ORM\Table(schema="chill_asideactivity")
|
||||
*/
|
||||
class AsideActivity implements TrackUpdateInterface, TrackCreationInterface
|
||||
{
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
private ?int $id;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=AsideActivityCategory::class, inversedBy="asideActivities")
|
||||
* @ORM\JoinColumn(nullable=false)
|
||||
*/
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=User::class)
|
||||
* @ORM\JoinColumn(nullable=false)
|
||||
*/
|
||||
private \Chill\MainBundle\Entity\User $createdBy;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetime")
|
||||
*/
|
||||
private $createdAt;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=User::class)
|
||||
*/
|
||||
private \Chill\MainBundle\Entity\User $updatedBy;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetime", nullable=true)
|
||||
*/
|
||||
private $updatedAt;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=User::class)
|
||||
* @ORM\JoinColumn(nullable=false)
|
||||
* @Assert\NotBlank()
|
||||
*/
|
||||
private \Chill\MainBundle\Entity\User $agent;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetime")
|
||||
*/
|
||||
private $date;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="time", nullable=true)
|
||||
*/
|
||||
private ?\DateTimeInterface $duration = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", length=100, nullable=true)
|
||||
*/
|
||||
private $location;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="text", nullable=true)
|
||||
*/
|
||||
private $note;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getType(): ?AsideActivityCategory
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function setType(?AsideActivityCategory $type): self
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreatedBy(): ?User
|
||||
{
|
||||
return $this->createdBy;
|
||||
}
|
||||
|
||||
public function setCreatedBy(?User $createdBy): self
|
||||
{
|
||||
$this->createdBy = $createdBy;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): ?\DateTimeInterface
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function setCreatedAt(\DateTimeInterface $createdAt): self
|
||||
{
|
||||
$this->createdAt = $createdAt;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUpdatedBy(): ?User
|
||||
{
|
||||
return $this->updatedBy;
|
||||
}
|
||||
|
||||
public function setUpdatedBy(?User $updatedBy): self
|
||||
{
|
||||
$this->updatedBy = $updatedBy;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): ?\DateTimeInterface
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
|
||||
public function setUpdatedAt(\DateTimeInterface $updatedAt): self
|
||||
{
|
||||
$this->updatedAt = $updatedAt;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAgent(): ?User
|
||||
{
|
||||
return $this->agent;
|
||||
}
|
||||
|
||||
public function setAgent(?User $agent): self
|
||||
{
|
||||
$this->agent = $agent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDate(): ?\DateTimeInterface
|
||||
{
|
||||
return $this->date;
|
||||
}
|
||||
|
||||
public function setDate(\DateTimeInterface $date): self
|
||||
{
|
||||
$this->date = $date;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDuration(): ?\DateTimeInterface
|
||||
{
|
||||
return $this->duration;
|
||||
}
|
||||
|
||||
public function setDuration(?\DateTimeInterface $duration): self
|
||||
{
|
||||
$this->duration = $duration;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLocation(): ?string
|
||||
{
|
||||
return $this->location;
|
||||
}
|
||||
|
||||
public function setLocation(?string $location): self
|
||||
{
|
||||
$this->location = $location;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNote(): ?string
|
||||
{
|
||||
return $this->note;
|
||||
}
|
||||
|
||||
public function setNote(?string $note): self
|
||||
{
|
||||
$this->note = $note;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\AsideActivityBundle\Entity;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
* @ORM\Table(schema="chill_asideactivity")
|
||||
*/
|
||||
class AsideActivityCategory
|
||||
{
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
private int $id;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="json", length=255)
|
||||
*/
|
||||
private array $title;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity=AsideActivityCategory::class, mappedBy="parent")
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private bool $isActive = true;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
* @ORM\Column(type="float", options={"default": 0.00})
|
||||
*/
|
||||
private float $ordering = 0.00;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=AsideActivityCategory::class, inversedBy="children")
|
||||
* @ORM\JoinColumn(nullable=true)
|
||||
*/
|
||||
private $parent;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity=AsideActivityCategory::class, mappedBy="parent")
|
||||
*/
|
||||
private $children;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->children = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getTitle(): ?array
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
public function setTitle(array $title): self
|
||||
{
|
||||
$this->title = $title;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIsActive(): bool
|
||||
{
|
||||
return $this->isActive;
|
||||
}
|
||||
|
||||
public function setIsActive(bool $isActive): self
|
||||
{
|
||||
$this->isActive = $isActive;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getParent(): ?self
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @Assert\Callback()
|
||||
*/
|
||||
public function preventRecursiveParent(ExecutionContextInterface $context, $payload)
|
||||
{
|
||||
if (!$this->hasParent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->getParent() === $this) {
|
||||
// replace parent with old parent. This prevent recursive loop
|
||||
// when displaying form
|
||||
$this->parent = $this->oldParent;
|
||||
$context->buildViolation('You must not add twice the same category in the parent tree (previous result returned)')
|
||||
->atPath('parent')
|
||||
->addViolation()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
public function hasParent(): bool
|
||||
{
|
||||
return $this->parent !== null;
|
||||
}
|
||||
|
||||
public function setParent(?self $parent): self
|
||||
{
|
||||
// cache the old result for changing it during validaiton
|
||||
$this->oldParent = $this->parent;
|
||||
$this->parent = $parent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|self[]
|
||||
*/
|
||||
public function getChildren(): Collection
|
||||
{
|
||||
return $this->children;
|
||||
}
|
||||
|
||||
public function addChild(self $child): self
|
||||
{
|
||||
if (!$this->children->contains($child)) {
|
||||
$this->children[] = $child;
|
||||
$child->setParent($this);
|
||||
}
|
||||
|
||||
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 getOrdering(): float
|
||||
{
|
||||
return $this->ordering;
|
||||
}
|
||||
|
||||
public function setOrdering(float $ordering): AsideActivityCategory
|
||||
{
|
||||
$this->ordering = $ordering;
|
||||
return $this;
|
||||
}
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\Form;
|
||||
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivityCategory;
|
||||
use Chill\AsideActivityBundle\Templating\Entity\CategoryRender;
|
||||
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
final class AsideActivityCategoryType extends AbstractType
|
||||
{
|
||||
|
||||
protected $translatableStringHelper;
|
||||
|
||||
public function __construct(TranslatableStringHelper $translatableStringHelper, CategoryRender $categoryRender)
|
||||
{
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->categoryRender = $categoryRender;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->add('title', TranslatableStringFormType::class,
|
||||
[
|
||||
'label' => 'Nom',
|
||||
])
|
||||
->add('parent', EntityType::class, [
|
||||
'class' => AsideActivityCategory::class,
|
||||
'required' => false,
|
||||
'label' => 'Parent',
|
||||
'choice_label' => function (AsideActivityCategory $category){
|
||||
$options = [];
|
||||
return $this->categoryRender->renderString($category, $options);
|
||||
}
|
||||
])
|
||||
->add('ordering', NumberType::class)
|
||||
->add('isActive', ChoiceType::class,
|
||||
[
|
||||
'choices' => [
|
||||
'Yes' => true,
|
||||
'No' => false
|
||||
],
|
||||
'expanded' => true
|
||||
]);
|
||||
}
|
||||
}
|
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\Form;
|
||||
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivity;
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivityCategory;
|
||||
use Chill\AsideActivityBundle\Templating\Entity\CategoryRender;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||
use Chill\MainBundle\Form\Type\ChillTextareaType;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Templating\EngineInterface;
|
||||
|
||||
final class AsideActivityFormType extends AbstractType
|
||||
{
|
||||
protected array $timeChoices;
|
||||
private TokenStorageInterface $storage;
|
||||
private CategoryRender $categoryRender;
|
||||
|
||||
public function __construct (
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
ParameterBagInterface $parameterBag,
|
||||
TokenStorageInterface $storage,
|
||||
CategoryRender $categoryRender
|
||||
){
|
||||
$this->timeChoices = $parameterBag->get('chill_aside_activity.form.time_duration');
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->storage = $storage;
|
||||
$this->categoryRender = $categoryRender;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$timeChoices = [];
|
||||
|
||||
foreach ($this->timeChoices as $e) {
|
||||
$timeChoices[$e['label']] = $e['seconds'];
|
||||
}
|
||||
|
||||
$durationTimeTransformer = new DateTimeToTimestampTransformer('GMT', 'GMT');
|
||||
$durationTimeOptions = [
|
||||
'choices' => $timeChoices,
|
||||
'placeholder' => 'Choose the duration',
|
||||
];
|
||||
|
||||
$builder
|
||||
->add('agent', EntityType::class,
|
||||
[
|
||||
'label' => 'Agent',
|
||||
'required' => true,
|
||||
'class' => User::class,
|
||||
'data' => $this->storage->getToken()->getUser(),
|
||||
'query_builder' => function(EntityRepository $er){
|
||||
return $er->createQueryBuilder('u')->where('u.enabled = true');
|
||||
},
|
||||
'attr' => array('class' => 'select2 '),
|
||||
'placeholder' => 'Choose the agent for whom this activity is created',
|
||||
'choice_label' => 'username'
|
||||
])
|
||||
->add('date', ChillDateType::class,
|
||||
[
|
||||
'label' => 'date',
|
||||
'data' => new \DateTime(),
|
||||
'required' => true
|
||||
])
|
||||
->add('type', EntityType::class,
|
||||
[
|
||||
'label' => 'Type',
|
||||
'required' => true,
|
||||
'class' => AsideActivityCategory::class,
|
||||
'placeholder' => 'Choose the activity category',
|
||||
'query_builder' => function(EntityRepository $er) {
|
||||
$qb = $er->createQueryBuilder('ac');
|
||||
$qb->where($qb->expr()->eq('ac.isActive', 'TRUE'))
|
||||
->addOrderBy('ac.ordering', 'ASC')
|
||||
;
|
||||
|
||||
return $qb;
|
||||
},
|
||||
'choice_label' => function (AsideActivityCategory $asideActivityCategory) {
|
||||
$options = [];
|
||||
return $this->categoryRender->renderString($asideActivityCategory, $options);
|
||||
},
|
||||
])
|
||||
->add('duration', ChoiceType::class, $durationTimeOptions)
|
||||
->add('note', ChillTextareaType::class, [
|
||||
'label' => 'Note',
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
foreach (['duration'] as $fieldName)
|
||||
{
|
||||
$builder->get($fieldName)
|
||||
->addModelTransformer($durationTimeTransformer);
|
||||
|
||||
$builder->get($fieldName)
|
||||
->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $formEvent) use (
|
||||
$timeChoices,
|
||||
$builder,
|
||||
$durationTimeTransformer,
|
||||
$durationTimeOptions,
|
||||
$fieldName
|
||||
) {
|
||||
// set the timezone to GMT, and fix the difference between current and GMT
|
||||
// the datetimetransformer will then handle timezone as GMT
|
||||
$timezoneUTC = new \DateTimeZone('GMT');
|
||||
/* @var $data \DateTimeImmutable */
|
||||
$data = $formEvent->getData() === NULL ?
|
||||
\DateTime::createFromFormat('U', 300) :
|
||||
$formEvent->getData();
|
||||
$seconds = $data->getTimezone()->getOffset($data);
|
||||
$data->setTimeZone($timezoneUTC);
|
||||
$data->add(new \DateInterval('PT'.$seconds.'S'));
|
||||
|
||||
// test if the timestamp is in the choices.
|
||||
// If not, recreate the field with the new timestamp
|
||||
if (!in_array($data->getTimestamp(), $timeChoices)) {
|
||||
// the data are not in the possible values. add them
|
||||
$timeChoices[$data->format('H:i')] = $data->getTimestamp();
|
||||
$form = $builder->create($fieldName, ChoiceType::class, array_merge(
|
||||
$durationTimeOptions, [
|
||||
'choices' => $timeChoices,
|
||||
'auto_initialize' => false
|
||||
]
|
||||
));
|
||||
$form->addModelTransformer($durationTimeTransformer);
|
||||
$formEvent->getForm()->getParent()->add($form->getForm());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => AsideActivity::class,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getBlockPrefix(): string
|
||||
{
|
||||
return 'chill_asideactivitybundle_asideactivity';
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\Menu;
|
||||
|
||||
use Knp\Menu\MenuItem;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
final class AdminMenuBuilder implements \Chill\MainBundle\Routing\LocalMenuBuilderInterface
|
||||
{
|
||||
private Security $security;
|
||||
|
||||
public function __construct(Security $security)
|
||||
{
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
public static function getMenuIds(): array
|
||||
{
|
||||
return ['admin_index', 'admin_section', 'admin_aside_activity'];
|
||||
}
|
||||
|
||||
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
||||
{
|
||||
// all the entries below must have ROLE_ADMIN permissions
|
||||
if (!$this->security->isGranted('ROLE_ADMIN')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (in_array($menuId, ['admin_index', 'admin_section'])) {
|
||||
$menu->addChild('Aside activities', [
|
||||
'route' => 'chill_crud_aside_activity_category_index'
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 900,
|
||||
'explain' => "Configure aside activities categories"
|
||||
]);
|
||||
} else {
|
||||
$menu
|
||||
->addChild('Aside activity categories', [
|
||||
'route' => 'chill_crud_aside_activity_category_index'
|
||||
])
|
||||
->setExtras([
|
||||
'order' => '50'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\Menu;
|
||||
|
||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||
use Knp\Menu\MenuItem;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* Class SectionMenuBuilder
|
||||
*
|
||||
* @package Chill\AsideActivityBundle\Menu
|
||||
*/
|
||||
class SectionMenuBuilder implements LocalMenuBuilderInterface
|
||||
{
|
||||
protected TranslatorInterface $translator;
|
||||
public AuthorizationCheckerInterface $authorizationChecker;
|
||||
|
||||
public function __construct(TranslatorInterface $translator, AuthorizationCheckerInterface $authorizationChecker)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
$this->authorizationChecker = $authorizationChecker;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $menuId
|
||||
* @param MenuItem $menu
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
||||
{
|
||||
if ($this->authorizationChecker->isGranted('ROLE_USER')){
|
||||
$menu->addChild($this->translator->trans('Create an aside activity'), [
|
||||
'route' => 'chill_crud_aside_activity_new'
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 11,
|
||||
'icons' => [ 'plus' ]
|
||||
]);
|
||||
$menu->addChild($this->translator->trans('Phonecall'), [
|
||||
'route' => 'chill_crud_aside_activity_new',
|
||||
'routeParameters' => [
|
||||
'type' => 1,
|
||||
'duration' => 900,
|
||||
]
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 12,
|
||||
'icons' => ['plus']
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getMenuIds(): array
|
||||
{
|
||||
return [ 'section' ];
|
||||
}
|
||||
}
|
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2018 Champs Libres Cooperative <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
namespace Chill\AsideActivityBundle\Menu;
|
||||
|
||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||
use Knp\Menu\MenuItem;
|
||||
use Chill\TaskBundle\Templating\UI\CountNotificationTask;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class UserMenuBuilder implements LocalMenuBuilderInterface
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* @var CountNotificationTask
|
||||
*/
|
||||
public $counter;
|
||||
|
||||
/*
|
||||
* @var TokenStorageInterface
|
||||
*/
|
||||
public $tokenStorage;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
public $translator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var AuthorizationCheckerInterface
|
||||
*/
|
||||
public $authorizationChecker;
|
||||
|
||||
public function __construct(
|
||||
CountNotificationTask $counter,
|
||||
TokenStorageInterface $tokenStorage,
|
||||
TranslatorInterface $translator,
|
||||
AuthorizationCheckerInterface $authorizationChecker
|
||||
) {
|
||||
$this->counter = $counter;
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->translator = $translator;
|
||||
$this->authorizationChecker = $authorizationChecker;
|
||||
}
|
||||
|
||||
|
||||
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
||||
{
|
||||
if ($this->authorizationChecker->isGranted('ROLE_USER')){
|
||||
$menu->addChild("My aside activities", [
|
||||
'route' => 'chill_crud_aside_activity_index'
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 10,
|
||||
'icon' => 'tasks'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static function getMenuIds(): array
|
||||
{
|
||||
return [ 'user' ];
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\AsideActivityBundle\Repository;
|
||||
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivityCategory;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\Persistence\ObjectRepository;
|
||||
|
||||
class AsideActivityCategoryRepository implements ObjectRepository
|
||||
{
|
||||
private EntityRepository $repository;
|
||||
|
||||
public function __construct(EntityManagerInterface $entityManager)
|
||||
{
|
||||
$this->repository = $entityManager->getRepository(AsideActivityCategory::class);
|
||||
}
|
||||
|
||||
|
||||
public function find($id): ?AsideActivityCategory
|
||||
{
|
||||
return $this->repository->find($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AsideActivityCategory[]
|
||||
*/
|
||||
public function findAll(): array
|
||||
{
|
||||
return $this->repository->findAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AsideActivityCategory[]
|
||||
*/
|
||||
public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array
|
||||
{
|
||||
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
|
||||
}
|
||||
|
||||
public function findOneBy(array $criteria): ?AsideActivityCategory
|
||||
{
|
||||
return $this->repository->findOneBy($criteria);
|
||||
}
|
||||
|
||||
public function getClassName(): string
|
||||
{
|
||||
return AsideActivityCategory::class;
|
||||
}
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\AsideActivityBundle\Repository;
|
||||
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivity;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\Persistence\ObjectRepository;
|
||||
|
||||
final class AsideActivityRepository implements ObjectRepository
|
||||
{
|
||||
private EntityRepository $repository;
|
||||
|
||||
public function __construct(EntityManagerInterface $entityManager)
|
||||
{
|
||||
$this->repository = $entityManager->getRepository(AsideActivity::class);
|
||||
}
|
||||
|
||||
public function find($id): ?AsideActivity
|
||||
{
|
||||
return $this->repository->find($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AsideActivity[]
|
||||
*/
|
||||
public function findAll(): array
|
||||
{
|
||||
return $this->repository->findAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AsideActivity[]
|
||||
*/
|
||||
public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array
|
||||
{
|
||||
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
|
||||
}
|
||||
|
||||
public function findOneBy(array $criteria): ?AsideActivity
|
||||
{
|
||||
return $this->repository->findOneBy($criteria);
|
||||
}
|
||||
|
||||
public function getClassName(): string
|
||||
{
|
||||
return AsideActivity::class;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
{% extends "@ChillMain/Admin/layoutWithVerticalMenu.html.twig" %}
|
||||
|
||||
{% block vertical_menu_content %}
|
||||
{{ chill_menu('admin_aside_activity') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block layout_wvm_content %}
|
||||
{% block admin_content %}
|
||||
<!-- block personcontent empty -->
|
||||
<h1>{{ 'Aside activity configuration'|trans }}</h1>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
@@ -0,0 +1,12 @@
|
||||
{% set reversed_parents = parents|reverse %}
|
||||
<span
|
||||
class="chill-entity entity-aside_activity-category">
|
||||
{%- for p in reversed_parents %}
|
||||
<span class="parent-{{ loop.revindex0 }}">
|
||||
{{ p.title|localize_translatable_string }}{{ options['default.separator'] }}
|
||||
</span>
|
||||
{%- endfor -%}
|
||||
<span class="child">
|
||||
{{ asideActivityCategory.title|localize_translatable_string }}
|
||||
</span>
|
||||
</span>
|
@@ -0,0 +1,30 @@
|
||||
<div class="{% block crud_content_main_div_class %}col-10 centered{% endblock %}">
|
||||
{% block crud_content_header %}
|
||||
<h1>{{ ('crud.'~crud_name~'.title_delete')|trans({ '%as_string%': 'Aside Activity' }) }}</h1>
|
||||
{% endblock crud_content_header %}
|
||||
|
||||
<p class="message-confirm">{{ ('crud.'~crud_name~'.confirm_message_delete')|trans({ '%as_string%': 'Aside Activity' }) }}</p>
|
||||
|
||||
{{ form_start(form) }}
|
||||
|
||||
<ul class="record_actions">
|
||||
{% block content_form_actions_back %}
|
||||
<li class="cancel">
|
||||
<a class="btn btn-cancel" href="{{ chill_return_path_or('chill_crud_'~crud_name~'_index') }}">
|
||||
{{ 'Cancel'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
{% endblock %}
|
||||
{% block content_form_actions_before %}
|
||||
|
||||
{% endblock %}
|
||||
{% block content_form_actions_confirm_delete %}
|
||||
<li>
|
||||
<button type="submit" class="btn btn-delete" value="delete-and-close">{{ ('crud.'~crud_name~'.button_delete')|trans }}</button>
|
||||
</li>
|
||||
{% endblock content_form_actions_confirm_delete %}
|
||||
{% block content_form_actions_after %}{% endblock %}
|
||||
</ul>
|
||||
|
||||
{{ form_end(form) }}
|
||||
</div>
|
@@ -0,0 +1,8 @@
|
||||
{% extends '@ChillMain/layout.html.twig' %}
|
||||
|
||||
{# {% block title %}{{ ('crud.' ~ crud_name ~ '.delete.title')|trans({'%crud_name%': crud_name}) }}{% endblock %} #}
|
||||
|
||||
{% block content %}
|
||||
{% embed '@ChillAsideActivity/asideActivity/_delete.html.twig' %}
|
||||
{% endembed %}
|
||||
{% endblock content %}
|
@@ -0,0 +1,14 @@
|
||||
{% extends '@ChillMain/Admin/layout.html.twig' %}
|
||||
|
||||
{% block title %}
|
||||
{% include('@ChillMain/CRUD/_edit_title.html.twig') %}
|
||||
{% endblock %}
|
||||
|
||||
{% block admin_content %}
|
||||
{# {% as we are in the admin layout, we override the admin content with the CRUD content %} #}
|
||||
{% embed '@ChillMain/CRUD/_edit_content.html.twig' %}
|
||||
{# we do not have "view" page. We empty the corresponding block #}
|
||||
{% block content_form_actions_view %}{% endblock %}
|
||||
{% block content_form_actions_save_and_show %}{% endblock %}
|
||||
{% endembed %}
|
||||
{% endblock %}
|
@@ -0,0 +1,91 @@
|
||||
{% extends "@ChillMain/layout.html.twig" %}
|
||||
|
||||
{% block title %}
|
||||
{{ 'Aside activity list'|trans }}
|
||||
{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
<div class="col-md-10 asideactivity-list">
|
||||
<h2>{{ 'My aside activities'|trans }}</h2>
|
||||
|
||||
{% if entities|length == 0 %}
|
||||
<p class="chill-no-data-statement">
|
||||
{{ "There aren't any aside activities."|trans }}
|
||||
<a href="{{ path('chill_crud_aside_activity_new') }}" class="btn btn-create button-small"></a>
|
||||
</p>
|
||||
{% else %}
|
||||
|
||||
<div class="flex-table">
|
||||
|
||||
{% for entity in entities %}
|
||||
|
||||
<div class="item-bloc">
|
||||
<div class="item-row wrap-header">
|
||||
|
||||
<div class="item-col">
|
||||
<h3>
|
||||
{{ entity.type|chill_entity_render_box }}
|
||||
</h3>
|
||||
<div>
|
||||
{% if entity.date %}
|
||||
<span>{{ entity.date|format_date('long') }}</span>
|
||||
{% endif %}
|
||||
{% if entity.date %}
|
||||
<span class="duration">
|
||||
|
||||
<i class="fa fa-fw fa-hourglass-end"></i>
|
||||
{{ entity.duration|date('H:i') }}
|
||||
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-col">
|
||||
<div class="box">
|
||||
<ul class="list-content fa-ul">
|
||||
<li>
|
||||
<span>
|
||||
<abbr class="referrer" title={{ 'Created by'|trans }}>{{ 'By'|trans }}:</abbr>
|
||||
<b>{{ entity.createdBy|chill_entity_render_box }}</b>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>
|
||||
<abbr class="referrer" title={{ 'Created for'|trans }}>{{ 'For'|trans }}:</abbr>
|
||||
<b>{{ entity.agent|chill_entity_render_box }}</b>
|
||||
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="action">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_aside_activity_view', { 'id': entity.id } ) }}" class="btn btn-show btn-mini"></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_aside_activity_edit', { 'id': entity.id }) }}" class="btn btn-update btn-mini "></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_aside_activity_delete', { 'id': entity.id } ) }}" class="btn btn-delete btn-mini"></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{{ chill_pagination(paginator) }}
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_aside_activity_new') }}" class="btn btn-create">
|
||||
{{ 'Create'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
@@ -0,0 +1,11 @@
|
||||
{% extends '@ChillMain/Admin/layout.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 %}
|
@@ -0,0 +1,52 @@
|
||||
{% extends '@ChillMain/layout.html.twig' %}
|
||||
|
||||
{% set activeRouteKey = '' %}
|
||||
|
||||
{% block title %}
|
||||
{% include('@ChillMain/CRUD/_view_title.html.twig') %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% embed '@ChillMain/CRUD/_view_content.html.twig' %}
|
||||
{% block crud_content_header %}
|
||||
<h1>{{ ('crud.' ~ crud_name ~ '.title_view')|trans }}</h1>
|
||||
{% endblock crud_content_header %}
|
||||
{% block crud_content_view_details %}
|
||||
<dl class="chill_view_data">
|
||||
|
||||
<dt class="inline">{{ 'Type'|trans }}</dt>
|
||||
<dd>{{ entity.type|chill_entity_render_box }}</dd>
|
||||
|
||||
<dt class="inline">{{ 'Created by'|trans }}</dt>
|
||||
<dd>{{ entity.createdBy }}</dd>
|
||||
|
||||
<dt class="inline">{{ 'Created for'|trans }}</dt>
|
||||
<dd>{{ entity.agent }}</dd>
|
||||
|
||||
<h2 class="chill-red">{{ 'Activity data'|trans }}</h2>
|
||||
|
||||
<dt class="inline">{{ 'Date'|trans }}</dt>
|
||||
<dd>{{ entity.date|format_date('long') }}</dd>
|
||||
|
||||
<dt class="inline">{{ 'Duration'|trans }}</dt>
|
||||
<dd>{{ entity.duration|date('H:i') }}</dd>
|
||||
|
||||
<dt class="inline">{{ 'Remark'|trans }}</dt>
|
||||
{%- if entity.note is empty -%}
|
||||
<dd>
|
||||
<span class="chill-no-data-statement">{{ 'No comments'|trans }}</span>
|
||||
</dd>
|
||||
{%- else -%}
|
||||
<dd>
|
||||
<section class="chill-entity entity-comment-embeddable">
|
||||
<blockquote class="chill-user-quote">
|
||||
<p>{{ entity.note }}</p>
|
||||
</blockquote>
|
||||
</section>
|
||||
</dd>
|
||||
{%- endif -%}
|
||||
</dl>
|
||||
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
{% endblock %}
|
@@ -0,0 +1,12 @@
|
||||
{% extends "@ChillAsideActivity/Admin/layout_asideactivity.html.twig" %}
|
||||
|
||||
{% block title %}
|
||||
{% include('@ChillMain/CRUD/_edit_title.html.twig') %}
|
||||
{% endblock %}
|
||||
|
||||
{% block layout_wvm_content %}
|
||||
{% embed '@ChillMain/CRUD/_edit_content.html.twig' %}
|
||||
{% block content_form_actions_view %}{% endblock %}
|
||||
{% block content_form_actions_save_and_show %}{% endblock %}
|
||||
{% endembed %}
|
||||
{% endblock %}
|
@@ -0,0 +1,46 @@
|
||||
{% extends "@ChillAsideActivity/Admin/layout_asideactivity.html.twig" %}
|
||||
|
||||
{% block admin_content %}
|
||||
<h1>{{ 'Aside Activity Type list'|trans }}</h1>
|
||||
|
||||
<table class="records_list table table-bordered border-dark">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'Ordering'|trans }}</th>
|
||||
<th>{{ 'Name'|trans }}</th>
|
||||
<th>{{ 'Active'|trans }}</th>
|
||||
<th>{{ 'Actions'|trans }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for entity in entities %}
|
||||
<tr>
|
||||
<td>{{ entity.ordering }}</td>
|
||||
<td>{{ entity|chill_entity_render_box }}</td>
|
||||
<td style="text-align:center;">
|
||||
{%- if entity.isActive -%}
|
||||
<i class="fa fa-check-square-o"></i>
|
||||
{%- else -%}
|
||||
<i class="fa fa-square-o"></i>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
<td>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_crud_aside_activity_category_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_crud_aside_activity_category_new') }}" class="btn btn-create">
|
||||
{{ 'Create a new aside activity type'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endblock %}
|
@@ -0,0 +1,11 @@
|
||||
{% extends "@ChillAsideActivity/Admin/layout_asideactivity.html.twig" %}
|
||||
|
||||
{% block title %}
|
||||
{% include('@ChillMain/CRUD/_new_title.html.twig') %}
|
||||
{% endblock %}
|
||||
|
||||
{% block layout_wvm_content %}
|
||||
{% embed '@ChillMain/CRUD/_new_content.html.twig' %}
|
||||
{% block content_form_actions_save_and_show %}{% endblock %}
|
||||
{% endembed %}
|
||||
{% endblock %}
|
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\Templating\Entity;
|
||||
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivityCategory;
|
||||
use Chill\MainBundle\Templating\Entity\ChillEntityRenderInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Symfony\Component\Templating\EngineInterface;
|
||||
|
||||
final class CategoryRender implements ChillEntityRenderInterface
|
||||
{
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
private EngineInterface $engine;
|
||||
|
||||
public const SEPERATOR_KEY = 'default.separator';
|
||||
public const DEFAULT_ARGS = [
|
||||
self::SEPERATOR_KEY => ' > '
|
||||
];
|
||||
|
||||
public function __construct(TranslatableStringHelper $translatableStringHelper, EngineInterface $engine)
|
||||
{
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->engine = $engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AsideActivityCategory $asideActivityCategory
|
||||
*/
|
||||
public function renderString($asideActivityCategory, array $options): string
|
||||
{
|
||||
$options = array_merge(self::DEFAULT_ARGS, $options);
|
||||
|
||||
$titles[] = $this->translatableStringHelper->localize($asideActivityCategory->getTitle());
|
||||
|
||||
while ($asideActivityCategory->hasParent()) {
|
||||
$asideActivityCategory = $asideActivityCategory->getParent();
|
||||
$titles[] = $this->translatableStringHelper->localize($asideActivityCategory->getTitle());
|
||||
}
|
||||
|
||||
$titles = array_reverse($titles);
|
||||
|
||||
return implode($options[self::SEPERATOR_KEY], $titles);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AsideActivityCategory $asideActivityCategory
|
||||
*/
|
||||
public function supports($asideActivityCategory, array $options): bool
|
||||
{
|
||||
return $asideActivityCategory instanceof AsideActivityCategory;
|
||||
}
|
||||
|
||||
public function buildParents(AsideActivityCategory $asideActivityCategory)
|
||||
{
|
||||
$parents = [];
|
||||
|
||||
while($asideActivityCategory->hasParent()) {
|
||||
$asideActivityCategory = $parents[] = $asideActivityCategory->getParent();
|
||||
}
|
||||
|
||||
return $parents;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AsideActivityCategory $asideActivityCategory
|
||||
*/
|
||||
public function renderBox($asideActivityCategory, array $options): string
|
||||
{
|
||||
$options = array_merge(self::DEFAULT_ARGS, $options);
|
||||
$parents = $this->buildParents($asideActivityCategory);
|
||||
|
||||
return $this->engine->render('@ChillAsideActivity/Entity/asideActivityCategory.html.twig',
|
||||
[
|
||||
'asideActivityCategory' => $asideActivityCategory,
|
||||
'parents' => $parents,
|
||||
'options' => $options
|
||||
]);
|
||||
}
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\AsideActivityBundle\Tests\Controller;
|
||||
|
||||
use Chill\MainBundle\Test\PrepareClientTrait;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
use Chill\AsideActivityBundle\Entity\AsideActivity;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
|
||||
class AccompanyingCourseControllerTest extends WebTestCase
|
||||
{
|
||||
use PrepareClientTrait;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
self::bootKernel();
|
||||
$this->client = $this->getClientAuthenticated();
|
||||
}
|
||||
|
||||
public function testIndexWithoutUsers()
|
||||
{
|
||||
$this->client->request('GET', '/fr/asideactivity');
|
||||
|
||||
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
public function testNewWithoutUsers()
|
||||
{
|
||||
$this->client->request('GET', '/fr/asideactivity/new');
|
||||
|
||||
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider generateAsideActivityId
|
||||
*/
|
||||
|
||||
public function testEditWithoutUsers(int $asideActivityId)
|
||||
{
|
||||
$this->client->request('GET', "/fr/asideactivity/{$asideActivityId}/edit");
|
||||
|
||||
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
public function generateAsideActivityId()
|
||||
{
|
||||
self::bootKernel();
|
||||
|
||||
$qb = self::$container->get(EntityManagerInterface::class)
|
||||
->createQueryBuilder();
|
||||
|
||||
$asideActivityIds = $qb
|
||||
->select('DISTINCT asideactivity.id')
|
||||
->from(AsideActivity::class, 'asideactivity')
|
||||
->innerJoin('asideactivity.agent', 'agent')
|
||||
->where($qb->expr()->eq('agent.username', ':center_name'))
|
||||
->setParameter('center_name', 'center a_social')
|
||||
->setMaxResults(100)
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
|
||||
\shuffle($asideActivityIds);
|
||||
|
||||
yield [ \array_pop($asideActivityIds)['id'] ];
|
||||
yield [ \array_pop($asideActivityIds)['id'] ];
|
||||
yield [ \array_pop($asideActivityIds)['id'] ];
|
||||
}
|
||||
|
||||
|
||||
}
|
12
src/Bundle/ChillAsideActivityBundle/src/config/routes.yaml
Normal file
12
src/Bundle/ChillAsideActivityBundle/src/config/routes.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
chill_asideactivities_controllers:
|
||||
resource: "@ChillAsideActivityBundle/Controller"
|
||||
type: annotation
|
||||
|
||||
chill_admin_aside_activity_redirect_to_admin_index:
|
||||
path: /{_locale}/admin/activity_redirect_to_main
|
||||
controller: Chill\ActivityBundle\Controller\AdminController::redirectToAdminIndexAction
|
||||
options:
|
||||
menus:
|
||||
admin_aside_activity:
|
||||
order: 0
|
||||
label: Main admin menu
|
22
src/Bundle/ChillAsideActivityBundle/src/config/services.yaml
Normal file
22
src/Bundle/ChillAsideActivityBundle/src/config/services.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
services:
|
||||
Chill\AsideActivityBundle\DataFixtures\:
|
||||
resource: "./../DataFixtures"
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
Chill\AsideActivityBundle\Templating\Entity\:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
resource: "../Templating/Entity"
|
||||
tags:
|
||||
- "chill.render_entity"
|
||||
|
||||
Chill\AsideActivityBundle\Repository\:
|
||||
resource: "../Repository"
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
Chill\AsideActivityBundle\Controller\:
|
||||
resource: "../Controller"
|
||||
autowire: true
|
||||
autoconfigure: true
|
@@ -0,0 +1,6 @@
|
||||
---
|
||||
services:
|
||||
Chill\AsideActivityBundle\Form\:
|
||||
resource: './../../Form'
|
||||
autowire: true
|
||||
autoconfigure: true
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user