LinkEditable.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <script>
  2. import JSONAPI from '@api/json-axios'
  3. import REST from '@api/rest-axios'
  4. import { mapActions, mapState } from 'pinia'
  5. import { ConcernementsStore } from '@stores/concernements'
  6. import { UserStore } from '@stores/user'
  7. import ContentEditable from '@components/editable/ContentEditable.vue';
  8. import SvgIcon from '@jamescoyle/vue-icon';
  9. import { mdiTrashCanOutline } from '@mdi/js';
  10. import { mdiMusicNotePlus } from '@mdi/js';
  11. import { mdiLinkVariantPlus } from '@mdi/js';
  12. import { nextTick } from 'vue'
  13. export default {
  14. props: {
  15. can_update: Boolean,
  16. links: Array,
  17. data: Object
  18. },
  19. emits: ['updated'],
  20. data(){
  21. return {
  22. mdiTrashCanOutline_path: mdiTrashCanOutline,
  23. mdiMusicNotePlus_path: mdiMusicNotePlus,
  24. mdiLinkVariantPlus_path: mdiLinkVariantPlus,
  25. // links_nb : 0
  26. }
  27. },
  28. computed: {
  29. ...mapState(UserStore,['csrf_token']),
  30. },
  31. created () {
  32. console.log('LinkEditable created', this.links);
  33. // this.links_nb = this.links.length;
  34. },
  35. beforeUpdate() {
  36. console.log('LinkEditable beforeUpdate', this.links);
  37. },
  38. updated() {
  39. console.log('LinkEditable updated', this.links, this.$refs.links_list);
  40. this.$refs.links_list.lastChild.querySelector('input.new.title').value = null;
  41. this.$refs.links_list.lastChild.querySelector('input.new.url').value = null;
  42. },
  43. mounted () {
  44. },
  45. methods: {
  46. ...mapActions(ConcernementsStore, ['reloadConcernements']),
  47. // addLink(e){
  48. // console.log('addLink');
  49. // this.links_nb++;
  50. // },
  51. onFocusOut(e){
  52. console.log('onfocusOut', e, this.$refs.links_list);
  53. this.buildLinkListThenSave();
  54. },
  55. buildLinkListThenSave(force_Save){
  56. console.log('buildLinkListThenSave links', this.links);
  57. // build links list
  58. let list = [];
  59. let tobesaved = false;
  60. for (let i = 0; i < this.$refs.links_list.children.length; i++) {
  61. const $li = this.$refs.links_list.children[i];
  62. if ($li.querySelector('input.url').value) {
  63. let title = $li.querySelector('input.title').value;
  64. let url = $li.querySelector('input.url').value;
  65. list.push({
  66. title: title,
  67. uri: url
  68. });
  69. tobesaved = (typeof this.links[i] === 'undefined' || title !== this.links[i].title || url !== this.links[i].url);
  70. }
  71. }
  72. if (!tobesaved) {
  73. tobesaved = this.links.length !== list.length;
  74. }
  75. if (tobesaved || force_Save) {
  76. this.save(list);
  77. }
  78. },
  79. save(list){
  80. console.log('save list', list);
  81. const params = {
  82. type: this.data.bundle,
  83. [this.data.field.field_name]: list
  84. };
  85. if (this.data.entitytype === 'node') {
  86. params.nid = [{"value":this.data.id}];
  87. } else {
  88. params.id = [{"value":this.data.id}];
  89. }
  90. // // we need additional values for image alt for example
  91. // // console.log('additional_values', this.data.field.additional_values);
  92. // if (this.data.field.additional_values) {
  93. // for (const key in this.data.field.additional_values) {
  94. // if (Object.hasOwnProperty.call(this.data.field.additional_values, key)) {
  95. // params[this.data.field.field_name][0][key] = this.data.field.additional_values[key]
  96. // }
  97. // }
  98. // }
  99. const configs = {
  100. headers: {'X-CSRF-Token': this.csrf_token}
  101. };
  102. // url is not the same between nodes and others entities
  103. let url_base = `/${this.data.entitytype === 'node' ? '' : 'entity/'}${this.data.entitytype}`;
  104. // call the api
  105. REST.patch(`${url_base}/${this.data.id}?_format=json`, params, configs)
  106. .then(({ data }) => {
  107. console.log('user REST post node data', data)
  108. this.$emit('updated');
  109. })
  110. .catch(error => {
  111. console.warn(`Issue with patch ${this.data.entitytype} ${this.data.bundle}`, error)
  112. Promise.reject(error)
  113. })
  114. },
  115. async onDeleteLink(i){
  116. console.log(`onDeleteLink ${i}`, this.$refs.links_list.children[i]);
  117. // this.links_nb = this.$refs.links_list.children.length;
  118. // this.$refs.links_list.children[i].remove();
  119. this.links.splice(i,1);
  120. await nextTick();
  121. this.buildLinkListThenSave(true);
  122. }
  123. },
  124. components: {
  125. SvgIcon,
  126. ContentEditable
  127. }
  128. }
  129. </script>
  130. <template>
  131. <ul ref="links_list">
  132. <li v-for="(link, l) in links" :key="l" :class="{'link-editable':can_update}">
  133. <!-- link exists can't update -->
  134. <template v-if="!can_update">
  135. <a :href="link.url">
  136. {{ link.title }}
  137. </a>
  138. </template>
  139. <!-- link exists and can update -->
  140. <template v-else>
  141. <input type="text" class="title" :value="link.title" placeholder="Titre du lien" @focusout="onFocusOut" />
  142. <input type="text" class="url" :value="link.url" @focusout="onFocusOut" placeholder="Url du lien" />
  143. <div @click="onDeleteLink(l)" class="delete-btn">
  144. <svg-icon type="mdi" :path="mdiTrashCanOutline_path" />
  145. </div>
  146. </template>
  147. <!-- link does not exists yet and can create -->
  148. </li>
  149. <li v-if="can_update" class="link-editable">
  150. <input type="text" class="new title" placeholder="Titre du lien" @focusout="onFocusOut" />
  151. <input type="text" class="new url" placeholder="https://..." @focusout="onFocusOut" />
  152. <div class="delete-btn">
  153. <svg-icon type="mdi" />
  154. </div>
  155. </li>
  156. </ul>
  157. <!-- <div v-if="can_update" @click="addLink(i)" class="add-btn">
  158. <svg-icon type="mdi" :path="mdiLinkVariantPlus_path" />
  159. </div> -->
  160. </template>
  161. <style scoped>
  162. </style>