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

After

Width:  |  Height:  |  Size: 829 KiB

+133 -14
View File
@@ -7,11 +7,19 @@ 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()
@@ -22,20 +30,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 +142,36 @@ export default {
<template> <template>
<header id="header"> <header id="header">
<h1 class="row"> <div class="row title">
<router-link :to="{ name: 'home' }"><span class="title">Atlas</span> des cartes d'atterrissage</router-link> <h1>
</h1> <router-link :to="{ name: 'home' }"><span class="title">Atlas</span> des cartes d'atterrissage</router-link>
</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>
<ConcernementMapItem <transition name="fade">
v-for="(concernement,index) in concernements" <div class="loading" v-if="mapitems.length === 0">Chargement</div>
:key="index" </transition>
:concernement="concernement" <template v-if="mapitems.length > 0">
:opened="concernement.opened" <template v-for="(mapitem,index) in mapitems">
/> <!-- && ((map_mode === 'superposition' && mapitem.clone) || !mapitem.clone) -->
<ConcernementMapItem
v-if="mapitem.visible"
:key="mapitem.id"
:mapitem="mapitem"
/>
</template>
</template>
</MapConcernements> </MapConcernements>
<div id="content"> <div id="content" :class="{'recit-opened':opened_recit}">
<RouterView /> <RouterView />
</div> </div>
</div> </div>
@@ -69,4 +179,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>
+85 -6
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
@@ -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
}
}
}
}
+16 -1
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
@@ -0,0 +1,15 @@
fragment ResultsConcernementFields on Concernement {
id
title
author {
username
structure {
name
}
}
created
changed
lieu {
name
}
}
+18
View File
@@ -0,0 +1,18 @@
fragment ResultsEntiteFields on Entite {
id
concernement {
id
title
}
action
menacemaintien
title
author {
username
structure {
name
}
}
created
changed
}
+33
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

+19
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

+358
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

+355
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

+5 -4
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');
} }
+79
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

+75 -71
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

+13 -13
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

+16 -16
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

+14 -25
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

+33 -18
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

+8 -1
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;
}
} }
+1143 -98
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+102 -40
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">
<h1>{{ concernement.title }}</h1> <div class="concernement-map-popup-content">
<ul class="icons"> <h1>{{ concernement.title }}</h1>
<li v-if="concernement.has_puissancedagir" ><span class="icon puissancedagir"></span></li> <div class="author info">
<li v-if="concernement.has_proximite" ><span class="icon proximite"></span></li> <span>une enquête de</span> {{ concernement.author.username }}<br/>
<li v-if="concernement.has_superposition" ><span class="icon superposition"></span></li> </div>
<li v-if="concernement.has_agissantes" ><span class="icon action"></span></li> <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_doleance" ><span class="icon doleancer"></span></li> <li v-if="concernement.has_puissancedagir" ><span class="icon puissancedagir"></span></li>
</ul> <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_agissantes" ><span class="icon action"></span></li>
<li v-if="concernement.has_doleance" ><span class="icon doleancer"></span></li>
</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>Où</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
+108
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>
@@ -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()
} }
} }
} }
+120
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>
+16 -5
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">
<span>connexion</span> <label>
<svg-icon type="mdi" :path="login_path"></svg-icon>
<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{
+78
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>
+20 -11
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,22 +25,27 @@ export default {
...mapActions(StaticsStore,['loadStatics']) ...mapActions(StaticsStore,['loadStatics'])
}, },
components: { components: {
// LoginBlock, SvgIcon
// UserTools
} }
} }
</script> </script>
<template> <template>
<ul> <div id="static-menu">
<li <ul>
v-for="staticnode in statics" <li
v-bind:key="staticnode.id" v-for="staticnode in statics"
> v-bind:key="staticnode.id"
<router-link :to="{ name: 'static', params: { id:staticnode.id } }">{{staticnode.title}}</router-link> >
</li> <router-link :to="{ name: 'static', params: { id:staticnode.id } }">
</ul> <svg-icon type="mdi" :path="infos_path"></svg-icon>
<span>{{staticnode.title}}</span>
</router-link>
</li>
</ul>
</div>
</template> </template>
+25 -4
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
+183
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>
+469
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">Où</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>
+180
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>
+723
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>
+176
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>
@@ -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>
+138
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>
+152
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>
+195
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>
+172
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>
+184
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>
@@ -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>
+211
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>
+119
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>
+34 -3
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");
+20 -2
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
+30 -2
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;
} }
} }
}) })
+752 -47
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)
concernement.entites_byid = {};
concernement.entitesagissantes_byid = {};
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
entites_temp.forEach(entite => {
if (entite.entite) { // entite.entite may be null because of workflow confidentiality
concernement.entites_byid[entite.entite.id] = entite;
// record entite agissante
if (entite.entite.agissante) {
concernement.entitesagissantes_byid[entite.entite.id] = entite;
concernement.has_agissantes = true;
}
// record a flat list of all entités of all concernement for map-popup
this.allEntitesById[entite.entite.id] = entite;
concernement.entites.push(entite); // fill the entites array with visible entite only
}
});
// puissance d'agir
concernement.has_puissancedagir = concernement.besoins.length ? true : false;
concernement.besoins.forEach(besoin => {
this.allBesoinsById[besoin.id] = besoin;
});
// doleance
concernement.has_doleance = concernement.doleances.length ? true : false;
// common
this.concernements.push(concernement);
this.concernementsByID[concernement.id] = concernement;
});
this.concernements_loaded = true; this.concernements_loaded = true;
this.concernements_loading_nb ++;
this.concernements_are_loading = false;
resolve();
}) })
.catch(error => { .catch(error => {
console.warn('Issue with loadConcernements', error) console.warn('Issue with loadConcernements', error)
this.concernements_are_loading = false;
Promise.reject(error) 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.entitesagissantes_byid = {};
concernement.has_proximites = false;
concernement.has_superpositions = false;
concernement.has_agissantes = false;
concernement.entites.forEach(entite => {
// console.log(`parsing entite ${entite.id}`);
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;
}
// 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
if (entite.entite.agissante) {
if (!concernement.entitesagissantes_byid[entite.entite.id]) {
concernement.entitesagissantes_byid[entite.entite.id] = entite;
}
concernement.has_agissantes = true;
}
// PROXIMITES
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
concernement.has_puissancedagir = concernement.besoins.length ? true : false;
// console.log('concernement.besoins', concernement.besoins);
concernement.besoins.forEach(besoin => {
if (besoin) {
this.allBesoinsById[besoin.id] = besoin;
}
});
// doleance
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
// if (!concernement_is_reloaded) {
this.concernements.push(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;
}
});
// 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 => {
console.warn('Issue with graphql userentites loading', error);
})
resolve(concernement);
})
.catch(error => {
console.warn('Issue with reloadConcernementEntites', error)
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;
} }
} }
}) })
-12
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
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);
})
}
}
})
+5 -5
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
}); });
+59 -18
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,7 +126,18 @@ 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()
resolve()
this.getUserEntitees()
.then(() => { //{ data : { data : { userentites } } }
console.log('then from get user, graphql userentites loaded')
// this.user_entites = userentites;
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)
@@ -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 => {
+194 -157
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 class="caillou">
<label v-if="ct_concernement">{{ ct_concernement.field_caillou.description }}</label>
<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">Où</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>
<section v-if="map_mode === 'superposition' && superposition && superposed_cid_eid" class="concernement clone">
<TerrainDeVie :cid="superposed_cid_eid.cid" :eid="superposed_cid_eid.eid" />
</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>
<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
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>
+32 -6
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>
<span v-if="!loaded">loading ...</span> <section class="static">
<!-- <h2 v-if="loaded">{{ this.id }}</h2> --> <span v-if="!loaded">loading ...</span>
<h2 v-if="loaded">{{ statics_byid[id].title }}</h2> <!-- <h2 v-if="loaded">{{ this.id }}</h2> -->
<div v-if="loaded" v-html="statics_byid[id].texte"/> <h2 v-if="loaded">{{ statics_byid[id].title }}</h2>
<div v-if="loaded" v-html="getParsedText()"/>
</section>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
+31 -2
View File
@@ -4,18 +4,37 @@ 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: "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 +46,14 @@ export default defineConfig({
}, },
}, },
}, },
build: {
sourcemap: true,
rollupOptions: {
// https://rollupjs.org/configuration-options/
},
},
// https://github.com/vitejs/vite/discussions/7920
esbuild: {
drop: ['console', 'debugger'],
},
}) })