瀏覽代碼

puissance d'agir almost ok

bach 1 年之前
父節點
當前提交
6d91dcc86d

+ 68 - 4
src/assets/main.scss

@@ -99,7 +99,7 @@ body{
         font-size: 0.882em;
         padding: 0 0 1em 0;
       }
-      header{
+      >header{
         display: flex;
         height: 8rem;
         flex-direction: column;
@@ -125,6 +125,71 @@ body{
         font-weight: 300;
       }
 
+      // PUISSANCE D'AGIR
+      section.content-besoins{
+        ul, li{
+          padding:0; margin:0;
+          list-style: none;
+        }
+        li.besoin{
+          position: relative;
+          label.mdi:before{
+            font-size: 0.8em;
+            padding-right: 0.2em;
+
+          }
+          label.mdi:hover:before,
+          label.mdi.hover:before{
+            color:#01ffe2;
+          }
+          span.open-btn{
+            position: absolute;
+            right:0; top:0;
+            cursor: pointer;
+          }
+          >header{
+            padding: 0 0 0 0;
+            >label{
+              padding:0.5em 0 0.5em 0;
+              cursor: pointer;
+            }
+            h4.besoin-description{
+              font-weight: 400;
+              font-size: 1.2em;
+              padding: 0.5em 0;
+            }
+            a.contribute-link{
+              display: block;
+              text-align: right;
+              font-weight: 100;
+              font-size: 0.882em;
+            }
+          }
+          ul.reponses{
+            overflow: hidden;
+            max-height: 1px;
+            transition: all 0.7s ease-in-out;
+            li.reponse{
+              padding:1em 0;
+              section{
+                padding:0;
+                label{ padding: 0 0 0 0; }
+                p{margin: 0 0 1em 0;}
+              }
+
+            }
+          }
+          &.opened{
+            ul.reponses{
+              max-height: 1000px;
+            }
+          }
+
+          padding-bottom: 0.5em;
+          border-bottom: #aaa 1px solid;
+          margin-bottom: 1em;
+        }
+      }
     }
   }
 
@@ -139,8 +204,7 @@ body{
       background-color: white;
       padding: 1em;
       border-radius: 3px;
-      // min-width: 10em;
-      // max-width: 30em;
+      max-width: 30em;
       .concernement-map-popup{
         ul.icons{
           display: flex;
@@ -154,7 +218,7 @@ body{
           }
         }
       }
-      h1{
+      h1, div{
         font-size: 1em;
         font-weight: 400;
       }

+ 2 - 1
src/components/ConcernementMapItem.vue

@@ -212,7 +212,7 @@ export default {
           this.salientPoints.push(farest)
         }
       }
-      console.log(`this.salientPoints ${this.concernement.id}`, this.salientPoints);
+      // console.log(`this.salientPoints ${this.concernement.id}`, this.salientPoints);
     },
     initCanvasMap (){
       // console.log(`ConcernementsMapItem ${this.concernement.id} initCanvasMap`);
@@ -375,6 +375,7 @@ export default {
               
               this.body_parts.push(Matter.Bodies.circle(rx, ry, 0.8, {
                 item_type: 'reponse',
+                field: res_fields[f],
                 id: this.concernement.besoins[i].reponses[j].id,
                 bid: this.concernement.besoins[i].id,
                 cid: this.concernement.id,

+ 14 - 7
src/components/ConcernementMapPopup.vue

@@ -13,19 +13,25 @@ export default {
       dom: null,
       type: null,
       concernement: null,
-      entite: null
+      entite: null,
+      besoin: null,
+      reponse: null
     }
   },
   created () {
-    // console.log(`popup created type: ${this.infos.type}`);
+    // console.log(`popup created type: ${this.infos.type}`, this.infos);
     if (this.infos.type === 'concernement') {
       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 () {
@@ -36,7 +42,8 @@ export default {
   computed: {
     ...mapState(ConcernementsStore,['concernements']),
     ...mapState(ConcernementsStore,['concernementsByID']),
-    ...mapState(ConcernementsStore,['allEntitesById'])
+    ...mapState(ConcernementsStore,['allEntitesById']),
+    ...mapState(ConcernementsStore,['allBesoinsById'])
   },
   watch: {
     infos: {
@@ -112,10 +119,10 @@ export default {
         <h1>{{ entite.entite.title }}</h1>
       </section>
       <section v-if="infos.type === 'besoin'" class="besoin-map-popup">
-        <h1>Besoin</h1>
+        <div v-html="besoin.description"></div>
       </section>
       <section v-if="infos.type === 'reponse'" class="reponse-map-popup">
-        <h1>Réponse</h1>
+        <div v-html="reponse"></div>
       </section>
     </div>
   </div>

+ 4 - 1
src/components/MapConcernements.vue

@@ -173,7 +173,10 @@ export default {
             && this.opened) { // if a concernement is opened
               hover_elmt = {
                 type: 'reponse',
-                id: body.id
+                field: body.field,
+                id: body.id,
+                bid: body.bid,
+                cid: body.cid
               };
           }
         }

+ 5 - 1
src/main.js

@@ -8,9 +8,12 @@ import '@csstools/normalize.css';
 import '@mdi/font/css/materialdesignicons.css'
 import './assets/main.scss'
 
+// import VueCollapsiblePanel from '@dafcoe/vue-collapsible-panel'
+// import '@dafcoe/vue-collapsible-panel/dist/vue-collapsible-panel.css'
+
 // var decomp = require('poly-decomp');
 // window.decomp = decomp;
-          
+       
 
 const app = createApp(App)
 // https://vuejs.org/guide/components/provide-inject.html#provide
@@ -20,4 +23,5 @@ const pinia = createPinia()
 pinia.use( ({store}) => { store.router = router } )
 app.use(pinia)
 app.use(router)
+// app.use(VueCollapsiblePanel)
 app.mount('#app')

+ 5 - 0
src/stores/concernements.js

@@ -20,6 +20,7 @@ export const ConcernementsStore = defineStore({
     concernements: [],
     concernementsByID: {},
     allEntitesById: {},
+    allBesoinsById: {},
     opened: false,
     opened_entite_id: null,
     ct_concernement: {},
@@ -70,8 +71,12 @@ export const ConcernementsStore = defineStore({
                   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;
+              });
 
               // common
               this.concernements.push(concernement);

+ 72 - 13
src/views/Concernement.vue

@@ -3,17 +3,20 @@
 import { mapActions, mapState } from 'pinia'
 import { ConcernementsStore } from '@stores/concernements'
 import { UserStore } from '@/stores/user'
+import { CommonStore } from '@/stores/common'
 
 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'
 
+
 export default {
   props: ['id', 'eid'],
   data(){
     return {
       entite: null,
+      opened_besoin_id: null
     }
   },
   computed: {
@@ -23,7 +26,8 @@ export default {
     // ...mapState(ConcernementsStore,['opened_entity_id']),
     ...mapState(ConcernementsStore,['concernements_loaded']),
     ...mapState(ConcernementsStore,['ct_concernement']),
-    ...mapState(ConcernementsStore,['ct_entite'])
+    ...mapState(ConcernementsStore,['ct_entite']),
+    ...mapState(CommonStore,['hover_elmt'])
   },
   created () {
     console.log(`Concernement view created, id: ${this.id}, eid: ${this.eid}, opened:${this.opened}`);
@@ -82,6 +86,13 @@ export default {
         .catch(error => {
           console.warn('Issue with load entite', error)
         })
+    },
+    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" : "";
     }
   },
   components: {
@@ -93,7 +104,11 @@ export default {
 <template>
   <section v-if="opened" class="concernement">
     <header v-if="concernements_loaded">
-      <label v-if="ct_concernement && !entite">{{ ct_concernement.title.description }}</label>
+      <label 
+        v-if="ct_concernement && !entite && map_mode !== 'puissancedagir'"
+        >
+          {{ 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>
@@ -129,19 +144,63 @@ export default {
     <section
       v-if="map_mode === 'puissancedagir'"
       class="content-besoins">
-        <ul>
+        <ul class="besoins">
           <li
-            v-for="(besoin,index) in opened.besoins"
-            :key="index"
+            v-for="besoin in opened.besoins"
+            :key="besoin.id"
+            class="besoin"
+            :id="besoin.id"
+            :class="besoinClass(besoin.id)"
           >
-            <p v-html="besoin.description"/>
-            <a 
-              v-if="isloggedin"
-              :href="'/api/node/add/reponse?besoin_id='+besoin.id" 
-              target="_blank" 
-              rel="noopener noreferrer">
-                contribuer à ce besoin
-            </a>
+            <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>