ImageEditable.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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 { mdiImagePlus } from '@mdi/js';
  11. export default {
  12. props: {
  13. can_update: Boolean,
  14. image: Object,
  15. data: Object
  16. },
  17. emits: ['updated'],
  18. data(){
  19. return {
  20. mdiTrashCanOutline_path: mdiTrashCanOutline,
  21. mdiImagePlus_path: mdiImagePlus
  22. }
  23. },
  24. computed: {
  25. ...mapState(UserStore,['csrf_token']),
  26. },
  27. created () {
  28. console.log('ImageEditable created');
  29. },
  30. mounted () {
  31. },
  32. methods: {
  33. ...mapActions(ConcernementsStore, ['reloadConcernements']),
  34. addImage(e){
  35. console.log('addImage', this.$refs);
  36. this.$refs.image_input.click();
  37. },
  38. onInput(e){
  39. console.log('onFileInput', e);
  40. let file = e.target.files[0];
  41. console.log('onFileInput file', file);
  42. this.save(file);
  43. },
  44. save(file){
  45. const configs = {
  46. headers: {
  47. 'X-CSRF-Token': this.csrf_token,
  48. 'Content-Type': 'application/octet-stream',
  49. 'Content-Disposition': `file; filename="${file.name}"`,
  50. },
  51. };
  52. JSONAPI.post(`/${this.data.entitytype}/${this.data.bundle}/${this.data.uuid}/${this.data.field}`, file, configs)
  53. .then(({ data : { data } }) => {
  54. console.log('jsonapi post image', data)
  55. this.$emit('updated');
  56. })
  57. .catch(error => {
  58. console.warn('Issue with jsonapi post image', error)
  59. Promise.reject(error)
  60. })
  61. },
  62. onDeleteImg(e){
  63. console.log('onDeleteImg', e);
  64. const params = {
  65. type: this.data.bundle,
  66. // nid: [{"value":this.data.id}],
  67. [this.data.field]: {value: null}
  68. };
  69. if (this.data.entitytype === 'node') {
  70. params.nid = [{"value":this.data.id}];
  71. } else {
  72. params.id = [{"value":this.data.id}];
  73. }
  74. const configs = {
  75. headers: {'X-CSRF-Token': this.csrf_token}
  76. };
  77. let url_base = `/${this.data.entitytype === 'node' ? '' : 'entity/'}${this.data.entitytype}`;
  78. REST.patch(`${url_base}/${this.data.id}?_format=json`, params, configs)
  79. .then(({ data }) => {
  80. console.log(`user REST patch node ${this.data.bundle} ${this.data.field}`, data)
  81. // TODO if success update the data in pinia
  82. // this.reloadConcernements();
  83. this.$emit('updated');
  84. })
  85. .catch(error => {
  86. console.warn(`Issue with patch node ${this.data.bundle} ${this.data.field}`, error)
  87. Promise.reject(error)
  88. })
  89. // 405 JSONAPI operation not allowed, don't know why
  90. // const configs = {
  91. // headers: {
  92. // 'X-CSRF-Token': this.csrf_token,
  93. // 'Content-Type': 'application/octet-stream',
  94. // 'Content-Disposition': `file; filename=""`,
  95. // },
  96. // };
  97. // JSONAPI.delete(`/${this.data.entitytype}/${this.data.bundle}/${this.data.uuid}/${this.data.field}`, {}, configs)
  98. // .then(({ data : { data } }) => {
  99. // console.log('jsonapi delete image', data)
  100. // this.$emit('updated');
  101. // })
  102. // .catch(error => {
  103. // console.warn('Issue with jsonapi post image', error)
  104. // Promise.reject(error)
  105. // })
  106. // console.log('save csrf_token', this.csrf_token);
  107. },
  108. onUpdated(){
  109. this.$emit('updated');
  110. }
  111. },
  112. components: {
  113. SvgIcon,
  114. ContentEditable
  115. }
  116. }
  117. </script>
  118. <template>
  119. <div class="editable-image">
  120. <!-- with img -->
  121. <template v-if="image">
  122. <figure>
  123. <img :src="image.url" :alt="image.alt"/>
  124. <!-- <figcaption
  125. :contenteditable="can_update"
  126. v-if="image.alt || can_update"
  127. >
  128. {{ image.alt }}
  129. </figcaption> -->
  130. <ContentEditable
  131. tag="figcaption"
  132. :value="image.alt"
  133. :contenteditable="can_update"
  134. :data="{
  135. entitytype: data.entitytype,
  136. bundle: data.bundle,
  137. id: data.id,
  138. field: {field_name: data.field, value:'alt', additional_values:{target_id:image.id}}
  139. }"
  140. v-on:updated="onUpdated" />
  141. </figure>
  142. <div v-if="can_update" @click="onDeleteImg" class="delete-btn">
  143. <svg-icon type="mdi" :path="mdiTrashCanOutline_path" />
  144. </div>
  145. </template>
  146. <!-- with out img -->
  147. <template v-else-if="can_update">
  148. <div @click="addImage" class="file-btn">
  149. <svg-icon type="mdi" :path="mdiImagePlus_path" @click="onDeleteImg" />
  150. <!-- <span>ajouter une image</span> -->
  151. </div>
  152. <input ref="image_input" type="file" accept ="image/jpeg, image/png, image/jpg" @input="onInput">
  153. </template>
  154. </div>
  155. </template>