ConcernementMapPopup.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <script>
  2. // import { RouterLink, RouterView } from 'vue-router'
  3. import SvgIcon from '@jamescoyle/vue-icon';
  4. import { mdiHeadphones } from '@mdi/js';
  5. import { mapState, mapActions } from 'pinia'
  6. // import { UserStore } from '@/stores/user'
  7. import { ConcernementsStore } from '@/stores/concernements'
  8. export default {
  9. name: 'concernementMapPopup',
  10. props: ['infos'],
  11. data() {
  12. return {
  13. dom: null,
  14. type: null,
  15. concernement: null,
  16. entites: null,
  17. entite_parent: null,
  18. besoin: null,
  19. reponse: null,
  20. superposition: null,
  21. headphones_path: mdiHeadphones
  22. }
  23. },
  24. created () {
  25. // console.log(`popup created type: ${this.infos.type}`, this.infos);
  26. this.parseInfos()
  27. },
  28. mounted () {
  29. // console.log('APP onMounted')
  30. this.dom = this.$refs['map-popup'];
  31. window.addEventListener('mousemove', this.onMousemove);
  32. },
  33. beforeUnmount () {
  34. window.removeEventListener('mousemove', this.onMousemove);
  35. },
  36. computed: {
  37. ...mapState(ConcernementsStore,['concernements',
  38. 'concernementsByID',
  39. 'allEntitesById',
  40. 'allBesoinsById'])
  41. },
  42. watch: {
  43. infos: {
  44. handler (n, o){
  45. this.parseInfos()
  46. },
  47. deep: true
  48. },
  49. },
  50. methods: {
  51. parseInfos(){
  52. // console.log('mapPopup infos', this.infos);
  53. switch (this.infos.type) {
  54. case 'concernement':
  55. this.concernement = this.concernementsByID[this.infos.cid];
  56. break;
  57. case 'entite':
  58. case 'entite_proximite':
  59. case 'entite_superpose':
  60. case 'entite_action':
  61. this.entites = [this.allEntitesById[this.infos.id]];
  62. break;
  63. case 'entite_proximite_reference':
  64. this.entites = [this.allEntitesById[this.infos.id]];
  65. this.concernement = this.concernementsByID[this.infos.ref_cid];
  66. this.entite_parent = this.allEntitesById[this.infos.parent_eid];
  67. break;
  68. case 'besoin':
  69. this.besoin = this.allBesoinsById[this.infos.id];
  70. break;
  71. case 'reponse':
  72. this.besoin = this.allBesoinsById[this.infos.id];
  73. for (let i = 0; i < this.allBesoinsById[this.infos.bid].reponses.length; i++) {
  74. if (this.allBesoinsById[this.infos.bid].reponses[i].id === this.infos.id) {
  75. this.reponse = this.allBesoinsById[this.infos.bid].reponses[i];
  76. break;
  77. }
  78. }
  79. break;
  80. case 'superposition':
  81. this.concernement = this.concernementsByID[this.infos.cid];
  82. this.entites = [this.allEntitesById[this.infos.eid]];
  83. break;
  84. }
  85. },
  86. onMousemove(e){
  87. // console.log(`popup move type: ${this.infos.type}`);
  88. let v = "top";
  89. let h = "right";
  90. if (e.clientX + this.dom.clientWidth > document.body.clientWidth) {
  91. h = "left";
  92. } else {
  93. h = "right";
  94. }
  95. if (e.clientY - this.dom.clientHeight < 0) {
  96. v = "bottom";
  97. } else {
  98. v = "top";
  99. }
  100. this.dom.setAttribute("pos", `${v}-${h}`);
  101. switch (h) {
  102. case "right":
  103. this.dom.style.left = `${e.clientX+2}px`;
  104. break;
  105. case "left":
  106. this.dom.style.left = `${e.clientX - this.dom.clientWidth-2}px`;
  107. break;
  108. }
  109. switch (v) {
  110. case "top":
  111. this.dom.style.top = `${e.clientY - this.dom.clientHeight-2}px`;
  112. break;
  113. case "bottom":
  114. this.dom.style.top = `${e.clientY+2}px`;
  115. break;
  116. }
  117. },
  118. truncate( str, n, useWordBoundary ){
  119. if (str.length <= n) { return str; }
  120. const subString = str.slice(0, n-1); // the original check
  121. return (useWordBoundary
  122. ? subString.slice(0, subString.lastIndexOf(" "))
  123. : subString) + " &hellip;";
  124. }
  125. },
  126. components: {
  127. SvgIcon
  128. }
  129. }
  130. </script>
  131. <template>
  132. <div id="map-popup" ref="map-popup">
  133. <div class="popup-content-wrapper">
  134. <section v-if="infos.type === 'concernement' || infos.type === 'superposition'" class="concernement-map-popup">
  135. <div class="concernement-map-popup-content">
  136. <h1>{{ concernement.title }}</h1>
  137. <div class="author info">
  138. <span>une enquête de</span> {{ concernement.author.username }}<br/>
  139. </div>
  140. <ul class="icons" v-if="concernement.has_puissancedagir || concernement.has_proximite || concernement.has_superposition || concernement.has_agissantes || concernement.has_doleance">
  141. <li v-if="concernement.has_puissancedagir" ><span class="icon puissancedagir"></span></li>
  142. <li v-if="concernement.has_proximite" ><span class="icon proximite"></span></li>
  143. <li v-if="concernement.has_superposition" ><span class="icon superposition"></span></li>
  144. <li v-if="concernement.has_agissantes" ><span class="icon action"></span></li>
  145. <li v-if="concernement.has_doleance" ><span class="icon doleancer"></span></li>
  146. </ul>
  147. </div>
  148. <div v-if="(infos.type === 'concernement' || infos.type === 'superposition') && concernement.has_recit" class="concernement-map-popup-recit">
  149. <svg-icon type="mdi" :path="headphones_path"></svg-icon>
  150. </div>
  151. </section>
  152. <section v-if="infos.type === 'entite' || infos.type === 'entite_action' || infos.type === 'superposition' || infos.type === 'entite_superpose' || infos.type === 'entite_proximite'" class="entite-map-popup">
  153. <template
  154. v-for="(entite, index) of entites"
  155. :key="index"
  156. >
  157. <h1><span class="point">&bull;</span> {{ entite.entite.title }}</h1>
  158. </template>
  159. </section>
  160. <section v-if="infos.type === 'entite_proximite_reference'" class="entite-proximite-reference-map-popup">
  161. <h1 class="parent-entite"><span class="point">&bull;</span> {{ entite_parent.entite.title }}</h1>
  162. <div class="conjunction">entité a proximité</div>
  163. <h1 class="ref-entite"><span class="point">&bull;</span> {{ entites[0].entite.title }}</h1>
  164. <!-- <h2>{{ concernement.title }}</h2> -->
  165. </section>
  166. <section v-if="infos.type === 'besoin'" class="besoin-map-popup">
  167. <div v-html="besoin.description"></div>
  168. </section>
  169. <section v-if="infos.type === 'reponse'" class="reponse-map-popup">
  170. <div v-if="reponse.qui"><label>Qui</label><p v-html="truncate(reponse.qui, 100, true)"/></div>
  171. <div v-if="reponse.quoi"><label>Quoi</label><p v-html="truncate(reponse.quoi, 100, true)"/></div>
  172. <div v-if="reponse.ou"><label>Où</label><p v-html="truncate(reponse.ou, 100, true)"/></div>
  173. <div v-if="reponse.avec"><label>Avec</label><p v-html="truncate(reponse.avec, 100, true)"/></div>
  174. </section>
  175. </div>
  176. </div>
  177. </template>
  178. <style lang="scss" scoped>
  179. </style>