Compare commits

...

296 Commits

Author SHA1 Message Date
77640c9d16 bugfix concernementmapitem this.constraint 2025-05-05 10:43:45 +02:00
2837705a38 bugfix graphql-axios 2025-05-05 10:19:50 +02:00
01d3278a6a sentry vite plugin sourcemap fixed release.name, removed test error 2025-03-21 23:16:55 +01:00
2d9f83cfef added sentry test throw error 2025-03-21 23:00:44 +01:00
0e92cbb060 @sentry/vite-plugin & sourcemap bugfix 2025-03-21 22:45:52 +01:00
5d27c489a1 @sentry/vite-plugin & sourcemap bugfix 2025-03-21 22:44:12 +01:00
629dd738f5 added @sentry/vite-plugin & sourcemap 2025-03-21 22:40:20 +01:00
78480e4958 removed sentry captur message test 2025-03-20 22:26:53 +01:00
18a90fec0a sentry captur message test 2025-03-20 22:25:15 +01:00
c63740fe1c integrated sentry/glitchtip 2025-03-20 20:45:44 +01:00
424c251f26 cercle politique admin front fine tunning 2025-03-13 14:11:29 +01:00
86074b4bb0 cercle politique admin front fine tunning 2025-03-13 12:02:21 +01:00
076a0b4c67 cercle politique admin front completed 2025-03-12 16:22:22 +01:00
64d174dcfc cercle po: adresse de la decision ok 2025-02-26 19:17:01 +01:00
77ca3a85cf cercle po: mise en œuvre de la decision ok 2025-02-26 19:06:18 +01:00
a33104e402 cercle po: active steo is visualy focused 2025-02-26 16:48:30 +01:00
55b213af64 cercle po: decision ok 2025-02-26 12:39:48 +01:00
4afa5fbfa0 cercle po: adresse doleance & reception et traitement OK 2025-02-26 12:24:23 +01:00
b3c6f3bb9c admin front doleance groupes d'intérets done 2025-02-13 12:43:05 +01:00
d324c0436e admin front doleance improved dateEditable with optional range 2025-02-13 11:50:29 +01:00
e0651f9ac9 admin front doleance add new groupe interet 2025-02-12 17:13:50 +01:00
86bd454791 admin front doleance DateEditable 2025-02-12 15:21:31 +01:00
a87d7ac5ff admin front l'enquete 2025-02-12 13:44:56 +01:00
85f4100fe9 admin front create new doleance 2025-02-10 16:22:12 +01:00
1da22af863 doleance le problème is editable 2025-02-10 12:09:42 +01:00
0b92ab8e9f restored prev bug fix 2024-12-04 13:00:04 +01:00
7db1608051 bug fix 2024-12-04 11:31:18 +01:00
45a1e25e66 bug fix 2024-10-10 10:31:12 +02:00
d6b3bdf2aa admin front: entite active boolean 2024-10-04 15:46:36 +02:00
984ec07084 fileeditable filename with accent bug fix 2024-10-03 23:02:35 +02:00
6fb04ede84 linkeditable save bug fix 2024-10-03 22:30:39 +02:00
0fae2dee66 bug fix: revisions mismatch 2024-10-03 22:18:45 +02:00
f44d52bc2c bug fix: open boussole from search failed when mapitem_id different from cid 2024-10-03 22:18:11 +02:00
b988b43a66 commented some consolelog 2024-10-03 21:21:31 +02:00
c90baf9a31 bug fix: open boussole from search failed when mapitem_id different from cid 2024-10-03 21:21:07 +02:00
d4c3eb5f76 removed granim, replaced with generated static css gradient 2024-10-03 17:11:11 +02:00
3eb9403817 admin front: puiisance dagir: updating besoin reponse confidentialite 2024-06-04 15:43:10 +02:00
aba6de580f admin front: puiisance dagir: updating besoin reponse is updating mapItem display 2024-06-04 13:30:59 +02:00
8351ee71e3 amdin front: creating reponse (ressource) to besoin OK 2024-06-03 15:30:48 +02:00
f78f086b64 admin front besoin confidentialite 2024-06-03 14:17:13 +02:00
2d01c43061 admin front: editing besoin description OK 2024-06-03 13:45:52 +02:00
883e7b5896 loop bug fix 2024-06-03 13:06:25 +02:00
16f0e0818c loop bug fix 2024-06-03 13:04:41 +02:00
eeed61df4b admin front: create new besoin on puissance d'agir is ok 2024-06-03 12:10:08 +02:00
b260ab1b87 puissance d'agir bug fix 2024-05-29 20:23:05 +02:00
f3703d6657 admin front proximite bug fix 2024-05-29 20:17:31 +02:00
c9655a1e49 front admin DONE 2024-05-29 19:59:39 +02:00
46599a1ec0 linkEditable bug fix 2024-05-29 19:59:21 +02:00
9a7db9d7d2 fix gql cache probleme for getUserEntites 2024-05-29 17:47:28 +02:00
f683978b7c front admin proximites is ok 2024-05-29 16:14:24 +02:00
29dacfdde8 front admin proximites almost done 2024-05-28 22:14:25 +02:00
fc947913f7 concernement with less than 3 entites are visible only if can_update 2024-05-21 17:01:23 +02:00
433383437d display concernements with less than 3 entites 2024-05-21 16:44:40 +02:00
560c4eda72 vite build drop console 2024-04-10 10:12:13 +02:00
9aecfc62e9 BIG UPDATE: can now change the entites position in front 2024-04-09 15:56:23 +02:00
052a37d714 admin front : create new entite refresh concernementMapitem; fixed historique (active_revision) 2024-04-05 22:59:13 +02:00
340da92a46 admin front create new entite on cartouche 2024-04-04 20:34:45 +02:00
5521fe9998 amdin front can create paragraphe source on entite via REST 2024-04-03 21:23:24 +02:00
24b41ed00d source documents editable-file ok 2024-04-03 16:21:09 +02:00
34a0ec18e0 paragraphe source field_liens editable (mutliple) 2024-04-02 21:48:37 +02:00
e34c9cbd9c audio editable 2024-04-02 12:27:11 +02:00
a96230ebe7 field video on paragraphe source 2024-04-02 11:32:48 +02:00
820edbd36e links in html contentEditable with medium-editor-x 2024-03-27 22:47:22 +01:00
e4104a52ef refactoring; saving first paragraph contentEditable 2024-03-27 17:10:02 +01:00
d1716ce7f6 Source component 2024-03-27 15:54:49 +01:00
b5f8835214 field_confidentialite initial value 2024-03-27 15:29:51 +01:00
7d249aefca image alt field 2024-03-26 22:45:41 +01:00
67c2008d1f field confidentialite SelectEditable 2024-03-26 16:33:58 +01:00
4b215617f1 editable image add image icon 2024-03-19 21:44:04 +01:00
e9b6b90816 entite image is now editable, add, delete. remains the alt field 2024-03-19 15:33:40 +01:00
d4797e75dc more editable fields, created CheckboxEditable 2024-03-18 21:19:44 +01:00
8c90f54b3c can patch node from editablecontent fields 2024-03-18 18:57:07 +01:00
4dc5644898 fixed image caption #2564 2024-03-11 14:36:56 +01:00
88be181204 #2204 entite lables are clikable 2024-03-11 12:29:39 +01:00
fe55f6dbf9 #2204 restore mapitem position when scale back to zoom_detaille 1 2024-03-11 11:07:27 +01:00
0c4721fbfc #2325 corps typo reponse egale question 2024-03-11 10:47:43 +01:00
9c1b14ad5a #2325 cartouche header elipse chrome bug fixed 2024-03-11 10:39:33 +01:00
f1d2268517 #2501 entite future 2024-03-11 09:52:40 +01:00
496981832d display entites lable on détails zoom 2024-02-07 20:28:54 +01:00
f53e08a005 grab cursor on map_item if grabable 2024-02-06 15:43:06 +01:00
e88a4c30a7 entite are not growing while we zoom in terrain de vie 2024-02-06 15:35:46 +01:00
0acad592e7 we can now dragg the zoomed mapitem in the opened terrain de vie 2024-02-06 11:58:50 +01:00
8518ebf7df we can now zoom in the opened terrain de vie 2024-02-05 16:52:05 +01:00
7984c9c7d0 rescaling superposition constraints on reseting mapitem scale 2024-02-05 16:04:58 +01:00
609964b358 better responsivness #2416 2024-02-05 15:57:09 +01:00
b2614bf755 better responsivness #2416 2024-02-05 11:58:01 +01:00
40dbbb2384 resizing window is working 2024-01-30 16:51:40 +01:00
7607fc0e23 typo fix #2509 2024-01-29 09:46:25 +01:00
ea562f8ceb trying to debug the mis-scaling of proximity 2024-01-23 17:04:01 +01:00
fb242da7f2 cleaning 2024-01-23 15:46:17 +01:00
b5aaeeeb6b bug fix 2024-01-23 11:49:44 +01:00
568d941d90 proximite double cartouch width for boussole #2333 2024-01-23 11:44:52 +01:00
13fd182c60 bug fix 2024-01-17 11:17:33 +01:00
a88d2e4ee7 proximite rollover blue strpke color #2332 2024-01-16 16:03:06 +01:00
8e0edfed5b vuejs emits warn fix 2024-01-16 16:01:27 +01:00
ede55100e0 superpositions clone bug fixe #2303 2024-01-16 15:02:15 +01:00
fb9e7091b4 added loader fade 2024-01-15 15:57:39 +01:00
26338792b5 added loader #2235 2024-01-15 15:51:07 +01:00
cc49b939d0 more cartouche lisibility improvements: concernement title ellipsis on scroll #2325 2024-01-15 15:18:57 +01:00
8b79c2312b hidden empty questions #2415 2024-01-15 14:59:54 +01:00
b3f83db120 more cartouche lisibility improvements: header lables hide on scroll #2325 2024-01-15 14:40:25 +01:00
9b7f661e33 removed cartouch layout icons #2325 2024-01-12 12:24:58 +01:00
28c008ae1f improved entite content layout #2325 2024-01-12 12:16:29 +01:00
9d36ed7941 better doleance transition #2233 2024-01-12 11:10:42 +01:00
89889df66c better doleance transition #2233 2024-01-09 22:27:39 +01:00
510ca72d0a inverser hirarchie typo question réponse #2458 2023-12-11 13:27:46 +01:00
5331252f61 improved doleance transtions #2233 2023-11-17 16:24:34 +01:00
3680dc6cf7 speedup initial appearence of concernements #2390 2023-11-17 12:30:07 +01:00
a937b4085b contour concernement historique bug fix #2326 2023-11-17 12:21:28 +01:00
9e180f59d8 third version of superpositions is almost done 2023-11-10 22:15:51 +01:00
9b70d8071b refactoring: renamed allSuperpositions_byid by allSuperpositions_bycids 2023-11-10 11:27:25 +01:00
039f44072b entite action picto #2249 2023-11-06 17:06:37 +01:00
6b4e8ae99c map nav icon picto size padding #2330 2023-11-01 13:58:05 +01:00
80b585edab #2331 2023-11-01 13:51:50 +01:00
447f7bb1be better cartouch lisibility #2325 2023-11-01 13:47:04 +01:00
4bf9baac4d better cartouch lisibility #2325 2023-11-01 13:45:26 +01:00
fba8fcd6d7 proximites main features done ! 2023-10-26 12:43:58 +02:00
5a6a71359d made mapPopup hover proximites 2023-10-26 12:11:45 +02:00
fcce41aa77 drawing the contours of the contours in proximités 2023-10-25 16:43:15 +02:00
8aa8403f76 refactored getJarvisEnvelopeConvexe getPaddedRoundedSegments & setPaperContour
displaying proximites concernement contours around the entite ref point
2023-10-25 11:56:55 +02:00
ecc838abbb modified superpositions to get only one superposition by mapitem 2023-10-24 11:28:40 +02:00
6f5062b774 fix map nav responsive #2221 2023-10-10 11:31:35 +02:00
69b0d79591 search bugfix #2293 2023-10-10 10:00:52 +02:00
1dd82a855e added fadein intro to mapitems #2235 2023-10-06 15:12:19 +02:00
5fcff3f6dd enite higlignt bug fix #2306 2023-10-06 14:46:44 +02:00
3b4acd6949 reset active revision on mapitem close #2307 2023-10-06 12:45:04 +02:00
a8692abfb9 removed dashed circles from boussole #2309 2023-10-06 12:18:55 +02:00
8c126fbe26 decreased velocities on map #2150 2023-10-06 11:33:22 +02:00
7fb5244d1c highlighted icons on mapnav active item #2244 2023-10-06 11:15:21 +02:00
5e5cf061c5 removed puissance d'agir, action & doleance icons on map #2249 2023-10-06 10:50:32 +02:00
3da18ba960 upgraded npm modules 2023-10-06 10:13:26 +02:00
eeb5eb766b trying to fix npm gulp-better-rollup issue 2023-10-02 17:11:33 +02:00
fc5ed6cb86 trying to fix npm gulp-better-rollup issue 2023-10-02 17:05:09 +02:00
8d7bbe2b68 do not fill doleance step with empty fields #2311 2023-10-02 16:33:10 +02:00
980ae6e5a1 mapitems matter body is not scaling anymore 2023-10-02 16:00:07 +02:00
a9812b403a reduced icons size #2313 2023-10-02 15:50:03 +02:00
4c969958ba updated node modules 2023-10-02 15:38:50 +02:00
51d0c7118a preserving whitespaces #2199 2023-10-02 12:18:31 +02:00
9698cb6e34 bugfix 2023-10-02 11:57:17 +02:00
7983d40942 display doleance dates on front #2246 2023-10-02 11:53:15 +02:00
dff891e980 added doleance date fields to gql fragments #2246 2023-10-02 11:21:02 +02:00
954ae2ca0d history bug fix 2023-10-02 10:22:47 +02:00
ad010e5c8d concenrment history bug fix #2295 2023-10-02 09:55:25 +02:00
e032fd91a7 doleancer, by default if no field opened, display le problème #2233 2023-10-02 09:34:57 +02:00
55cb0698bd doleancer added arrow btn to go to previous and next doleance #2303 2023-09-29 14:47:29 +02:00
9b357e6d6e doleancer: click on le problème to display it #2285 #2286 2023-09-29 11:40:29 +02:00
c94679017e bugfix cartouchlayout props 2023-09-29 11:23:23 +02:00
86cb049c94 redesigned entites agissante icon #2249 2023-09-29 11:15:38 +02:00
58a42b4f93 added 'aucun resultats' in empty search results 2023-09-29 10:49:03 +02:00
65912e5b11 added author name on cartel popup #2300 2023-09-29 10:15:55 +02:00
5db02242aa bug fix cartouch_is_opened #2296 2023-09-29 09:52:35 +02:00
31c049e657 typo fix #2297 2023-09-29 09:43:33 +02:00
d813759ad7 added date field to entite display #2294 2023-09-29 09:39:20 +02:00
9c5db8527d superposition : resolved the three stage rocket pushaside syndrome 2023-09-20 17:03:13 +02:00
aa087e6694 bugfix highlighting entite on opened superposed mapitem 2023-09-20 16:06:29 +02:00
db51224556 highlighting entite on opened superposed mapitem 2023-09-20 16:02:48 +02:00
c67afa76e3 on multiple superpositions can switch by clicking on superposed mapitem 2023-09-20 15:25:36 +02:00
139db3516a entite are opening well in all modes 2023-09-20 12:28:19 +02:00
fbde40263f bugfix 2023-09-19 16:50:12 +02:00
fea17b2d6b bugfix 2023-09-19 16:30:12 +02:00
e490195d36 improved mapitem opening scaling regarding surounding contents
ex: double cartouche for superpositions
2023-09-19 16:08:21 +02:00
36e88290e6 refactored mapitem (main and clones) generation for better superpositions opening 2023-09-18 12:09:55 +02:00
c1c1eab95d displaying double cartouche on superposition opening 2023-09-15 11:27:59 +02:00
36b76a9ba6 superposition: mapitem openeing and entite clickable 2023-09-14 10:42:31 +02:00
43290d3c5d better mouseover mapitem mvt stop 2023-09-14 09:50:07 +02:00
ef0d8cedf6 superposition map behaviours bug fix 2023-09-13 21:30:12 +02:00
119ae3f242 superposition highlight on mouse hover 2023-09-12 14:58:55 +02:00
5836d39a38 map_popup for superpositions OK 2023-09-12 12:20:35 +02:00
aae6d0c9d5 superpositions: displaying the right entite to the right map_item 2023-09-12 11:20:11 +02:00
8377a4b2b1 applied matter constraints to superposed concernements clones 2023-09-11 15:12:22 +02:00
c4dd253b98 creating clones of map_item for duplicates superposition concernement couples 2023-09-11 11:57:38 +02:00
8e9941c1d1 bug fix 2023-09-11 10:11:02 +02:00
8a5c57cd13 refactored superposition constraint point tweening 2023-09-05 11:06:40 +02:00
a418682a72 scaling superpositions constraints on concernement opening 2023-09-04 14:36:14 +02:00
a6dc15d646 superpositions on map are ok 2023-09-01 15:50:24 +02:00
764ec8ad18 started to code superpositions 2023-08-31 15:34:02 +02:00
e080c4ac5e fix search nav behaviour 2023-08-18 19:57:02 +02:00
e256733c94 better search ui 2023-08-18 19:47:16 +02:00
c7b71e5530 search misc: results links, ... 2023-08-18 12:52:56 +02:00
6d00fecdb3 added content type filter to search, displaying reults 2023-08-17 19:14:29 +02:00
97b4c9c098 first api request for search is working 2023-08-14 13:47:32 +02:00
749ffd3867 started search router view 2023-08-13 20:18:11 +02:00
0fc1cd12dd started search block in header 2023-08-13 12:42:40 +02:00
2e3ffd0d40 etiquette less padding #2239 2023-07-20 19:12:31 +02:00
fdaeb3a433 recit player fadeout bug fix 2 #2240 2023-07-20 19:01:37 +02:00
af84d7c27c recit player fadeout bug fix #2240 2023-07-20 18:49:11 +02:00
bf4f4dcc04 mappopup bug fix #2238 2023-07-20 18:29:11 +02:00
62b43a5d44 coquille #2264 2023-07-19 22:16:09 +02:00
4b5d7a69f1 concernement close btn arrow up #2196 2023-07-19 22:13:55 +02:00
2bea597981 point bleu entite ouverte #2256 2023-07-19 12:55:57 +02:00
4800d99ed7 cercle politique latour video #2245 2023-07-18 23:16:25 +02:00
7ec9f057b6 initial recit volume #2242 2023-07-18 22:50:47 +02:00
eb0bbb5346 entite action hover bug fux #2241 2023-07-18 22:48:47 +02:00
315c271185 point entité #2197 2023-07-18 22:42:38 +02:00
00f8659b20 better numbers to doleancer legends #2218 2023-07-16 23:29:55 +02:00
6461a1246b added numbers to doleancer legends #2218 2023-07-16 23:26:04 +02:00
ab076c612f bug fix 2023-07-16 23:22:25 +02:00
677fae57f1 reduced map icons #2244 2023-07-16 23:17:28 +02:00
f2b1ed58b5 fix puissance agir duplicate label #2243 2023-07-16 23:11:43 +02:00
bf809c72a6 point devant entités #2197 2023-07-16 23:09:13 +02:00
fd30488a3b picto action with all entite #2241 2023-07-16 22:58:47 +02:00
25a1f671f3 picot action #2190 2023-07-16 22:57:14 +02:00
c258593341 entite source liens display fix #2200 2023-07-16 22:50:12 +02:00
759376983a more line-height in texts and new-line #2199 2023-07-15 22:48:20 +02:00
8fb1a716dc plier deplier infos meta concernement #2232 2023-07-15 22:28:44 +02:00
0bb60fe21e menace / maintient #2205 2023-07-15 22:12:40 +02:00
4cd2d78e07 marge en haut des contenus #2229 2023-07-15 22:11:30 +02:00
2a90e7c787 forms are stoping on mouse over #2234 #2150 2023-07-15 21:36:44 +02:00
0507cfcdcb fixed recit player transition #2183 2023-07-14 22:48:50 +02:00
c9b226f649 fixed agissante picto bug #2190 2023-07-14 21:58:56 +02:00
6b2146ea8f history is working #2203 2023-07-14 13:14:04 +02:00
0a5f1adf90 fixed agissantes icons size #2190 2023-07-14 11:39:04 +02:00
84852a434e cleaning 2023-07-14 11:09:48 +02:00
8f001f8a1b created paper contents once concernement opened and not on init, UI should be smoother #2150 2023-07-14 11:05:54 +02:00
f17781b8be started to create paper contents once concernement opened and not on init (doleance left to do) 2023-07-13 22:49:31 +02:00
be3d7f622d displaying slider for revisions with right data #2203 2023-07-13 12:56:30 +02:00
5b5a84c1a0 better mouse over on map items #2192 2023-07-13 10:31:31 +02:00
e9e4627cf2 liens soulignés #2200 2023-07-13 10:26:28 +02:00
7ef77fd71e hidden entite points are displayed without being accessible #2151 #2188 2023-07-13 09:34:49 +02:00
9e523af2ff some fixes on paysage sonore #2146 2023-07-12 13:18:37 +02:00
109705d11a paysage sonor done #2146 2023-07-12 13:08:34 +02:00
fcf01e4d6a cercel politique minor fix 2023-07-11 23:00:03 +02:00
58f77d22e3 cercle politique nav is done #2156 2023-07-11 22:55:25 +02:00
28c653dcab can choose doleance then get a click infos on doleance steps 2023-07-07 16:01:12 +02:00
d1164c4353 fixed recit crédits #2148 2023-07-07 14:33:11 +02:00
f6360e5902 fixed puissancedagir btn in concernement content cartouche 2023-07-07 12:52:53 +02:00
962335a154 fixed auto open concernement on first load 2023-07-07 12:49:32 +02:00
654843bfc9 fix bg decalage #2195 2023-07-07 12:25:53 +02:00
7edb505b96 restored basique cercle politique content display 2023-07-07 11:20:13 +02:00
901c66fe9a mapmode action done 2023-07-07 10:51:25 +02:00
213f151557 puissance agir hover events both ways (map <-> cartouche) are done 2023-07-06 22:43:27 +02:00
19e61bbcd7 fixed puissance agir mouse hover map items 2023-07-06 21:39:25 +02:00
04eb79af8b fixed puissance d'agir cartouch display 2023-07-06 16:15:24 +02:00
576cdc0445 v-if recit 2023-07-06 15:31:35 +02:00
15c6e2e0d2 fix iframe embed urls 2023-07-06 15:25:23 +02:00
50f7375eed removed video-embed dependency 2023-07-06 15:18:59 +02:00
52c0700d29 header static menu promoted & static content well displayed #2194 2023-07-06 15:05:59 +02:00
5c41bfc04a promoted statics on header menu #2194, crédits paysage sonor (récit) #2148 2023-07-06 11:08:07 +02:00
689d00d3de displaying all entite fields 2023-07-05 15:03:37 +02:00
965d08c432 youtube player is working 2023-07-05 12:34:01 +02:00
049185cd4c reduced matter restitution, map item's ray is now responsive #2150 2023-07-05 11:13:46 +02:00
15e8a381d4 fixed content cartouche layout flex 2023-07-05 10:39:45 +02:00
c85af7eacc created layout component for concernement content cartouche, continued to integrate entites 2023-07-04 22:28:42 +02:00
e162adaae8 splitted concernement content cartouche into components for each mapmode, completed terrain de vie concernement display 2023-07-03 16:09:36 +02:00
524b815d37 better mode nav, from concernement & main menu 2023-07-03 14:26:11 +02:00
6197db37ee gogs wbehook test 2023-06-30 10:31:32 +02:00
f55e16038b #2150 matter body circle ray proportional to entites length 2023-06-30 10:22:31 +02:00
037aa83a21 matter: bigger walls, respawn, bug fix 2023-06-30 10:15:02 +02:00
d69c194cd3 #2150 map improvement 2023-06-29 17:15:32 +02:00
b105c9ddff refactoring: convertion off entites, besoin, reponse items into symbols for perf optimization DONE 2023-06-29 11:29:16 +02:00
ba7f2a6ec0 refactoring: convertion off all static common paper objects (backgrounds & icon) into symbols for perf optimization DONE 2023-06-28 15:32:59 +02:00
344b07c93b refactoring: converting all static commun paper objects (like backgrounds) into symbols for perf optimization 2023-06-28 12:17:06 +02:00
b0bfd5cd1f full page reload on user login or logout, would be better to refresh the concernements list 2023-06-28 11:30:46 +02:00
936cf1befa fixed salient points bug #2140 2023-06-26 17:58:38 +02:00
7c589b0327 refactoring: replaced all matter sub body part (entites, etc) by directly paperjs groups 2023-06-26 15:49:02 +02:00
a90458f145 better pushAside & bringToCenter logarithmic algorithem 2023-06-26 13:07:32 +02:00
45cd0341fe refactoring: replaced global var opened by opened_concernement 2023-06-26 12:26:16 +02:00
36275fb9f3 misc 2023-06-26 09:41:19 +02:00
56f8a40555 #2143 paperjs font-family 2023-06-16 14:27:24 +02:00
a3fa2ef000 #2156 2023-06-16 14:15:14 +02:00
6dee6fb1d9 #2159 user link to edit 2023-06-16 12:29:15 +02:00
7acd312cc5 #2140 contours test 2023-06-16 11:01:40 +02:00
02c921a7c0 #2140 contours test 2023-06-16 10:59:48 +02:00
b4ab835250 #2140 physics test 2023-06-16 10:50:39 +02:00
c56929901c #2140 contours test 2023-06-16 10:41:28 +02:00
2b9a94c6ef #2140 added stroke to contours 2023-06-16 10:38:44 +02:00
20ded36456 #2140 added stroke to contours 2023-06-16 10:36:03 +02:00
5bb5dde7fe #2140 removed rounded angle in concernement contour 2023-06-16 10:11:57 +02:00
9a699929c5 fixed recit icon position on map-popup 2023-06-13 15:22:50 +02:00
fb14d83f6d fixed mdi icons, added recit icon on map-popup 2023-06-13 15:16:45 +02:00
0ccbc9257e fixed doleance BG fontsize 2023-06-13 13:59:29 +02:00
5b52b6ff0b #2140 implemented rounding concernement contour form 2023-06-13 13:52:12 +02:00
62c422f560 #2140 implemented padding in concernement contour form 2023-06-13 11:49:02 +02:00
a7ff77364d implemented Gift wrapping algorithm 2023-06-12 23:37:02 +02:00
ae404e5c75 #2143 better boussole bg 2023-06-12 22:56:12 +02:00
343b01977f #2143 legende boussole 2023-06-12 16:50:33 +02:00
21c8209c85 #2141 opened concernement siez to big, now is responsive 2023-06-12 16:11:43 +02:00
2ee902e578 #2139 #2147 background 2023-06-12 15:40:07 +02:00
f47b2fd7e3 many display fixes 2023-06-09 12:34:56 +02:00
e242d04df8 fixed mence / maintient 2023-06-09 10:43:04 +02:00
d6eebe3598 more salientpoints arcs 2023-06-09 10:23:01 +02:00
da903ca550 more salientpoints arcs 2023-06-09 10:22:09 +02:00
389d824106 deactivated materioaldesignicons.css du to a bug, hidden proximite et superposition menu 2023-06-09 09:26:10 +02:00
0a9a36255e fixed the opened concernement scale (was to big) 2023-06-07 22:35:04 +02:00
caced38845 generic paper item hover highlight behaviour, + some tweaks 2023-06-07 22:30:39 +02:00
c0028a636b some css on doleance content, started mouse events 2023-06-07 16:53:19 +02:00
0b9a1ae946 display all doleance fields in cartouche 2023-06-07 12:51:40 +02:00
be824fd325 started to build paper dynamic objects in doleancer 2023-06-06 21:48:41 +02:00
4f82e8021d made the first camenbert of doleance 2023-06-06 18:27:13 +02:00
894b0219c5 fixing and cleaning 2023-06-06 15:34:11 +02:00
3b1565c82f paper bg for doleance done! 2023-06-06 11:18:42 +02:00
6afc3f945f started cercle politique bg legendes 2023-06-05 22:54:37 +02:00
6021809ce3 finished paperjs refactoring 2023-06-05 22:32:04 +02:00
f314ff11f2 more paperjs refactoring 2023-06-05 14:33:03 +02:00
3a473ea932 more paperjs refactoring 2023-06-05 12:46:05 +02:00
18ab3b2b7d started paperjs events instead of matterjs (query) events 2023-06-04 22:39:41 +02:00
65 changed files with 16148 additions and 4947 deletions

2
.gitignore vendored
View File

@ -14,6 +14,8 @@ dist-ssr
coverage coverage
*.local *.local
.env
/cypress/videos/ /cypress/videos/
/cypress/screenshots/ /cypress/screenshots/

View File

@ -3,7 +3,8 @@
app (VueJs) app (VueJs)
part of https://figureslibres.io/gogs/bachir/docker-enfrancais
part of https://figureslibres.io/gogs/bachir/docker-ouatterrir
..... .....

6160
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -9,33 +9,55 @@
}, },
"dependencies": { "dependencies": {
"@csstools/normalize.css": "^12.0.0", "@csstools/normalize.css": "^12.0.0",
"@jamescoyle/vue-icon": "^0.1.2",
"@material-design-icons/svg": "^0.14.2", "@material-design-icons/svg": "^0.14.2",
"@mdi/font": "^7.1.96", "@mdi/font": "^7.1.96",
"@tweenjs/tween.js": "^19.0.0", "@mdi/js": "^7.2.96",
"@sentry/browser": "^9.7.0",
"@sentry/integrations": "^7.114.0",
"@sentry/vue": "^9.7.0",
"@tweenjs/tween.js": "^21.0.0",
"@vojtechlanka/vue-simple-suggest": "^2.0.6",
"@vuepic/vue-datepicker": "^11.0.1",
"dotenv": "^16.4.7",
"fabric": "^6.0.0-beta7", "fabric": "^6.0.0-beta7",
"granim": "^2.0.0", "granim": "^2.0.0",
"lodash": "^4.17.21",
"matter-attractors": "^0.1.6", "matter-attractors": "^0.1.6",
"matter-js": "^0.19.0", "matter-js": "^0.19.0",
"medium-editor-x": "^0.0.5",
"paper": "^0.12.17", "paper": "^0.12.17",
"pinia": "^2.0.21", "pinia": "^2.0.21",
"poly-decomp": "^0.3.0", "poly-decomp": "^0.3.0",
"vue": "^3.2.38", "vue": "^3.2.38",
"vue-router": "^4.1.5" "vue-easy-lightbox": "^1.16.0",
"vue-plyr": "^7.0.0",
"vue-router": "^4.1.5",
"vue-select": "^4.0.0-beta.6",
"vue-slider-component": "^4.1.0-beta.7"
}, },
"devDependencies": { "devDependencies": {
"@rollup/plugin-graphql": "^2.0.0", "@rollup/plugin-graphql": "^2.0.0",
"@rushstack/eslint-patch": "^1.1.4", "@rushstack/eslint-patch": "^1.1.4",
"@vitejs/plugin-vue": "^3.0.3", "@sentry/vite-plugin": "^3.2.2",
"@vue/eslint-config-prettier": "^7.0.0", "@types/medium-editor": "^5.0.8",
"@vitejs/plugin-vue": "^4.4.0",
"@vue/eslint-config-prettier": "^8.0.0",
"axios": "^1.0.0", "axios": "^1.0.0",
"eslint": "^8.22.0", "eslint": "^8.22.0",
"eslint-plugin-vue": "^9.3.0", "eslint-plugin-vue": "^9.3.0",
"graphql": "^16.6.0", "graphql": "^16.6.0",
"graphql-tag": "^2.12.6", "graphql-tag": "^2.12.6",
"prettier": "^2.7.1", "prettier": "^3.0.3",
"querystring-es3": "^0.2.1", "querystring-es3": "^0.2.1",
"sass": "^1.57.1", "sass": "^1.57.1",
"vite": "^3.0.9", "vite": "^4.4.11",
"vite-require": "^0.2.3" "vite-require": "^0.2.3",
"vite-svg-loader": "^4.0.0"
},
"overrides": {
"vue-plyr": {
"plyr": "^3.7.8"
}
} }
} }

BIN
padded-salient-points.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 KiB

View File

@ -7,14 +7,25 @@ import { ConcernementsStore } from '@/stores/concernements'
import StaticMenu from '@components/block/StaticMenu.vue' import StaticMenu from '@components/block/StaticMenu.vue'
import UserBlock from '@components/block/UserBlock.vue' import UserBlock from '@components/block/UserBlock.vue'
import SearchBlock from '@components/block/SearchBlock.vue'
import MapConcernements from '@components/MapConcernements.vue' import MapConcernements from '@components/MapConcernements.vue'
import ConcernementMapItem from '@components/ConcernementMapItem.vue' import ConcernementMapItem from '@components/ConcernementMapItem.vue'
export default { export default {
data() {
return {
mapitems: [],
// not_cloned_mapitems: [],
// superposed_cloned_mapitems: []
}
},
created () { created () {
this.loadContentTypeDefinition(); this.loadContentTypeDefinition()
this.loadConcernements() this.loadConcernements()
// setTimeout(()=>{
// throw new Error("sentry test error");
// })
}, },
mounted () { mounted () {
console.log('APP onMounted') console.log('APP onMounted')
@ -22,20 +33,111 @@ export default {
}, },
computed: { computed: {
...mapState(UserStore,['isloggedin']), ...mapState(UserStore,['isloggedin']),
...mapState(ConcernementsStore,['concernements']), ...mapState(ConcernementsStore,['map_mode',
...mapState(ConcernementsStore,['concernementsByID']), 'concernements',
...mapState(ConcernementsStore,['opened']) 'concernements_loaded',
'concernements_loading_nb',
'concernementsByID',
'allSuperpositions_bycids',
'allSuperpositions_clustered',
'allMapItems_byid',
'opened_recit']),
},
watch: {
concernements_loaded:{
handler (n, o) {
if(n && !o){
this.parseMapitems()
}
},
deep: true
},
concernements_loading_nb: {
handler (n, o) {
console.log('App watch concernements_loading_nb o, n', o, n);
this.parseMapitems();
},
deep: true
},
// concernementsByID:{
// handler (n, o) {
// console.log('App watch concernementsByID o, n', o, n);
// this.parseMapitems();
// },
// deep: true
// }
}, },
methods: { methods: {
...mapActions(ConcernementsStore,['loadConcernements']), ...mapActions(ConcernementsStore,['loadConcernements']),
...mapActions(ConcernementsStore,['loadContentTypeDefinition']), ...mapActions(ConcernementsStore,['loadContentTypeDefinition']),
...mapActions(UserStore,['checkUser']), ...mapActions(UserStore,['checkUser']),
parseMapitems() {
console.log(`App parseMapitems`);
this.mapitems = [];
// let couple_ids = Object.keys(this.allSuperpositions_bycids);
// console.log('App couple_ids', couple_ids);
// loop through all concernement
for(let [concernement_id, concernement] of Object.entries(this.concernementsByID)){
concernement.mapitems_ids = [];
// TODO check if more than 3 entities or if connected user if author
if (concernement.entites.length > 3 || concernement.can_update) {
// create the main mapitem object
let mapitem = {
id: concernement.id,
cid: concernement.id,
visible: concernement.visible,
// concernement: concernement,
// superposition_ids: [],
superposition_cluster_index: -1,
clone: false,
concernements_loading_nb: this.concernements_loading_nb
}
// loop through all superposition_clusters
for( let [cluster_index, cluster] of this.allSuperpositions_clustered.entries()){
let cids = [];
// console.log(`cluster ${cluster_index}`, cluster);
for( let s of cluster){
cids.push(s.cid)
}
// console.log(`cids:${cids}`);
if(cids.indexOf(concernement.id) !== -1){
// console.log('concernement in cluster');
if (mapitem.superposition_cluster_index === -1) {
// if main map item does not yet have a superposition use it and alter his id (for matter constraints)
mapitem.superposition_cluster_index = cluster_index
mapitem.id = `${concernement.id}___${cluster_index}`
}else{
let mapitem_superposition = {
id: `${concernement.id}___${cluster_index}`,
cid: concernement.id,
// concernement: concernement,
superposition_cluster_index: cluster_index,
clone: true
};
this.mapitems.push(mapitem_superposition);
this.allMapItems_byid[mapitem_superposition.id] = mapitem_superposition;
concernement.mapitems_ids.push(mapitem_superposition.id)
}
}
}
this.mapitems.push(mapitem)
this.allMapItems_byid[mapitem.id] = mapitem;
concernement.mapitems_ids.push(mapitem.id)
}
}
console.log('App mapitems', this.mapitems);
console.log('this.allMapItems_byid', this.allMapItems_byid);
}
}, },
components: { components: {
MapConcernements, MapConcernements,
ConcernementMapItem, ConcernementMapItem,
StaticMenu, StaticMenu,
UserBlock UserBlock,
SearchBlock
} }
} }
@ -43,25 +145,36 @@ export default {
<template> <template>
<header id="header"> <header id="header">
<h1 class="row"> <div class="row title">
<h1>
<router-link :to="{ name: 'home' }"><span class="title">Atlas</span> des cartes d'atterrissage</router-link> <router-link :to="{ name: 'home' }"><span class="title">Atlas</span> des cartes d'atterrissage</router-link>
</h1> </h1>
</div>
<div class="row top"> <div class="row top">
<StaticMenu/> <StaticMenu/>
<SearchBlock/>
<UserBlock/> <UserBlock/>
</div> </div>
</header> </header>
<div id="main-content"> <div id="main-content">
<MapConcernements> <MapConcernements>
<transition name="fade">
<div class="loading" v-if="mapitems.length === 0">Chargement</div>
</transition>
<template v-if="mapitems.length > 0">
<template v-for="(mapitem,index) in mapitems">
<!-- && ((map_mode === 'superposition' && mapitem.clone) || !mapitem.clone) -->
<ConcernementMapItem <ConcernementMapItem
v-for="(concernement,index) in concernements" v-if="mapitem.visible"
:key="index" :key="mapitem.id"
:concernement="concernement" :mapitem="mapitem"
:opened="concernement.opened"
/> />
</template>
</template>
</MapConcernements> </MapConcernements>
<div id="content"> <div id="content" :class="{'recit-opened':opened_recit}">
<RouterView /> <RouterView />
</div> </div>
</div> </div>
@ -69,4 +182,13 @@ export default {
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.fade-enter-active,
.fade-leave-active {
transition: opacity 1s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style> </style>

View File

@ -1,5 +1,6 @@
fragment ConcernementFields on Concernement { fragment ConcernementFields on Concernement {
id id
revision_id
description description
caillou caillou
title title
@ -13,10 +14,24 @@ fragment ConcernementFields on Concernement {
} }
description description
} }
author recit_colophon
author {
username
structure {
name
}
}
created
changed
can_update
lieu {
name
}
entites { entites {
id
revision_id
active
menacemaintien menacemaintien
prise
actuelfuture actuelfuture
entite { entite {
title title
@ -32,12 +47,40 @@ fragment ConcernementFields on Concernement {
} }
} }
} }
revisions {
revision_id
changed
entites {
id
revision_id
active
menacemaintien
prise
actuelfuture
entite {
id
title
agissante
proximite {
id
title
}
superposition {
id
title
}
}
}
}
besoins { besoins {
author author
description description
id id
index index
confidentialite
reponses { reponses {
confidentialite
can_update
author author
avec avec
id id
@ -54,36 +97,72 @@ fragment ConcernementFields on Concernement {
title title
uuid uuid
#1 #1
date_leprobleme {
start
}
leprobleme leprobleme
lenquete lenquete
groupesinterets { groupesinterets {
id
revision_id
date {
end
start
}
groupe_interets groupe_interets
accorder_interets accorder_interets
formuler formuler
} }
#2 #2
entite_addresse_doleance date_adresse {
comment_ennonce_doleance start
aqui_addresse_doleance }
entite_adresse_doleance
comment_enonce_doleance
a_qui_adresse_doleance
reception_traitement { reception_traitement {
id
revision_id
date {
end
start
}
entite_adressee entite_adressee
doleance_formulee doleance_formulee
traite_doleance traite_doleance
entite_recoit_doleance entite_recoit_doleance
} }
#3 #3
date_decision {
start
}
entites_decisionnaires entites_decisionnaires
decision_formule decision_formulee
mise_en_oeuvre_decision { mise_en_oeuvre_decision {
id
revision_id
date {
end
start
}
entite_adresse_decision entite_adresse_decision
formule_decision formule_decision
entite_metenoeuvre_decisio entite_metenoeuvre_decisio
} }
#4 #4
date_application {
start
}
entite_adresse_application entite_adresse_application
aqui_adresse_decision aqui_adresse_decision
comment_formule_decision comment_formule_decision
receptions_et_applications { receptions_et_applications {
id
revision_id
date {
end
start
}
applique_decision applique_decision
formule_decision_applic formule_decision_applic
entite_recoit_decision entite_recoit_decision

View File

@ -0,0 +1,22 @@
fragment ConcernementRevisionsFields on Concernement {
id
revision_id
entites {
menacemaintien
prise
actuelfuture
entite {
title
id
agissante
proximite {
id
title
}
superposition {
id
title
}
}
}
}

View File

@ -1,12 +1,25 @@
fragment EntiteFields on Entite { fragment EntiteFields on Entite {
id
uuid
title
can_update
confidentialite
agissante
action action
menacemaintien menacemaintien
title image {
alt
url
id
}
sources { sources {
id
uuid
description description
images { images {
alt alt
url url
id
} }
liens { liens {
title title
@ -15,6 +28,7 @@ fragment EntiteFields on Entite {
documents { documents {
description description
file { file {
fid
filemime filemime
filename filename
url url
@ -31,6 +45,7 @@ fragment EntiteFields on Entite {
audios { audios {
description description
file { file {
fid
filemime filemime
filename filename
filesize filesize

View File

@ -0,0 +1,15 @@
fragment ResultsConcernementFields on Concernement {
id
title
author {
username
structure {
name
}
}
created
changed
lieu {
name
}
}

View File

@ -0,0 +1,18 @@
fragment ResultsEntiteFields on Entite {
id
concernement {
id
title
}
action
menacemaintien
title
author {
username
structure {
name
}
}
created
changed
}

View File

@ -21,8 +21,8 @@ MGQ.interceptors.response.use(
return Promise.resolve(response) return Promise.resolve(response)
}, },
error => { error => {
const { status } = error.response // const { status } = error.response
console.warn('error in graphql-axios', status) // console.warn('error in graphql-axios', status)
// if (status === 403) { // if (status === 403) {
// window.location = '/' // window.location = '/'
// } // }

33
src/api/ma-axios.js Normal file
View File

@ -0,0 +1,33 @@
import axios from 'axios'
// https://github.com/alvar0hurtad0/drupal-vuejs-todo/blob/master/frontend/src/api/axiosInterceptor.js
// console.log('drupalSettings', drupalSettings)
const MA = axios.create({
baseURL: `${window.location.origin}/api`,
withCredentials: true,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
})
MA.interceptors.response.use(
response => {
return Promise.resolve(response)
},
error => {
const { status } = error.response
console.warn('error in ma-axios interceptor', status)
// if (status === 403) {
// window.location = '/'
// }
return Promise.reject(error)
}
)
export default MA

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="margin: auto; background: none; display: block; shape-rendering: auto; animation-play-state: running; animation-delay: 0s;" width="100px" height="100px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
<circle cx="84" cy="50" r="10" fill="#000000" style="animation-play-state: running; animation-delay: 0s;">
<animate attributeName="r" repeatCount="indefinite" dur="1.25s" calcMode="spline" keyTimes="0;1" values="10;0" keySplines="0 0.5 0.5 1" begin="0s" style="animation-play-state: running; animation-delay: 0s;"></animate>
<animate attributeName="fill" repeatCount="indefinite" dur="5s" calcMode="discrete" keyTimes="0;0.25;0.5;0.75;1" values="#000000;#000000;#000000;#000000;#000000" begin="0s" style="animation-play-state: running; animation-delay: 0s;"></animate>
</circle><circle cx="16" cy="50" r="10" fill="#000000" style="animation-play-state: running; animation-delay: 0s;">
<animate attributeName="r" repeatCount="indefinite" dur="5s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="0;0;10;10;10" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="0s" style="animation-play-state: running; animation-delay: 0s;"></animate>
<animate attributeName="cx" repeatCount="indefinite" dur="5s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="16;16;16;50;84" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="0s" style="animation-play-state: running; animation-delay: 0s;"></animate>
</circle><circle cx="50" cy="50" r="10" fill="#000000" style="animation-play-state: running; animation-delay: 0s;">
<animate attributeName="r" repeatCount="indefinite" dur="5s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="0;0;10;10;10" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-1.25s" style="animation-play-state: running; animation-delay: 0s;"></animate>
<animate attributeName="cx" repeatCount="indefinite" dur="5s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="16;16;16;50;84" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-1.25s" style="animation-play-state: running; animation-delay: 0s;"></animate>
</circle><circle cx="84" cy="50" r="10" fill="#000000" style="animation-play-state: running; animation-delay: 0s;">
<animate attributeName="r" repeatCount="indefinite" dur="5s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="0;0;10;10;10" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-2.5s" style="animation-play-state: running; animation-delay: 0s;"></animate>
<animate attributeName="cx" repeatCount="indefinite" dur="5s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="16;16;16;50;84" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-2.5s" style="animation-play-state: running; animation-delay: 0s;"></animate>
</circle><circle cx="16" cy="50" r="10" fill="#000000" style="animation-play-state: running; animation-delay: 0s;">
<animate attributeName="r" repeatCount="indefinite" dur="5s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="0;0;10;10;10" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-3.75s" style="animation-play-state: running; animation-delay: 0s;"></animate>
<animate attributeName="cx" repeatCount="indefinite" dur="5s" calcMode="spline" keyTimes="0;0.25;0.5;0.75;1" values="16;16;16;50;84" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" begin="-3.75s" style="animation-play-state: running; animation-delay: 0s;"></animate>
</circle>
<!-- [ldio] generated by https://loading.io/ --></svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@ -0,0 +1,358 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg1"
width="560"
height="530.56"
viewBox="0 0 560 530.56"
sodipodi:docname="cercle_politique-hover.svg"
inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"
inkscape:export-filename="cercle_politique.png"
inkscape:export-xdpi="149.987"
inkscape:export-ydpi="149.987"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1">
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath31">
<g
id="g32"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path32"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath32">
<g
id="g33"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path33"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath33">
<g
id="g34"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path34"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath34">
<g
id="g35"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path35"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath35">
<g
id="g36"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path36"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath36">
<g
id="g37"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path37"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath37">
<g
id="g38"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path38"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath38">
<g
id="g39"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path39"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath39">
<g
id="g40"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path40"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath40">
<g
id="g41"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path41"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath41">
<g
id="g42"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path42"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath42">
<g
id="g43"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path43"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath43">
<g
id="g44"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path44"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath44">
<g
id="g45"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path45"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath45">
<g
id="g46"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path46"
style="stroke-width:0.320403" />
</g>
</clipPath>
</defs>
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="true"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="1.9390791"
inkscape:cx="171.98885"
inkscape:cy="238.25742"
inkscape:window-width="1920"
inkscape:window-height="1057"
inkscape:window-x="0"
inkscape:window-y="60"
inkscape:window-maximized="1"
inkscape:current-layer="g1">
<inkscape:page
x="0"
y="0"
inkscape:label="1"
id="page1"
width="560"
height="530.56"
margin="0"
bleed="0"
inkscape:export-filename="cercle_politique.png"
inkscape:export-xdpi="149.987"
inkscape:export-ydpi="149.987" />
</sodipodi:namedview>
<g
id="g1"
inkscape:groupmode="layer"
inkscape:label="1">
<path
d="M 241.07201,507.43799 C 121.31,496.34799 26.323,399.258 18.518,278.57901 c 0.159999,-0.087 0.321001,-0.084 0.482,-0.084 8.278999,0 15,-6.72101 15,-15 0,-8.279 -6.721001,-15 -15,-15 -0.205999,0 -0.410999,0.004 -0.615,0.012 C 25.372,124.203 124.825,24.43 248.998,16.945999 249.50101,24.768 256.02802,31 264,31 c 7.96201,0 14.483,-6.216 14.97101,-14.056 124.16,7.442999 223.65399,107.23 230.63699,231.563 -7.62601,0.754 -13.608,7.178 -13.608,14.988 0,7.77001 5.92001,14.16699 13.491,14.92501 C 501.785,399.108 406.823,496.27399 287.05499,507.427 c -0.061,-0.30099 -0.055,-0.616 -0.055,-0.932 0,-12.69401 -10.306,-23 -23,-23 -12.694,0 -23,10.30599 -23,23 0,0.316 0.006,0.63101 0.072,0.94299 z M 264,166.174 c -53.161,0 -96.321,43.16 -96.321,96.321 0,53.16101 43.16,96.32101 96.321,96.32101 53.16101,0 96.32101,-43.16 96.32101,-96.32101 0,-53.161 -43.16,-96.321 -96.32101,-96.321 z"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath45)"
id="path16" />
<path
d="M 36,262.495 H 168"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath44)"
id="path17" />
<path
d="M 91,436.147 195.65199,331.495"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath43)"
id="path18" />
<path
d="m 264,482.495 v -123"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath42)"
id="path19" />
<path
d="M 360,262.495 H 496"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath41)"
id="path20" />
<path
d="M 332.707,330.495 438.06601,435.854"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath40)"
id="path21" />
<path
d="M 264,165.49499 V 31.495001"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath39)"
id="path22" />
<path
d="m 86.444,275.495 15.983,-11.732 15.129,11.732"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.99749;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,-27.352712,-444.93573)"
clip-path="url(#clipPath38)"
id="path23" />
<path
d="M 250.5,82.939003 262.23199,98.921997 250.5,114.051"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.99749;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,-248.13901,165.44344)"
clip-path="url(#clipPath37)"
id="path24" />
<path
d="M 443.556,247.995 427.573,259.72699 412.444,247.995"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.99749;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,-27.352712,-444.93573)"
clip-path="url(#clipPath36)"
id="path25" />
<path
d="M 277.556,436.55099 265.82501,420.56799 277.556,405.439"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.99749;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,279.84067,-156.09696)"
clip-path="url(#clipPath35)"
id="path26" />
<path
d="m 34,263.495 c -4e-6,0.98489 -0.09608,1.96035 -0.288227,2.92633 -0.19215,0.96597 -0.476677,1.90396 -0.853584,2.8139 -0.376912,0.90994 -0.838959,1.77435 -1.386149,2.59329 -0.547188,0.81891 -1.169,1.5766 -1.86544,2.27304 -0.69644,0.69644 -1.454123,1.31824 -2.273051,1.86542 -0.818925,0.54718 -1.683359,1.00925 -2.593299,1.38617 -0.909943,0.37689 -1.847908,0.66141 -2.813898,0.85358 -0.965989,0.19217 -1.941439,0.28823 -2.926352,0.28827 -0.984915,-4e-5 -1.960365,-0.0961 -2.926355,-0.28827 -0.96599,-0.19217 -1.903956,-0.47669 -2.813897,-0.85358 -0.909942,-0.37692 -1.774376,-0.83899 -2.593302,-1.38617 C 9.8475189,275.4198 9.0898371,274.798 8.3933983,274.10156 7.696959,273.40512 7.0751448,272.64743 6.527956,271.82852 5.9807668,271.00958 5.5187168,270.14517 5.1418066,269.23523 4.7648959,268.32529 4.4803672,267.3873 4.2882204,266.42133 4.0960732,265.45535 3.9999998,264.47989 4,263.495 c -2e-7,-0.98493 0.096073,-1.96039 0.2882199,-2.9264 0.1921473,-0.96597 0.476676,-1.90393 0.8535867,-2.81387 0.3769102,-0.90994 0.8389602,-1.7744 1.3861494,-2.59332 0.5471888,-0.81893 1.169003,-1.5766 1.8654423,-2.27303 0.6964388,-0.69644 1.4541206,-1.31825 2.2730477,-1.86545 0.818926,-0.54719 1.68336,-1.00923 2.593302,-1.38613 0.909941,-0.37691 1.847907,-0.66143 2.813897,-0.85358 0.96599,-0.19216 1.94144,-0.28822 2.926355,-0.28822 0.984913,0 1.960363,0.0961 2.926352,0.28822 0.96599,0.19215 1.903955,0.47667 2.813896,0.85358 0.90994,0.3769 1.774376,0.83894 2.593301,1.38613 0.818928,0.5472 1.576611,1.16901 2.273051,1.86545 0.69644,0.69643 1.318252,1.4541 1.86544,2.27303 0.54719,0.81892 1.009237,1.68338 1.386149,2.59332 0.376907,0.90994 0.661434,1.8479 0.853584,2.81387 0.19215,0.96601 0.288223,1.94147 0.288227,2.9264 z"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath34)"
id="path27" />
<path
d="m 287,506.495 c 0,0.75326 -0.0369,1.50476 -0.11078,2.25442 -0.0738,0.74963 -0.1842,1.49384 -0.33118,2.23261 -0.14694,0.73883 -0.32977,1.46865 -0.54843,2.18948 -0.21866,0.72082 -0.47213,1.4292 -0.7604,2.12512 -0.28827,0.69598 -0.60996,1.3761 -0.96503,2.04047 -0.3551,0.6643 -0.74191,1.30963 -1.16043,1.93591 -0.41849,0.6264 -0.86667,1.23071 -1.34454,1.81305 -0.47788,0.58227 -0.98313,1.13971 -1.51578,1.67236 -0.53266,0.53266 -1.09012,1.03797 -1.6724,1.51581 -0.5823,0.47791 -1.18664,0.92609 -1.81298,1.34454 -0.62632,0.41852 -1.27164,0.8053 -1.93595,1.1604 -0.66434,0.35505 -1.34445,0.6767 -2.0404,0.96497 -0.69593,0.28827 -1.4043,0.54175 -2.12516,0.76038 -0.72085,0.21869 -1.45068,0.40155 -2.18948,0.54846 -0.7388,0.14703 -1.483,0.25744 -2.23267,0.33124 -0.74963,0.0738 -1.50109,0.11078 -2.25439,0.11078 -0.75327,0 -1.50473,-0.0369 -2.25436,-0.11078 -0.74967,-0.0738 -1.4939,-0.18421 -2.23273,-0.33124 -0.7388,-0.14691 -1.4686,-0.32977 -2.18945,-0.54846 -0.72086,-0.21863 -1.42925,-0.47211 -2.1252,-0.76038 -0.69594,-0.28827 -1.37609,-0.60992 -2.04041,-0.96497 -0.66432,-0.3551 -1.30966,-0.74188 -1.936,-1.1604 -0.62633,-0.41845 -1.23064,-0.86663 -1.81293,-1.34454 -0.58228,-0.47784 -1.13974,-0.98315 -1.67239,-1.51581 -0.53264,-0.53265 -1.03789,-1.09009 -1.51578,-1.67236 -0.47788,-0.58234 -0.92607,-1.18665 -1.34458,-1.81305 -0.41848,-0.62628 -0.80528,-1.27161 -1.16036,-1.93591 -0.35509,-0.66437 -0.67678,-1.34449 -0.96506,-2.04047 -0.28826,-0.69592 -0.5417,-1.4043 -0.76036,-2.12512 -0.21868,-0.72083 -0.40149,-1.45065 -0.54846,-2.18948 -0.14695,-0.73877 -0.25733,-1.48298 -0.33117,-2.23264 -0.0738,-0.74966 -0.11074,-1.50113 -0.11076,-2.25439 2e-5,-0.75327 0.0369,-1.50474 0.11076,-2.2544 0.0738,-0.74963 0.18422,-1.49387 0.33117,-2.23273 0.14697,-0.7388 0.32978,-1.46859 0.54844,-2.18945 0.21868,-0.72082 0.47212,-1.42923 0.76038,-2.12518 0.28828,-0.69596 0.60997,-1.37607 0.96506,-2.04038 0.35508,-0.66433 0.74188,-1.30966 1.16036,-1.936 0.41851,-0.62631 0.8667,-1.23059 1.34458,-1.8129 0.47789,-0.5823 0.98314,-1.13977 1.51578,-1.67242 0.53265,-0.53263 1.09011,-1.03791 1.67241,-1.51581 0.58229,-0.47788 1.18658,-0.92606 1.81291,-1.34458 0.62634,-0.41845 1.27168,-0.80523 1.936,-1.16033 0.66432,-0.35511 1.34447,-0.67679 2.04041,-0.96509 0.69595,-0.28824 1.40434,-0.54169 2.1252,-0.76035 0.72082,-0.21866 1.45062,-0.40146 2.18942,-0.54846 0.73883,-0.14694 1.48309,-0.25732 2.23276,-0.33115 0.74963,-0.0738 1.50109,-0.11074 2.25436,-0.11077 0.7533,3e-5 1.50476,0.0369 2.25439,0.11077 0.74967,0.0738 1.49387,0.18421 2.23267,0.33115 0.7388,0.147 1.46863,0.3298 2.18948,0.54846 0.72086,0.21866 1.42923,0.47211 2.12516,0.76035 0.69595,0.2883 1.37606,0.60998 2.0404,0.96509 0.66431,0.3551 1.30963,0.74188 1.93595,1.16033 0.62634,0.41852 1.23068,0.86673 1.81298,1.34461 0.58228,0.47787 1.13974,0.98315 1.6724,1.51578 0.53265,0.53265 1.0379,1.09012 1.51578,1.67239 0.47787,0.58231 0.92605,1.18659 1.34454,1.8129 0.41852,0.62634 0.80533,1.2717 1.1604,1.93603 0.3551,0.66431 0.67679,1.34442 0.96506,2.04038 0.28827,0.69595 0.54174,1.40436 0.7604,2.12515 0.21866,0.72086 0.40149,1.45068 0.54843,2.18948 0.14698,0.73886 0.25736,1.4831 0.33118,2.23273 0.0738,0.74966 0.11078,1.50113 0.11078,2.2544 z"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath33)"
id="path28" />
<path
d="m 279,16 c -3e-5,0.984915 -0.0961,1.960365 -0.28827,2.926353 -0.19217,0.965991 -0.47668,1.903956 -0.85358,2.813897 -0.37692,0.90994 -0.83898,1.774374 -1.38617,2.593299 -0.54718,0.818926 -1.16897,1.576611 -1.86541,2.273051 -0.69644,0.696438 -1.45413,1.31825 -2.27307,1.86544 -0.81891,0.54719 -1.68335,1.009239 -2.5933,1.386151 -0.90994,0.376911 -1.8479,0.661439 -2.81387,0.853588 C 265.96036,30.903925 264.98489,30.999998 264,31 c -0.98489,-2e-6 -1.96036,-0.09607 -2.92639,-0.288221 -0.96601,-0.192149 -1.90396,-0.476677 -2.81391,-0.853588 -0.90994,-0.376912 -1.77435,-0.838961 -2.5933,-1.386151 -0.81891,-0.54719 -1.57659,-1.169002 -2.27303,-1.86544 -0.69646,-0.69644 -1.31827,-1.454125 -1.86545,-2.273051 -0.54719,-0.818925 -1.00924,-1.683359 -1.38615,-2.593299 -0.37691,-0.909941 -0.66142,-1.847906 -0.85358,-2.813897 C 249.09605,17.960365 248.99998,16.984915 249,16 c -2e-5,-0.984915 0.096,-1.960367 0.28819,-2.926356 0.19216,-0.965989 0.47667,-1.903955 0.85358,-2.813896 0.37691,-0.9099422 0.83896,-1.7743764 1.38615,-2.5933023 0.54718,-0.8189263 1.16899,-1.5766086 1.86545,-2.2730479 0.69644,-0.6964393 1.45412,-1.3182535 2.27303,-1.8654425 0.81895,-0.547189 1.68336,-1.0092385 2.5933,-1.3861485 0.90995,-0.3769102 1.8479,-0.6614389 2.81391,-0.853586 C 262.03964,1.0960736 263.01511,1 264,1 c 0.98489,0 1.96036,0.096074 2.92633,0.2882208 0.96597,0.1921471 1.90393,0.4766758 2.81387,0.853586 0.90995,0.37691 1.77439,0.8389595 2.5933,1.3861485 0.81894,0.547189 1.57663,1.1690032 2.27307,1.8654425 0.69644,0.6964393 1.31823,1.4541216 1.86541,2.2730479 0.54719,0.8189268 1.00925,1.6833611 1.38617,2.5933033 0.3769,0.909941 0.66141,1.847907 0.85358,2.813896 C 278.9039,14.039634 278.99997,15.015085 279,16 Z"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath32)"
id="path29" />
<path
d="m 526,263.495 c 0,0.98489 -0.0961,1.96035 -0.28821,2.92633 -0.1922,0.96597 -0.47674,1.90396 -0.85364,2.8139 -0.37689,0.90994 -0.83892,1.77435 -1.3861,2.59329 -0.54718,0.81891 -1.16901,1.5766 -1.86548,2.27304 -0.69647,0.69644 -1.4541,1.31824 -2.27301,1.86542 -0.81897,0.54718 -1.68341,1.00925 -2.59333,1.38617 -0.90997,0.37689 -1.8479,0.66141 -2.8139,0.85358 -0.966,0.19217 -1.94144,0.28823 -2.92633,0.28827 -0.98492,-4e-5 -1.96039,-0.0961 -2.92642,-0.28827 -0.96601,-0.19217 -1.90396,-0.47669 -2.81391,-0.85358 -0.90994,-0.37692 -1.77438,-0.83899 -2.59329,-1.38617 -0.81894,-0.54718 -1.5766,-1.16898 -2.27301,-1.86542 -0.69644,-0.69644 -1.31827,-1.45413 -1.86548,-2.27304 -0.54718,-0.81894 -1.00921,-1.68335 -1.38614,-2.59329 -0.37692,-0.90994 -0.66143,-1.84793 -0.85357,-2.8139 -0.19214,-0.96598 -0.28821,-1.94144 -0.28818,-2.92633 -3e-5,-0.98493 0.096,-1.96039 0.28818,-2.9264 0.19214,-0.96597 0.47665,-1.90393 0.85357,-2.81387 0.37693,-0.90994 0.83896,-1.7744 1.38611,-2.59332 0.54721,-0.81893 1.16907,-1.5766 1.86551,-2.27303 0.69641,-0.69644 1.45407,-1.31825 2.27298,-1.86545 0.81894,-0.54719 1.68338,-1.00923 2.59332,-1.38613 0.90995,-0.37691 1.8479,-0.66143 2.81391,-0.85358 0.96603,-0.19216 1.9415,-0.28822 2.92642,-0.28822 0.98489,0 1.96033,0.0961 2.92633,0.28822 0.966,0.19215 1.90393,0.47667 2.8139,0.85358 0.90992,0.3769 1.77436,0.83894 2.59333,1.38613 0.81891,0.5472 1.57654,1.16901 2.27301,1.86545 0.69647,0.69643 1.3183,1.4541 1.86548,2.27303 0.54718,0.81892 1.00921,1.68338 1.3861,2.59332 0.3769,0.90994 0.66144,1.8479 0.85364,2.81387 0.19214,0.96601 0.28821,1.94147 0.28821,2.9264 z"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath31)"
id="path30" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -0,0 +1,355 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.1"
id="svg1"
width="560"
height="530.56"
viewBox="0 0 560 530.56"
sodipodi:docname="cercle_politique.svg"
inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"
inkscape:export-filename="cercle_politique.png"
inkscape:export-xdpi="149.987"
inkscape:export-ydpi="149.987"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1">
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath31">
<g
id="g32"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path32"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath32">
<g
id="g33"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path33"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath33">
<g
id="g34"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path34"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath34">
<g
id="g35"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path35"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath35">
<g
id="g36"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path36"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath36">
<g
id="g37"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path37"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath37">
<g
id="g38"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path38"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath38">
<g
id="g39"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path39"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath39">
<g
id="g40"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path40"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath40">
<g
id="g41"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path41"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath41">
<g
id="g42"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path42"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath42">
<g
id="g43"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path43"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath43">
<g
id="g44"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path44"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath44">
<g
id="g45"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path45"
style="stroke-width:0.320403" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath45">
<g
id="g46"
style="stroke-width:1.00126"
transform="scale(0.99874378)">
<path
d="M 0,0 H 530.66667 V 530.66667 H 0 Z"
clip-rule="evenodd"
id="path46"
style="stroke-width:0.320403" />
</g>
</clipPath>
</defs>
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="true"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="1.9390791"
inkscape:cx="171.98885"
inkscape:cy="238.25742"
inkscape:window-width="1920"
inkscape:window-height="1057"
inkscape:window-x="0"
inkscape:window-y="60"
inkscape:window-maximized="1"
inkscape:current-layer="g1">
<inkscape:page
x="0"
y="0"
inkscape:label="1"
id="page1"
width="560"
height="530.56"
margin="0"
bleed="0" />
</sodipodi:namedview>
<g
id="g1"
inkscape:groupmode="layer"
inkscape:label="1">
<path
d="M 241.07201,507.43799 C 121.31,496.34799 26.323,399.258 18.518,278.57901 c 0.159999,-0.087 0.321001,-0.084 0.482,-0.084 8.278999,0 15,-6.72101 15,-15 0,-8.279 -6.721001,-15 -15,-15 -0.205999,0 -0.410999,0.004 -0.615,0.012 C 25.372,124.203 124.825,24.43 248.998,16.945999 249.50101,24.768 256.02802,31 264,31 c 7.96201,0 14.483,-6.216 14.97101,-14.056 124.16,7.442999 223.65399,107.23 230.63699,231.563 -7.62601,0.754 -13.608,7.178 -13.608,14.988 0,7.77001 5.92001,14.16699 13.491,14.92501 C 501.785,399.108 406.823,496.27399 287.05499,507.427 c -0.061,-0.30099 -0.055,-0.616 -0.055,-0.932 0,-12.69401 -10.306,-23 -23,-23 -12.694,0 -23,10.30599 -23,23 0,0.316 0.006,0.63101 0.072,0.94299 z M 264,166.174 c -53.161,0 -96.321,43.16 -96.321,96.321 0,53.16101 43.16,96.32101 96.321,96.32101 53.16101,0 96.32101,-43.16 96.32101,-96.32101 0,-53.161 -43.16,-96.321 -96.32101,-96.321 z"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath45)"
id="path16" />
<path
d="M 36,262.495 H 168"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath44)"
id="path17" />
<path
d="M 91,436.147 195.65199,331.495"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath43)"
id="path18" />
<path
d="m 264,482.495 v -123"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath42)"
id="path19" />
<path
d="M 360,262.495 H 496"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath41)"
id="path20" />
<path
d="M 332.707,330.495 438.06601,435.854"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath40)"
id="path21" />
<path
d="M 264,165.49499 V 31.495001"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath39)"
id="path22" />
<path
d="m 86.444,275.495 15.983,-11.732 15.129,11.732"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.99749;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,-27.352712,-444.93573)"
clip-path="url(#clipPath38)"
id="path23" />
<path
d="M 250.5,82.939003 262.23199,98.921997 250.5,114.051"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.99749;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,-248.13901,165.44344)"
clip-path="url(#clipPath37)"
id="path24" />
<path
d="M 443.556,247.995 427.573,259.72699 412.444,247.995"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.99749;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,-27.352712,-444.93573)"
clip-path="url(#clipPath36)"
id="path25" />
<path
d="M 277.556,436.55099 265.82501,420.56799 277.556,405.439"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.99749;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,279.84067,-156.09696)"
clip-path="url(#clipPath35)"
id="path26" />
<path
d="m 34,263.495 c -4e-6,0.98489 -0.09608,1.96035 -0.288227,2.92633 -0.19215,0.96597 -0.476677,1.90396 -0.853584,2.8139 -0.376912,0.90994 -0.838959,1.77435 -1.386149,2.59329 -0.547188,0.81891 -1.169,1.5766 -1.86544,2.27304 -0.69644,0.69644 -1.454123,1.31824 -2.273051,1.86542 -0.818925,0.54718 -1.683359,1.00925 -2.593299,1.38617 -0.909943,0.37689 -1.847908,0.66141 -2.813898,0.85358 -0.965989,0.19217 -1.941439,0.28823 -2.926352,0.28827 -0.984915,-4e-5 -1.960365,-0.0961 -2.926355,-0.28827 -0.96599,-0.19217 -1.903956,-0.47669 -2.813897,-0.85358 -0.909942,-0.37692 -1.774376,-0.83899 -2.593302,-1.38617 C 9.8475189,275.4198 9.0898371,274.798 8.3933983,274.10156 7.696959,273.40512 7.0751448,272.64743 6.527956,271.82852 5.9807668,271.00958 5.5187168,270.14517 5.1418066,269.23523 4.7648959,268.32529 4.4803672,267.3873 4.2882204,266.42133 4.0960732,265.45535 3.9999998,264.47989 4,263.495 c -2e-7,-0.98493 0.096073,-1.96039 0.2882199,-2.9264 0.1921473,-0.96597 0.476676,-1.90393 0.8535867,-2.81387 0.3769102,-0.90994 0.8389602,-1.7744 1.3861494,-2.59332 0.5471888,-0.81893 1.169003,-1.5766 1.8654423,-2.27303 0.6964388,-0.69644 1.4541206,-1.31825 2.2730477,-1.86545 0.818926,-0.54719 1.68336,-1.00923 2.593302,-1.38613 0.909941,-0.37691 1.847907,-0.66143 2.813897,-0.85358 0.96599,-0.19216 1.94144,-0.28822 2.926355,-0.28822 0.984913,0 1.960363,0.0961 2.926352,0.28822 0.96599,0.19215 1.903955,0.47667 2.813896,0.85358 0.90994,0.3769 1.774376,0.83894 2.593301,1.38613 0.818928,0.5472 1.576611,1.16901 2.273051,1.86545 0.69644,0.69643 1.318252,1.4541 1.86544,2.27303 0.54719,0.81892 1.009237,1.68338 1.386149,2.59332 0.376907,0.90994 0.661434,1.8479 0.853584,2.81387 0.19215,0.96601 0.288223,1.94147 0.288227,2.9264 z"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath34)"
id="path27" />
<path
d="m 287,506.495 c 0,0.75326 -0.0369,1.50476 -0.11078,2.25442 -0.0738,0.74963 -0.1842,1.49384 -0.33118,2.23261 -0.14694,0.73883 -0.32977,1.46865 -0.54843,2.18948 -0.21866,0.72082 -0.47213,1.4292 -0.7604,2.12512 -0.28827,0.69598 -0.60996,1.3761 -0.96503,2.04047 -0.3551,0.6643 -0.74191,1.30963 -1.16043,1.93591 -0.41849,0.6264 -0.86667,1.23071 -1.34454,1.81305 -0.47788,0.58227 -0.98313,1.13971 -1.51578,1.67236 -0.53266,0.53266 -1.09012,1.03797 -1.6724,1.51581 -0.5823,0.47791 -1.18664,0.92609 -1.81298,1.34454 -0.62632,0.41852 -1.27164,0.8053 -1.93595,1.1604 -0.66434,0.35505 -1.34445,0.6767 -2.0404,0.96497 -0.69593,0.28827 -1.4043,0.54175 -2.12516,0.76038 -0.72085,0.21869 -1.45068,0.40155 -2.18948,0.54846 -0.7388,0.14703 -1.483,0.25744 -2.23267,0.33124 -0.74963,0.0738 -1.50109,0.11078 -2.25439,0.11078 -0.75327,0 -1.50473,-0.0369 -2.25436,-0.11078 -0.74967,-0.0738 -1.4939,-0.18421 -2.23273,-0.33124 -0.7388,-0.14691 -1.4686,-0.32977 -2.18945,-0.54846 -0.72086,-0.21863 -1.42925,-0.47211 -2.1252,-0.76038 -0.69594,-0.28827 -1.37609,-0.60992 -2.04041,-0.96497 -0.66432,-0.3551 -1.30966,-0.74188 -1.936,-1.1604 -0.62633,-0.41845 -1.23064,-0.86663 -1.81293,-1.34454 -0.58228,-0.47784 -1.13974,-0.98315 -1.67239,-1.51581 -0.53264,-0.53265 -1.03789,-1.09009 -1.51578,-1.67236 -0.47788,-0.58234 -0.92607,-1.18665 -1.34458,-1.81305 -0.41848,-0.62628 -0.80528,-1.27161 -1.16036,-1.93591 -0.35509,-0.66437 -0.67678,-1.34449 -0.96506,-2.04047 -0.28826,-0.69592 -0.5417,-1.4043 -0.76036,-2.12512 -0.21868,-0.72083 -0.40149,-1.45065 -0.54846,-2.18948 -0.14695,-0.73877 -0.25733,-1.48298 -0.33117,-2.23264 -0.0738,-0.74966 -0.11074,-1.50113 -0.11076,-2.25439 2e-5,-0.75327 0.0369,-1.50474 0.11076,-2.2544 0.0738,-0.74963 0.18422,-1.49387 0.33117,-2.23273 0.14697,-0.7388 0.32978,-1.46859 0.54844,-2.18945 0.21868,-0.72082 0.47212,-1.42923 0.76038,-2.12518 0.28828,-0.69596 0.60997,-1.37607 0.96506,-2.04038 0.35508,-0.66433 0.74188,-1.30966 1.16036,-1.936 0.41851,-0.62631 0.8667,-1.23059 1.34458,-1.8129 0.47789,-0.5823 0.98314,-1.13977 1.51578,-1.67242 0.53265,-0.53263 1.09011,-1.03791 1.67241,-1.51581 0.58229,-0.47788 1.18658,-0.92606 1.81291,-1.34458 0.62634,-0.41845 1.27168,-0.80523 1.936,-1.16033 0.66432,-0.35511 1.34447,-0.67679 2.04041,-0.96509 0.69595,-0.28824 1.40434,-0.54169 2.1252,-0.76035 0.72082,-0.21866 1.45062,-0.40146 2.18942,-0.54846 0.73883,-0.14694 1.48309,-0.25732 2.23276,-0.33115 0.74963,-0.0738 1.50109,-0.11074 2.25436,-0.11077 0.7533,3e-5 1.50476,0.0369 2.25439,0.11077 0.74967,0.0738 1.49387,0.18421 2.23267,0.33115 0.7388,0.147 1.46863,0.3298 2.18948,0.54846 0.72086,0.21866 1.42923,0.47211 2.12516,0.76035 0.69595,0.2883 1.37606,0.60998 2.0404,0.96509 0.66431,0.3551 1.30963,0.74188 1.93595,1.16033 0.62634,0.41852 1.23068,0.86673 1.81298,1.34461 0.58228,0.47787 1.13974,0.98315 1.6724,1.51578 0.53265,0.53265 1.0379,1.09012 1.51578,1.67239 0.47787,0.58231 0.92605,1.18659 1.34454,1.8129 0.41852,0.62634 0.80533,1.2717 1.1604,1.93603 0.3551,0.66431 0.67679,1.34442 0.96506,2.04038 0.28827,0.69595 0.54174,1.40436 0.7604,2.12515 0.21866,0.72086 0.40149,1.45068 0.54843,2.18948 0.14698,0.73886 0.25736,1.4831 0.33118,2.23273 0.0738,0.74966 0.11078,1.50113 0.11078,2.2544 z"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath33)"
id="path28" />
<path
d="m 279,16 c -3e-5,0.984915 -0.0961,1.960365 -0.28827,2.926353 -0.19217,0.965991 -0.47668,1.903956 -0.85358,2.813897 -0.37692,0.90994 -0.83898,1.774374 -1.38617,2.593299 -0.54718,0.818926 -1.16897,1.576611 -1.86541,2.273051 -0.69644,0.696438 -1.45413,1.31825 -2.27307,1.86544 -0.81891,0.54719 -1.68335,1.009239 -2.5933,1.386151 -0.90994,0.376911 -1.8479,0.661439 -2.81387,0.853588 C 265.96036,30.903925 264.98489,30.999998 264,31 c -0.98489,-2e-6 -1.96036,-0.09607 -2.92639,-0.288221 -0.96601,-0.192149 -1.90396,-0.476677 -2.81391,-0.853588 -0.90994,-0.376912 -1.77435,-0.838961 -2.5933,-1.386151 -0.81891,-0.54719 -1.57659,-1.169002 -2.27303,-1.86544 -0.69646,-0.69644 -1.31827,-1.454125 -1.86545,-2.273051 -0.54719,-0.818925 -1.00924,-1.683359 -1.38615,-2.593299 -0.37691,-0.909941 -0.66142,-1.847906 -0.85358,-2.813897 C 249.09605,17.960365 248.99998,16.984915 249,16 c -2e-5,-0.984915 0.096,-1.960367 0.28819,-2.926356 0.19216,-0.965989 0.47667,-1.903955 0.85358,-2.813896 0.37691,-0.9099422 0.83896,-1.7743764 1.38615,-2.5933023 0.54718,-0.8189263 1.16899,-1.5766086 1.86545,-2.2730479 0.69644,-0.6964393 1.45412,-1.3182535 2.27303,-1.8654425 0.81895,-0.547189 1.68336,-1.0092385 2.5933,-1.3861485 0.90995,-0.3769102 1.8479,-0.6614389 2.81391,-0.853586 C 262.03964,1.0960736 263.01511,1 264,1 c 0.98489,0 1.96036,0.096074 2.92633,0.2882208 0.96597,0.1921471 1.90393,0.4766758 2.81387,0.853586 0.90995,0.37691 1.77439,0.8389595 2.5933,1.3861485 0.81894,0.547189 1.57663,1.1690032 2.27307,1.8654425 0.69644,0.6964393 1.31823,1.4541216 1.86541,2.2730479 0.54719,0.8189268 1.00925,1.6833611 1.38617,2.5933033 0.3769,0.909941 0.66141,1.847907 0.85358,2.813896 C 278.9039,14.039634 278.99997,15.015085 279,16 Z"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath32)"
id="path29" />
<path
d="m 526,263.495 c 0,0.98489 -0.0961,1.96035 -0.28821,2.92633 -0.1922,0.96597 -0.47674,1.90396 -0.85364,2.8139 -0.37689,0.90994 -0.83892,1.77435 -1.3861,2.59329 -0.54718,0.81891 -1.16901,1.5766 -1.86548,2.27304 -0.69647,0.69644 -1.4541,1.31824 -2.27301,1.86542 -0.81897,0.54718 -1.68341,1.00925 -2.59333,1.38617 -0.90997,0.37689 -1.8479,0.66141 -2.8139,0.85358 -0.966,0.19217 -1.94144,0.28823 -2.92633,0.28827 -0.98492,-4e-5 -1.96039,-0.0961 -2.92642,-0.28827 -0.96601,-0.19217 -1.90396,-0.47669 -2.81391,-0.85358 -0.90994,-0.37692 -1.77438,-0.83899 -2.59329,-1.38617 -0.81894,-0.54718 -1.5766,-1.16898 -2.27301,-1.86542 -0.69644,-0.69644 -1.31827,-1.45413 -1.86548,-2.27304 -0.54718,-0.81894 -1.00921,-1.68335 -1.38614,-2.59329 -0.37692,-0.90994 -0.66143,-1.84793 -0.85357,-2.8139 -0.19214,-0.96598 -0.28821,-1.94144 -0.28818,-2.92633 -3e-5,-0.98493 0.096,-1.96039 0.28818,-2.9264 0.19214,-0.96597 0.47665,-1.90393 0.85357,-2.81387 0.37693,-0.90994 0.83896,-1.7744 1.38611,-2.59332 0.54721,-0.81893 1.16907,-1.5766 1.86551,-2.27303 0.69641,-0.69644 1.45407,-1.31825 2.27298,-1.86545 0.81894,-0.54719 1.68338,-1.00923 2.59332,-1.38613 0.90995,-0.37691 1.8479,-0.66143 2.81391,-0.85358 0.96603,-0.19216 1.9415,-0.28822 2.92642,-0.28822 0.98489,0 1.96033,0.0961 2.92633,0.28822 0.966,0.19215 1.90393,0.47667 2.8139,0.85358 0.90992,0.3769 1.77436,0.83894 2.59333,1.38613 0.81891,0.5472 1.57654,1.16901 2.27301,1.86545 0.69647,0.69643 1.3183,1.4541 1.86548,2.27303 0.54718,0.81892 1.00921,1.68338 1.3861,2.59332 0.3769,0.90994 0.66144,1.8479 0.85364,2.81387 0.19214,0.96601 0.28821,1.94147 0.28821,2.9264 z"
style="opacity:0.749;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.998744;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.0012578,0,0,1.0012578,16,0)"
clip-path="url(#clipPath31)"
id="path30" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -11,12 +11,13 @@ $pad_btn: 0.5em;
span.icon{ span.icon{
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: middle center; background-position: center;
background-size: contain; background-size: 75%;
display: inline-block; display: inline-block;
vertical-align:bottom; vertical-align:bottom;
width: 2em; width: 1.5em;
height:2em; height:1.5em;
border-radius: 0.75em;
&.terraindevie{ &.terraindevie{
background-image: url('./icons/terraindevie.svg'); background-image: url('./icons/terraindevie.svg');
} }

View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="35px"
height="35px"
viewBox="0 0 35 35"
version="1.1"
id="svg6251"
sodipodi:docname="action_2.svg"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs6255" />
<sodipodi:namedview
id="namedview6253"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="20.296452"
inkscape:cx="12.834756"
inkscape:cy="21.998919"
inkscape:window-width="1920"
inkscape:window-height="1170"
inkscape:window-x="1920"
inkscape:window-y="16"
inkscape:window-maximized="0"
inkscape:current-layer="svg6251" />
<g
id="g7491"
transform="translate(0.00940843)">
<circle
class="circle-fill"
fill="#000000"
cx="17.5"
cy="17.5"
r="2.5"
id="circle6224"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" />
<line
class="thin"
x1="17.5"
y1="11"
x2="17.5"
y2="24"
id="line6226"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" />
<line
class="thin"
x1="22.096193"
y1="12.903806"
x2="12.903806"
y2="22.096193"
id="line6228"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" />
<line
class="thin"
x1="24"
y1="17.5"
x2="11"
y2="17.5"
id="line6230"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" />
<line
class="thin"
x1="22.096193"
y1="22.096193"
x2="12.903806"
y2="12.903806"
id="line6232"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -5,7 +5,7 @@
viewBox="0 0 35 35" viewBox="0 0 35 35"
version="1.1" version="1.1"
id="svg5344" id="svg5344"
sodipodi:docname="doleance.svg" sodipodi:docname="doleancer.svg"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)" inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
@ -20,17 +20,17 @@
borderopacity="1.0" borderopacity="1.0"
inkscape:showpageshadow="2" inkscape:showpageshadow="2"
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0" inkscape:pagecheckerboard="true"
inkscape:deskcolor="#d1d1d1" inkscape:deskcolor="#d1d1d1"
showgrid="false" showgrid="false"
inkscape:zoom="25.8" inkscape:zoom="11.819053"
inkscape:cx="14.903101" inkscape:cx="9.856966"
inkscape:cy="17.53876" inkscape:cy="4.6111987"
inkscape:window-width="1920" inkscape:window-width="1920"
inkscape:window-height="1026" inkscape:window-height="1170"
inkscape:window-x="0" inkscape:window-x="1920"
inkscape:window-y="30" inkscape:window-y="16"
inkscape:window-maximized="1" inkscape:window-maximized="0"
inkscape:current-layer="svg5344" /> inkscape:current-layer="svg5344" />
<circle <circle
class="thick" class="thick"
@ -39,39 +39,71 @@
cy="17.5" cy="17.5"
r="17" r="17"
id="circle5315" id="circle5315"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" /> style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1;fill:none" />
<line <line
class="thin" class="thin"
x1="17.5" x1="17.5"
y1="0" y1="0"
x2="17.5" x2="17.5"
y2="35" y2="9.5"
id="line5317" id="line5317"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" /> style="stroke:#000000;stroke-width:0.749999;stroke-dasharray:none;stroke-opacity:1" />
<line <line
class="thin" class="thin"
x1="29.874369" x1="17.5"
y1="5.1256313" y1="25.658915"
x2="5.1256313" x2="17.5"
y2="29.874369" y2="35.158916"
id="line5319" id="line5317-7"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" /> style="stroke:#000000;stroke-width:0.749999;stroke-dasharray:none;stroke-opacity:1" />
<line <line
class="thin" class="thin"
x1="35" x1="9.5"
y1="17.5" y1="17.5"
x2="0" x2="0"
y2="17.5" y2="17.5"
id="line5321" id="line5321"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" /> style="stroke:#000000;stroke-width:0.749999;stroke-dasharray:none;stroke-opacity:1" />
<line <line
class="thin" class="thin"
x1="29.874369" x1="11.866509"
y1="29.874369" y1="11.866509"
x2="5.1256313" x2="5.1489959"
y2="5.1256313" y2="5.1489949"
id="line5323" id="line5321-3"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" /> style="stroke:#000000;stroke-width:0.749999;stroke-dasharray:none;stroke-opacity:1" />
<line
class="thin"
x1="29.870384"
y1="29.870384"
x2="23.15287"
y2="23.15287"
id="line5321-3-5"
style="stroke:#000000;stroke-width:0.749999;stroke-dasharray:none;stroke-opacity:1" />
<line
class="thin"
x1="29.870384"
y1="5.1296153"
x2="23.15287"
y2="11.84713"
id="line5321-3-5-6"
style="stroke:#000000;stroke-width:0.749999;stroke-dasharray:none;stroke-opacity:1" />
<line
class="thin"
x1="11.866508"
y1="23.133492"
x2="5.1489949"
y2="29.851006"
id="line5321-3-5-6-2"
style="stroke:#000000;stroke-width:0.749999;stroke-dasharray:none;stroke-opacity:1" />
<line
class="thin"
x1="34.810078"
y1="17.5"
x2="25.310078"
y2="17.5"
id="line5321-5"
style="stroke:#000000;stroke-width:0.749999;stroke-dasharray:none;stroke-opacity:1" />
<circle <circle
class="thin" class="thin"
fill="#ffffff" fill="#ffffff"
@ -79,61 +111,33 @@
cy="17.5" cy="17.5"
r="8" r="8"
id="circle5325" id="circle5325"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" /> style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1;fill:none" />
<path <path
class="thin" class="thin"
fill="none" fill="none"
d="m 3.5,22.5 2,-3 2,3" d="m 3.5,21.737498 2,-3 2,3"
transform-origin="center" transform-origin="center"
id="path5327" id="path5327"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" /> style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" />
<path <path
class="thin" class="thin"
fill="none" fill="none"
d="m -13.435029,18.384776 3.5355343,-0.707106 -0.7071063,3.535534" d="M 31.841686,13.344229 29.81831,16.328513 27.841808,13.312979"
transform-origin="center"
id="path5329"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" />
<path
class="thin"
fill="none"
d="m -22.5,3.5 3,2 -3,2"
transform-origin="center"
id="path5331"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" />
<path
class="thin"
fill="none"
d="m -18.384776,-13.435029 0.707106,3.535534 -3.535534,-0.707107"
transform-origin="center"
id="path5333"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" />
<path
class="thin"
fill="none"
d="m -3.5,-22.5 -2,3 -2,-3"
transform-origin="center"
id="path5335"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" />
<path
class="thin"
fill="none"
d="m 13.435029,-18.384776 -3.535534,0.707107 0.707107,-3.535534"
transform-origin="center"
id="path5337"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" />
<path
class="thin"
fill="none"
d="m 22.5,-3.5 -3,-2 3,-2"
transform-origin="center"
id="path5339"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" />
<path
class="thin"
fill="none"
d="M 31.841686,13.177822 29.81831,16.162106 27.841808,13.146572"
transform-origin="center" transform-origin="center"
id="path5341" id="path5341"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" /> style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" />
<path
class="thin"
fill="none"
d="m 13.294665,3.4773346 2.999999,2 -2.999999,2"
transform-origin="center"
id="path5327-9"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" />
<path
class="thin"
fill="none"
d="m 21.687933,31.819021 -2.984284,-2.023376 3.015534,-1.976502"
transform-origin="center"
id="path5341-1"
style="stroke:#000000;stroke-width:0.75;stroke-dasharray:none;stroke-opacity:1" />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -20,27 +20,27 @@
borderopacity="1.0" borderopacity="1.0"
inkscape:showpageshadow="2" inkscape:showpageshadow="2"
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0" inkscape:pagecheckerboard="true"
inkscape:deskcolor="#d1d1d1" inkscape:deskcolor="#d1d1d1"
showgrid="false" showgrid="false"
inkscape:zoom="25.8" inkscape:zoom="25.8"
inkscape:cx="14.903101" inkscape:cx="12.344961"
inkscape:cy="17.53876" inkscape:cy="17.577519"
inkscape:window-width="1920" inkscape:window-width="1920"
inkscape:window-height="1026" inkscape:window-height="1170"
inkscape:window-x="0" inkscape:window-x="1920"
inkscape:window-y="30" inkscape:window-y="16"
inkscape:window-maximized="1" inkscape:window-maximized="0"
inkscape:current-layer="svg4457" /> inkscape:current-layer="svg4457" />
<g <g
id="picto" id="picto"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none"> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none;fill:none">
<path <path
class="thick" class="thick"
fill="white" fill="white"
d="M 4, 4 L 13, 1 L 19, 5 L 28, 3 L 34, 12 L 29, 22 L 27, 29 L 21, 34 L 14, 31 L 12, 23 L 4, 17 L 1, 12 Z" d="M 4, 4 L 13, 1 L 19, 5 L 28, 3 L 34, 12 L 29, 22 L 27, 29 L 21, 34 L 14, 31 L 12, 23 L 4, 17 L 1, 12 Z"
id="path4446" id="path4446"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" /> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none;fill:none" />
<circle <circle
class="circle-fill" class="circle-fill"
fill="black" fill="black"
@ -48,24 +48,24 @@
cy="17.5" cy="17.5"
r="2.5" r="2.5"
id="circle4448" id="circle4448"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" /> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none;fill:none" />
<path <path
class="thin" class="thin"
fill="none" fill="none"
d="M 7, 7 L 11, 5 L 15, 7 L 12, 12 L 12, 15 L 9, 16 L 5, 12 Z" d="M 7, 7 L 11, 5 L 15, 7 L 12, 12 L 12, 15 L 9, 16 L 5, 12 Z"
id="path4450" id="path4450"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" /> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none;fill:none" />
<path <path
class="thin" class="thin"
fill="none" fill="none"
d="M 20, 11 L 22, 9 L 24, 9 L 27, 7 L 29, 11 L 26, 15 L 24, 16 L 21, 14 Z" d="M 20, 11 L 22, 9 L 24, 9 L 27, 7 L 29, 11 L 26, 15 L 24, 16 L 21, 14 Z"
id="path4452" id="path4452"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" /> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none;fill:none" />
<path <path
class="thin" class="thin"
fill="none" fill="none"
d="M 18, 23 L 22, 22 L 24, 25 L 22, 28 L 20, 29 L 17, 27 Z" d="M 18, 23 L 22, 22 L 24, 25 L 22, 28 L 20, 29 L 17, 27 Z"
id="path4454" id="path4454"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" /> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none;fill:none" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -5,7 +5,7 @@
viewBox="0 0 35 35" viewBox="0 0 35 35"
version="1.1" version="1.1"
id="svg3586" id="svg3586"
sodipodi:docname="puissance-d-agir.svg" sodipodi:docname="puissancedagir.svg"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)" inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
@ -20,21 +20,21 @@
borderopacity="1.0" borderopacity="1.0"
inkscape:showpageshadow="2" inkscape:showpageshadow="2"
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0" inkscape:pagecheckerboard="true"
inkscape:deskcolor="#d1d1d1" inkscape:deskcolor="#d1d1d1"
showgrid="false" showgrid="false"
inkscape:zoom="25.8" inkscape:zoom="25.8"
inkscape:cx="14.903101" inkscape:cx="12.344961"
inkscape:cy="17.53876" inkscape:cy="17.577519"
inkscape:window-width="1920" inkscape:window-width="1920"
inkscape:window-height="1026" inkscape:window-height="1170"
inkscape:window-x="0" inkscape:window-x="1920"
inkscape:window-y="30" inkscape:window-y="16"
inkscape:window-maximized="1" inkscape:window-maximized="0"
inkscape:current-layer="svg3586" /> inkscape:current-layer="svg3586" />
<g <g
id="picto" id="picto"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none"> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none;fill:none">
<circle <circle
class="thick" class="thick"
fill="white" fill="white"
@ -42,7 +42,7 @@
cy="17.5" cy="17.5"
r="17" r="17"
id="circle3571" id="circle3571"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" /> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none;fill:none" />
<circle <circle
class="thin" class="thin"
fill="none" fill="none"
@ -50,7 +50,7 @@
cy="17.5" cy="17.5"
r="9.3" r="9.3"
id="circle3573" id="circle3573"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" /> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none;fill:none" />
<circle <circle
class="circle-fill" class="circle-fill"
fill="black" fill="black"
@ -58,7 +58,7 @@
cy="17.5" cy="17.5"
r="2.5" r="2.5"
id="circle3575" id="circle3575"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" /> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none;fill:none" />
<line <line
class="thin" class="thin"
x1="17.5" x1="17.5"
@ -66,7 +66,7 @@
x2="17.5" x2="17.5"
y2="35" y2="35"
id="line3577" id="line3577"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" /> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none;fill:none" />
<line <line
class="thin" class="thin"
x1="17.5" x1="17.5"
@ -75,7 +75,7 @@
y2="35" y2="35"
transform="rotate(45, 17.5, 17.5)" transform="rotate(45, 17.5, 17.5)"
id="line3579" id="line3579"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" /> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none;fill:none" />
<line <line
class="thin" class="thin"
x1="17.5" x1="17.5"
@ -84,7 +84,7 @@
y2="35" y2="35"
transform="rotate(90, 17.5, 17.5)" transform="rotate(90, 17.5, 17.5)"
id="line3581" id="line3581"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" /> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none;fill:none" />
<line <line
class="thin" class="thin"
x1="17.5" x1="17.5"
@ -93,6 +93,6 @@
y2="35" y2="35"
transform="rotate(135, 17.5, 17.5)" transform="rotate(135, 17.5, 17.5)"
id="line3583" id="line3583"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" /> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none;fill:none" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -20,18 +20,22 @@
borderopacity="1.0" borderopacity="1.0"
inkscape:showpageshadow="2" inkscape:showpageshadow="2"
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0" inkscape:pagecheckerboard="true"
inkscape:deskcolor="#d1d1d1" inkscape:deskcolor="#d1d1d1"
showgrid="false" showgrid="false"
inkscape:zoom="25.8" inkscape:zoom="28.934453"
inkscape:cx="14.903101" inkscape:cx="18.9912"
inkscape:cy="17.53876" inkscape:cy="14.498287"
inkscape:window-width="1920" inkscape:window-width="1920"
inkscape:window-height="1026" inkscape:window-height="1146"
inkscape:window-x="0" inkscape:window-x="1920"
inkscape:window-y="30" inkscape:window-y="30"
inkscape:window-maximized="1" inkscape:window-maximized="1"
inkscape:current-layer="svg1973" /> inkscape:current-layer="picto">
<inkscape:grid
type="xygrid"
id="grid1365" />
</sodipodi:namedview>
<g <g
id="picto" id="picto"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none"> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none">
@ -39,32 +43,17 @@
class="thick" class="thick"
d="M 12, 13 L 21, 13 L 31, 22 L 22, 32 L 8, 26 Z" d="M 12, 13 L 21, 13 L 31, 22 L 22, 32 L 8, 26 Z"
id="path1952" id="path1952"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" /> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none;fill:none" />
<path <path
class="thick" class="thick"
d="M 1, 11 L 9, 2 L 25, 9 L 21, 23 L 3, 20 Z" d="M 1, 11 L 9, 2 L 25, 9 L 21, 23 L 3, 20 Z"
id="path1954" id="path1954"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" /> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none;fill:none" />
<path <path
class="thick" class="thick"
d="M 21, 2 L 30, 6 L 33, 13 L 25, 24 L 18, 27 L 7, 12 Z" d="M 21, 2 L 30, 6 L 33, 13 L 25, 24 L 18, 27 L 7, 12 Z"
id="path1956" id="path1956"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" /> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none;fill:none" />
<path
fill="white"
d="M 12, 13 L 21, 13 L 31, 22 L 22, 32 L 8, 26 Z"
id="path1958"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" />
<path
fill="white"
d="M 1, 11 L 9, 2 L 25, 9 L 21, 23 L 3, 20 Z"
id="path1960"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" />
<path
fill="white"
d="M 21, 2 L 30, 6 L 33, 13 L 25, 24 L 18, 27 L 7, 12 Z"
id="path1962"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" />
<circle <circle
class="circle-fill" class="circle-fill"
fill="black" fill="black"

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -5,7 +5,7 @@
viewBox="0 0 35 35" viewBox="0 0 35 35"
version="1.1" version="1.1"
id="svg13" id="svg13"
sodipodi:docname="terrain-de-vie.svg" sodipodi:docname="terraindevie.svg"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)" inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
@ -20,18 +20,18 @@
borderopacity="1.0" borderopacity="1.0"
inkscape:showpageshadow="2" inkscape:showpageshadow="2"
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0" inkscape:pagecheckerboard="true"
inkscape:deskcolor="#d1d1d1" inkscape:deskcolor="#d1d1d1"
showgrid="false" showgrid="false"
inkscape:zoom="1.7479522" inkscape:zoom="32.684168"
inkscape:cx="-20.881578" inkscape:cx="17.347848"
inkscape:cy="62.644733" inkscape:cy="23.910659"
inkscape:window-width="1920" inkscape:window-width="1920"
inkscape:window-height="1026" inkscape:window-height="1170"
inkscape:window-x="0" inkscape:window-x="1920"
inkscape:window-y="30" inkscape:window-y="16"
inkscape:window-maximized="1" inkscape:window-maximized="0"
inkscape:current-layer="svg13" /> inkscape:current-layer="picto" />
<g <g
id="picto" id="picto"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none"> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none">
@ -42,31 +42,46 @@
cy="17.5" cy="17.5"
r="17" r="17"
id="circle2" id="circle2"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" /> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none;fill:none" />
<line <line
class="thin" class="thin"
x1="17.5" x1="17.5"
y1="0" y1="0"
x2="17.5" x2="17.5"
y2="35" y2="9.666667"
id="line4" id="line4"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" /> style="stroke:#000000;stroke-width:0.750001;stroke-dasharray:none;stroke-opacity:1" />
<line <line
class="thin" class="thin"
x1="17.5" x1="17.5"
y1="0" y1="26.714285"
x2="17.5" x2="17.5"
y2="35" y2="35.061226"
transform="rotate(90, 17.5, 17.5)" id="line4-6"
style="stroke:#000000;stroke-width:0.750001;stroke-dasharray:none;stroke-opacity:1" />
<line
class="thin"
x1="7.3333335"
y1="17.5"
x2="-5.0000001e-08"
y2="17.5"
id="line6" id="line6"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" /> style="stroke:#000000;stroke-width:0.749999;stroke-dasharray:none;stroke-opacity:1" />
<line
class="thin"
x1="35.022579"
y1="17.5"
x2="27.000002"
y2="17.5"
id="line6-3"
style="stroke:#000000;stroke-width:0.749999;stroke-dasharray:none;stroke-opacity:1" />
<path <path
class="thick" class="thick"
fill="white" fill="white"
d="M 9, 12 L 21, 8 L 27, 14 L 27, 21 L 19, 26 L 12, 27 L 6, 21 Z" d="M 9, 12 L 21, 8 L 27, 14 L 27, 21 L 19, 26 L 12, 27 L 6, 21 Z"
transform="translate(0 0.5)" transform="translate(0 0.5)"
id="path8" id="path8"
style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none" /> style="stroke:#000000;stroke-opacity:1;stroke-width:0.75;stroke-dasharray:none;fill:none" />
<path <path
class="thin" class="thin"
fill="none" fill="none"

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -41,7 +41,7 @@ html,body{
height:100vh; height:100vh;
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: hidden;
// padding: 1rem 0; // padding: 1rem 0;
#map-backgrounds{ #map-backgrounds{
@ -97,5 +97,12 @@ html,body{
padding: 0.5rem; padding: 0.5rem;
} }
#recit-player{
box-sizing: border-box;
position: absolute;
bottom: 0; right: 0;
padding: 0.5rem;
z-index: 100;
}
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,9 @@
<script> <script>
// import { RouterLink, RouterView } from 'vue-router' // import { RouterLink, RouterView } from 'vue-router'
import SvgIcon from '@jamescoyle/vue-icon';
import { mdiHeadphones } from '@mdi/js';
import { mapState, mapActions } from 'pinia' import { mapState, mapActions } from 'pinia'
// import { UserStore } from '@/stores/user' // import { UserStore } from '@/stores/user'
import { ConcernementsStore } from '@/stores/concernements' import { ConcernementsStore } from '@/stores/concernements'
@ -13,55 +16,77 @@ export default {
dom: null, dom: null,
type: null, type: null,
concernement: null, concernement: null,
entite: null, entites: null,
entite_parent: null,
besoin: null, besoin: null,
reponse: null reponse: null,
superposition: null,
headphones_path: mdiHeadphones
} }
}, },
created () { created () {
// console.log(`popup created type: ${this.infos.type}`, this.infos); // console.log(`popup created type: ${this.infos.type}`, this.infos);
if (this.infos.type === 'concernement') { this.parseInfos()
this.concernement = this.concernementsByID[this.infos.id];
} else if(this.infos.type === 'entite') {
this.entite = this.allEntitesById[this.infos.id];
} else if (this.infos.type === 'besoin') {
this.besoin = this.allBesoinsById[this.infos.id];
} else if (this.infos.type === 'reponse') {
for (let i = 0; i < this.allBesoinsById[this.infos.bid].reponses.length; i++) {
if (this.allBesoinsById[this.infos.bid].reponses[i].id === this.infos.id) {
this.reponse = this.allBesoinsById[this.infos.bid].reponses[i][this.infos.field];
}
}
}
}, },
mounted () { mounted () {
// console.log('APP onMounted') // console.log('APP onMounted')
this.dom = this.$refs['map-popup']; this.dom = this.$refs['map-popup'];
window.addEventListener('mousemove', this.onMousemove); window.addEventListener('mousemove', this.onMousemove);
}, },
beforeUnmount () {
window.removeEventListener('mousemove', this.onMousemove);
},
computed: { computed: {
...mapState(ConcernementsStore,['concernements']), ...mapState(ConcernementsStore,['concernements',
...mapState(ConcernementsStore,['concernementsByID']), 'concernementsByID',
...mapState(ConcernementsStore,['allEntitesById']), 'allEntitesById',
...mapState(ConcernementsStore,['allBesoinsById']) 'allBesoinsById'])
}, },
watch: { watch: {
infos: { infos: {
handler (n, o){ handler (n, o){
if (n.type === 'concernement') { this.parseInfos()
this.concernement = this.concernementsByID[n.id];
} else if(n.type === 'entite') {
this.entite = this.allEntitesById[this.infos.id];
} else if (n.type === 'besoin') {
} else if (n.type === 'reponse') {
}
}, },
deep: true deep: true
}, },
}, },
methods: { methods: {
parseInfos(){
console.log('mapPopup infos', this.infos);
switch (this.infos.type) {
case 'concernement':
this.concernement = this.concernementsByID[this.infos.cid];
break;
case 'entite':
case 'entite_inactive':
case 'entite_proximite':
case 'entite_superpose':
case 'entite_action':
this.entites = [this.allEntitesById[this.infos.id]];
break;
case 'entite_proximite_reference':
this.entites = [this.allEntitesById[this.infos.id]];
this.concernement = this.concernementsByID[this.infos.ref_cid];
this.entite_parent = this.allEntitesById[this.infos.parent_eid];
break;
case 'besoin':
this.besoin = this.allBesoinsById[this.infos.id];
break;
case 'reponse':
this.besoin = this.allBesoinsById[this.infos.id];
for (let i = 0; i < this.allBesoinsById[this.infos.bid].reponses.length; i++) {
if (this.allBesoinsById[this.infos.bid].reponses[i].id === this.infos.id) {
this.reponse = this.allBesoinsById[this.infos.bid].reponses[i];
break;
}
}
break;
case 'superposition':
this.concernement = this.concernementsByID[this.infos.cid];
this.entites = [this.allEntitesById[this.infos.eid]];
break;
}
},
onMousemove(e){ onMousemove(e){
// console.log(`popup move type: ${this.infos.type}`); // console.log(`popup move type: ${this.infos.type}`);
let v = "top"; let v = "top";
@ -93,9 +118,17 @@ export default {
this.dom.style.top = `${e.clientY+2}px`; this.dom.style.top = `${e.clientY+2}px`;
break; break;
} }
},
truncate( str, n, useWordBoundary ){
if (str.length <= n) { return str; }
const subString = str.slice(0, n-1); // the original check
return (useWordBoundary
? subString.slice(0, subString.lastIndexOf(" "))
: subString) + " &hellip;";
} }
}, },
components: { components: {
SvgIcon
} }
} }
@ -105,28 +138,57 @@ export default {
<div id="map-popup" ref="map-popup"> <div id="map-popup" ref="map-popup">
<div class="popup-content-wrapper"> <div class="popup-content-wrapper">
<section v-if="infos.type === 'concernement'" class="concernement-map-popup"> <section v-if="infos.type === 'concernement' || infos.type === 'superposition'" class="concernement-map-popup">
<div class="concernement-map-popup-content">
<h1>{{ concernement.title }}</h1> <h1>{{ concernement.title }}</h1>
<ul class="icons"> <div class="author info">
<span>une enquête de</span> {{ concernement.author.username }}<br/>
</div>
<ul class="icons" v-if="concernement.has_puissancedagir || concernement.has_proximite || concernement.has_superposition || concernement.has_agissantes || concernement.has_doleance">
<li v-if="concernement.has_puissancedagir" ><span class="icon puissancedagir"></span></li> <li v-if="concernement.has_puissancedagir" ><span class="icon puissancedagir"></span></li>
<li v-if="concernement.has_proximite" ><span class="icon proximite"></span></li> <li v-if="concernement.has_proximite" ><span class="icon proximite"></span></li>
<li v-if="concernement.has_superposition" ><span class="icon superposition"></span></li> <li v-if="concernement.has_superposition" ><span class="icon superposition"></span></li>
<li v-if="concernement.has_agissantes" ><span class="icon action"></span></li> <li v-if="concernement.has_agissantes" ><span class="icon action"></span></li>
<li v-if="concernement.has_doleance" ><span class="icon doleancer"></span></li> <li v-if="concernement.has_doleance" ><span class="icon doleancer"></span></li>
</ul> </ul>
</div>
<div v-if="(infos.type === 'concernement' || infos.type === 'superposition') && concernement.has_recit" class="concernement-map-popup-recit">
<svg-icon type="mdi" :path="headphones_path"></svg-icon>
</div>
</section> </section>
<section v-if="infos.type === 'entite'" class="entite-map-popup">
<h1>{{ entite.entite.title }}</h1> <section v-if="infos.type === 'entite' || infos.type === 'entite_inactive' || infos.type === 'entite_action' || infos.type === 'superposition' || infos.type === 'entite_superpose' || infos.type === 'entite_proximite'" class="entite-map-popup">
<template
v-for="(entite, index) of entites"
:key="index"
>
<h1><span class="point">&bull;</span> {{ entite.entite.title }}</h1>
</template>
</section> </section>
<section v-if="infos.type === 'entite_proximite_reference'" class="entite-proximite-reference-map-popup">
<h1 class="parent-entite"><span class="point">&bull;</span> {{ entite_parent.entite.title }}</h1>
<div class="conjunction">entité a proximité</div>
<h1 class="ref-entite"><span class="point">&bull;</span> {{ entites[0].entite.title }}</h1>
<!-- <h2>{{ concernement.title }}</h2> -->
</section>
<section v-if="infos.type === 'besoin'" class="besoin-map-popup"> <section v-if="infos.type === 'besoin'" class="besoin-map-popup">
<div v-html="besoin.description"></div> <div v-html="besoin.description"></div>
</section> </section>
<section v-if="infos.type === 'reponse'" class="reponse-map-popup"> <section v-if="infos.type === 'reponse'" class="reponse-map-popup">
<div v-html="reponse"></div> <div v-if="reponse.qui"><label>Qui</label><p v-html="truncate(reponse.qui, 100, true)"/></div>
<div v-if="reponse.quoi"><label>Quoi</label><p v-html="truncate(reponse.quoi, 100, true)"/></div>
<div v-if="reponse.ou"><label></label><p v-html="truncate(reponse.ou, 100, true)"/></div>
<div v-if="reponse.avec"><label>Avec</label><p v-html="truncate(reponse.avec, 100, true)"/></div>
</section> </section>
</div> </div>
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
</style> </style>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,108 @@
<script>
export default {
data() {
return {
// granim1: null,
// granim2: null
}
},
mounted() {
this.initGradients()
this.initTrame()
window.addEventListener("resize", this.onWindowResize.bind(this));
},
// computed: {
// },
// created () {
// },
methods: {
initGradients () {
let gradientBackground = this.$refs['background-gradient'];
let gradients = [];
let num_colors = Math.floor(2 + Math.random()*2);
for (let i = 0; i < Math.floor(2 + Math.random()*4); i++) {
// for (let i = 0; i < 1; i++) {
let colors = [];
// let hue = Math.floor(Math.random()*360)
for (let j = 0; j < num_colors; j++) {
let pos = (1/num_colors*j + 1/num_colors/3 + Math.random()*1/num_colors/3)*100;
// console.log('gradient pos', pos);
colors.push({
color: this.getRandBGColor(),
// pos: parseFloat(`${parseFloat(Math.random()).toFixed(2)}`.slice(1))
// pos: parseFloat(`${parseFloat(pos).toFixed(2)}`.slice(1))
pos: parseInt(pos)
})
}
// colors.sort((a,b) => {
// return a.pos > b.pos ? 1 : -1
// })
gradients.push(colors)
}
// console.log('gradients', gradients);
let cssgrad = '';
gradients.forEach((gradient, index) => {
let alpha = Math.floor(Math.random()*360);
cssgrad += `\n linear-gradient(${alpha}deg`;
gradient.forEach(color => {
cssgrad += `, ${color.color} ${color.pos}%`
});
cssgrad += index < gradients.length-1 ? '),' : ')';
});
// cssgrad += ';';
// console.log('cssgrad', cssgrad);
gradientBackground.style.background = cssgrad;
},
getRandBGColor (hue) {
let h = !hue ? Math.floor(Math.random()*360) : hue + -30 + Math.floor(Math.random()*60);
let s = 25 + Math.floor(Math.random()*5);
let l = 40 + Math.floor(Math.random()*10);
let a = `${parseFloat(0.2 + Math.random()*.4).toFixed(3)}`.slice(1);
let hsla = `hsla(${h}, ${s}%, ${l}%, ${a})`;
// console.log(hsla);
return hsla;
},
initTrame () {
let canvasBackgroundTrame = this.$refs['canvas-background-trame'];
canvasBackgroundTrame.width = canvasBackgroundTrame.parentElement.clientWidth;
canvasBackgroundTrame.height = canvasBackgroundTrame.parentElement.clientHeight;
let ctx = canvasBackgroundTrame.getContext('2d');
ctx.clearRect(0,0, canvasBackgroundTrame.width, canvasBackgroundTrame.height);
let step = 1;
for (let i = 0; i < parseInt(canvasBackgroundTrame.width); i+=step) {
for (let j = 0; j < parseInt(canvasBackgroundTrame.height); j+=step) {
if (Math.random() > 0.6) {
ctx.beginPath();
// ctx.arc(i, j, 0.5, 0, 2 * Math.PI, false);
ctx.rect(i, j, 1, 1);
ctx.fillStyle = "rgba(0,0,0,0.1)";
ctx.fill();
}
}
}
},
onWindowResize () {
this.initTrame()
}
}
}
</script>
<template>
<div class="map-bg gradient" ref="background-gradient"></div>
<canvas class="map-bg trame" ref="canvas-background-trame"></canvas>
</template>
<style lang="css" scoped>
</style>

View File

@ -12,6 +12,7 @@ export default {
mounted() { mounted() {
this.initGradients() this.initGradients()
this.initTrame() this.initTrame()
window.addEventListener("resize", this.onWindowResize.bind(this));
}, },
// computed: { // computed: {
// }, // },
@ -103,7 +104,7 @@ export default {
}, },
getRandBGColor (hue) { getRandBGColor (hue) {
let h = !hue ? Math.floor(Math.random()*360) : hue + -30 + Math.floor(Math.random()*60); let h = !hue ? Math.floor(Math.random()*360) : hue + -30 + Math.floor(Math.random()*60);
let s = 40 + Math.floor(Math.random()*20); let s = 25 + Math.floor(Math.random()*5);
let l = 40 + Math.floor(Math.random()*10); let l = 40 + Math.floor(Math.random()*10);
let a = `${parseFloat(0.2 + Math.random()*.4).toFixed(3)}`.slice(1); let a = `${parseFloat(0.2 + Math.random()*.4).toFixed(3)}`.slice(1);
let hsla = `hsla(${h}, ${s}%, ${l}%, ${a})`; let hsla = `hsla(${h}, ${s}%, ${l}%, ${a})`;
@ -116,19 +117,25 @@ export default {
canvasBackgroundTrame.height = canvasBackgroundTrame.parentElement.clientHeight; canvasBackgroundTrame.height = canvasBackgroundTrame.parentElement.clientHeight;
let ctx = canvasBackgroundTrame.getContext('2d'); let ctx = canvasBackgroundTrame.getContext('2d');
ctx.clearRect(0,0, canvasBackgroundTrame.width, canvasBackgroundTrame.height);
let step = 1; let step = 1;
for (let i = 0; i < parseInt(canvasBackgroundTrame.width); i+=step) { for (let i = 0; i < parseInt(canvasBackgroundTrame.width); i+=step) {
for (let j = 0; j < parseInt(canvasBackgroundTrame.height); j+=step) { for (let j = 0; j < parseInt(canvasBackgroundTrame.height); j+=step) {
if (Math.random() > 0.95) { if (Math.random() > 0.6) {
ctx.beginPath(); ctx.beginPath();
ctx.arc(i, j, 0.5, 0, 2 * Math.PI, false); // ctx.arc(i, j, 0.5, 0, 2 * Math.PI, false);
ctx.fillStyle = "rgba(200,200,200,0.7)"; ctx.rect(i, j, 1, 1);
ctx.fillStyle = "rgba(0,0,0,0.1)";
ctx.fill(); ctx.fill();
} }
} }
} }
},
onWindowResize () {
this.initTrame()
} }
} }
} }

View File

@ -0,0 +1,120 @@
<script>
import { mapActions, mapState } from 'pinia'
import { ConcernementsStore } from '@stores/concernements'
import { CommonStore } from '@/stores/common'
export default {
props: [],
data() {
return {
plyr_options: {
controls: ['play', 'progress', 'current-time', 'mute', 'volume']
},
fadeOutInterval: null
}
},
computed: {
...mapState(ConcernementsStore,['opened_recit', 'recit_plyr_player']),
// ...mapState(CommonStore,['hover_elmt'])
},
mounted() {
console.log('RecitPlayer mounted', this.$refs, this.opened_recit);
this.setRecitPlayer(this.$refs.plyr_player.player);
this.recit_plyr_player.on('ended', ()=>{
this.setOpenedRecit(null);
})
this.recit_plyr_player.volume = 0.6;
if (this.opened_recit) {
if (!this.fadeOutInterval) {
this.recit_plyr_player.play();
}
}
},
watch: {
opened_recit: {
handler (n,o){
console.log('recitPlayer watch opened_recit o, n', o, n);
this.recitTransition(n,o);
},
deep: true
}
},
methods: {
...mapActions(ConcernementsStore, ['setOpenedRecit', 'setRecitPlayer']),
recitTransition(n, o){
if(o){
this.fadeOutInterval = setInterval(()=>{
if (this.recit_plyr_player.volume > 0.05) {
// console.log(`recitPlayer fading volume:${this.recit_plyr_player.volume}`);
this.recit_plyr_player.volume *= 0.9;
}else{
console.log('fadeout done');
this.recit_plyr_player.volume = 0.6;
this.recit_plyr_player.stop();
clearInterval(this.fadeOutInterval);
this.fadeOutInterval = null;
// if during the the fadeout we opened an other recit, play it
if (this.opened_recit) {
console.log('recitPlayer fade done, this.opened_recit', this.opened_recit);
this.recit_plyr_player.source = {
type: 'audio',
sources: [
{
src: this.opened_recit.file.url,
type: this.opened_recit.file.filemine,
}
]
}
this.recit_plyr_player.volume = 0.6;
this.recit_plyr_player.play();
}
}
}, 1);
}
console.log('recitPlayer new n', n, this.fadeOutInterval);
if (n && !this.fadeOutInterval) { // if new and we are not in in a fadeout
if(n.file.url){
// console.log(`switching source`);
this.recit_plyr_player.source = {
type: 'audio',
sources: [
{
src: n.file.url,
type: n.file.filemine,
}
]
}
this.recit_plyr_player.volume = 0.6;
this.recit_plyr_player.play();
}
}
}
},
}
</script>
<template>
<!-- <Transition
@leave="onLeave"
> -->
<aside
:class="{visible: opened_recit}"
id="recit-player">
<vue-plyr ref="plyr_player" :options="plyr_options">
<audio playsinline>
<source v-if="opened_recit" :src="opened_recit.file.url" :type="opened_recit.file.filemime" />
</audio>
</vue-plyr>
</aside>
<!-- </Transition> -->
</template>

View File

@ -5,6 +5,10 @@ import { mapState } from 'pinia'
// import router from 'vuejs/route' // import router from 'vuejs/route'
import { UserStore } from '@/stores/user' import { UserStore } from '@/stores/user'
import SvgIcon from '@jamescoyle/vue-icon';
import { mdiLoginVariant } from '@mdi/js';
export default { export default {
setup() { setup() {
const userStore = UserStore() const userStore = UserStore()
@ -17,7 +21,8 @@ export default {
return { return {
template: null, template: null,
mail: '', mail: '',
passwd: '' passwd: '',
login_path: mdiLoginVariant
} }
}, },
computed: { computed: {
@ -49,13 +54,19 @@ export default {
// }) // })
// }) // })
} }
},
components: {
SvgIcon
} }
} }
</script> </script>
<template> <template>
<div id="login-block"> <div id="login-block">
<label>
<svg-icon type="mdi" :path="login_path"></svg-icon>
<span>connexion</span> <span>connexion</span>
</label>
<form action="" @submit.prevent="onSubmitLogin"> <form action="" @submit.prevent="onSubmitLogin">
<input type="email" placeholder="email" name="email" v-model="mail"> <input type="email" placeholder="email" name="email" v-model="mail">
<input type="password" placeholder="mot de passe" name="passwd" v-model="passwd"> <input type="password" placeholder="mot de passe" name="passwd" v-model="passwd">
@ -66,7 +77,7 @@ export default {
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
$pad: 1em; $pad: 0.75em;
#login-block{ #login-block{
position: relative; position: relative;
@ -79,7 +90,7 @@ export default {
border-radius: 5px; border-radius: 5px;
padding: 0 $pad; padding: 0 $pad;
position: absolute; position: absolute;
bottom: 100%; bottom: 110%;
left: -$pad; left: -$pad;
>*{ >*{
margin: 0 0 0.5em 0; margin: 0 0 0.5em 0;
@ -87,7 +98,7 @@ export default {
overflow: hidden; overflow: hidden;
max-height:1px; max-height:1px;
opacity: 0; opacity: 0;
$delay: 4s; $delay: 0.5s;
transition: opacity 0.3s ease-out $delay,max-height 0.3s ease-out $delay, padding 0.3s ease-out $delay + 0.1s; transition: opacity 0.3s ease-out $delay,max-height 0.3s ease-out $delay, padding 0.3s ease-out $delay + 0.1s;
} }
&:hover{ &:hover{

View File

@ -0,0 +1,78 @@
<script>
import { mapActions, mapState } from 'pinia'
// import { SearchStore } from '@/stores/search'
import SvgIcon from '@jamescoyle/vue-icon';
import { mdiMagnify } from '@mdi/js';
export default {
props: [],
data(){
return {
magnify_path: mdiMagnify
}
},
computed: {
// ...mapState(SearchStore,['statics'])
},
created () {
console.log("search created");
// this.loadStatics()
},
methods: {
// ...mapActions(SearchStore,['loadStatics']),
},
components: {
SvgIcon
}
}
</script>
<template>
<div id="search-block">
<router-link :to="{ name: 'search' }">
<svg-icon type="mdi" :path="magnify_path"></svg-icon>
<span>recherche</span>
</router-link>
</div>
</template>
<style lang="scss" scoped>
// $pad: 0.75em;
// #search-block{
// position: relative;
// span{
// display: inline-block;
// @include btn();
// }
// form{
// background-color: #fff;
// border-radius: 5px;
// padding: 0 $pad;
// position: absolute;
// bottom: 110%;
// left: -$pad;
// >*{
// margin: 0 0 0.5em 0;
// }
// overflow: hidden;
// max-height:1px;
// opacity: 0;
// $delay: 0.5s;
// transition: opacity 0.3s ease-out $delay,max-height 0.3s ease-out $delay, padding 0.3s ease-out $delay + 0.1s;
// }
// &:hover{
// form{
// box-shadow: 0 0 5px $btns_back;
// padding: $pad;
// max-height: 100px;
// opacity: 1;
// transition: opacity 0.3s ease-out,max-height 0.3s ease-out, padding 0.3s ease-out 0.1s;
// }
// }
// }
</style>

View File

@ -3,11 +3,15 @@
import { mapActions, mapState } from 'pinia' import { mapActions, mapState } from 'pinia'
import { StaticsStore } from '@/stores/statics' import { StaticsStore } from '@/stores/statics'
import SvgIcon from '@jamescoyle/vue-icon';
import { mdiInformationOutline } from '@mdi/js';
export default { export default {
props: [], props: [],
data(){ data(){
return { return {
// block: null infos_path: mdiInformationOutline
} }
}, },
computed: { computed: {
@ -21,23 +25,28 @@ export default {
...mapActions(StaticsStore,['loadStatics']) ...mapActions(StaticsStore,['loadStatics'])
}, },
components: { components: {
// LoginBlock, SvgIcon
// UserTools
} }
} }
</script> </script>
<template> <template>
<div id="static-menu">
<ul> <ul>
<li <li
v-for="staticnode in statics" v-for="staticnode in statics"
v-bind:key="staticnode.id" v-bind:key="staticnode.id"
> >
<router-link :to="{ name: 'static', params: { id:staticnode.id } }">{{staticnode.title}}</router-link> <router-link :to="{ name: 'static', params: { id:staticnode.id } }">
<svg-icon type="mdi" :path="infos_path"></svg-icon>
<span>{{staticnode.title}}</span>
</router-link>
</li> </li>
</ul> </ul>
</div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -1,4 +1,11 @@
<script> <script>
import SvgIcon from '@jamescoyle/vue-icon';
import { mdiAccount } from '@mdi/js';
import { mdiLogout } from '@mdi/js';
import { mdiCogOutline } from '@mdi/js';
import { mapState } from 'pinia' import { mapState } from 'pinia'
import { UserStore } from '@/stores/user' import { UserStore } from '@/stores/user'
@ -8,8 +15,15 @@ export default {
return { userStore } return { userStore }
}, },
data() {
return {
account_path: mdiAccount,
cogoutline_path: mdiCogOutline,
logout_path: mdiLogout
}
},
computed: { computed: {
...mapState(UserStore,['isloggedin', 'isAdmin', 'mail', 'name']) ...mapState(UserStore,['isloggedin', 'isAdmin', 'mail', 'name', 'uid'])
}, },
methods: { methods: {
// ...mapActions({ // ...mapActions({
@ -23,14 +37,15 @@ export default {
} }
}, },
components: { components: {
// Loggout SvgIcon
} }
} }
</script> </script>
<template> <template>
<div id="user-tools"> <div id="user-tools">
<a class="mdi mdi-account" href="/api/user"> <a class="mdi mdi-account" :href="'/api/user/'+uid+'/edit'">
<svg-icon type="mdi" :path="account_path"></svg-icon>
<span>{{ name }}</span> <span>{{ name }}</span>
<!-- <span v-else>{{ mail }}</span> --> <!-- <span v-else>{{ mail }}</span> -->
</a><br/> </a><br/>
@ -38,13 +53,16 @@ export default {
v-if="isAdmin" v-if="isAdmin"
class="api" class="api"
href="/api/admin/content/concernements"> href="/api/admin/content/concernements">
<svg-icon type="mdi" :path="cogoutline_path"></svg-icon>
<span>API</span> <span>API</span>
</a><br/> </a><br/>
<a href="/user/logout" <a href="/user/logout"
@click.prevent="onLogout()" @click.prevent="onLogout()"
class="mdi mdi-logout" class="mdi mdi-logout"
title="logout" title="logout"
/> >
<svg-icon type="mdi" :path="logout_path"></svg-icon>
</a>
</div> </div>
</template> </template>
@ -56,6 +74,9 @@ export default {
gap: 0em; gap: 0em;
a{ a{
padding: $pad_btn; padding: $pad_btn;
svg{
height:0.8em;
}
} }
} }
</style> </style>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,183 @@
<script>
import REST from '@api/rest-axios'
import JSONAPI from '@api/json-axios'
import { mapActions, mapState } from 'pinia'
import { ConcernementsStore } from '@stores/concernements'
import { UserStore } from '@stores/user'
import Source from '@components/contents/Source.vue';
import ContentEditable from '@components/editable/ContentEditable.vue';
import CheckboxEditable from '@components/editable/CheckboxEditable.vue';
import ImageEditable from '@components/editable/ImageEditable.vue';
import SvgIcon from '@jamescoyle/vue-icon';
import { mdiTextBoxPlusOutline } from '@mdi/js';
export default {
props: ['concernement', 'entite', 'eid'],
emits: ['reloadEntite'],
data() {
return {
mdiTextBoxPlusOutline_path: mdiTextBoxPlusOutline,
}
},
computed: {
...mapState(ConcernementsStore,['opened_concernement',
'ct_concernement',
'ct_entite']),
...mapState(UserStore,['csrf_token']),
field_menace_maintien_label (){
let str;
if (this.concernement.entites_byid[this.eid].menacemaintien < 0) {
str = this.ct_entite.field_menace_maintien.description.replace('/maintient', '')
} else {
str = this.ct_entite.field_menace_maintien.description.replace('menace/', '')
}
return str;
},
},
methods: {
reloadEntite(){
this.$emit('reloadEntite');
},
addSource(){
console.log('add source');
const params_parag = {
type: [{target_id: 'source'}],
parent_type:{value: 'node'},
parent_id:{value: this.entite.id},
parent_field_name:{value: 'field_sources'}
};
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
// call the api
// https://www.drupal.org/project/paragraphs/issues/3012600
REST.post(`/entity/paragraph?_format=json`, params_parag, configs)
.then(({ data }) => {
console.log('REST post new source parag', data);
const params_node = {
type: 'entite',
nid: [{value: this.entite.id}],
'field_sources': [{
target_id: data.id[0].value,
target_revision_id: data.revision_id[0].value
}]
};
// call the api
REST.patch(`/node/${this.entite.id}?_format=json`, params_node, configs)
.then(({ data }) => {
console.log('REST patch entite new field_sources', data)
this.reloadEntite();
})
.catch(error => {
console.warn(`Issue with patch node entite field_sources`, error)
Promise.reject(error)
})
})
.catch(error => {
console.warn(`Issue with post new paragraph source`, error)
Promise.reject(error)
})
}
},
components: {
Source,
ContentEditable,
CheckboxEditable,
ImageEditable,
SvgIcon
}
}
</script>
<template>
<section class="entite">
<section v-if="entite.image.length || entite.can_update" class="image">
<ImageEditable
:can_update="entite.can_update"
:image="entite.image[0]"
:data="{
entitytype: 'node',
bundle: 'entite',
id: this.entite.id,
uuid: this.entite.uuid,
field: 'field_image'
}"
v-on:updated="reloadEntite" />
</section>
<section v-if="entite.action || entite.can_update" class="action">
<label v-if="ct_entite">{{ ct_entite.field_action.description }}</label>
<!-- <p>{{ entite.action }}</p> -->
<ContentEditable
tag="p"
:value="entite.action"
:contenteditable="entite.can_update"
:data="{
entitytype: 'node',
bundle: 'entite',
id: this.entite.id,
field: {field_name: 'field_action', value:'value'}
}"
v-on:updated="reloadEntite" />
</section>
<section v-if="entite.menacemaintien || entite.can_update" class="menace-maintien">
<label v-if="ct_entite">{{ field_menace_maintien_label }}</label>
<!-- <p>{{ entite.menacemaintien }}</p> -->
<ContentEditable
tag="p"
:value="entite.menacemaintien"
:contenteditable="entite.can_update"
:data="{
entitytype: 'node',
bundle: 'entite',
id: this.entite.id,
field: {field_name: 'field_menace_maintien', value:'value'}
}"
v-on:updated="reloadEntite" />
</section>
<!-- SOURCES (experiences vecues) -->
<section
v-if="entite.sources.length"
class="sources multiple">
<!-- <h5>Experience(s) Vécue(s)</h5> -->
<Source
v-for="(source, index) in entite.sources"
:key="index"
:concernement="concernement"
:entite="entite"
:eid="eid"
:source="source"
v-on:reloadEntite="reloadEntite" />
</section>
<section
v-else-if="entite.can_update"
class="sources add">
<div @click="addSource" class="add-source-btn">
<span>Ajouter une experience vécue</span>
<svg-icon type="mdi" :path="mdiTextBoxPlusOutline_path"/>
</div>
</section>
</section>
</template>
<style lang="css">
section.action p,
section.menace-maintien p {
white-space: pre-wrap;
}
</style>

View File

@ -0,0 +1,469 @@
<script>
import { mapActions, mapState } from 'pinia'
import { ConcernementsStore } from '@stores/concernements'
import { UserStore } from '@/stores/user'
import { CommonStore } from '@/stores/common'
import REST from '@api/rest-axios'
import CartoucheLayout from '@components/layout/CartoucheLayout.vue';
import SvgIcon from '@jamescoyle/vue-icon';
import { mdiChevronRight } from '@mdi/js';
import { mdiChevronDown } from '@mdi/js';
import { mdiPencilPlus } from '@mdi/js';
import { mdiPencilPlusOutline } from '@mdi/js';
import { mdiRhombus } from '@mdi/js';
import { mdiRhombusOutline } from '@mdi/js';
import { mdiStickerPlusOutline } from '@mdi/js';
import ContentEditable from '@components/editable/ContentEditable.vue';
import SelectEditable from '@components/editable/SelectEditable.vue';
export default {
props: ['cid'],
data(){
return {
opened_besoin_id: null,
chevronright_path: mdiChevronRight,
chevrondown_path: mdiChevronDown,
pencilplus_path: mdiPencilPlus,
pencilplusoutline_path: mdiPencilPlusOutline,
rhombus_path: mdiRhombus,
rhombusoutline_path: mdiRhombusOutline,
mdiStickerPlusOutline_path: mdiStickerPlusOutline,
reloading_concernements: false,
}
},
computed: {
...mapState(UserStore,['isloggedin', 'csrf_token']),
...mapState(ConcernementsStore,['opened_concernement',
'ct_concernement',
'ct_entite',
'allBesoinsById'
]),
...mapState(CommonStore,['hover_elmt'])
},
created () {
console.log(`puissance d'agir content created, id: ${this.id}, opened_concernement:`,this.opened_concernement);
},
mounted() {
},
methods: {
...mapActions(CommonStore,['setHoverElmt']),
...mapActions(ConcernementsStore, ['reloadConcernementBesoins']),
onClickBesoin(id){
console.log("onClickBesoin", id);
this.opened_besoin_id = id === this.opened_besoin_id ? null : id;
},
besoinClass(id){
return this.opened_besoin_id === id ? "opened" : "";
},
onHoverItem(type, pid, bid, rid){
console.log(`onHoverItem type:${type}, paper_id:${pid} bid:${bid}, rid:${rid}`);
this.setHoverElmt({
type: type,
paper_id: pid,
id: rid ? rid : bid,
bid: rid ? bid : null,
no_popup: true
});
},
addBesoin(e){
console.log('add besoin');
this.reloading_concernements = true;
// 1 create besoin node
this.createBesoinNode()
.then((besoin) => {
console.log('createBesoinNode then node', besoin);
// 2 record new besoin in concernement's field_besoin
this.recordConcernementBesoinField(besoin)
.then((concernement) => {
console.log('concernement', concernement);
// reload the map item
this.reloadConcernementBesoins(concernement.nid[0].value)
.then(() => {
this.reloading_concernements = false;
});
})
})
},
reloadBesoins(){
this.reloadConcernementBesoins(this.cid);
},
createBesoinNode(){
return new Promise((resolve, reject) => {
// 1 create entite node
const params_node_besoin = {
type: 'besoin',
body: [{value:'Description à personaliser'}],
field_confidentialite: [{value:'confidentialite_public'}]
};
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
REST.post(`/node?_format=json`, params_node_besoin, configs)
.then(({ data }) => {
console.log('REST post new node besoin', data);
resolve(data)
})
.catch(error => {
console.warn(`Issue with post new node besoin`, error)
reject(error)
})
})
},
recordConcernementBesoinField(new_besoin){
return new Promise((resolve, reject) => {
// 3 record concernement field_entite
// get all the field_entite values, we don't want to ersae everything
let besoins = [];
this.opened_concernement.besoins.forEach((besoin) =>{
besoins.push({
target_id: besoin.id
})
})
// add the new field value
besoins.push({
target_id: new_besoin.nid[0].value
})
console.log('besoins', besoins);
const params_node = {
type: 'concernement',
nid: [{value: this.cid}],
'field_besoin': besoins
};
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
REST.patch(`/node/${this.cid}?_format=json`, params_node, configs)
.then(({ data }) => {
console.log('REST patch entite new field_entite', data)
resolve(data)
})
.catch(error => {
console.warn(`Issue with patch node entite field_entite`, error)
reject(error)
})
// resolve('test')
})
},
addRessource(besoin_id){
console.log('addRessource', besoin_id);
this.reloading_concernements = true;
// 1 create reponse node
this.createRessourceNode(besoin_id)
.then((ressource) => {
console.log('createRessourceNode then node', ressource);
// 2 record new besoin in concernement's field_besoin
// this.recordBesoinRessourceField(besoin_id, ressource)
// .then((besoin) => {
// console.log('besoin', besoin);
// reload the map item
this.reloadConcernementBesoins(this.cid)
.then(() => {
this.reloading_concernements = false;
});
// })
})
},
createRessourceNode(besoin_id){
return new Promise((resolve, reject) => {
// 1 create entite node
let besoin_title = this.allBesoinsById[besoin_id].title;
const params_node_ressource = {
type: 'reponse',
title: [{value:`reponse-${besoin_title}-${Date.now()}`}],
field_besoin_on_reponses: [{target_id: besoin_id}],
field_confidentialite: [{value:'confidentialite_public'}]
};
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
REST.post(`/node?_format=json`, params_node_ressource, configs)
.then(({ data }) => {
console.log('REST post new node ressource', data);
resolve(data)
})
.catch(error => {
console.warn(`Issue with post new node ressource`, error)
reject(error)
})
})
},
recordBesoinRessourceField(besoin_id, new_reponse){
return new Promise((resolve, reject) => {
// 3 record concernement field_entite
// get all the field_entite values, we don't want to ersae everything
let reponses = [];
this.allBesoinsById[besoin_id].reponses.forEach((reponse) =>{
reponses.push({
target_id: reponse.id
})
})
// add the new field value
reponses.push({
target_id: new_reponse.nid[0].value
})
console.log('reponses', reponses);
const params_node = {
type: 'besoin',
nid: [{value: besoin_id}],
'field_reponse': reponses
};
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
REST.patch(`/node/${this.cid}?_format=json`, params_node, configs)
.then(({ data }) => {
console.log('REST patch besoin new field_reponse', data)
resolve(data)
})
.catch(error => {
console.warn(`Issue with patch node besoin field_reponse`, error)
reject(error)
})
// resolve('test')
})
}
},
components: {
CartoucheLayout,
SvgIcon,
ContentEditable,
SelectEditable
}
}
</script>
<template>
<CartoucheLayout :cid="cid">
<!-- <template v-slot:header>
</template> -->
<template v-slot:main>
<ul class="besoins">
<li
v-for="besoin in opened_concernement.besoins"
:key="besoin.id"
class="besoin"
:id="besoin.id"
:class="besoinClass(besoin.id)"
@mouseover="onHoverItem('besoin', besoin.paper_id, besoin.id)"
>
<svg-icon
type="mdi"
:path="besoin.id !== opened_besoin_id ? chevronright_path : chevrondown_path"
class="open-btn"
@click="onClickBesoin(besoin.id)"
></svg-icon>
<header @click="onClickBesoin(besoin.id)">
<label
:class="{ 'hover': hover_elmt
&& (hover_elmt.type === 'besoin' || hover_elmt.type === 'reponse')
&& (hover_elmt.id === besoin.id || hover_elmt.bid === besoin.id) }"
>
<svg-icon
type="mdi"
:path="rhombus_path"
/>
Besoin de l'enqueteur
</label>
<!-- <h4 class="besoin-description" v-html="besoin.description"/> -->
<ContentEditable
tag="p"
:value="besoin.description"
:html="true"
:contenteditable="opened_concernement.can_update"
:data="{
entitytype: 'node',
bundle: 'besoin',
id: besoin.id,
field: {field_name: 'body', value:'value'}
}"
v-on:updated="reloadBesoins" />
<SelectEditable
v-if="opened_concernement.can_update"
label="Confidentialité"
:value="besoin.confidentialite"
:options="{
'confidentialite_prive': 'privé',
'confidentialite_interne': 'interne',
'confidentialite_public': 'public'
}"
:data="{
entitytype: 'node',
bundle: 'besoin',
nid: besoin.id,
field: 'field_confidentialite'
}"
v-on:updated="reloadBesoins" />
</header>
<ul class="reponses">
<li
v-for="reponse in besoin.reponses"
:key="reponse.id"
class="reponse"
:id="reponse.id"
@mouseover.stop="onHoverItem('reponse', reponse.paper_id, besoin.id, reponse.id)"
>
<label
:class="{ 'hover': hover_elmt
&& hover_elmt.type === 'reponse'
&& hover_elmt.id === reponse.id }"
>
<svg-icon
type="mdi"
:path="hover_elmt && hover_elmt.type === 'reponse' && hover_elmt.id === reponse.id ? rhombus_path : rhombusoutline_path"
/>
Ressource</label>
<SelectEditable
v-if="reponse.can_update"
label="Confidentialité"
:value="reponse.confidentialite"
:options="{
'confidentialite_prive': 'privé',
'confidentialite_interne': 'interne',
'confidentialite_public': 'public'
}"
:data="{
entitytype: 'node',
bundle: 'reponse',
nid: reponse.id,
field: 'field_confidentialite'
}"
v-on:updated="reloadBesoins" />
<section v-if="reponse.qui || reponse.can_update">
<label for="reponse-qui">Qui</label>
<!-- <p name="reponse-qui" v-html="reponse.qui" /> -->
<ContentEditable
tag="p"
:value="reponse.qui"
:html="true"
:contenteditable="reponse.can_update"
placeholder="Ajouter un élement de réponse."
:data="{
entitytype: 'node',
bundle: 'reponse',
id: reponse.id,
field: {field_name: 'field_qui', value:'value'}
}"
v-on:updated="reloadBesoins" />
</section>
<section v-if="reponse.quoi || reponse.can_update">
<label for="reponse-quoi">Quoi</label>
<!-- <p name="reponse-quoi" v-html="reponse.quoi" /> -->
<ContentEditable
tag="p"
:value="reponse.quoi"
:html="true"
:contenteditable="reponse.can_update"
placeholder="Ajouter un élement de réponse."
:data="{
entitytype: 'node',
bundle: 'reponse',
id: reponse.id,
field: {field_name: 'field_quoi', value:'value'}
}"
v-on:updated="reloadBesoins" />
</section>
<section v-if="reponse.ou || reponse.can_update">
<label for="reponse-ou"></label>
<!-- <p name="reponse-ou" v-html="reponse.ou" /> -->
<ContentEditable
tag="p"
:value="reponse.ou"
:html="true"
:contenteditable="reponse.can_update"
placeholder="Ajouter un élement de réponse."
:data="{
entitytype: 'node',
bundle: 'reponse',
id: reponse.id,
field: {field_name: 'field_ou', value:'value'}
}"
v-on:updated="reloadBesoins" />
</section>
<section v-if="reponse.avec || reponse.can_update">
<label for="reponse-avec">Avec</label>
<!-- <p name="reponse-avec" v-html="reponse.avec" /> -->
<ContentEditable
tag="p"
:value="reponse.avec"
:html="true"
:contenteditable="reponse.can_update"
placeholder="Ajouter un élement de réponse."
:data="{
entitytype: 'node',
bundle: 'reponse',
id: reponse.id,
field: {field_name: 'field_avec', value:'value'}
}"
v-on:updated="reloadBesoins" />
</section>
</li>
<li>
<template v-if="isloggedin && !opened_concernement.can_update">
<div v-if="!reloading_concernements" @click="addRessource(besoin.id)" class="add-ressource-btn">
<span>Proposer une ressource</span>
<svg-icon type="mdi" :path="mdiStickerPlusOutline_path"/>
</div>
<div v-else class="add-ressource-btn">
<div class="loading">Chargement</div>
</div>
</template>
</li>
</ul>
<!-- <a
v-if="isloggedin && !opened_concernement.can_update"
:href="'/api/node/add/reponse?besoin_id='+besoin.id"
target="_blank"
rel="noopener noreferrer"
class="contribute-link mdi mdi-pencil-plus">
<svg-icon type="mdi" :path="pencilplusoutline_path" /> contribuer à ce besoin
</a> -->
</li>
</ul>
</template>
<template v-slot:footer>
<template v-if="opened_concernement.can_update">
<div v-if="!reloading_concernements" @click="addBesoin" class="add-besoin-btn">
<span>Ajouter un besoin</span>
<svg-icon type="mdi" :path="mdiStickerPlusOutline_path"/>
</div>
<div v-else class="add-besoin-btn">
<div class="loading">Chargement</div>
</div>
</template>
</template>
</CartoucheLayout>
</template>

View File

@ -0,0 +1,180 @@
<script>
import { mapActions, mapState } from 'pinia'
import { ConcernementsStore } from '@stores/concernements'
import { UserStore } from '@stores/user'
import ContentEditable from '@components/editable/ContentEditable.vue';
import CheckboxEditable from '@components/editable/CheckboxEditable.vue';
import ImageEditable from '@components/editable/ImageEditable.vue';
import VideoEditable from '@components/editable/VideoEditable.vue';
import AudioEditable from '@components/editable/AudioEditable.vue';
import LinkEditable from '@components/editable/LinkEditable.vue';
import FileEditable from '@components/editable/FileEditable.vue';
export default {
props: ['concernement', 'entite', "eid", 'source'],
emits: ['reloadEntite'],
data() {
return {
// plyr_options: {
// controls: ['play', 'progress', 'current-time', 'mute', 'volume']
// }
}
},
computed: {
...mapState(ConcernementsStore,['ct_entite']),
field_sources_label () {
let str;
if (this.concernement.entites_byid[this.eid].menacemaintien < 0) {
str = this.ct_entite.field_sources.description.replace('/ ce maintien', '')
} else {
str = this.ct_entite.field_sources.description.replace('cette menace /', '')
}
return str;
}
},
methods: {
reloadEntite(){
this.$emit('reloadEntite');
}
},
components: {
ContentEditable,
CheckboxEditable,
ImageEditable,
VideoEditable,
AudioEditable,
LinkEditable,
FileEditable
}
}
</script>
<template>
<section class="source">
<!-- <div class="date">{{ source.date.start }}</div> -->
<section v-if="source.description || entite.can_update" class="description">
<label v-if="ct_entite"> {{ field_sources_label }}</label>
<!-- <div v-html="source.description"/> -->
<ContentEditable
tag="div"
:value="source.description"
:contenteditable="entite.can_update"
:html="true"
:data="{
entitytype: 'paragraph',
bundle: 'source',
id: this.source.id,
field: {field_name: 'field_description', value:'value'}
}"
v-on:updated="reloadEntite" />
</section>
<!-- v-if="source.images.length"
:key="j"
-->
<section
class="images">
<ImageEditable
:can_update="entite.can_update"
:image="source.images[0]"
:data="{
entitytype: 'paragraph',
bundle: 'source',
id: this.source.id,
uuid: this.source.uuid,
field: 'field_images'
}"
v-on:updated="reloadEntite" />
</section>
<!-- v-if="source.videos.length" -->
<section
class="video">
<VideoEditable
:can_update="entite.can_update"
:video="source.videos[0]"
:data="{
entitytype: 'paragraph',
bundle: 'source',
id: this.source.id,
uuid: this.source.uuid,
field: {
field_name: 'field_videos',
value: 'value'
}
}"
v-on:updated="reloadEntite"/>
</section>
<!-- v-if="source.audios.length" -->
<section
class="audio">
<AudioEditable
:can_update="entite.can_update"
:audio="source.audios[0]"
:data="{
entitytype: 'paragraph',
bundle: 'source',
id: this.source.id,
uuid: this.source.uuid,
field: {
field_name: 'field_audio',
value: 'value'
}
}"
v-on:updated="reloadEntite"/>
</section>
<!-- v-if="source.liens.length" -->
<section class="liens multiple">
<LinkEditable
:can_update="entite.can_update"
:links="source.liens"
:data="{
entitytype: 'paragraph',
bundle: 'source',
id: this.source.id,
uuid: this.source.uuid,
field: {
field_name: 'field_liens'
}
}"
label="Liens"
v-on:updated="reloadEntite "/>
</section>
<!-- v-if="source.documents.length" -->
<section class="documents multiple">
<!-- <a
v-for="(doc,d) in source.documents"
:key="d"
:href="doc.file.url">
<template v-if="doc.description">{{ doc.description }}</template>
<template v-else>{{ doc.file.url }}</template>
</a> -->
<FileEditable
:can_update="entite.can_update"
:files="source.documents"
:data="{
entitytype: 'paragraph',
bundle: 'source',
id: this.source.id,
uuid: this.source.uuid,
field: {
field_name: 'field_documents'
}
}"
label="Documents"
v-on:updated="reloadEntite "/>
</section>
</section>
</template>
<style lang="css">
</style>

View File

@ -0,0 +1,723 @@
<script>
import { mapActions, mapState } from 'pinia'
import { ConcernementsStore } from '@stores/concernements'
import { UserStore } from '@/stores/user'
// import { CommonStore } from '@/stores/common'
import REST from '@api/rest-axios'
import { print } from 'graphql/language/printer'
import gql from 'graphql-tag'
import GQL from '@api/graphql-axios'
import EntiteFields from '@api/gql/entite.fragment.gql'
import CartoucheLayout from '@components/layout/CartoucheLayout.vue';
import Entite from '@components/contents/Entite.vue';
import VueSlider from 'vue-slider-component'
import 'vue-slider-component/theme/default.css'
import SvgIcon from '@jamescoyle/vue-icon';
import { mdiChevronRight } from '@mdi/js';
import { mdiChevronDown } from '@mdi/js';
import { mdiStickerPlusOutline } from '@mdi/js';
import { mdiCloseBox } from '@mdi/js';
import ContentEditable from '@components/editable/ContentEditable.vue';
import CheckboxEditable from '@components/editable/CheckboxEditable.vue';
import SelectEditable from '@components/editable/SelectEditable.vue';
// import vueAutocomplete from "@venegrad/vue3-autocomplete"
import VueSimpleSuggest from '@vojtechlanka/vue-simple-suggest';
export default {
props: ['cid', 'eid'],
data(){
return {
concernement: null,
entite: null,
history_value: 0,
history_slider_ops: null,
details_value: 1,
details_slider_ops: null,
infos_opened: false,
chevronright_path: mdiChevronRight,
chevrondown_path: mdiChevronDown,
headerreduced: false,
mdiStickerPlusOutline_path: mdiStickerPlusOutline,
reloading_concernements: false,
prox_default_values: [],
prox_new_value: {},
prox_suggestions: [],
mdiCloseBox_path: mdiCloseBox,
}
},
computed: {
...mapState(ConcernementsStore,['map_mode',
'opened_concernement',
'concernementsByID',
'ct_concernement',
'ct_entite',
'detailsZoomValue',
'allEntitesById'
// 'concernements_are_loading'
]),
...mapState(UserStore,['name',
'csrf_token',
'isloggedin',
'user_entites']),
created(){
let d = new Date(this.concernement.created);
console.log('d', d);
return d.toLocaleDateString("fr-FR");//.toISOString().split('T')[0];
},
changed(){
let d = new Date(this.concernement.changed);
console.log('d', d);
return d.toLocaleDateString("fr-FR");//.toISOString().split('T')[0];
},
display_concernement(){
return this.ct_concernement && !this.entite && this.map_mode !== 'puissancedagir' && this.map_mode !== 'doleancer';
},
entity_title_label(){
let menacemaintien_str;
if (this.concernement.entites_byid[this.eid].menacemaintien > 0) {
menacemaintien_str = 'maintenu';
} else {
menacemaintien_str = 'menacé';
}
let actuelfuture_str;
if (this.concernement.entites_byid[this.eid].actuelfuture > 0) {
actuelfuture_str = 'sera';
} else {
actuelfuture_str = 'est';
}
return `Pouvez-vous nommer par qui ou par quoi cet élément ${actuelfuture_str} ${menacemaintien_str} ?`;
}
},
created () {
this.concernement = this.concernementsByID[this.cid];
console.log(`terraindevie created, cid: ${this.cid}, eid: ${this.eid}, this.concernement:`, this.concernement);
//entite
if (this.eid) {
this.loadEntite()
}
// revisions
let data=[];
if (this.concernement && this.concernement.revisions) {
this.concernement.revisions.forEach(rev => {
if (rev.entites.length > 3) {
let d = new Date(rev.changed);
data.push({
'id': rev.revision_id,
'changed': d.toLocaleDateString("fr-FR")
})
this.history_value = Math.max(this.history_value, parseInt(rev.revision_id));
}
});
}
if (data.length > 1) {
this.history_slider_ops = {
dotSize:10,
data: data,
'data-value': 'id',
'data-label': 'changed',
adsorb: true,
'hide-label': true
}
} else {
this.history_slider_ops = null;
}
// details
this.details_slider_ops = {
min: 1,
max: 4,
interval: 0.05,
'hide-label': true,
tooltip: 'none',
dotSize:10,
}
},
// mounted(){
// console.log('terrain de vie mounted', this);
// // this.$refs.cartouche_main.addEventListener('scroll', (event) => {
// // console.log('main is scrolling', event);
// // })
// },
watch: {
history_value: {
handler (n, o) {
// console.log(`TerrainDeVie watch history_value o:${o}, n:${n}`);
this.setActiveRevision(this.cid, n);
},
deep: true
},
details_value: {
handler (n, o) {
// console.log(`TerrainDeVie watch history_value o:${o}, n:${n}`);
this.setDetailsZoomValue(n);
},
deep: true
},
detailsZoomValue: {
handler (n, o) {
// console.log(`TerrainDeVie watch history_value o:${o}, n:${n}`);
this.details_value = n;
},
deep: true
},
cid: {
handler (n,o) {
console.log(`TerrainDeVie watch cid o:${o}, n:${n}`);
if (n) {
this.concernement = this.concernementsByID[n];
}
},
deep: true
},
eid: {
handler (n, o) {
console.log(`TerrainDeVie watch eid o:${o}, n:${n}`);
if (n) {
this.loadEntite()
}else{
this.entite = null;
}
},
deep: true
},
user_entites: {
handler (n, o) {
console.log('TerrainDeVie watch user_entites');
if (n) {
this.checkForUserProxmite();
}
},
deep: true
}
},
methods: {
...mapActions(ConcernementsStore, ['setActiveRevision',
'setDetailsZoomValue',
'loadConcernements',
'reloadConcernements',
'reloadConcernementEntites',
'reloadProximites'
]),
...mapActions(UserStore, ['getUserEntitees']),
onClickInfos(){
this.infos_opened = !this.infos_opened;
},
loadEntite(){
const ast = gql`{
entite (id: ${this.eid}) {
...EntiteFields
}
}
${EntiteFields}
`
console.log('ast', ast);
GQL.post('', { query: print(ast) })
.then(({data: { data: { entite }}}) => {
console.log('load entite loaded', entite)
this.entite = entite;
// record the paragraphe field id from concernement wher the entity is referenced
this.concernement.entites.forEach(parag_entite => {
if (parag_entite.entite && parag_entite.entite.id === this.entite.id) {
this.parag_entite = parag_entite;
}
});
// this.setProxSuggestions()
this.checkForUserProxmite();
})
.catch(error => {
console.warn('Issue with load entite', error)
})
},
onMainScrolled(scrolled){
// console.log('this.$refs', this.$refs);
let cartouche_main = this.$refs.cartouche_layout.$refs.cartouche_main;
// console.log('cartouche_main', cartouche_main);
if(scrolled && cartouche_main.scrollHeight > 600){
this.headerreduced = true;
} else {
this.headerreduced = false;
}
},
onContentEditableFocusOut(e){
console.log('onContentEditableFocusOut', e);
let new_field_content = e.target.innerText;
console.log('onContentEditableFocusOut', new_field_content);
console.log('onContentEditableFocusOut this.concernement.title', this.concernement.title);
},
addEntite(e){
console.log('add entite');
this.reloading_concernements = true;
// 1 create entite node
this.createEntiteNode()
.then((entite) => {
console.log('createEntiteNode then node', entite);
// 2 create entite paragraph with entite in it
this.createEntiteParag(entite)
.then((parag) => {
console.log('createEntiteParag then parag', parag);
// 3 record on concernement field_entites
this.recordConcernementEntiteField(parag)
.then((concernement) => {
console.log('concernement', concernement);
// reload the map item
this.reloadConcernementEntites(concernement.nid[0].value)
.then(() => {
this.reloading_concernements = false;
});
})
})
})
},
createEntiteNode(){
return new Promise((resolve, reject) => {
// 1 create entite node
const params_node_entite = {
type: 'entite',
title: [{value:'Titre à personaliser'}],
field_confidentialite: [{value:'confidentialite_public'}]
};
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
REST.post(`/node?_format=json`, params_node_entite, configs)
.then(({ data }) => {
console.log('REST post new node entite', data);
resolve(data)
})
.catch(error => {
console.warn(`Issue with post new node cercle_politique`, error)
reject(error)
})
})
},
createEntiteParag(entite){
return new Promise((resolve, reject) => {
// 2 create paragraphe
const params_parag_entite = {
type: [{target_id: 'entite_concernement'}],
parent_type:{value: 'node'},
parent_id:{value: this.cid},
parent_field_name:{value: 'field_entite'}, // entity reference revision
'field_entite':[{target_id: entite.nid[0].value}] // entity reference
};
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
REST.post(`/entity/paragraph?_format=json`, params_parag_entite, configs)
.then(({ data }) => {
console.log('REST post new source parag', data);
resolve(data)
})
.catch(error => {
console.warn(`Issue with post new paragraph source`, error)
reject(error)
})
})
},
recordConcernementEntiteField(parag){
return new Promise((resolve, reject) => {
// 3 record concernement field_entite
// get all the field_entite values, we don't want to ersae everything
let entites = [];
this.concernement.entites.forEach((entite) =>{
entites.push({
target_id: entite.id,
target_revision_id: entite.revision_id
})
})
// add the new field value
entites.push({
target_id: parag.id[0].value,
target_revision_id: parag.revision_id[0].value
})
console.log('entites', entites);
const params_node = {
type: 'concernement',
nid: [{value: this.cid}],
'field_entite': entites
};
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
REST.patch(`/node/${this.cid}?_format=json`, params_node, configs)
.then(({ data }) => {
console.log('REST patch entite new field_entite', data)
resolve(data)
})
.catch(error => {
console.warn(`Issue with patch node entite field_entite`, error)
reject(error)
})
// resolve('test')
})
},
// setProxSuggestions(){
// this.prox_suggestions = [];
// // check that entite is well referenced in a loaded concernement
// this.user_entites.forEach((entite) => {
// if (this.allEntitesById[entite.id]) {
// // check if not already proximited
// let tobesuggested = true;
// this.prox_default_values.forEach((default_entite) => {
// if (default_entite.id === entite.id) {
// tobesuggested = false;
// }
// })
// if (tobesuggested) {
// this.prox_suggestions.push(entite)
// }
// }
// })
// console.log('this.prox_suggestions', this.prox_suggestions);
// // this.checkForUserProxmite();
// },
checkForUserProxmite(){
if (this.entite && this.isloggedin && !this.entite.can_update ) {
console.log('checkForUserProxmite', this.entite);
// this.prox_suggestions.forEach((user_entite) => {
this.prox_default_values = [];
this.prox_suggestions = [];
this.user_entites.forEach((user_entite) => {
console.log('user_entite', user_entite);
console.log('entite', this.allEntitesById[user_entite.id]);
if (this.allEntitesById[user_entite.id]) {
let tobesuggested = true
this.allEntitesById[user_entite.id].entite.proximite.forEach((prox_field_entite) => {
if(prox_field_entite.id === this.entite.id) {
this.prox_default_values.push(user_entite);
tobesuggested = false
}
})
if (tobesuggested) {
this.prox_suggestions.push(user_entite)
}
}
})
console.log('this.prox_default_values', this.prox_default_values);
}
},
onProximiteSelected(src_entite){
console.log('onProximiteSelected', src_entite);
console.log('onProximiteSelected', this.prox_new_value);
if (src_entite) {
this.proxvaluetitle = src_entite.title;
// get all the field_proximite values, we don't want to ersae everything
let proximites = [];
this.allEntitesById[src_entite.id].entite.proximite.forEach((target_entite) =>{
proximites.push({
target_id: target_entite.id,
})
})
// add the new field value
proximites.push({
target_id: this.entite.id,
})
console.log('proximites', proximites);
this.recordProximites(src_entite.id, proximites);
}
},
deleteProximite(src_entite){
console.log('deleteProximite', src_entite);
if (src_entite) {
// get all the field_proximite values, excpet the one we want to delete
let proximites = [];
this.allEntitesById[src_entite.id].entite.proximite.forEach((target_entite) =>{
if(target_entite.id !== this.entite.id){
proximites.push({
target_id: target_entite.id,
})
}
})
this.recordProximites(src_entite.id, proximites);
}
},
recordProximites(src_id, proximites){
console.log(`recordProximites proximites`, proximites);
const params_node = {
type: 'entite',
nid: [{value: src_id}],
'field_proximite': proximites
};
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
REST.patch(`/node/${src_id}?_format=json`, params_node, configs)
.then(({ data }) => {
console.log('REST patch entite new field_proximite', data)
this.reloadProximites(src_id)
.then(() => {
if (this.$refs.simplesuggest) {
console.log('Proximites reloaded, $refs', this.$refs.simplesuggest);
// clear the autocomplete field
this.$refs.simplesuggest.setText('');
this.$refs.simplesuggest.selected = null;
this.$refs.simplesuggest.isSelectedUpToDate = false;
this.$refs.simplesuggest.clearSuggestions();
}
})
})
.catch(error => {
console.warn(`Issue with patch node entite field_proximite`, error)
// reject(error)
})
},
},
components: {
CartoucheLayout,
Entite,
VueSlider,
SvgIcon,
ContentEditable,
CheckboxEditable,
SelectEditable,
VueSimpleSuggest
}
}
</script>
<template>
<CartoucheLayout ref="cartouche_layout" :cid="cid" @main_scrolled="onMainScrolled">
<template v-slot:header>
<div class="entite">
<!-- TODO update entite with revisions -->
<label v-if="entite" class="menacemaintient" :class="{ hidden: headerreduced}">{{ entity_title_label }}</label>
<!-- <h3 v-if="entite" class="entite-title">{{ entite.title }}</h3> -->
<ContentEditable
v-if="entite"
tag="h3"
:value="entite.title"
class="entite-title"
:contenteditable="entite.can_update"
:data="{
entitytype: 'node',
bundle: 'entite',
id: this.entite.id,
field: {field_name: 'title', value:'value'}
}"
v-on:updated="reloadConcernementEntites(cid)"/>
<!-- proximité -->
<section
v-if="entite && isloggedin && !entite.can_update"
id="new-proxomite"
class="editable-proximites"
>
<label>Mes proximités</label>
<div class="wrapper">
<ul v-if="prox_default_values.length">
<li v-for="(prox_entite, i) in prox_default_values" v-key="i">
<em>{{ prox_entite.title }}</em>
<!-- <span
class="delete"
@click="deleteProximite(prox_entite)"
> -->
<svg-icon
type="mdi"
:path="mdiCloseBox_path"
class="delete"
@click="deleteProximite(prox_entite)"
></svg-icon>
<!-- </span> -->
</li>
</ul>
<template v-if="prox_suggestions.length" >
<span>Lier <em>{{ entite.title }}</em> a une de mes entitées</span>
<VueSimpleSuggest
ref="simplesuggest"
mode="select"
:list="prox_suggestions"
v-model="prox_new_value"
display-attribute="title"
value-attribute="id"
filter-by-query="true"
min-length="0"
placeholder="Tappez le nom de votre entite..."
@update:model-select="onProximiteSelected"
/>
</template>
</div>
</section>
<!-- active -->
<CheckboxEditable
v-if="entite && entite.can_update"
:checked="this.parag_entite.active"
label="Active"
:data="{
entitytype: 'paragraph',
bundle: 'entite_concernement',
id: this.parag_entite.id,
field: 'field_active'}"
v-on:updated="reloadConcernementEntites(cid)"/>
<!-- agissante -->
<CheckboxEditable
v-if="entite && entite.can_update"
:checked="entite.agissante"
label="Entité action"
:data="{
entitytype: 'node',
bundle: 'entite',
id: this.entite.id,
field: 'field_entite_agissante'}"
v-on:updated="reloadConcernementEntites(cid)"/>
<SelectEditable
v-if="entite && entite.can_update"
label="Confidentialité"
:value="entite.confidentialite"
:options="{
'confidentialite_prive': 'privé',
'confidentialite_interne': 'interne',
'confidentialite_public': 'public'}"
:data="{
entitytype: 'node',
bundle: 'entite',
nid: this.entite.id,
field: 'field_confidentialite'}"
v-on:updated="reloadConcernementEntites(cid)"/>
</div>
</template>
<template v-slot:main>
<!-- concernement -->
<template v-if="!entite">
<section v-if="concernement.description || concernement.can_update" class="description">
<label v-if="ct_concernement">{{ ct_concernement.field_description.description }}</label>
<ContentEditable
tag="p"
:value="concernement.description"
:html="true"
:class="{ ellipsed: headerreduced }"
:contenteditable="concernement.can_update"
:data="{
entitytype: 'node',
bundle: 'concernement',
id: this.concernement.id,
field: {field_name: 'field_description', value:'value'}
}" />
</section>
<section v-if="concernement.caillou || concernement.can_update" class="caillou">
<label v-if="ct_concernement">{{ ct_concernement.field_caillou.description }}</label>
<ContentEditable
tag="p"
:value="concernement.caillou"
:class="{ ellipsed: headerreduced }"
:contenteditable="concernement.can_update"
:data="{
entitytype: 'node',
bundle: 'concernement',
id: this.concernement.id,
field: {field_name: 'field_caillou', value:'value'}
}" />
</section>
<template v-if="concernement.can_update">
<div v-if="!reloading_concernements" @click="addEntite" class="add-entite-btn">
<span>Ajouter une entité</span>
<svg-icon type="mdi" :path="mdiStickerPlusOutline_path"/>
</div>
<div v-else class="add-entite-btn">
<div class="loading">Chargement</div>
</div>
</template>
</template>
<!-- entite -->
<Entite v-if="entite" :concernement="concernement" :entite="entite" :eid="eid" v-on:reloadEntite="loadEntite"/>
</template>
<template v-slot:footer>
<section class="infos">
<svg-icon
type="mdi"
:path="!infos_opened ? chevronright_path : chevrondown_path"
class="open-btn"
@click="onClickInfos"
></svg-icon>
<div
class="author info"
@click="onClickInfos">
<span>une enquête de</span> {{ concernement.author.username }}<br/>
</div>
<div class="wrapper" :class="{ 'opened': infos_opened }">
<div class="info structure" v-if="concernement.author.structure.length"><span>avec</span> {{ concernement.author.structure[0].name }}<br/></div>
<div class="info lieu" v-if="concernement.lieu.length"><span>à</span> {{ concernement.lieu[0].name }}<br/></div>
<div class="info created"><span>démarrée le</span> {{ created }}<br/></div>
<div class="info changed"><span>mise à jour le</span> {{ changed }}</div>
<div class="info recit-colophon" v-if="concernement.recit_colophon" v-html="concernement.recit_colophon"/>
</div>
</section>
<section class="sliders" v-if="history_slider_ops || details_slider_ops">
<section class="historique" v-if="history_slider_ops">
<label>Historique</label>
<!-- <h3>{{ history_value }}</h3> -->
<vue-slider
ref="slider"
v-model="history_value"
v-bind="history_slider_ops"
></vue-slider>
</section>
<section class="details" v-if="details_slider_ops && map_mode === 'terraindevie'">
<label>Détails</label>
<!-- <h3>{{ details_value }}</h3> -->
<vue-slider
ref="details_slider"
v-model="details_value"
v-bind="details_slider_ops"
></vue-slider>
</section>
</section>
</template>
</CartoucheLayout>
</template>
<style lang="css">
span.entite-point{
color: #01ffe2;
}
</style>

View File

@ -0,0 +1,176 @@
<script>
import JSONAPI from '@api/json-axios'
import REST from '@api/rest-axios'
import { mapActions, mapState } from 'pinia'
import { ConcernementsStore } from '@stores/concernements'
import { UserStore } from '@stores/user'
import ContentEditable from '@components/editable/ContentEditable.vue';
import SvgIcon from '@jamescoyle/vue-icon';
import { mdiTrashCanOutline } from '@mdi/js';
import { mdiMusicNotePlus } from '@mdi/js';
export default {
props: {
can_update: Boolean,
audio: Object,
data: Object
},
emits: ['updated'],
data(){
return {
mdiTrashCanOutline_path: mdiTrashCanOutline,
mdiMusicNotePlus_path: mdiMusicNotePlus,
plyr_options: {
controls: ['play', 'progress', 'current-time', 'mute', 'volume']
}
}
},
computed: {
...mapState(UserStore,['csrf_token']),
},
created () {
console.log('ImageEditable created')
},
mounted () {
},
methods: {
...mapActions(ConcernementsStore, ['reloadConcernements']),
addAudio(e){
console.log('addAudio', this.$refs);
this.$refs.audio_input.click();
},
onInput(e){
console.log('onFileInput', e);
let file = e.target.files[0];
console.log('onFileInput file', file);
this.save(file);
},
save(file){
const configs = {
headers: {
'X-CSRF-Token': this.csrf_token,
'Content-Type': 'application/octet-stream',
'Content-Disposition': `file; filename="${file.name}"`,
},
};
JSONAPI.post(`/${this.data.entitytype}/${this.data.bundle}/${this.data.uuid}/${this.data.field.field_name}`, file, configs)
.then(({ data : { data } }) => {
console.log('jsonapi post audio', data)
this.$emit('updated');
})
.catch(error => {
console.warn('Issue with jsonapi post image', error)
Promise.reject(error)
})
},
onDeleteAudio(e){
console.log('onDeleteImg', e);
const params = {
type: this.data.bundle,
// nid: [{"value":this.data.id}],
[this.data.field.field_name]: {[this.data.field.value]: null}
};
if (this.data.entitytype === 'node') {
params.nid = [{"value":this.data.id}];
} else {
params.id = [{"value":this.data.id}];
}
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
let url_base = `/${this.data.entitytype === 'node' ? '' : 'entity/'}${this.data.entitytype}`;
REST.patch(`${url_base}/${this.data.id}?_format=json`, params, configs)
.then(({ data }) => {
console.log(`user REST patch ${this.data.entitytype} ${this.data.bundle} ${this.data.field}`, data)
// TODO if success update the data in pinia
// this.reloadConcernements();
this.$emit('updated');
})
.catch(error => {
console.warn(`Issue with patch ${this.data.entitytype} ${this.data.bundle} ${this.data.field}`, error)
Promise.reject(error)
})
// 405 JSONAPI operation not allowed, don't know why
// const configs = {
// headers: {
// 'X-CSRF-Token': this.csrf_token,
// 'Content-Type': 'application/octet-stream',
// 'Content-Disposition': `file; filename=""`,
// },
// };
// JSONAPI.delete(`/${this.data.entitytype}/${this.data.bundle}/${this.data.uuid}/${this.data.field}`, {}, configs)
// .then(({ data : { data } }) => {
// console.log('jsonapi delete image', data)
// this.$emit('updated');
// })
// .catch(error => {
// console.warn('Issue with jsonapi post image', error)
// Promise.reject(error)
// })
// console.log('save csrf_token', this.csrf_token);
},
onUpdated(){
this.$emit('updated');
}
},
components: {
SvgIcon,
ContentEditable
}
}
</script>
<template>
<div class="editable-audios" :class="{'can-update': can_update}">
<!-- with audio -->
<template v-if="audio">
<div>
<!-- <label v-if="audio.description">{{ audio.description }}</label>
<label v-else>{{ audio.file.filename }}</label> -->
<ContentEditable
tag="label"
:value="audio.description ? audio.description : audio.file.filename"
:contenteditable="can_update"
:data="{
entitytype: data.entitytype,
bundle: data.bundle,
id: data.id,
field: {field_name: data.field.field_name, value:'description', additional_values:{target_id:audio.file.fid}}
}"
v-on:updated="onUpdated" />
<vue-plyr :options="plyr_options">
<audio>
<source :src="audio.file.url" :type="audio.file.filemime" />
</audio>
</vue-plyr>
</div>
<div v-if="can_update" @click="onDeleteAudio" class="delete-btn">
<svg-icon type="mdi" :path="mdiTrashCanOutline_path" />
</div>
</template>
<!-- with out audio -->
<template v-else-if="can_update">
<div @click="addAudio" class="file-btn">
<svg-icon type="mdi" :path="mdiMusicNotePlus_path"/>
<!-- <span>ajouter une image</span> -->
</div>
<input ref="audio_input" type="file" accept ="audio/mp3, audio/flac, audio/ogg" @input="onInput">
</template>
</div>
</template>

View File

@ -0,0 +1,76 @@
<script>
import REST from '@api/rest-axios'
import { mapActions, mapState } from 'pinia'
import { ConcernementsStore } from '@stores/concernements'
import { UserStore } from '@stores/user'
export default {
props: {
checked: Boolean,
label: String,
data: Object
},
emits: ['updated'],
data(){
return {
}
},
computed: {
...mapState(UserStore,['csrf_token']),
},
created () {
console.log('CheckboxEditable created');
},
mounted () {
},
methods: {
...mapActions(ConcernementsStore, ['reloadConcernements']),
onInput(e){
// console.log('onInput checkbox e', e);
let checked = e.target.checked;
// console.log('onInput checkbox checked', checked);
this.save(checked)
},
save(checked){
// console.log('save csrf_token', this.csrf_token);
let params = {
type: this.data.bundle,
// nid: [{"value":this.data.nid}],
[this.data.field]: {value: checked}
};
if (this.data.entitytype === 'node') {
params.nid = [{"value":this.data.id}];
} else {
params.id = [{"value":this.data.id}];
}
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
let url_base = `/${this.data.entitytype === 'node' ? '' : 'entity/'}${this.data.entitytype}`;
REST.patch(`${url_base}/${this.data.id}?_format=json`, params, configs)
.then(({ data }) => {
console.log(`checkboxEditable REST patch ${this.data.entitytype} data`, data)
// TODO if success update the data in pinia
// this.reloadConcernements();
this.$emit('updated');
})
.catch(error => {
console.warn(`Issue with patch node ${this.data.bundle}`, error)
Promise.reject(error)
})
}
},
}
</script>
<template>
<section class="editable">
<label><input type="checkbox" :checked="checked" @input="onInput"> {{ label }}</label>
</section>
</template>

View File

@ -0,0 +1,138 @@
<script>
import REST from '@api/rest-axios'
import { mapActions, mapState } from 'pinia'
import { ConcernementsStore } from '@stores/concernements'
import { UserStore } from '@stores/user'
import MediumEditor from 'medium-editor-x'
import 'medium-editor-x/dist/css/medium-editor.css'
import 'medium-editor-x/dist/css/themes/beagle.css'
export default {
props: {
tag: String,
value: String,
contenteditable : {
type : [Boolean, String],
default : true,
},
html : {
type : [Boolean, String],
default : false,
},
data: Object,
placeholder : {
type : String,
default : 'Ajouter du texte'
}
},
emits: ['updated'],
data(){
return {
editor: null,
spellcheck: false
}
},
computed: {
...mapState(UserStore,['csrf_token']),
},
created () {
console.log('ContentEditable created');
},
mounted () {
if (this.contenteditable && this.html) {
this.editor = new MediumEditor(this.$refs.html_editable, {
toolbar: {
allowMultiParagraphSelection: false,
buttons: ['anchor'],
},
placeholder: {
/* This example includes the default options for placeholder,
if nothing is passed this is what it used */
text: this.placeholder,
hideOnClick: true
}
});
}
},
beforeUnmount() {
},
methods: {
...mapActions(ConcernementsStore, ['reloadConcernements']),
onContentEditableFocusOut(e){
console.log('onContentEditableFocusOut', e);
// console.log('onContentEditableFocusOut data', this.data);
let new_field_content = this.html ? e.target.innerHTML : e.target.innerText;
new_field_content = new_field_content.replace(/<br>$/g, '');
// console.log('onContentEditableFocusOut', new_field_content);
this.$emit('focusout');
if (this.data) {
this.save(new_field_content)
}
},
save(content){
// console.log('save csrf_token', this.csrf_token);
const params = {
type: this.data.bundle,
[this.data.field.field_name]: [{[this.data.field.value]: content}]
};
if (this.data.entitytype === 'node') {
params.nid = [{"value":this.data.id}];
} else {
params.id = [{"value":this.data.id}];
}
// we need additional values for image alt for example
// console.log('additional_values', this.data.field.additional_values);
if (this.data.field.additional_values) {
for (const key in this.data.field.additional_values) {
if (Object.hasOwnProperty.call(this.data.field.additional_values, key)) {
params[this.data.field.field_name][0][key] = this.data.field.additional_values[key]
}
}
}
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
// url is not the same between nodes and others entities
let url_base = `/${this.data.entitytype === 'node' ? '' : 'entity/'}${this.data.entitytype}`;
// call the api
REST.patch(`${url_base}/${this.data.id}?_format=json`, params, configs)
.then(({ data }) => {
console.log('user REST post node data', data)
this.$emit('updated');
})
.catch(error => {
console.warn(`Issue with patch ${this.data.entitytype} ${this.data.bundle}`, error)
Promise.reject(error)
})
}
},
components: {
}
}
</script>
<template>
<component
v-if="!html"
:is="tag"
:contenteditable="contenteditable"
:spellcheck="spellcheck"
@focusout="onContentEditableFocusOut"
>{{ value }}</component>
<component
v-else
:is="tag"
class="html-editable"
ref="html_editable"
v-html="value"
:contenteditable="contenteditable"
:spellcheck="spellcheck"
@focusout="onContentEditableFocusOut"
/>
</template>

View File

@ -0,0 +1,152 @@
<script>
import REST from '@api/rest-axios'
import { mapActions, mapState } from 'pinia'
import { ConcernementsStore } from '@stores/concernements'
import { UserStore } from '@stores/user'
import VueDatePicker from '@vuepic/vue-datepicker';
import '@vuepic/vue-datepicker/dist/main.css';
export default {
props: {
tag: String,
value: String,
end_value : {
type : String,
default : null
},
contenteditable : {
type : [Boolean, String],
default : true
},
mode : {
type : String,
default : null
},
data: Object,
placeholder : {
type : String,
default : 'Choisir une date'
}
},
emits: ['updated'],
data(){
return {
date: null
}
},
computed: {
...mapState(UserStore,['csrf_token']),
attrs() {
// console.log(`this.mode: ${this.mode}`);
let a = {};
if (this.mode && this.mode === 'range') {
a.range = true;
}
return a;
}
},
created () {
console.log('DateEditable created');
this.initDateValues();
},
// updated() {
// console.log('DateEditable updated');
// this.initDateValues();
// },
mounted () {
},
beforeUnmount() {
},
watch: {
value (n, o) {
console.log(`dateEditable watch value n, o`, n, o);
if(n !== o){
this.initDateValues();
}
},
},
methods: {
...mapActions(ConcernementsStore, ['reloadConcernements']),
initDateValues(){
if (this.value) {
if (this.mode && this.mode === 'range') {
this.date = [this.value, this.end_value]
}else{
this.date = this.value;
}
} else {
this.date = null;
}
},
onDateSelected(modeldata){
console.log('onDateSelected, modeldata', modeldata);
this.save();
},
save(){
console.log('save csrf_token', this.csrf_token);
console.log('save this.data', this.data);
console.log('save this.date', this.date);
let params = {
type: this.data.bundle,
};
if (this.data.entitytype === 'node') {
params.nid = [{"value":this.data.id}];
} else {
params.id = [{"value":this.data.id}];
}
if (this.mode && this.mode === "range") {
params[this.data.field.field_name] = [{
value: this.date[0],
end_value: this.date[1]
}]
} else {
params[this.data.field.field_name] = [{
value: this.date
}]
}
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
// url is not the same between nodes and others entities
let url_base = `/${this.data.entitytype === 'node' ? '' : 'entity/'}${this.data.entitytype}`;
// call the api
REST.patch(`${url_base}/${this.data.id}?_format=json`, params, configs)
.then(({ data }) => {
console.log('user REST post node data', data)
this.$emit('updated');
})
.catch(error => {
console.warn(`Issue with patch ${this.data.entitytype} ${this.data.bundle}`, error)
Promise.reject(error)
})
}
},
components: {
VueDatePicker
}
}
</script>
<template>
<VueDatePicker
v-if="contenteditable"
v-model="date"
model-type="yyyy-MM-dd"
format="dd-MM-yyyy"
:enable-time-picker="false"
:clearable="false"
@update:model-value="onDateSelected"
:placeholder="placeholder"
v-bind="attrs"/>
<span v-else class="date">{{ value }}</span>
</template>

View File

@ -0,0 +1,195 @@
<script>
import JSONAPI from '@api/json-axios'
import REST from '@api/rest-axios'
import { mapActions, mapState } from 'pinia'
import { ConcernementsStore } from '@stores/concernements'
import { UserStore } from '@stores/user'
import ContentEditable from '@components/editable/ContentEditable.vue';
import SvgIcon from '@jamescoyle/vue-icon';
import { mdiTrashCanOutline } from '@mdi/js';
import { mdiFilePlusOutline } from '@mdi/js';
import { nextTick } from 'vue'
export default {
props: {
can_update: Boolean,
files: Object,
data: Object,
label: String,
},
emits: ['updated'],
data(){
return {
mdiTrashCanOutline_path: mdiTrashCanOutline,
mdiFilePlusOutline_path: mdiFilePlusOutline,
}
},
computed: {
...mapState(UserStore,['csrf_token']),
},
created () {
console.log('ImageEditable created')
},
mounted () {
},
methods: {
...mapActions(ConcernementsStore, ['reloadConcernements']),
addFile(e){
console.log('addFile', this.$refs);
this.$refs.file_input.click();
},
onInputNewfile(e){
console.log('onFileInput', e);
let file = e.target.files[0];
console.log('onFileInput file', file);
this.saveNewFile(file);
},
saveNewFile(file){
const filename = file.name.normalize('NFD').replace(/[\u0300-\u036f]/g, "").replace(/[^a-zA-Z0-9_\-\.]/g, "_"); // Normalisation Unicode et suppression des accents
console.log('filename', filename);
const configs = {
headers: {
'X-CSRF-Token': this.csrf_token,
'Content-Type': 'application/octet-stream',
'Content-Disposition': `file; filename="${filename}"`,
},
};
JSONAPI.post(`/${this.data.entitytype}/${this.data.bundle}/${this.data.uuid}/${this.data.field.field_name}`, file, configs)
.then(({ data : { data } }) => {
console.log('jsonapi post file', data)
this.$emit('updated');
})
.catch(error => {
console.warn('Issue with jsonapi post file', error)
Promise.reject(error)
})
},
onFocusOut(e){
console.log('onfocusOut', e, this.$refs.file_list);
this.buildFileListThenSaveList();
},
buildFileListThenSaveList(force_Save){
console.log('buildLinkListThenSave files', this.files);
// build links list
let list = [];
let tobesaved = false;
for (let i = 0; i < this.$refs.file_list.children.length; i++) {
const $li = this.$refs.file_list.children[i];
console.log('$li', $li);
if ($li.querySelector('input.description')) {
let description = $li.querySelector('input.description').value;
list.push({
description: description,
target_id: this.files[i].file.fid
});
tobesaved = (description !== this.files[i].description);
}
}
if (!tobesaved) {
tobesaved = this.files.length !== list.length;
}
if (tobesaved || force_Save) {
this.saveList(list);
}
},
saveList(list){
console.log('saveList list', list);
const params = {
type: this.data.bundle,
[this.data.field.field_name]: list
};
if (this.data.entitytype === 'node') {
params.nid = [{"value":this.data.id}];
} else {
params.id = [{"value":this.data.id}];
}
// // we need additional values for image alt for example
// // console.log('additional_values', this.data.field.additional_values);
// if (this.data.field.additional_values) {
// for (const key in this.data.field.additional_values) {
// if (Object.hasOwnProperty.call(this.data.field.additional_values, key)) {
// params[this.data.field.field_name][0][key] = this.data.field.additional_values[key]
// }
// }
// }
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
// url is not the same between nodes and others entities
let url_base = `/${this.data.entitytype === 'node' ? '' : 'entity/'}${this.data.entitytype}`;
// call the api
REST.patch(`${url_base}/${this.data.id}?_format=json`, params, configs)
.then(({ data }) => {
console.log('user REST post node data', data)
this.$emit('updated');
})
.catch(error => {
console.warn(`Issue with patch ${this.data.entitytype} ${this.data.bundle}`, error)
Promise.reject(error)
})
},
async onDeleteFile(i){
console.log(`onDeleteLink ${i}`, this.$refs.file_list.children[i]);
// this.links_nb = this.$refs.links_list.children.length;
// this.$refs.links_list.children[i].remove();
this.files.splice(i,1);
await nextTick();
this.buildFileListThenSaveList(true);
},
onUpdated(){
this.$emit('updated');
},
fileMime(mime){
return mime.replace('application/', '');
},
docLabel(doc){
return doc.description ? doc.description : doc.file.filename;
}
},
components: {
SvgIcon,
ContentEditable
}
}
</script>
<template>
<label>{{ label }}</label>
<ul ref="file_list" class="editable-files" :class="{'can-update': can_update}">
<li v-for="(doc,d) in files" :key="d" class="file-editable">
<template v-if="!can_update">
<a
:href="doc.file.url"
target="_blank"
>
{{ docLabel(doc) }} [{{ fileMime(doc.file.filemime) }}]
</a>
</template>
<template v-else>
<input type="text" class="description" :value="doc.description" placeholder="Description du fichier" @focusout="onFocusOut" />
<!-- <input type="text" class="url" :value="link.url" @focusout="onFocusOut" placeholder="Url du lien" /> -->
<div class="filename">{{ doc.file.filename }}</div>
<div @click="onDeleteFile(d)" class="delete-btn">
<svg-icon type="mdi" :path="mdiTrashCanOutline_path" />
</div>
</template>
</li>
<li v-if="can_update">
<div @click="addFile" class="file-btn">
<svg-icon type="mdi" :path="mdiFilePlusOutline_path"/>
</div>
<input ref="file_input" type="file" accept="application/txt, application/pdf, application/doc, application/docx, application/obs, application/xls" @input="onInputNewfile"/>
</li>
</ul>
</template>

View File

@ -0,0 +1,172 @@
<script>
import JSONAPI from '@api/json-axios'
import REST from '@api/rest-axios'
import { mapActions, mapState } from 'pinia'
import { ConcernementsStore } from '@stores/concernements'
import { UserStore } from '@stores/user'
import ContentEditable from '@components/editable/ContentEditable.vue';
import SvgIcon from '@jamescoyle/vue-icon';
import { mdiTrashCanOutline } from '@mdi/js';
import { mdiImagePlus } from '@mdi/js';
export default {
props: {
can_update: Boolean,
image: Object,
data: Object
},
emits: ['updated'],
data(){
return {
mdiTrashCanOutline_path: mdiTrashCanOutline,
mdiImagePlus_path: mdiImagePlus
}
},
computed: {
...mapState(UserStore,['csrf_token']),
},
created () {
console.log('ImageEditable created');
},
mounted () {
},
methods: {
...mapActions(ConcernementsStore, ['reloadConcernements']),
addImage(e){
console.log('addImage', this.$refs);
this.$refs.image_input.click();
},
onInput(e){
console.log('onFileInput', e);
let file = e.target.files[0];
console.log('onFileInput file', file);
this.save(file);
},
save(file){
const configs = {
headers: {
'X-CSRF-Token': this.csrf_token,
'Content-Type': 'application/octet-stream',
'Content-Disposition': `file; filename="${file.name}"`,
},
};
JSONAPI.post(`/${this.data.entitytype}/${this.data.bundle}/${this.data.uuid}/${this.data.field}`, file, configs)
.then(({ data : { data } }) => {
console.log('jsonapi post image', data)
this.$emit('updated');
})
.catch(error => {
console.warn('Issue with jsonapi post image', error)
Promise.reject(error)
})
},
onDeleteImg(e){
console.log('onDeleteImg', e);
const params = {
type: this.data.bundle,
// nid: [{"value":this.data.id}],
[this.data.field]: {value: null}
};
if (this.data.entitytype === 'node') {
params.nid = [{"value":this.data.id}];
} else {
params.id = [{"value":this.data.id}];
}
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
let url_base = `/${this.data.entitytype === 'node' ? '' : 'entity/'}${this.data.entitytype}`;
REST.patch(`${url_base}/${this.data.id}?_format=json`, params, configs)
.then(({ data }) => {
console.log(`user REST patch node ${this.data.bundle} ${this.data.field}`, data)
// TODO if success update the data in pinia
// this.reloadConcernements();
this.$emit('updated');
})
.catch(error => {
console.warn(`Issue with patch node ${this.data.bundle} ${this.data.field}`, error)
Promise.reject(error)
})
// 405 JSONAPI operation not allowed, don't know why
// const configs = {
// headers: {
// 'X-CSRF-Token': this.csrf_token,
// 'Content-Type': 'application/octet-stream',
// 'Content-Disposition': `file; filename=""`,
// },
// };
// JSONAPI.delete(`/${this.data.entitytype}/${this.data.bundle}/${this.data.uuid}/${this.data.field}`, {}, configs)
// .then(({ data : { data } }) => {
// console.log('jsonapi delete image', data)
// this.$emit('updated');
// })
// .catch(error => {
// console.warn('Issue with jsonapi post image', error)
// Promise.reject(error)
// })
// console.log('save csrf_token', this.csrf_token);
},
onUpdated(){
this.$emit('updated');
}
},
components: {
SvgIcon,
ContentEditable
}
}
</script>
<template>
<div class="editable-image">
<!-- with img -->
<template v-if="image">
<figure>
<img :src="image.url" :alt="image.alt"/>
<!-- <figcaption
:contenteditable="can_update"
v-if="image.alt || can_update"
>
{{ image.alt }}
</figcaption> -->
<ContentEditable
tag="figcaption"
:value="image.alt"
:contenteditable="can_update"
:data="{
entitytype: data.entitytype,
bundle: data.bundle,
id: data.id,
field: {field_name: data.field, value:'alt', additional_values:{target_id:image.id}}
}"
v-on:updated="onUpdated" />
</figure>
<div v-if="can_update" @click="onDeleteImg" class="delete-btn">
<svg-icon type="mdi" :path="mdiTrashCanOutline_path" />
</div>
</template>
<!-- with out img -->
<template v-else-if="can_update">
<div @click="addImage" class="file-btn">
<svg-icon type="mdi" :path="mdiImagePlus_path" @click="onDeleteImg" />
<!-- <span>ajouter une image</span> -->
</div>
<input ref="image_input" type="file" accept ="image/jpeg, image/png, image/jpg" @input="onInput">
</template>
</div>
</template>

View File

@ -0,0 +1,184 @@
<script>
import JSONAPI from '@api/json-axios'
import REST from '@api/rest-axios'
import { mapActions, mapState } from 'pinia'
import { ConcernementsStore } from '@stores/concernements'
import { UserStore } from '@stores/user'
import ContentEditable from '@components/editable/ContentEditable.vue';
import SvgIcon from '@jamescoyle/vue-icon';
import { mdiTrashCanOutline } from '@mdi/js';
import { mdiMusicNotePlus } from '@mdi/js';
import { mdiLinkVariantPlus } from '@mdi/js';
import { nextTick } from 'vue'
export default {
props: {
can_update: Boolean,
links: Array,
data: Object,
label: String
},
emits: ['updated'],
data(){
return {
mdiTrashCanOutline_path: mdiTrashCanOutline,
mdiMusicNotePlus_path: mdiMusicNotePlus,
mdiLinkVariantPlus_path: mdiLinkVariantPlus,
// links_nb : 0
}
},
computed: {
...mapState(UserStore,['csrf_token']),
},
created () {
console.log('LinkEditable created', this.links);
// this.links_nb = this.links.length;
},
beforeUpdate() {
console.log('LinkEditable beforeUpdate', this.links);
},
updated() {
console.log('LinkEditable updated', this.links, this.$refs.links_list);
if (this.$refs.links_list.lastElementChild) {
this.$refs.links_list.lastElementChild.querySelector('input.new.title').value = null;
this.$refs.links_list.lastElementChild.querySelector('input.new.url').value = null;
}
},
mounted () {
},
methods: {
...mapActions(ConcernementsStore, ['reloadConcernements']),
// addLink(e){
// console.log('addLink');
// this.links_nb++;
// },
onFocusOut(e){
console.log('onfocusOut', e, this.$refs.links_list);
this.buildLinkListThenSave();
},
buildLinkListThenSave(force_Save){
console.log('buildLinkListThenSave links', this.links);
// build links list
let list = [];
let tobesaved = false;
for (let i = 0; i < this.$refs.links_list.children.length; i++) {
const $li = this.$refs.links_list.children[i];
if ($li.querySelector('input.url').value) {
let title = $li.querySelector('input.title').value;
let url = $li.querySelector('input.url').value;
console.log(`title ${title}, url ${url}`);
list.push({
title: title,
uri: url
});
console.log(`title ${title} | this.links[i].title ${this.links[i].title}`);
if (!tobesaved) {
tobesaved = (typeof this.links[i] === 'undefined' || title !== this.links[i].title || url !== this.links[i].url);
}
}
}
if (!tobesaved) {
tobesaved = this.links.length !== list.length;
}
if (tobesaved || force_Save) {
this.save(list);
}
},
save(list){
console.log('save list', list);
const params = {
type: this.data.bundle,
[this.data.field.field_name]: list
};
if (this.data.entitytype === 'node') {
params.nid = [{"value":this.data.id}];
} else {
params.id = [{"value":this.data.id}];
}
// // we need additional values for image alt for example
// // console.log('additional_values', this.data.field.additional_values);
// if (this.data.field.additional_values) {
// for (const key in this.data.field.additional_values) {
// if (Object.hasOwnProperty.call(this.data.field.additional_values, key)) {
// params[this.data.field.field_name][0][key] = this.data.field.additional_values[key]
// }
// }
// }
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
// url is not the same between nodes and others entities
let url_base = `/${this.data.entitytype === 'node' ? '' : 'entity/'}${this.data.entitytype}`;
// call the api
REST.patch(`${url_base}/${this.data.id}?_format=json`, params, configs)
.then(({ data }) => {
console.log('user REST post node data', data)
this.$emit('updated');
})
.catch(error => {
console.warn(`Issue with patch ${this.data.entitytype} ${this.data.bundle}`, error)
Promise.reject(error)
})
},
async onDeleteLink(i){
console.log(`onDeleteLink ${i}`, this.$refs.links_list.children[i]);
// this.links_nb = this.$refs.links_list.children.length;
// this.$refs.links_list.children[i].remove();
this.links.splice(i,1);
await nextTick();
this.buildLinkListThenSave(true);
}
},
components: {
SvgIcon,
ContentEditable
}
}
</script>
<template>
<label>{{ label }}</label>
<ul ref="links_list">
<li v-for="(link, l) in links" :key="l" :class="{'link-editable':can_update}">
<!-- link exists can't update -->
<template v-if="!can_update">
<a :href="link.url">
{{ link.title }}
</a>
</template>
<!-- link exists and can update -->
<template v-else>
<input type="text" class="title" :value="link.title" placeholder="Titre du lien" @focusout="onFocusOut" />
<input type="text" class="url" :value="link.url" @focusout="onFocusOut" placeholder="Url du lien" />
<div @click="onDeleteLink(l)" class="delete-btn">
<svg-icon type="mdi" :path="mdiTrashCanOutline_path" />
</div>
</template>
<!-- link does not exists yet and can create -->
</li>
<li v-if="can_update" class="link-editable">
<input type="text" class="new title" placeholder="Titre du lien" @focusout="onFocusOut" />
<input type="text" class="new url" placeholder="https://..." @focusout="onFocusOut" />
<div class="delete-btn">
<svg-icon type="mdi" />
</div>
</li>
</ul>
<!-- <div v-if="can_update" @click="addLink(i)" class="add-btn">
<svg-icon type="mdi" :path="mdiLinkVariantPlus_path" />
</div> -->
</template>
<style scoped>
</style>

View File

@ -0,0 +1,76 @@
<script>
import REST from '@api/rest-axios'
import { mapActions, mapState } from 'pinia'
import { ConcernementsStore } from '@stores/concernements'
import { UserStore } from '@stores/user'
export default {
props: {
value: String,
options: Object,
label: String,
data: Object
},
emits: ['updated'],
data(){
return {
}
},
computed: {
...mapState(UserStore,['csrf_token']),
},
created () {
console.log('SelectEditable created');
},
mounted () {
},
methods: {
...mapActions(ConcernementsStore, ['reloadConcernements']),
onInput(e){
console.log('onInput select e', e);
// let checked = e.target.checked;
let value = e.target.value;
// console.log('onInput checkbox checked', checked);
this.save(value)
},
save(value){
// console.log('save csrf_token', this.csrf_token);
const params = {
type: this.data.bundle,
nid: [{"value":this.data.nid}],
[this.data.field]: {value: value}
};
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
REST.patch(`/node/${this.data.nid}?_format=json`, params, configs)
.then(({ data }) => {
console.log('user REST post node data', data)
// TODO if success update the data in pinia
// this.reloadConcernements();
this.$emit('updated');
})
.catch(error => {
console.warn(`Issue with patch node ${this.data.bundle}`, error)
Promise.reject(error)
})
}
},
}
</script>
<template>
<section class="editable">
<label>{{ label }}</label>
<select :value="value" @input="onInput">
<template v-for="(name,value,index) in options" :key="index">
<option :value="value">{{name}}</option>
</template>
</select>
</section>
</template>

View File

@ -0,0 +1,211 @@
<script>
import JSONAPI from '@api/json-axios'
import REST from '@api/rest-axios'
import { mapActions, mapState } from 'pinia'
import { ConcernementsStore } from '@stores/concernements'
import { UserStore } from '@stores/user'
import ContentEditable from '@components/editable/ContentEditable.vue';
import SvgIcon from '@jamescoyle/vue-icon';
import { mdiTrashCanOutline } from '@mdi/js';
import { mdiMovieOpenPlusOutline } from '@mdi/js';
export default {
props: {
can_update: Boolean,
video: Object,
data: Object
},
emits: ['updated'],
data(){
return {
mdiTrashCanOutline_path: mdiTrashCanOutline,
mdiMovieOpenPlusOutline_path: mdiMovieOpenPlusOutline,
plyr_options: {
controls: ['play', 'progress', 'current-time', 'mute', 'volume']
}
}
},
computed: {
...mapState(UserStore,['csrf_token']),
},
created () {
console.log('VideoEditable created');
},
mounted () {
},
methods: {
...mapActions(ConcernementsStore, ['reloadConcernements']),
// addImage(e){
// console.log('addImage', this.$refs);
// this.$refs.image_input.click();
// },
onSaveVideoLink(e){
console.log('onSaveVideoLink', e);
let url = this.$refs.video_link_input.innerText;
console.log('onSaveVideoLink url', url);
this.save(url);
},
save(content){
// console.log('save csrf_token', this.csrf_token);
const params = {
type: this.data.bundle,
[this.data.field.field_name]: [{[this.data.field.value]: content}]
};
if (this.data.entitytype === 'node') {
params.nid = [{"value":this.data.id}];
} else {
params.id = [{"value":this.data.id}];
}
// we need additional values for image alt for example
// console.log('additional_values', this.data.field.additional_values);
if (this.data.field.additional_values) {
for (const key in this.data.field.additional_values) {
if (Object.hasOwnProperty.call(this.data.field.additional_values, key)) {
params[this.data.field.field_name][0][key] = this.data.field.additional_values[key]
}
}
}
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
let url_base = `/${this.data.entitytype === 'node' ? '' : 'entity/'}${this.data.entitytype}`;
REST.patch(`${url_base}/${this.data.id}?_format=json`, params, configs)
.then(({ data }) => {
console.log('user REST post node data', data)
// TODO if success update the data in pinia
// this.reloadConcernements();
this.$emit('updated');
})
.catch(error => {
console.warn(`Issue with patch ${this.data.entitytype} ${this.data.bundle}`, error)
Promise.reject(error)
})
},
onDeleteVideo(e){
console.log('onDeleteVideo', e);
const params = {
type: this.data.bundle,
// nid: [{"value":this.data.id}],
[this.data.field.field_name]: {[this.data.field.value]: null}
};
if (this.data.entitytype === 'node') {
params.nid = [{"value":this.data.id}];
} else {
params.id = [{"value":this.data.id}];
}
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
let url_base = `/${this.data.entitytype === 'node' ? '' : 'entity/'}${this.data.entitytype}`;
REST.patch(`${url_base}/${this.data.id}?_format=json`, params, configs)
.then(({ data }) => {
console.log(`user REST patch node ${this.data.bundle} ${this.data.field}`, data)
this.$emit('updated');
})
.catch(error => {
console.warn(`Issue with patch node ${this.data.bundle} ${this.data.field}`, error)
Promise.reject(error)
})
// 405 JSONAPI operation not allowed, don't know why
// const configs = {
// headers: {
// 'X-CSRF-Token': this.csrf_token,
// 'Content-Type': 'application/octet-stream',
// 'Content-Disposition': `file; filename=""`,
// },
// };
// JSONAPI.delete(`/${this.data.entitytype}/${this.data.bundle}/${this.data.uuid}/${this.data.field}`, {}, configs)
// .then(({ data : { data } }) => {
// console.log('jsonapi delete image', data)
// this.$emit('updated');
// })
// .catch(error => {
// console.warn('Issue with jsonapi post image', error)
// Promise.reject(error)
// })
// console.log('save csrf_token', this.csrf_token);
}
},
components: {
SvgIcon,
ContentEditable
}
}
</script>
<template>
<div class="editable-video">
<!-- with video -->
<template v-if="video">
<!-- v-for="(video,v) in source.videos"
:key="v" -->
<vue-plyr
>
<div class="plyr__video-embed">
<!-- TODO fix vimeo embed url -->
<iframe
:src="video.url"
allowfullscreen
></iframe>
</div>
</vue-plyr>
<div v-if="can_update" @click="onDeleteVideo" class="delete-btn">
<svg-icon type="mdi" :path="mdiTrashCanOutline_path" />
</div>
</template>
<!-- with out video -->
<template v-else-if="can_update">
<!-- <input ref="videolink_input" type="text" @input="onInput"> -->
<div class="editable-wrapper">
<div
ref="video_link_input"
:contenteditable="can_update"
:spellcheck="spellcheck"
data-placeholder="coller un lien de video" />
<!-- @focusout="onVideoInputFocusOut" -->
<svg-icon class="video-btn" type="mdi" :path="mdiMovieOpenPlusOutline_path" @click="onSaveVideoLink"/>
</div>
</template>
</div>
</template>
<style scoped>
.editable-wrapper{
display: flex;
flex-direction: row;
align-items: center;
gap: 0.5em;
}
[contenteditable] {
flex: auto 1 0;
/* display: inline-block; */
/* padding:12px; */
/* background:red; */
/* min-height: 1em; */
}
[data-placeholder]:empty:before{
content: attr(data-placeholder);
color: #888;
font-style: italic;
}
svg{
/* display: inline-block; */
flex: auto 0 0;
}
</style>

View File

@ -0,0 +1,119 @@
<script>
import { mapActions, mapState } from 'pinia'
import { ConcernementsStore } from '@stores/concernements'
import SvgIcon from '@jamescoyle/vue-icon';
import { mdiHeadphones } from '@mdi/js';
import ContentEditable from '@components/editable/ContentEditable.vue';
export default {
props: ['cid'],
emits: ['main_scrolled'],
data(){
return {
headphones_path: mdiHeadphones,
mainscrolled: false,
headerreduced: false,
}
},
created () {
console.log('Cartouch layout created', this.cid);
this.concernement = this.concernementsByID[this.cid];
console.log('can_update', this.concernement.can_update);
},
mounted () {
// console.log('cartouche layout mounted', this);
this.$refs.cartouche_main.addEventListener('scroll', (event) => {
// console.log('main is scrolling', event);
let $main = event.target;
let scrolled = $main.scrollTop > 0;
this.$emit('main_scrolled', scrolled);
// TODO how to make this failsafe limit responsive ?
if(scrolled && $main.scrollHeight > 900){
this.headerreduced = true;
} else {
this.headerreduced = false;
}
})
},
computed: {
...mapState(ConcernementsStore,['concernementsByID', 'opened_concernement', 'ct_concernement']),
},
watch: {
cid: {
handler (n,o) {
console.log(`TerrainDeVie watch cid o:${o}, n:${n}`);
if (n) {
this.concernement = this.concernementsByID[n];
console.log('can_update', this.concernement.can_update);
}
},
deep: true
}
},
methods: {
...mapActions(ConcernementsStore,['setMapMode']),
},
components: {
SvgIcon,
ContentEditable
}
}
</script>
<template>
<header ref="cartouche_header">
<div class="concernement-cartouche-icons">
<label :class="{ hidden: headerreduced }">{{ ct_concernement.title.description }}</label>
<ContentEditable
tag="h2"
:value="concernement.title"
:class="{ ellipsed: headerreduced }"
:contenteditable="concernement.can_update"
:data="{
entitytype: 'node',
bundle: 'concernement',
id: this.concernement.id,
field: {field_name: 'title', value:'value'}
}" />
<!-- <nav class="icons">
<ul>
<li v-if="concernement.has_recit" >
<svg-icon type="mdi" :path="headphones_path"></svg-icon>
</li>
<li>
<a href="#terraindevie" @click="setMapMode('terraindevie')"><span class="icon terraindevie"></span></a>
</li>
<li v-if="concernement.has_puissancedagir" >
<a href="#puissanceagir" @click="setMapMode('puissancedagir')"><span class="icon puissancedagir"></span></a>
</li>
<li v-if="concernement.has_proximite" >
<a href="#proximite" @click="setMapMode('proximite')"><span class="icon proximite"></span></a>
</li>
<li v-if="concernement.has_superposition" >
<a href="#superposition" @click="setMapMode('superposition')"><span class="icon superposition"></span></a>
</li>
<li v-if="concernement.has_agissantes" >
<a href="#action" @click="setMapMode('action')"><span class="icon action"></span></a>
</li>
<li v-if="concernement.has_doleance" >
<a href="#doleancer" @click="setMapMode('doleancer')"><span class="icon doleancer"></span></a>
</li>
</ul>
</nav> -->
</div>
<slot name="header"></slot>
</header>
<main ref="cartouche_main">
<slot name="main"></slot>
</main>
<footer ref="cartouche_footer">
<slot name="footer"></slot>
</footer>
</template>

View File

@ -1,3 +1,4 @@
// import Vue from "vue"
import { createApp } from 'vue' import { createApp } from 'vue'
import { createPinia } from 'pinia' import { createPinia } from 'pinia'
@ -5,20 +6,50 @@ import App from './App.vue'
import router from './router' import router from './router'
import '@csstools/normalize.css'; import '@csstools/normalize.css';
import '@mdi/font/css/materialdesignicons.css' // import '@mdi/font/css/materialdesignicons.css'
import './assets/main.scss' import './assets/main.scss'
// var decomp = require('poly-decomp'); // var decomp = require('poly-decomp');
// window.decomp = decomp; // window.decomp = decomp;
import VuePlyr from 'vue-plyr'
import 'vue-plyr/dist/vue-plyr.css'
// import * as Sentry from "@sentry/browser";
// import * as Integrations from "@sentry/integrations";
// Sentry.init({
// dsn: "https://d1780f9da2fc4dd28c9c17cb344a088f@frontlog.figli.io/2",
// integrations: [new Integrations.Vue()],
// });
import * as Sentry from "@sentry/vue";
import { createSentryPiniaPlugin } from "@sentry/vue";
const app = createApp(App) const app = createApp(App)
// https://vuejs.org/guide/components/provide-inject.html#provide
app.config.unwrapInjectedRef = true; Sentry.init({
app,
dsn: "https://d1780f9da2fc4dd28c9c17cb344a088f@frontlog.figli.io/2",
integrations: [
Sentry.browserTracingIntegration({ router }),
],
tracesSampleRate: 0.01,
normalizeDepth: 10, // Or however deep you want your state context to be.
environment: "prod",
// release : '1'
});
const pinia = createPinia() const pinia = createPinia()
pinia.use( ({store}) => { store.router = router } ) pinia.use( ({store}) => { store.router = router } )
pinia.use(createSentryPiniaPlugin());
app.use(pinia) app.use(pinia)
app.use(router) app.use(router)
// app.use(VueCollapsiblePanel) // app.use(VueCollapsiblePanel)
app.use(VuePlyr, {
plyr: {}
})
app.mount('#app') app.mount('#app')
// Sentry.captureMessage("sentry vue is working", "info");

View File

@ -4,6 +4,7 @@ import HomeView from '@views/Home.vue'
// import ConcernementView from '@views/Concernement.vue' // import ConcernementView from '@views/Concernement.vue'
import { ConcernementsStore } from '@/stores/concernements' import { ConcernementsStore } from '@/stores/concernements'
import { CommonStore } from '@/stores/common'
const router = createRouter({ const router = createRouter({
@ -24,7 +25,7 @@ const router = createRouter({
props: true props: true
}, },
{ {
path: '/concernement/:id/:eid?', path: '/concernement/:cid/:eid?',
name: 'concernement', name: 'concernement',
// component: ConcernementView, // component: ConcernementView,
// route level code-splitting // route level code-splitting
@ -32,14 +33,24 @@ const router = createRouter({
// which is lazy-loaded when the route is visited. // which is lazy-loaded when the route is visited.
component: () => import('../views/Concernement.vue'), component: () => import('../views/Concernement.vue'),
props: true props: true
},
{
path: '/search/',
name: 'search',
// route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import('../views/Search.vue'),
props: true
} }
] ]
}) })
// set map_mode on first load // set map_mode on first load
router.afterEach((to, from) => { router.afterEach((to, from) => {
console.log('router afterEach', from, to);
const concernement_store = ConcernementsStore(); const concernement_store = ConcernementsStore();
// console.log('router afterEach', from, to, concernement_store.map_mode); const common_store = CommonStore();
if (!from.name) { // we are at first load if (!from.name) { // we are at first load
if (to.hash) { if (to.hash) {
console.log("we have a hash"); console.log("we have a hash");
@ -48,6 +59,13 @@ router.afterEach((to, from) => {
concernement_store.setMapMode("terraindevie"); concernement_store.setMapMode("terraindevie");
} }
} }
// prevent hover map item mouse event if cartouch is opened
if(['static', 'search'].indexOf(to.name) >= 0){
common_store.setCartoucheOpened(true);
concernement_store.resetConcernementOpened();
}else{
common_store.setCartoucheOpened(false);
}
}) })
export default router export default router

View File

@ -1,18 +1,46 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import paper from 'paper';
export const CommonStore = defineStore({ export const CommonStore = defineStore({
id: 'common', id: 'common',
state: () => ({ state: () => ({
hover_elmt: null hover_elmt: null,
map_item_ray: Math.min(window.innerWidth, window.innerHeight) * 0.08,
original_cartouch_width: 450,
cartouch_width: 450,
cartouch_is_opened: false,
paper_symbol_definitions: {}
}), }),
getters: { getters: {
}, },
actions: { actions: {
setHoverElmt(elmt) { setHoverElmt(elmt) {
console.log(`setHoverElmt ${elmt}`); // console.log(`setHoverElmt`, elmt);
// mode can be : terraindevie, proximite, superposition, puissancedagir, action, doleancer // mode can be : terraindevie, proximite, superposition, puissancedagir, action, doleancer
this.hover_elmt = elmt; this.hover_elmt = elmt;
},
setOriginalCartoucheWidth (w) {
console.log('CommonStore setOriginalCartoucheWidth', w);
this.original_cartouch_width = w;
},
setCartoucheWidth (delta) {
console.log('CommonStore setCartoucheWidth', delta);
this.cartouch_width = this.original_cartouch_width * delta + 8 * (delta+1);
},
setCartoucheOpened (v) {
console.log('setCartoucheOpened', v);
this.cartouch_is_opened = v;
},
addPaperSymbolDefinition(name, path) {
// console.log(`addPaperSymbolDefinition ${name}`, path);
// mode can be : terraindevie, proximite, superposition, puissancedagir, action, doleancer
this.paper_symbol_definitions[name] = new paper.SymbolDefinition(path);
},
updateMapItemRay(){
console.log('Common Store updateMapItemRay');
this.map_item_ray = Math.min(window.innerWidth, window.innerHeight) * 0.08;
} }
} }
}) })

View File

@ -1,4 +1,7 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { UserStore } from '@/stores/user';
// import REST from '@api/rest-axios' // import REST from '@api/rest-axios'
// import JSONAPI from '@api/json-axios' // import JSONAPI from '@api/json-axios'
import { print } from 'graphql/language/printer' import { print } from 'graphql/language/printer'
@ -13,19 +16,40 @@ import GQL from '@api/graphql-axios'
import ConcernementFields from '@api/gql/concernement.fragment.gql' import ConcernementFields from '@api/gql/concernement.fragment.gql'
// import EntityFields from '@api/gql/entitydef.fragment.gql' // import EntityFields from '@api/gql/entitydef.fragment.gql'
import _assign from 'lodash/assign';
import _assignIn from 'lodash/assignIn';
import _merge from 'lodash/merge';
export const ConcernementsStore = defineStore({ export const ConcernementsStore = defineStore({
id: 'concernements', id: 'concernements',
state: () => ({ state: () => ({
map_mode: null, map_mode: null,
concernements_loading_nb: 0,
concernements: [], concernements: [],
concernementsByID: {}, concernementsByID: {},
allEntitesById: {}, allEntitesById: {},
allBesoinsById: {}, allBesoinsById: {},
opened: false, allSuperpositions: [],
allSuperpositions_bycids: {},
allSuperpositions_clustered: [],
allMapItems_byid: {},
allProximites: [],
opened_concernement: false,
opened_entite_id: null, opened_entite_id: null,
opened_recit: false,
recit_plyr_player: null,
ct_concernement: {}, ct_concernement: {},
ct_entite: {}, ct_entite: {},
ct_cercle_politique: {},
p_groupes_interets: {},
p_reception_et_traitement: {},
p_mise_en_oeuvre_decision: {},
p_reception_application_decision: {},
concernements_loaded: false, concernements_loaded: false,
concernements_are_loading: false,
concernement_active_revision: null,
detailsZoomValue: 1,
}), }),
getters: { getters: {
@ -38,6 +62,7 @@ export const ConcernementsStore = defineStore({
}, },
loadConcernements () { loadConcernements () {
console.log('concernements store loadConcernements'); console.log('concernements store loadConcernements');
this.concernements_are_loading = true;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const ast = gql`{ const ast = gql`{
allconcernements { allconcernements {
@ -46,53 +71,602 @@ export const ConcernementsStore = defineStore({
} }
${ConcernementFields} ${ConcernementFields}
` `
console.log('ast', ast); // console.log('ast', ast);
GQL.post('', { query: print(ast) }) GQL.post('', { query: print(ast) })
.then(({ data : { data : { allconcernements } } }) => { .then(({ data : { data : { allconcernements } } }) => {
console.log('loadconcernements loaded', allconcernements) console.log('|||||||||||| loadconcernements loaded ||||||||||||||||||', allconcernements)
this.concernements = []; this.concernements = [];
allconcernements.forEach(concernement => { this.parseConcernements(allconcernements, true)
this.concernements_loaded = true;
this.concernements_loading_nb ++;
this.concernements_are_loading = false;
resolve();
})
.catch(error => {
console.warn('Issue with loadConcernements', error)
this.concernements_are_loading = false;
Promise.reject(error)
})
})
},
parseConcernements(allconcernements, init) {
console.log('parse concernements');
let temp_allSuperpositions = [];
allconcernements.forEach((concernement) => {
// console.log(`parsing concernement ${concernement.id}`);
concernement.visible = true;
concernement.entites_byid = {}; concernement.entites_byid = {};
concernement.entitesagissantes_byid = {}; concernement.entitesagissantes_byid = {};
concernement.has_proximites = false;
concernement.has_superpositions = false;
concernement.has_agissantes = false; concernement.has_agissantes = false;
var entites_temp = concernement.entites; // record a temp entites liste
concernement.entites = []; // erase the concernement.entite array as we want to keep only visible entites concernement.entites.forEach(entite => {
entites_temp.forEach(entite => { // console.log(`parsing entite ${entite.id}`);
if (entite.entite) { // entite.entite may be null because of workflow confidentiality if (entite.entite) { // entite.entite may be null because of workflow confidentiality
if (!concernement.entites_byid[entite.entite.id]) {
concernement.entites_byid[entite.entite.id] = entite; concernement.entites_byid[entite.entite.id] = entite;
}
// record a flat list of all entités of all concernement for map-popup
if (!this.allEntitesById[entite.entite.id]) {
this.allEntitesById[entite.entite.id] = entite;
this.allEntitesById[entite.entite.id].cid = concernement.id;
}
// Do not integrate the entite if not active
if(entite.active){
// record entite agissante // record entite agissante
if (entite.entite.agissante) { if (entite.entite.agissante) {
if (!concernement.entitesagissantes_byid[entite.entite.id]) {
concernement.entitesagissantes_byid[entite.entite.id] = entite; concernement.entitesagissantes_byid[entite.entite.id] = entite;
}
concernement.has_agissantes = true; concernement.has_agissantes = true;
} }
// record a flat list of all entités of all concernement for map-popup
this.allEntitesById[entite.entite.id] = entite; // PROXIMITES
concernement.entites.push(entite); // fill the entites array with visible entite only if (entite.entite.proximite.length) {
// console.log("proximite", entite.entite.proximite);
concernement.has_proximites = true;
} }
// SUPERPOSITIONS
if (entite.entite.superposition.length) {
// create properties for later
if (init) {
concernement.superpositions = {};
concernement.superposition_constraints_id = {};
concernement.all_superposed_concernements_id = [];
concernement.superposed_mapitem_id_by_mapitem_id = {};
}
entite.entite.superposition.forEach(entite_superpose => {
// console.log(`superposition eid:${entite.entite.id}, teid:${entite_superpose.id}`);
let already_recorded = false;
// loop through all already recorded superposition to complete the array instead of create duplicates
// TODO check if target cid and eid are accessible before recording the superposition
// check if half of the superpositions is already recorded, if yes complete it (add the missing concernement id)
for(let superposition of temp_allSuperpositions) {
for(let superposition_item of superposition) {
if (superposition_item.eid === entite.entite.id && !superposition_item.cid) {
// console.log(`already_recorded, eid:${entite.entite.id}, teid:${entite_superpose.id}`, entite.entite.title);
already_recorded = true;
superposition_item.cid = concernement.id;
break;
}
}
if (already_recorded) {
break;
}
}
// if not already recorded, add it to the array. It is incomplete has it's missing one concernement id wich will be filled in next loops
if (!already_recorded) {
// console.log(`NOT already_recorded, eid:${entite.entite.id}, teid:${entite_superpose.id}`, entite.entite.title);
let s = [
{
cid: concernement.id,
eid: entite.entite.id
},
{
cid: null,
eid: entite_superpose.id
}
];
// concernement.superpositions.push(s);
temp_allSuperpositions.push(s);
}
})
}
}
}
}); // end of concernement.entites loop
// revisions
concernement.active_revision = concernement.revision_id;
concernement.revisions_byid = {};
concernement.revisions.forEach(rev => {
concernement.revisions_byid[rev.revision_id] = rev;
}); });
// puissance d'agir // puissance d'agir
concernement.has_puissancedagir = concernement.besoins.length ? true : false; concernement.has_puissancedagir = concernement.besoins.length ? true : false;
// console.log('concernement.besoins', concernement.besoins);
concernement.besoins.forEach(besoin => { concernement.besoins.forEach(besoin => {
if (besoin) {
this.allBesoinsById[besoin.id] = besoin; this.allBesoinsById[besoin.id] = besoin;
}
}); });
// doleance // doleance
concernement.has_doleance = concernement.doleances.length ? true : false; concernement.has_doleance = concernement.doleances.length ? true : false;
if (concernement.has_doleance) {
// console.log('concernement has doleance', concernement.doleances);
concernement.opened_doleance = {
id: concernement.doleances[0].id
};
}
// recit
concernement.has_recit = concernement.recit !== null;
// common // common
// if (!concernement_is_reloaded) {
this.concernements.push(concernement); this.concernements.push(concernement);
this.concernementsByID[concernement.id] = concernement; this.concernementsByID[concernement.id] = concernement;
// }else{
// // this.concernements[concernement_index] = concernement;
// this.concernementsByID[concernement.id] = concernement;
// // TODO check that this.concernements and this.concernementsByID contains the same item
// }
}); // end of concernements loop
// console.log('this.concernements', this.concernements);
// console.log('this.concernementsByID', this.concernementsByID);
// console.log('temp_allSuperpositions', temp_allSuperpositions);
// cleaning superpositions, removing all incomplète onces
this.allSuperpositions = [];
temp_allSuperpositions.forEach(s => {
if (s[0] && s[0].cid && s[0].eid && s[1] && s[1].cid && s[1].eid) {
this.allSuperpositions.push(s);
this.concernementsByID[s[0].cid].has_superpositions = true;
this.concernementsByID[s[1].cid].has_superpositions = true;
}
}); });
this.concernements_loaded = true; // console.log('this.allSuperpositions', this.allSuperpositions);
// 1 check if cluster already exists and if yes complete with the next item of cluster
// 2 if cluster deos not exists, create the cluster and fill it with first item of cluster
// 1 check if cluster already exists and if yes complete with the next item of cluster
// get superpositions by cluster
for(let superpos_to_record of this.allSuperpositions){
let recorded = false;
// console.log('-- -- --');
// console.log(`superpos_to_record : ${superpos_to_record[0].cid}-${superpos_to_record[0].eid}, ${superpos_to_record[1].cid}-${superpos_to_record[1].eid}`);
// loop through alredy recorded clusters
for(let [cluster_index, superpo_cluster] of this.allSuperpositions_clustered.entries()){
// console.log('cluster_index', cluster_index);
// for each cluster loop throug each superposition
in_cluster_loop:{
for(let s of superpo_cluster){
// console.log(`s : ${s.cid}-${s.eid}`);
// loop through each cid_eid couple of superpo to be recorded
for(let i = 0; i <= 1; i++){
// if one couple already recorded in the cluster, add the other one to the same cluster
if (superpos_to_record[i].cid === s.cid && superpos_to_record[i].eid === s.eid){
// console.log('-- recorded');
let j = i === 0 ? 1 : 0;
// check if item is not already recorded in the cluster (in case of reparsing concernements)
let already_clustered = false;
for (let s2 of superpo_cluster) {
if (superpos_to_record[j].cid === s2.cid && superpos_to_record[j].eid === s2.eid){
already_clustered = true;
break;
}
}
// if not already recorded
if (!already_clustered) {
// add the right item to the cluster
this.allSuperpositions_clustered[cluster_index].push(superpos_to_record[j]);
}
// record the superposition on the concernement BY cluster index
// create array if not already exists
if(typeof this.concernementsByID[superpos_to_record[j].cid].superpositions[cluster_index] === 'undefined'){
this.concernementsByID[superpos_to_record[j].cid].superpositions[cluster_index] = [superpos_to_record];
}else if(!already_clustered){
this.concernementsByID[superpos_to_record[j].cid].superpositions[cluster_index].push(superpos_to_record);
}
recorded = true;
break in_cluster_loop;
}
}
}
}
}
// 2 if cluster deos not exists, create the cluster and fill it with first item of cluster
if(!recorded){
// console.log('-- not recorded');
// create cluster and fill it with first item of couple
this.allSuperpositions_clustered.push(superpos_to_record);
// record superposition on each concernement of each couple member BY cluster index
for( let i=0; i <= 1; i++){
this.concernementsByID[superpos_to_record[i].cid].superpositions[this.allSuperpositions_clustered.length-1] = [superpos_to_record];
// console.log(`concernement ${superpos_to_record[i].cid} superposition by cluster index`,this.concernementsByID[superpos_to_record[i].cid].superpositions);
}
}
}
// console.log('this.allSuperpositions_clustered', this.allSuperpositions_clustered);
// console.log(`end of parsing concernements`);
},
reloadConcernements () {
console.log('reloadConcernements');
return new Promise((resolve, reject) => {
// reset the arrays
this.concernements = [];
this.concernementsByID = {};
// this.concernements_loaded = false;
this.loadConcernements()
.then(()=>{
resolve();
});
})
},
reloadConcernementEntites(nid){
let tmp_conc = this.concernementsByID[nid];
console.log(`reloadConcernementEntites len: ${tmp_conc.entites.length} revision: ${tmp_conc.revision_id} nid: ${nid} ${Math.random()*10000}`);
return new Promise((resolve, reject) => {
const ast = gql`{
concernement(id:${nid}) {
id
entites {
id
revision_id
active
menacemaintien
actuelfuture
prise
entite {
title
id
agissante
proximite {
id
title
}
superposition {
id
title
}
}
}
revision_id
revisions {
revision_id
changed
entites {
id
revision_id
active
menacemaintien
prise
actuelfuture
entite {
id
title
agissante
proximite {
id
title
}
superposition {
id
title
}
}
}
}
}
}
`
// console.log('ast', ast);
GQL.post('', { query: print(ast) })
.then(({ data : { data : { concernement } } }) => {
console.log(`reloadConcernementEntites loaded len: ${concernement.entites.length} revision: ${concernement.revision_id}`, concernement)
let tmp_conc = this.concernementsByID[concernement.id];
// merge old concernement entites with new once
_assign(tmp_conc.entites, concernement.entites);
// records and/or merge into general object and on conernement entitites_byid
tmp_conc.entites.forEach(entite => {
entite.cid = tmp_conc.id;
if(entite.entite){
if (this.allEntitesById[entite.entite.id]) {
_assign(this.allEntitesById[entite.entite.id], entite);
}else{
this.allEntitesById[entite.entite.id] = entite;
}
if (tmp_conc.entites_byid[entite.entite.id]) {
_assign(tmp_conc.entites_byid[entite.entite.id], entite);
}else{
tmp_conc.entites_byid[entite.entite.id] = entite;
}
}
});
// add and/or merge revisions
tmp_conc.active_revision = concernement.revision_id;
concernement.revisions.forEach(rev => {
if(tmp_conc.revisions_byid[rev.revision_id]){
_assign(tmp_conc.revisions_byid[rev.revision_id], rev);
}else{
tmp_conc.revisions_byid[rev.revision_id] = rev;
tmp_conc.revisions.push(rev);
}
})
let user = UserStore();
user.getUserEntitees()
.then(() => {
console.log('reloadConcernementEntites graphql userentites loaded')
}) })
.catch(error => { .catch(error => {
console.warn('Issue with loadConcernements', error) console.warn('Issue with graphql userentites loading', error);
})
resolve(concernement);
})
.catch(error => {
console.warn('Issue with reloadConcernementEntites', error)
reject(error);
Promise.reject(error) Promise.reject(error)
}) })
}) })
}, },
reloadConcernementBesoins(nid){
let tmp_conc = this.concernementsByID[nid];
console.log(`reloadConcernementEntites len: ${tmp_conc.entites.length} revision: ${tmp_conc.revision_id} nid: ${nid}`);
return new Promise((resolve, reject) => {
const ast = gql`{
concernement(id:${nid}) {
id
besoins {
author
description
id
index
confidentialite
reponses {
author
avec
id
ou
qui
quoi
can_update
confidentialite
}
}
}
}
`
GQL.post('', { query: print(ast) })
.then(({ data : { data : { concernement } } }) => {
console.log(`reloadConcernementBesoins loaded len: ${concernement.besoins.length}`, concernement)
let tmp_conc = this.concernementsByID[concernement.id];
// tmp_conc.besoins.forEach(besoin => {
// besoin.reponses.forEach(reponse => {
// console.log(`BEFORE _merge besoin id:${besoin.id} reponse id:${reponse.id}, paper_id:${reponse.paper_id}`);
// });
// });
// merge old concernement besoins with new once
_merge(tmp_conc.besoins, concernement.besoins);
// tmp_conc.besoins.forEach(besoin => {
// besoin.reponses.forEach(reponse => {
// console.log(`AFTER _merge besoin id:${besoin.id} reponse id:${reponse.id}, paper_id:${reponse.paper_id}`);
// });
// });
tmp_conc.has_puissancedagir = tmp_conc.besoins.length ? true : false;
// records and/or merge into general object
tmp_conc.besoins.forEach(besoin => {
besoin.cid = tmp_conc.id;
if (this.allBesoinsById[besoin.id]) {
_merge(this.allBesoinsById[besoin.id], besoin);
}else{
this.allBesoinsById[besoin.id] = besoin;
}
});
resolve(concernement);
})
.catch(error => {
console.warn('Issue with reloadConcernementBesoins', error)
reject(error);
Promise.reject(error)
})
});
},
reloadProximites (entite_id) {
console.log(`reloadProximites src_id:${entite_id}`);
console.log('this.allEntitesById[entite_id]', this.allEntitesById[entite_id]);
return new Promise((resolve, reject) => {
let old_entite = this.allEntitesById[entite_id];
const ast = gql`{
entite(id:${entite_id}) {
title
id
proximite {
id
title
}
}
}
`
GQL.post('', { query: print(ast) })
.then(({ data : { data : { entite } } }) => {
console.log(`reloadProximites loaded`, entite);
let concernement = this.concernementsByID[old_entite.cid];
console.log('concernement', concernement);
if (entite.proximite.length) {
concernement.has_proximites = true;
// update the entites
concernement.entites_byid[entite.id].entite.proximite = entite.proximite;
// also update the current revision entite (needed for mapItem display)
let revision_entites_len = concernement.revisions_byid[concernement.revision_id].entites.length;
for (let i = 0; i < revision_entites_len; i++) {
let rev_entite = concernement.revisions_byid[concernement.revision_id].entites[i];
if (rev_entite.entite && rev_entite.entite.id === entite.id) {
concernement.revisions_byid[concernement.revision_id].entites[i].entite.proximite = entite.proximite;
break;
}
}
// update the user's entite list
let user = UserStore();
console.log('user', user);
user.getUserEntitees()
.then(() => { // { data : { data : { userentites } } }
console.log('reloadProximites graphql userentites loaded')
// this.user_entites = userentites;
resolve();
})
.catch(error => {
console.warn('Issue with graphql userentites loading', error)
Promise.reject(error)
})
}
})
.catch(error => {
console.warn('Issue with reloadProximites', error);
})
});
},
reloadConcernementCerclePol(nid){
// let tmp_conc = this.concernementsByID[nid];
console.log(`reloadConcernementCerclePol nid: ${nid} ${Math.random()*10000}`);
return new Promise((resolve, reject) => {
const ast = gql`{
concernement(id:${nid}) {
id
doleances {
id
author
bundle
path
title
uuid
#1
date_leprobleme {
start
}
leprobleme
lenquete
groupesinterets {
id
revision_id
date {
end
start
}
groupe_interets
accorder_interets
formuler
}
#2
date_adresse {
start
}
entite_adresse_doleance
comment_enonce_doleance
a_qui_adresse_doleance
reception_traitement {
id
revision_id
date {
end
start
}
entite_adressee
doleance_formulee
traite_doleance
entite_recoit_doleance
}
#3
date_decision {
start
}
entites_decisionnaires
decision_formulee
mise_en_oeuvre_decision {
id
revision_id
date {
end
start
}
entite_adresse_decision
formule_decision
entite_metenoeuvre_decisio
}
#4
date_application {
start
}
entite_adresse_application
aqui_adresse_decision
comment_formule_decision
receptions_et_applications {
id
revision_id
date {
end
start
}
applique_decision
formule_decision_applic
entite_recoit_decision
}
probleme_initial_resolu
oui_nouvelle_situation
non_adresse_doleance
}
}
}
`
// console.log('ast', ast);
GQL.post('', { query: print(ast) })
.then(({ data : { data : { concernement } } }) => {
console.log(`reloadConcernementCerclePol loaded len: ${concernement.doleances.length} revision: ${concernement.revision_id}`, concernement)
let tmp_conc = this.concernementsByID[concernement.id];
// merge old concernement entites with new once
_assign(tmp_conc.doleances, concernement.doleances);
// redefine opened doleance if needed
tmp_conc.has_doleance = tmp_conc.doleances.length ? true : false;
if (tmp_conc.has_doleance) {
// console.log('concernement has doleance', tmp_conc.doleances);
if (!tmp_conc.opened_doleance) {
tmp_conc.opened_doleance = {
id: tmp_conc.doleances[0].id
};
}
}
// resolve
resolve(concernement);
})
.catch(error => {
console.warn('Issue with reloadConcernementCerclePol', error)
reject(error);
Promise.reject(error)
})
});
},
loadContentTypeDefinition () { loadContentTypeDefinition () {
const body = { const body = {
query: ` query: `
@ -121,7 +695,7 @@ export const ConcernementsStore = defineStore({
}) })
// concernement // entite
body.variables = { type: 'node', bundle: 'entite' } body.variables = { type: 'node', bundle: 'entite' }
GQL.post('', body) GQL.post('', body)
.then(({ data: { data: { entitydef }}}) => { .then(({ data: { data: { entitydef }}}) => {
@ -133,24 +707,155 @@ export const ConcernementsStore = defineStore({
}) })
// cercle_politique
body.variables = { type: 'node', bundle: 'cercle_politique' }
GQL.post('', body)
.then(({ data: { data: { entitydef }}}) => {
// console.log('loadContentTypeDefinition entitydef', entitydef);
entitydef.fields.forEach(field => {
this.ct_cercle_politique[field.field_name] = field;
});
console.log('loadContentTypeDefinition entitydef cercle_politique', this.ct_cercle_politique);
})
// paragraphe groupes_interets
body.variables = { type: 'paragraph', bundle: 'groupes_interets' }
GQL.post('', body)
.then(({ data: { data: { entitydef }}}) => {
// console.log('loadContentTypeDefinition entitydef', entitydef);
entitydef.fields.forEach(field => {
this.p_groupes_interets[field.field_name] = field;
});
console.log('loadContentTypeDefinition entitydef p_groupes_interets', this.p_groupes_interets);
})
// paragraphe reception_et_traitement
body.variables = { type: 'paragraph', bundle: 'reception_et_traitement' }
GQL.post('', body)
.then(({ data: { data: { entitydef }}}) => {
// console.log('loadContentTypeDefinition entitydef', entitydef);
entitydef.fields.forEach(field => {
this.p_reception_et_traitement[field.field_name] = field;
});
console.log('loadContentTypeDefinition entitydef p_reception_et_traitement', this.p_reception_et_traitement);
})
// paragraphe mise_en_oeuvre_decision
body.variables = { type: 'paragraph', bundle: 'mise_en_oeuvre_decision' }
GQL.post('', body)
.then(({ data: { data: { entitydef }}}) => {
// console.log('loadContentTypeDefinition entitydef', entitydef);
entitydef.fields.forEach(field => {
this.p_mise_en_oeuvre_decision[field.field_name] = field;
});
console.log('loadContentTypeDefinition entitydef p_mise_en_oeuvre_decision', this.p_mise_en_oeuvre_decision);
})
// paragraphe reception_application_decision
body.variables = { type: 'paragraph', bundle: 'reception_application_decision' }
GQL.post('', body)
.then(({ data: { data: { entitydef }}}) => {
// console.log('loadContentTypeDefinition entitydef', entitydef);
entitydef.fields.forEach(field => {
this.p_reception_application_decision[field.field_name] = field;
});
console.log('loadContentTypeDefinition entitydef p_reception_application_decision', this.p_reception_application_decision);
})
}, },
openCloseConcernements (id) { hideShowConcernement (id, state) {
console.log(`openCloseConcernements id: ${id}`); // console.log(`disableConcernement id: ${id}`);
var state;
this.concernements.forEach((c, i) => { this.concernements.forEach((c, i) => {
state = id == c.id; if (c.id === id) {
this.concernements[i].opened = this.concernementsByID[c.id].opened = state; this.concernements[i].visible = this.concernementsByID[id].visible = state;
if (state) { }
this.opened = c; })
},
openCloseConcernements (cid, mi_id) {
console.log(`openCloseConcernements cid: ${cid}, mi_id: ${mi_id}`);
var state;
let mapitem_id = mi_id ? mi_id : cid ? this.concernementsByID[cid].mapitems_ids[this.concernementsByID[cid].mapitems_ids.length -1] : null;
this.opened_concernement = null;
this.opened_recit = null;
this.concernements.forEach((c, i) => {
// console.log(`openCloseConcernements foreach id: ${id}, c.id: ${c.id}, state: ${state}`, id, c.id);
c.opened = this.concernements[i].opened = this.concernementsByID[c.id].opened = cid === c.id;
if (c.opened) {
this.opened_concernement = c;
this.opened_concernement.opened_mapitem_id = mapitem_id;
if (c.has_recit && this.map_mode === "terraindevie") {
this.opened_recit = c.recit;
}
this.concernement_active_revision = {cid: cid, rid: c.active_revision}
// console.log('openCloseConcernements', this.opened_concernement.opened);
} }
}); });
}, },
resetConcernementOpened () { resetConcernementOpened () {
this.opened = null; this.opened_concernement = null;
this.openCloseConcernements(); this.openCloseConcernements();
}, },
setOpenedEntityId(id){ // setConcernementScale(cid, scale){
// console.log(`setConcernementScale ${cid} ${scale}`);
// this.concernementsByID[cid].scale = scale;
// },
setOpenedEntiteId(id){
this.opened_entite_id = id; this.opened_entite_id = id;
},
setBesoinPaperId(paper_id, cid, bid, rid){
console.log(`setBesoinPaperId paper_id: ${paper_id}, cid: ${cid}, bid: ${bid}, rid: ${rid}`);
this.concernementsByID[cid].besoins.forEach((b,j) => {
if(b.id === bid) {
if (!rid) {
this.concernementsByID[cid].besoins[j].paper_id = paper_id;
} else {
this.concernementsByID[cid].besoins[j].reponses.forEach((r,k) => {
if (r.id === rid) {
this.concernementsByID[cid].besoins[j].reponses[k].paper_id = paper_id;
console.log(`this.concernementsByID[${cid}].besoins[${j}].reponses[${k}].paper_id`, this.concernementsByID[cid].besoins[j].reponses[k].paper_id);
} }
})
}
}
})
// }
// })
},
setOpenedDoleance(cid, did){
console.log(`setOpenedDoleance cid:${cid}, did:${did})`, cid, did);
this.concernementsByID[cid].opened_doleance = {id: did};
// console.log('this.opened_concernement.opened_doleance', this.opened_concernement.opened_doleance);
},
setOpenedDoleanceField(cid, did, field, index){
console.log(`setOpenedDoleanceField cid, did, field, index`, cid, did, field, index);
this.concernementsByID[cid].opened_doleance = {
cid: cid,
id: did,
field: field,
field_index: index
};
},
setOpenedRecit (recit) {
this.opened_recit = recit;
},
setRecitPlayer (player) {
console.log('concernement store setRecitPlayer', player);
this.recit_plyr_player = player;
},
setActiveRevision (cid, rid) {
console.log(`setActiveRevision, cid:${cid}, rid:${rid}`);
// this.concernementsByID[cid].active_revision = rid;
this.concernement_active_revision = {cid: cid, rid: rid};
},
setDetailsZoomValue (z) {
console.log(`concernement store setDetailsZoomValue ${z}`);
this.detailsZoomValue = z;
}
} }
}) })

View File

@ -1,12 +0,0 @@
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})

99
src/stores/search.js Normal file
View File

@ -0,0 +1,99 @@
import { defineStore } from 'pinia'
import { print } from 'graphql/language/printer'
import gql from 'graphql-tag'
// import REST from '@api/rest-axios'
import GQL from '@api/graphql-axios'
// import JSONAPI from '@api/json-axios'
import MA from '@api/ma-axios'
import qs from 'querystring-es3'
import ResultsConcernementFields from '@api/gql/results_concernement.fragment.gql'
import ResultsEntiteFields from '@api/gql/results_entite.fragment.gql'
export const SearchStore = defineStore({
id: 'search',
state: () => ({
phrase: null,
contentTypeFilter: 'concernements',
results: null,
loaded_results: null
}),
getters: {
},
actions: {
setSearchValue (value) {
console.log('setSearchValue', value);
if (value) {
this.phrase = value;
}
},
setContentType (v) {
this.contentTypeFilter = v
},
newSearch () {
console.log('search store loadResults', this.keys);
// this.keys = keys;
const params = {
phrase: this.phrase,
content_type: this.contentTypeFilter
}
const q = qs.stringify(params)
return MA.get('/ouatt_searchapi/getresults?' + q)
.then(({ data }) => {
console.log('search MA getresults data', data, data.nids)
this.results = data;
this.loadeResults();
})
.catch((error) => {
console.warn('Issue with getResults', error)
// window.location.reload()
Promise.reject(error)
})
},
loadeResults () {
return new Promise((resolve, reject) => {
let ast;
if (this.contentTypeFilter === 'entites') {
ast = gql`{
entites(ids: [${this.results.nids}]) {
...ResultsEntiteFields
}
}
${ResultsEntiteFields}
`
GQL.post('', { query: print(ast) })
.then(({ data : { data : { entites } } }) => {
console.log('entites all loaded', entites)
this.loaded_results = entites
})
.catch(error => {
console.warn('Issue with loadResults', error)
Promise.reject(error)
})
} else {
ast = gql`{
concernements(ids: [${this.results.nids}]) {
...ResultsConcernementFields
}
}
${ResultsConcernementFields}
`
GQL.post('', { query: print(ast) })
.then(({ data : { data : { concernements } } }) => {
console.log('concernements all loaded', concernements)
this.loaded_results = concernements
})
.catch(error => {
console.warn('Issue with loadResults', error)
Promise.reject(error)
})
}
// console.log('ast', ast);
})
}
}
})

View File

@ -23,7 +23,7 @@ export const StaticsStore = defineStore({
console.log('statics store loadStatics'); console.log('statics store loadStatics');
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const ast = gql`{ const ast = gql`{
allstatics { promotedstatics {
...StaticsFields ...StaticsFields
} }
} }
@ -31,11 +31,11 @@ export const StaticsStore = defineStore({
` `
console.log('ast', ast); console.log('ast', ast);
GQL.post('', { query: print(ast) }) GQL.post('', { query: print(ast) })
.then(({ data : { data : { allstatics } } }) => { .then(({ data : { data : { promotedstatics } } }) => {
console.log('loadstatics loaded', allstatics) console.log('loadstatics loaded', promotedstatics)
this.statics = allstatics this.statics = promotedstatics
allstatics.forEach((s) => { promotedstatics.forEach((s) => {
// console.log("s", s); // console.log("s", s);
this.statics_byid[s.id] = s this.statics_byid[s.id] = s
}); });

View File

@ -1,4 +1,6 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ConcernementsStore as concrnmtStore } from '@/stores/concernements'
import REST from '@api/rest-axios' import REST from '@api/rest-axios'
import JSONAPI from '@api/json-axios' import JSONAPI from '@api/json-axios'
import qs from 'querystring-es3' import qs from 'querystring-es3'
@ -19,7 +21,8 @@ export const UserStore = defineStore({
name: null, name: null,
roles: [], roles: [],
isAdmin: false, isAdmin: false,
logginMessage: null logginMessage: null,
user_entites: null,
}), }),
getters: { getters: {
@ -37,26 +40,22 @@ export const UserStore = defineStore({
this.isloggedin = true //data.attributes.status this.isloggedin = true //data.attributes.status
console.log('user store checkuser isloggedin', this.isloggedin); console.log('user store checkuser isloggedin', this.isloggedin);
this.userGetRoles() this.getUser(); // necessery to get the csrf-token
.then(({ data : { data : { user } } }) => {
console.log('graphql user loaded', user)
this.roles = user.roles
this.checkIsAdmin()
})
.catch(error => {
console.warn('Issue with graphql user loading', error)
Promise.reject(error)
})
}) })
} }
}) })
},
getSessionToken(){
}, },
userLogin (credentials) { userLogin (credentials) {
console.log('user store userLogin', credentials); console.log('user store userLogin', credentials);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.getToken(credentials) this.postCredentials(credentials)
.then((response) => { .then((response) => {
console.log('userLogin getToken response', response) console.log('userLogin postCredentials response', response)
if (response.status === 200) { if (response.status === 200) {
this.uid = response.data.current_user.uid this.uid = response.data.current_user.uid
@ -67,23 +66,26 @@ export const UserStore = defineStore({
this.logout_token = response.data.logout_token this.logout_token = response.data.logout_token
this.getUser().then(userdata => { this.getUser().then(userdata => {
console.log('User Loggedin') console.log('User Loggedin')
// todo reload concernements
// concrnmtStore().reloadConcernements(); // INFO would be good but to much complicated for now, just reload the page
window.location.reload();
resolve() resolve()
}) })
} else { } else {
this.loginMessage = response.data.message this.loginMessage = response.data.message
console.warn('Issue with getToken', response) console.warn('Issue with postCredentials', response)
console.log('user loggein failed', this.loginMessage) console.log('user loggein failed', this.loginMessage)
Promise.reject(new Error('user loggin failed')) Promise.reject(new Error('user loggin failed'))
} }
}) })
.catch(error => { .catch(error => {
console.warn('Issue with Dispatch getToken', error) console.warn('Issue with Dispatch postCredentials', error)
Promise.reject(error) Promise.reject(error)
}) })
}) })
}, },
getToken (credentials) { postCredentials (credentials) {
console.log('userStore getToken', credentials) console.log('userStore postCredentials', credentials)
return REST.post('/user/login?_format=json', return REST.post('/user/login?_format=json',
credentials, credentials,
{ {
@ -124,8 +126,19 @@ export const UserStore = defineStore({
console.log('graphql user loaded', user) console.log('graphql user loaded', user)
this.roles = user.roles this.roles = user.roles
this.checkIsAdmin() this.checkIsAdmin()
this.getUserEntitees()
.then(() => { //{ data : { data : { userentites } } }
console.log('then from get user, graphql userentites loaded')
// this.user_entites = userentites;
resolve() resolve()
}) })
.catch(error => {
console.warn('Issue with graphql userentites loading', error)
Promise.reject(error)
})
})
.catch(error => { .catch(error => {
console.warn('Issue with graphql user loading', error) console.warn('Issue with graphql user loading', error)
Promise.reject(error) Promise.reject(error)
@ -164,6 +177,31 @@ export const UserStore = defineStore({
} }
} }
}, },
getUserEntitees () {
console.log('getUserEntitees');
return new Promise((resolve, reject) => {
const body = {
query: `
query UserEntites($uid: Int!, $time: String){
userentites(uid: $uid, time: $time) {
id
title
}
}`,
variables: { uid: parseInt(this.uid), time: `${Date.now()}` }
}
GQL.post('', body)
.then(({ data : { data : { userentites } } }) => {
console.log('then from getUserEntitees, graphql userentites loaded', userentites)
this.user_entites = userentites;
resolve();
});
});
},
userLogout () { userLogout () {
const credentials = qs.stringify({ const credentials = qs.stringify({
token: this.csrf_token token: this.csrf_token
@ -175,6 +213,9 @@ export const UserStore = defineStore({
this.isloggedin = false this.isloggedin = false
this.roles = [] this.roles = []
// window.location.reload(true) ??? // window.location.reload(true) ???
// todo reload concernements
// concrnmtStore().reloadConcernements(); // INFO would be good but to much complicated for now, just reload the page
window.location.reload();
resolve() resolve()
}) })
.catch(error => { .catch(error => {

View File

@ -2,211 +2,248 @@
import { mapActions, mapState } from 'pinia' import { mapActions, mapState } from 'pinia'
import { ConcernementsStore } from '@stores/concernements' import { ConcernementsStore } from '@stores/concernements'
import { UserStore } from '@/stores/user'
import { CommonStore } from '@/stores/common' import { CommonStore } from '@/stores/common'
import { print } from 'graphql/language/printer' // import { print } from 'graphql/language/printer'
import gql from 'graphql-tag' // import gql from 'graphql-tag'
import GQL from '@api/graphql-axios' // import GQL from '@api/graphql-axios'
import EntiteFields from '@api/gql/entite.fragment.gql' // import EntiteFields from '@api/gql/entite.fragment.gql'
// import SvgIcon from '@jamescoyle/vue-icon';
import { mdiArrowUp } from '@mdi/js';
import TerrainDeVie from '@components/contents/TerrainDeVie.vue';
import PuissanceAgir from '@components/contents/PuissanceAgir.vue';
import Doleancer from '@components/contents/Doleancer.vue';
export default { export default {
props: ['id', 'eid'], // props: {
// cid: {
// type: Number
// },
// eid: {
// type: Number
// }
// },
props: ['cid', 'eid'],
data(){ data(){
return { return {
entite: null, // entite: null,
opened_besoin_id: null proximite_cid_eid: null,
superposition_cluster_index: null,
superposition: null,
opened_besoin_id: null,
arrowup_path: mdiArrowUp
} }
}, },
computed: { computed: {
...mapState(UserStore,['isloggedin']), ...mapState(ConcernementsStore,['map_mode',
...mapState(ConcernementsStore,['map_mode']), 'opened_concernement',
...mapState(ConcernementsStore,['opened']), 'concernements_loaded',
// ...mapState(ConcernementsStore,['opened_entity_id']), 'allSuperpositions_clustered']),
...mapState(ConcernementsStore,['concernements_loaded']), ...mapState(CommonStore,['cartouch_width']),
...mapState(ConcernementsStore,['ct_concernement']), //
...mapState(ConcernementsStore,['ct_entite']), main_cid_eid () {
...mapState(CommonStore,['hover_elmt']) let r = {
cid: this.cid,
eid: null
};
if (this.eid) {
r.eid = this.eid
} else if (this.map_mode === "superposition" && this.superposition) {
this.superposition.forEach(s => {
// routeview param -> props do not respect type (Number), this.cid should be number
if(s.cid === parseInt(this.cid)){
r.eid = s.eid;
}
});
}
return r;
},
superposed_cid_eid () {
if (this.superposition) {
let r = null;
this.superposition.forEach(s => {
if(this.opened_concernement && s.cid !== this.opened_concernement.id){
r = {
cid: s.cid,
eid: s.eid
}
}
});
console.log('superposed_cid_eid', r);
return r;
} else {
return null
}
}
}, },
created () { created () {
console.log(`Concernement view created, id: ${this.id}, eid: ${this.eid}, opened:${this.opened}`); console.log(`Concernement view created, this.$route`, this.$route);
console.log(`Concernement view created, id: ${this.cid}, eid: ${this.eid}, opened_concernement:${this.opened_concernement}`);
console.log('Concernement view created, allSuperpositions_clustered', this.allSuperpositions_clustered);
console.log("superposition", this.superposition);
if(this.map_mode === "proximite"){
if (this.$route.query.proximite_cid && this.$route.query.proximite_eid) {
this.proximite_cid_eid = {
cid: this.$route.query.proximite_cid,
eid: this.$route.query.proximite_eid,
}
}
// as we have two content to show multiply the cartouch with by 2
// necessary for mapitem opening scale and position
this.setCartoucheWidth(2)
}else if(this.map_mode === "superposition" && this.$route.query.superposition_cluster_index){
this.getSuperposition()
// as we have two content to show multiply the cartouch with by 2
// necessary for mapitem opening scale and position
this.setCartoucheWidth(2)
}else{
// as we have one content to show multiply the cartouch with by 1
// necessary for mapitem opening scale and position
this.setCartoucheWidth(1)
}
// when we arrived directly to the url, load the entite // when we arrived directly to the url, load the entite
// this.eid provided by route params // this.eid provided by route params
if (!this.entity && this.eid) { if (this.map_mode === "terraindevie" && this.eid) {
this.openEntity(); this.setOpenedEntiteId(this.eid)
} }
}, },
watch: { watch: {
concernements_loaded: { concernements_loaded: {
handler (n, o){ handler (n, o){
console.log(`watch concernements_loaded n: ${n}, opened:${this.opened}, id:${this.id}`); // console.log(`watch concernements_loaded n: ${n}, opened_concernement:${this.opened_concernement}, id:${this.id}`);
// when we arrived directly to the url then all concernement are loaded: do open the concernement // when we arrived directly to the url then all concernement are loaded: do open the concernement
if (!this.opened) { if (!this.opened_concernement) {
this.openCloseConcernements(this.id) this.openCloseConcernements(parseInt(this.cid))
} }
}, },
deep: true deep: true
}, },
eid: { eid: {
handler (n, o){ handler (n, o){
if(n){ this.setOpenedEntiteId(n)
this.openEntity() },
deep: true
},
// watch superposition_id query
$route: {
handler (n, o) {
console.log("concernement view $route watcher o, n", o, n);
if (n.query && n.query.superposition_cluster_index) {
this.getSuperposition()
}
if (n.query && n.query.proximite_cid && n.query.proximite_eid) {
this.proximite_cid_eid = {
cid: n.query.proximite_cid,
eid: n.query.proximite_eid,
}
this.setCartoucheWidth(2)
}else{ }else{
this.entite = false; this.proximite_cid_eid = null;
this.setOpenedEntityId(null); this.setCartoucheWidth(1)
} }
}, },
deep: true deep: true
}, },
map_mode: {
handler (n, o) {
console.log('concernement watch map_mode', o, n);
if(n === "proximite" || n === "superposition"){
// as we have two content to show multiply the cartouch with by 2
// necessary for mapitem opening scale and position
this.setCartoucheWidth(2)
}else{
// as we have one content to show multiply the cartouch with by 1
// necessary for mapitem opening scale and position
this.setCartoucheWidth(1)
}
},
deep: true
}
}, },
methods: { methods: {
...mapActions(ConcernementsStore,['openCloseConcernements']), ...mapActions(ConcernementsStore,['openCloseConcernements',
...mapActions(ConcernementsStore,['setOpenedEntityId']), 'setOpenedEntiteId',
openEntity(){ 'setMapMode',
this.setOpenedEntityId(parseInt(this.eid)) 'resetConcernementOpened']),
this.loadEntite() ...mapActions(CommonStore,['setCartoucheWidth']),
}, getSuperposition(){
loadEntite(){ console.log('getSuperposition');
const ast = gql`{ // get superposition_cluster_id and superposition object
entite (id: ${this.eid}) { if (this.$route.query.superposition_cluster_index) {
...EntiteFields this.superposition_cluster_index = this.$route.query.superposition_cluster_index;
console.log('this.superposition_cluster_index', this.superposition_cluster_index);
if(this.superposition_cluster_index){
// let ids = this.superposition_id.match(/(\d+)_(\d+)__(\d+)_(\d+)/i)
// let couple_key = `${ids[1]}-${ids[3]}`
// // console.log('superposition_id', this.superposition_id, couple_key, ids);
// if (this.allSuperpositions_bycids[couple_key][this.superposition_id]) {
// this.superposition = this.allSuperpositions_bycids[couple_key][this.superposition_id]
// console.log("this.superposition", this.superposition);
// }
let cluster = this.allSuperpositions_clustered[this.superposition_cluster_index];
this.superposition = []
for(let cid_eid of cluster){
if (cid_eid.cid === this.cid) {
this.superposition.push(cid_eid)
}
if (cid_eid.cid === parseInt(this.$route.query.superposed_cid)){
this.superposition.push(cid_eid)
// console.log('this.superposition', this.superposition);
} }
} }
${EntiteFields} }
` }
console.log('ast', ast);
GQL.post('', { query: print(ast) })
.then(({data: { data: { entite }}}) => {
console.log('load entite loaded', entite)
this.entite = entite
})
.catch(error => {
console.warn('Issue with load entite', error)
})
}, },
onClickBesoin(id){ closeConcernement(){
console.log("onClickBesoin", id); this.resetConcernementOpened();
this.opened_besoin_id = id === this.opened_besoin_id ? null : id;
},
besoinClass(id){
return this.opened_besoin_id === id ? "opened" : "";
} }
}, },
components: { components: {
TerrainDeVie,
PuissanceAgir,
Doleancer
} }
} }
</script> </script>
<template> <template>
<section v-if="opened" class="concernement"> <section v-if="opened_concernement" class="concernement">
<header v-if="concernements_loaded"> <TerrainDeVie v-if="map_mode === 'terraindevie' || map_mode === 'action' || map_mode === 'superposition' || map_mode === 'proximite'" :cid="main_cid_eid.cid" :eid="main_cid_eid.eid"/>
<label <PuissanceAgir v-if="map_mode === 'puissancedagir'" :cid="cid"/>
v-if="ct_concernement && !entite && map_mode !== 'puissancedagir'" <Doleancer v-if="map_mode === 'doleancer'" :cid="cid"/>
>
{{ ct_concernement.title.description }}
</label>
<h3 v-if="entite">{{ entite.title }}</h3>
<span v-if="entite && opened.entites_byid[eid].menacemaintien > 0">menace</span>
<span v-if="entite && opened.entites_byid[eid].menacemaintien < 0">maintient</span>
<h2>{{ opened.title }}</h2>
</header>
<!-- concernement -->
<section
v-if="map_mode === 'terraindevie' && !entite"
class="content-concernement">
<section class="description">
<label v-if="ct_concernement">{{ ct_concernement.field_description.description }}</label>
<div v-html="opened.description"/>
</section> </section>
<section class="caillou"> <section v-if="map_mode === 'superposition' && superposition && superposed_cid_eid" class="concernement clone">
<label v-if="ct_concernement">{{ ct_concernement.field_caillou.description }}</label> <TerrainDeVie :cid="superposed_cid_eid.cid" :eid="superposed_cid_eid.eid" />
<div v-html="opened.caillou "/>
</section>
</section>
<!-- entite -->
<section
v-if="map_mode === 'terraindevie' && entite"
class="content-entite">
<section class="action">
<label v-if="ct_entite">{{ ct_entite.field_action.description }}</label>
<div v-html="entite.action"/>
</section>
<section class="menace-maintien">
<label v-if="ct_entite">{{ ct_entite.field_menace_maintien.description }}</label>
<div v-html="entite.menacemaintien"/>
</section>
</section>
<!-- puissance d'agir -->
<section
v-if="map_mode === 'puissancedagir'"
class="content-besoins">
<ul class="besoins">
<li
v-for="besoin in opened.besoins"
:key="besoin.id"
class="besoin"
:id="besoin.id"
:class="besoinClass(besoin.id)"
>
<span
class="open-btn mdi"
:class="{ 'mdi-chevron-right': besoin.id !== opened_besoin_id, 'mdi-chevron-down': besoin.id === opened_besoin_id } "
@click="onClickBesoin(besoin.id)"
/>
<header>
<label
class="mdi mdi-rhombus"
:class="{ hover: hover_elmt && hover_elmt.type === 'besoin' && (hover_elmt.id === besoin.id || hover_elmt.bid === besoin.id) }"
@click="onClickBesoin(besoin.id)"
>
Besoin de l'enqueteur
</label>
<h4 class="besoin-description" v-html="besoin.description"/>
<a
v-if="isloggedin"
:href="'/api/node/add/reponse?besoin_id='+besoin.id"
target="_blank"
rel="noopener noreferrer"
class="contribute-link mdi mdi-pencil-plus">
contribuer à ce besoin
</a>
</header>
<ul class="reponses">
<li
v-for="reponse in besoin.reponses"
:key="reponse.id"
class="reponse"
:id="reponse.id"
>
<label class="mdi mdi-rhombus-outline">Ressource</label>
<section v-if="reponse.qui">
<label for="reponse-qui">Qui</label>
<p name="reponse-qui" v-html="reponse.qui" />
</section>
<section v-if="reponse.quoi">
<label for="reponse-quoi">Quoi</label>
<p name="reponse-quoi" v-html="reponse.quoi" />
</section>
<section v-if="reponse.ou">
<label for="reponse-ou"></label>
<p name="reponse-ou" v-html="reponse.ou" />
</section>
<section v-if="reponse.avec">
<label for="reponse-avec">Avec</label>
<p name="reponse-avec" v-html="reponse.avec" />
</section>
</li>
</ul>
</li>
</ul>
</section> </section>
<section v-if="map_mode === 'proximite' && proximite_cid_eid" class="concernement clone">
<TerrainDeVie :cid="proximite_cid_eid.cid" :eid="proximite_cid_eid.eid" />
</section> </section>
<nav class="close-concernement" @click="closeConcernement">
<svg class="close-btn" viewbox="0 0 24 24" width="24" height="24" style="--sx: 1; --sy: 1; --r: 0deg;">
<mask id="arrowMask">
<rect x="0" y="0" width="24" height="24" fill="white"/>
<path :d="arrowup_path" fill="black"/>
</mask>
<circle cx="12" cy="12" r="12" mask="url(#arrowMask)" fill="white" />
</svg>
</nav>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
nav.close-concernement{
position: absolute;
top:65px;
left: -30px;
cursor: pointer;
}
</style> </style>

138
src/views/Search.vue Normal file
View File

@ -0,0 +1,138 @@
<script>
import { mapActions, mapState } from 'pinia'
import { SearchStore } from '@/stores/search'
import { ConcernementsStore } from '@/stores/concernements'
// import CartoucheLayout from '@components/layout/CartoucheLayout.vue';
export default {
props: [],
data(){
return {
value: null,
content_type: null
}
},
computed: {
...mapState(SearchStore,['phrase', 'contentTypeFilter', 'results', 'loaded_results']),
...mapState(ConcernementsStore,['map_mode', 'opened_concernement']),
// value(){
// return this.keys
// }
},
created () {
console.log("search created");
this.value = this.phrase;
this.content_type = this.contentTypeFilter;
},
watch: {
value: {
handler (n,o){
this.setSearchValue(n);
},
deep: true
},
content_type: {
handler (n,o){
this.setContentType(n);
},
deep: true
},
},
methods: {
...mapActions(SearchStore,['setSearchValue','setContentType','newSearch']),
...mapActions(ConcernementsStore,['openCloseConcernements']),
onSubmitSearch (event) {
console.log("onSubmitSearch", event, this.value);
// let value = event.target[0].value;
this.newSearch();
},
onClickResult(cid, eid) {
// open map item
this.openCloseConcernements(cid)
// apoen cartouch via routing
this.$router.push({
name: 'concernement',
hash: `#${this.map_mode}`,
params: {cid: cid, eid: eid}
});
}
},
components: {
// CartoucheLayout
}
}
</script>
<template>
<section class="search">
<header>
<h2>Recherche</h2>
<form action="" @submit.prevent="onSubmitSearch">
<input type="text" v-model="value">
<!-- <select name="content_type" id="content-type-select">
<option value="all">type de contenu</option>
<option value="concernement">Concernement</option>
<option value="entite">Entite</option>
</select> -->
<section class="content-type-checkboxes">
<input type="radio" name="concernement" id="concernement_radio" v-model="content_type" value="concernements">
<label for="concernement_radio">Concernements</label>
<input type="radio" name="entite" id="entite_radio" v-model="content_type" value="entites">
<label for="entite_radio">Entités</label>
</section>
<!-- <select name="bourgeons" id="content-type-select">
<option value="all">Bourgeon</option>
<option value="bourgeon1">Bourgeon1</option>
<option value="bourgeon2">Bourgeon2</option>
</select> -->
<input type="submit" value="rechercher">
</form>
</header>
<main>
<section class="results">
<ul v-if="loaded_results && loaded_results.length">
<li v-for="result in loaded_results">
<template v-if="results.content_type === 'entites'">
<h1 @click.prevent="onClickResult(result.concernement.id, result.id)">
{{ result.title }}
</h1>
<h2 @click.prevent="onClickResult(result.concernement.id, result.id)">
<span>une entité de </span>{{ result.author.username }}
</h2>
</template>
<template v-else>
<h1 @click.prevent="onClickResult(result.id)">
{{ result.title }}
</h1>
<h2 @click.prevent="onClickResult(result.id)">
<span>une enquête de </span>{{ result.author.username }}
</h2>
</template>
</li>
</ul>
<div v-else-if="loaded_results">Aucun résultats</div>
</section>
</main>
<footer>
</footer>
</section>
</template>
<style lang="scss" scoped>
</style>

View File

@ -3,7 +3,6 @@
import { mapActions, mapState } from 'pinia' import { mapActions, mapState } from 'pinia'
import { StaticsStore } from '@/stores/statics' import { StaticsStore } from '@/stores/statics'
export default { export default {
props: ['id'], props: ['id'],
// data(){ // data(){
@ -19,7 +18,31 @@ export default {
// this.loadStatics() // this.loadStatics()
}, },
methods: { methods: {
...mapActions(StaticsStore,['loadStatics']) ...mapActions(StaticsStore,['loadStatics']),
getParsedText(){
let text = this.statics_byid[this.id].texte;
console.log('text', text);
let reg = /https:\/\/(vimeo\.com|www\.youtube\.com)\/(watch\?v=)?(\w+)/g;
let videolinks = [...text.matchAll(reg)];
// console.log('videolinks', videolinks);
for (let link of videolinks){
console.log('videolink', link);
let url, iframe;
switch (link[1]) {
case 'vimeo.com':
url = `https://player.vimeo.com/video/${link[3]}`;
iframe = `<iframe src="${url}" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>`
break;
case 'www.youtube.com':
url = `https://www.youtube.com/embed/${link[3]}`;
iframe = `<iframe src="${url}" frameborder="0" allowfullscreen></iframe>`
break;
}
console.log('iframe', iframe);
text = text.replace(link[0], iframe);
};
return text;
}
}, },
components: { components: {
// MapConcernements // MapConcernements
@ -29,10 +52,13 @@ export default {
</script> </script>
<template> <template>
<section class="static">
<span v-if="!loaded">loading ...</span> <span v-if="!loaded">loading ...</span>
<!-- <h2 v-if="loaded">{{ this.id }}</h2> --> <!-- <h2 v-if="loaded">{{ this.id }}</h2> -->
<h2 v-if="loaded">{{ statics_byid[id].title }}</h2> <h2 v-if="loaded">{{ statics_byid[id].title }}</h2>
<div v-if="loaded" v-html="statics_byid[id].texte"/> <div v-if="loaded" v-html="getParsedText()"/>
</section>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -4,18 +4,39 @@ import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue' import vue from '@vitejs/plugin-vue'
import graphql from '@rollup/plugin-graphql'; import graphql from '@rollup/plugin-graphql';
import { viteRequire } from 'vite-require' import { viteRequire } from 'vite-require'
import svgLoader from 'vite-svg-loader'
import { sentryVitePlugin } from "@sentry/vite-plugin";
require('dotenv').config();
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [vue(), graphql(), viteRequire()], plugins: [vue({
template: {
compilerOptions: {
whitespace: 'preserve'
}
}
}), graphql(), viteRequire(), svgLoader({defaultImport: 'raw'}),
sentryVitePlugin({
org: "figures-libres",
project: "atlas-atterrissage.com",
authToken: process.env.AUTH_TOKEN,
release: {
name: "ouatterrir",
},
url: "https://frontlog.figli.io",
})
],
resolve: { resolve: {
alias: { alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)), '@': fileURLToPath(new URL('./src', import.meta.url)),
'@stores': fileURLToPath(new URL('./src/stores', import.meta.url)), '@stores': fileURLToPath(new URL('./src/stores', import.meta.url)),
'@components': fileURLToPath(new URL('./src/components', import.meta.url)), '@components': fileURLToPath(new URL('./src/components', import.meta.url)),
'@views': fileURLToPath(new URL('./src/views', import.meta.url)), '@views': fileURLToPath(new URL('./src/views', import.meta.url)),
'@api': fileURLToPath(new URL('./src/api', import.meta.url)) '@api': fileURLToPath(new URL('./src/api', import.meta.url)),
// '@icons': fileURLToPath(new URL('./node_modules/vue-material-design-icons', import.meta.url)), // '@icons': fileURLToPath(new URL('./node_modules/vue-material-design-icons', import.meta.url)),
'@node_modules': fileURLToPath(new URL('./node_modules', import.meta.url))
} }
}, },
css: { css: {
@ -27,4 +48,14 @@ export default defineConfig({
}, },
}, },
}, },
build: {
sourcemap: true,
rollupOptions: {
// https://rollupjs.org/configuration-options/
},
},
// https://github.com/vitejs/vite/discussions/7920
esbuild: {
drop: ['console', 'debugger'],
},
}) })