Browse Source

audio editable

bach 1 month ago
parent
commit
e34c9cbd9c

+ 1 - 0
src/api/gql/entite.fragment.gql

@@ -44,6 +44,7 @@ fragment EntiteFields on Entite {
     audios {
       description
       file {
+        fid
         filemime
         filename
         filesize

+ 9 - 1
src/assets/main.scss

@@ -1069,7 +1069,8 @@ body{
 }
 
 div.editable-image,
-div.editable-video{
+div.editable-video,
+div.editable-audios{
   background: #eee;
   max-width: 100%;
   div.file-btn{
@@ -1110,4 +1111,11 @@ div.editable-video{
   input[type="file"]{
     display: none;
   }
+  &.can-update{
+    .plyr--audio{
+      .plyr__controls{
+        background-color: transparent;
+      }
+    }
+  }
 }

+ 20 - 4
src/components/contents/Source.vue

@@ -9,6 +9,7 @@ import ContentEditable from '@components/editable/ContentEditable.vue';
 import CheckboxEditable from '@components/editable/CheckboxEditable.vue';
 import ImageEditable from '@components/editable/ImageEditable.vue';
 import VideoEditable from '@components/editable/VideoEditable.vue';
+import AudioEditable from '@components/editable/AudioEditable.vue';
 
 export default {
   props: ['concernement', 'entite', "eid", 'source'],
@@ -42,6 +43,7 @@ export default {
     CheckboxEditable,
     ImageEditable,
     VideoEditable,
+    AudioEditable,
   }
 }
 </script>
@@ -103,10 +105,10 @@ export default {
           v-on:updated="reloadEntite"/>
     </section>
 
+    <!-- v-if="source.audios.length" -->
     <section
-      v-if="source.audios.length"
-      class="audio multiple">
-        <div
+      class="audio">
+        <!-- <div
             v-for="(audio,a) in source.audios"
             :key="a">
           <label v-if="audio.description">{{ audio.description }}</label>
@@ -116,8 +118,22 @@ export default {
                 <source :src="audio.file.url" :type="audio.file.filemime" />
               </audio>
           </vue-plyr>
+        </div> -->
 
-        </div>
+      <AudioEditable
+        :can_update="entite.can_update"
+        :audio="source.audios[0]"
+        :data="{
+          entitytype: 'paragraph',
+          bundle: 'source',
+          id: this.source.id,
+          uuid: this.source.uuid,
+          field: {
+            field_name: 'field_audio',
+            value: 'value'
+          }
+        }"
+        v-on:updated="reloadEntite"/>
     </section>
 
     <section

+ 176 - 0
src/components/editable/AudioEditable.vue

@@ -0,0 +1,176 @@
+<script>
+
+import JSONAPI from '@api/json-axios'
+import REST from '@api/rest-axios'
+
+import { mapActions, mapState } from 'pinia'
+import { ConcernementsStore } from '@stores/concernements'
+import { UserStore } from '@stores/user'
+
+import ContentEditable from '@components/editable/ContentEditable.vue';
+
+import SvgIcon from '@jamescoyle/vue-icon';
+import { mdiTrashCanOutline } from '@mdi/js';
+import { mdiMusicNotePlus } from '@mdi/js';
+
+export default {
+  props: {
+    can_update: Boolean,
+    audio: Object,
+    data: Object
+  },
+  emits: ['updated'],
+  data(){
+    return {
+      mdiTrashCanOutline_path: mdiTrashCanOutline,
+      mdiMusicNotePlus_path: mdiMusicNotePlus,
+      plyr_options: {
+        controls: ['play', 'progress', 'current-time', 'mute', 'volume']
+      }
+    }
+  },
+  computed: {
+    ...mapState(UserStore,['csrf_token']),
+  },
+  created () {
+    console.log('ImageEditable created')
+  },
+  mounted () {
+
+  },
+  methods: {
+    ...mapActions(ConcernementsStore, ['reloadConcernements']),
+    addAudio(e){
+      console.log('addAudio', this.$refs);
+      this.$refs.audio_input.click();
+    },
+    onInput(e){
+      console.log('onFileInput', e);
+      let file = e.target.files[0];
+      console.log('onFileInput file', file);
+      this.save(file);
+    },
+    save(file){
+      const configs = {
+        headers: {
+          'X-CSRF-Token': this.csrf_token,
+          'Content-Type': 'application/octet-stream',
+          'Content-Disposition': `file; filename="${file.name}"`,
+        },
+      };
+
+      JSONAPI.post(`/${this.data.entitytype}/${this.data.bundle}/${this.data.uuid}/${this.data.field.field_name}`, file, configs)
+        .then(({ data : { data } }) => {
+          console.log('jsonapi post audio', data)
+          this.$emit('updated');
+        })
+        .catch(error => {
+          console.warn('Issue with jsonapi post image', error)
+          Promise.reject(error)
+        })
+    },
+    onDeleteAudio(e){
+      console.log('onDeleteImg', e);
+
+      const params = {
+        type: this.data.bundle,
+        // nid: [{"value":this.data.id}],
+        [this.data.field.field_name]: {[this.data.field.value]: null}
+      };
+      if (this.data.entitytype === 'node') {
+        params.nid = [{"value":this.data.id}];
+      } else {
+        params.id = [{"value":this.data.id}];
+      }
+
+      const configs = {
+        headers: {'X-CSRF-Token': this.csrf_token}
+      };
+      
+      let url_base = `/${this.data.entitytype === 'node' ? '' : 'entity/'}${this.data.entitytype}`;
+      REST.patch(`${url_base}/${this.data.id}?_format=json`, params, configs)
+        .then(({ data }) => {
+          console.log(`user REST patch ${this.data.entitytype} ${this.data.bundle} ${this.data.field}`, data)
+          // TODO if success update the data in pinia 
+          // this.reloadConcernements();
+          this.$emit('updated');
+        })
+        .catch(error => {
+          console.warn(`Issue with patch ${this.data.entitytype} ${this.data.bundle} ${this.data.field}`, error)
+          Promise.reject(error)
+        })
+
+      // 405 JSONAPI operation not allowed, don't know why
+      
+      // const configs = {
+      //   headers: {
+      //     'X-CSRF-Token': this.csrf_token,
+      //     'Content-Type': 'application/octet-stream',
+      //     'Content-Disposition': `file; filename=""`,
+      //   },
+      // };
+
+      // JSONAPI.delete(`/${this.data.entitytype}/${this.data.bundle}/${this.data.uuid}/${this.data.field}`, {}, configs)
+      //   .then(({ data : { data } }) => {
+      //     console.log('jsonapi delete image', data)
+      //     this.$emit('updated');
+      //   })
+      //   .catch(error => {
+      //     console.warn('Issue with jsonapi post image', error)
+      //     Promise.reject(error)
+      //   })
+      // console.log('save csrf_token', this.csrf_token);
+
+    },
+    onUpdated(){
+      this.$emit('updated');
+    }
+  },
+  components: {
+    SvgIcon,
+    ContentEditable
+  }
+}
+</script>
+
+<template>
+  <div class="editable-audios" :class="{'can-update': can_update}">
+    <!-- with audio -->
+    <template v-if="audio">
+      <div>
+        <!-- <label v-if="audio.description">{{ audio.description }}</label>
+        <label v-else>{{ audio.file.filename }}</label> -->
+        <ContentEditable 
+          tag="label"
+          :value="audio.description ? audio.description : audio.file.filename"
+          :contenteditable="can_update"
+          :data="{
+            entitytype: data.entitytype,
+            bundle: data.bundle,
+            id: data.id,
+            field: {field_name: data.field.field_name, value:'description', additional_values:{target_id:audio.file.fid}}
+          }"
+          v-on:updated="onUpdated" />
+
+        <vue-plyr  :options="plyr_options">
+            <audio>
+              <source :src="audio.file.url" :type="audio.file.filemime" />
+            </audio>
+        </vue-plyr>
+
+      </div>  
+      <div v-if="can_update" @click="onDeleteAudio" class="delete-btn">
+        <svg-icon type="mdi" :path="mdiTrashCanOutline_path" />
+      </div>
+    </template>
+    <!-- with out img -->
+    <template v-else-if="can_update">
+      <div @click="addAudio" class="file-btn">
+        <svg-icon type="mdi" :path="mdiMusicNotePlus_path"/>
+        <!-- <span>ajouter une image</span> -->
+      </div>
+      <input ref="audio_input" type="file" accept ="audio/mp3, audio/flac, audio/ogg" @input="onInput">
+    </template>
+    
+  </div>
+</template>

+ 5 - 1
src/components/editable/ImageEditable.vue

@@ -118,6 +118,9 @@ export default {
       //   })
       // console.log('save csrf_token', this.csrf_token);
 
+    },
+    onUpdated(){
+      this.$emit('updated');
     }
   },
   components: {
@@ -148,7 +151,8 @@ export default {
             bundle: data.bundle,
             id: data.id,
             field: {field_name: data.field, value:'alt', additional_values:{target_id:image.id}}
-          }" />
+          }"
+          v-on:updated="onUpdated" />
 
       </figure>
       <div v-if="can_update" @click="onDeleteImg" class="delete-btn">