ldc-dam/resources/js/components/media-manager/MmDisplayComponent.vue
2022-07-28 12:21:02 +02:00

388 lines
12 KiB
Vue

<template>
<div>
<div v-show="scrollLoader" class="scrollLoader">
<div class="animated slideInUp">
<font-awesome-icon icon="circle-notch" spin />
<span> Chargements des médias</span>
</div>
</div>
<div :class="`media_container ${isLoading === true ? 'loading' : ''}`">
<div class="loader">
<font-awesome-icon icon="circle-notch" spin />
</div>
<div
:class="'wrapper' + ($displayStatus == 'Grid' ? '' : ' inline')"
v-if="mediaList.data"
>
<div v-if="showDateSeparators() && mediaList.data.length" class="date-separator">
Date de {{ dateSorted === "updated_at" ? "modification" : "création" }} :
{{ formatDate(mediaList.data[0][dateSorted]) }}
</div>
<template v-for="(media, index) in mediaList.data">
<div
v-if="
showDateSeparators() &&
!isSameDay(media, mediaList.data[Math.max(index - 1, 0)])
"
class="date-separator"
>
Date de {{ dateSorted === "updated_at" ? "modification" : "création" }} :
{{ formatDate(media[dateSorted]) }}
</div>
<div
@dragstart="dragStart(media, $event)"
v-on:dblclick="edit(media)"
@click="select(media)"
:class="`${
isCAQuery && media.id !== lastVersion.id
? 'imageItem not-last-version'
: 'imageItem'
} ${media.isLocked ? 'locked' : ''}`"
:draggable="mediaList.draggable"
:aria-grabbed="storeGrabbed.filter((e) => e.id === media.id).length > 0"
>
<font-awesome-icon class="grabbed" icon="circle-check" />
<div
class="etiquette"
:style="
'background-color:' +
media.etiquette.color +
'; border-color:' +
media.etiquette.color +
';'
"
:data-id="media.etiquette.etiquette_id"
>
{{ media.etiquette.libelle }}
</div>
<div
v-if="
(media.type_media_id === 1 || media.type_media_id === 5) &&
media.extension !== 'pdf'
"
class="media"
:style="`background-image:url('${media.thumb_url}')`"
></div>
<div
v-if="
(media.type_media_id === 1 || media.type_media_id === 5) &&
media.extension === 'pdf'
"
class="media"
:style="`background-image:url('${media.thumb_url}')`"
></div>
<div
v-if="media.type_media_id === 2"
class="media"
:style="`background-image:url('${media.url}')`"
></div>
<div v-if="media.type_media_id === 3" class="media video">
<font-awesome-icon icon="file-video" />
</div>
<div v-if="media.type_media_id === 4" class="media son">
<font-awesome-icon icon="file-audio" />
</div>
<p class="libelle">{{ media.libelle }}</p>
<div
v-if="media.type_media_id === 1 || media.type_media_id === 5"
class="info"
>
<font-awesome-icon icon="file-image" />
<span>
{{
`${media.extension} - ${media.taille} - ${media.largeur}x${media.hauteur}px - v${media.version}`
}}
</span>
</div>
<div v-if="media.type_media_id === 2" class="info">
<font-awesome-icon icon="file-image" />
<span>
{{ `${media.extension} - ${media.taille} - v${media.version}` }}
</span>
</div>
<div v-if="media.type_media_id === 3" class="info">
<font-awesome-icon icon="file-video" />
<span>
{{
`${media.extension} - ${media.taille} - durée ${media.duree} - v${media.version}`
}}
</span>
</div>
<div v-if="media.type_media_id === 4" class="info">
<font-awesome-icon icon="file-audio" />
<span>
{{
`${media.extension} - ${media.taille} - durée ${media.duree} - v${media.version}`
}}
</span>
</div>
<div v-if="media.statut === 0" class="statut stat0">Brouillon</div>
<div v-if="media.statut === 1" class="statut stat1">Public</div>
<div v-if="media.statut === 2" class="statut stat2">Public étendu</div>
</div>
</template>
<div v-if="!mediaList.data.length" class="noresult">Aucun résultat</div>
<infinite-loading @infinite="infiniteScroll" :identifier="infiniteId">
<div slot="spinner"></div>
<div slot="no-more"></div>
<div slot="no-results"></div>
</infinite-loading>
</div>
</div>
</div>
</template>
<script>
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
export default {
name: "MmDisplayComponent",
components: { FontAwesomeIcon },
computed: {
storeFilters() {
return this.$store.state.filters;
},
storeFolder() {
return this.$store.state.folder;
},
storeSujet() {
return this.$store.state.sujet;
},
storeMedia() {
return this.$store.state.media;
},
storeGrabbed() {
return this.$store.state.grabbed;
},
storeLoading() {
return this.$store.state.loading;
},
storeReload() {
return this.$store.state.loading;
},
},
mounted() {
this.resetInfiniteScroll();
},
data: function () {
return {
mediaList: [],
offset: 0,
limit: 50,
scrollLoader: false,
isLoading: false,
infiniteId: "",
isCAQuery: false,
dateSorted: false,
lastVersion: {
version: 0,
id: 0,
},
};
},
watch: {
storeFilters() {
this.init();
},
storeLoading() {
this.isLoading = this.$store.state.loading;
},
storeReload() {
this.init();
},
storeMedia() {
if (Object.keys(this.storeMedia).length > 0) {
if (this.storeMedia.close !== undefined && this.storeMedia.close === true) {
if (this.storeMedia.isModified === true) {
this.init();
this.$store.commit({
type: "updateGrabbed",
grabbed: [],
});
}
this.$store.commit({
type: "updateMedia",
media: {},
});
}
}
},
},
methods: {
init() {
this.offset = 0;
this.resetInfiniteScroll();
// * Reset selected on component load
this.$store.commit({
type: "updateGrabbed",
grabbed: [],
});
this.loadMediaList();
//set dateSorted
this.dateSorted = false;
const _that = this;
_.each(this.storeFilters, function (value) {
if (value.type == "order") {
if (value.value == "updated_at" || value.value == "created_at") {
_that.dateSorted = value.value;
}
}
});
if (!this.dateSorted) {
//show/hide date toggler
$(".action_wrapper .display i.fa-calendar-check").hide();
} else {
//par défaut c'est selected
$(".action_wrapper .display i.fa-calendar-check").addClass("selected");
$(".action_wrapper .display i.fa-calendar-check").show();
}
},
loadMediaList($state = null) {
const self = this;
if (this.offset === 0) {
this.mediaList = [];
this.isLoading = true;
} else {
this.scrollLoader = true;
}
// * Dont call without filter (dirty patch)
if (!this.storeFilters.length) {
return;
}
axios
.post(`/ajax/load-media-list/${this.storeSujet}`, {
folder: this.storeFolder,
filters: this.storeFilters,
offset: this.offset,
limit: this.limit,
})
.then((response) => {
if (self.offset === 0) {
self.mediaList = response.data;
self.isLoading = false;
self.$store.commit({
type: "updateRole",
role: response.data.role,
});
} else {
if (response.data.data.length) {
self.mediaList.data.push(...response.data.data);
if ($state) {
$state.loaded();
}
self.$store.commit({
type: "updateRole",
role: response.data.role,
});
} else if ($state) {
$state.complete();
}
self.scrollLoader = false;
}
// Si requete CA alors on cherche la version la plus récente plus griser les autres
if (response.data.isCAQuery !== undefined) {
self.isCAQuery = response.data.isCAQuery ? true : false;
_.each(this.mediaList.data, function (value) {
if (value.version > self.lastVersion.version) {
self.lastVersion.version = value.version;
self.lastVersion.id = value.id;
}
});
} else {
self.isCAQuery = false;
}
self.offset = self.offset + self.limit;
})
.catch(function (error) {
console.error(error);
if (error?.response?.status === 419) {
__DAM.methods.sessionTimedOut();
return;
}
console.error(error);
});
},
infiniteScroll($state) {
this.loadMediaList($state);
},
resetInfiniteScroll() {
this.infiniteId =
Math.random().toString(36).substring(2, 15) +
Math.random().toString(36).substring(2, 15);
},
edit(media) {
media.isModified = false;
this.$store.commit({
type: "updateMedia",
media: media,
});
},
select(media) {
let grabbed = this.storeGrabbed;
const index = grabbed.find((e) => e.id === media.id);
if (!index) {
grabbed.push(media);
} else {
grabbed = grabbed.filter((e) => e.id !== media.id);
}
this.$store.commit({
type: "updateGrabbed",
grabbed: grabbed,
});
},
dragStart(media, evt) {
// ---- Restreint le Drag aux images
if (
media.type_media_id === 1 ||
media.type_media_id === 2 ||
media.type_media_id === 5
) {
evt.dataTransfer.dropEffect = "move";
evt.dataTransfer.effectAllowed = "move";
if (this.storeGrabbed.length === 0) {
this.select(media);
} else {
let grabbed = this.storeGrabbed;
const index = grabbed.find((e) => e.id === media.id);
if (!index) {
grabbed.push(media);
this.$store.commit({
type: "updateGrabbed",
grabbed: grabbed,
});
}
}
} else {
return false;
}
},
showDateSeparators() {
return this.dateSorted;
},
formatDate(str) {
return this.moment(str).format("DD/MM/YYYY");
},
isSameDay(current, previous) {
let currentdate = current[this.dateSorted];
let previousdate = previous[this.dateSorted];
let dateToCompare = this.moment(currentdate);
let datePrevious = this.moment(previousdate);
return dateToCompare.startOf("day").isSame(datePrevious.startOf("day"));
},
},
};
</script>
<style scoped>
.noresult {
padding: 5rem;
font-size: 2rem;
}
</style>