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