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

659 lines
19 KiB
Vue

<template>
<div>
<button
v-if="storeRole !== 2"
v-on:click.prevent="openUploadFrom"
class="action_add_media"
>
<font-awesome-icon icon="file-upload" />
<span> Ajouter un média</span>
</button>
<button v-on:click.prevent="download" class="action_download_media">
<font-awesome-icon icon="file-download" />
<span> Télécharger</span>
</button>
<button
v-if="(storeRole === 1 || storeRole === 4) && !selectionContainsLockedMedias"
v-on:click.prevent="deleteMedia"
class="action_delete_media"
>
<font-awesome-icon icon="trash-alt" />
<span> Supprimer</span>
</button>
<button
v-if="storeRole !== 2 && !selectionContainsLockedMedias"
v-on:click.prevent="duplicateMedia"
class="action_duplicate_media"
>
<font-awesome-icon icon="copy" />
<span> Dupliquer</span>
</button>
<button
v-if="storeRole !== 2 && !selectionContainsLockedMedias"
v-on:click.prevent="applySticker"
class="action_tag_media"
>
<font-awesome-icon icon="tags" />
<span> Etiquette</span>
</button>
<div id="form_etiquette" style="display: none">
<h3>Appliquez une étiquette</h3>
<hr />
<ul>
<li v-for="item in etiquettes">
<button
class="etiquette"
@click="selectSticker(item.etiquette_id)"
:style="
'background-color:' + item.color + '; border-color:' + item.color + ';'
"
:disabled="waitingRequest"
>
{{ item.libelle }}
</button>
</li>
</ul>
</div>
<div id="form_download" style="display: none">
<h3>Téléchargez</h3>
<hr />
<p>Sélectionnez l'un des formats ci-dessous pour télécharger votre sélection.</p>
<form
ref="downloadMedias"
id="the_form_download"
target="_blank"
:action="`/ajax/download-media${format_id ? '/' + format_id : ''}`"
method="POST"
>
<select class="download_format" v-model="format_id">
<option :value="null">Format original</option>
<option v-for="item in storeFormats" :value="item.id">
{{ item.libelle }} {{ item.largeur }}x{{ item.hauteur }}px
{{ item.extension }}
</option>
</select>
<input type="hidden" name="_token" :value="csrf" />
<input
type="hidden"
name="mediaList[]"
v-for="media of this.storeGrabbed"
:value="media.id"
/>
<button
type="submit"
class="btn btn_form_download ml-10"
v-on:click.prevent="performDownload"
>
<font-awesome-icon icon="arrow-circle-down" />
<span> Télécharger</span>
</button>
</form>
</div>
<div class="upload_container high-level">
<span class="fileinput-button" v-on:click.prevent="addFiles">
<button class="btn btn-primary basic-style">
<font-awesome-icon icon="plus-circle" style="background-color: unset" />
<span> Ajouter vos médias</span>
</button>
</span>
<div class="content_wrapper">
<!-- The container for the uploaded errors -->
<div id="upload_errors"></div>
<!-- The container for the uploaded files -->
<div id="files" class="files">
<div v-for="(file, key) in files">
<div>
<span>{{ file.fileName }}</span>
<button v-on:click="removeFile(file)" class="cancel">
<font-awesome-icon icon="times" />
</button>
</div>
<div>
<span>{{ FileConvertSize(file.size) }}</span>
<button class="upload" style="display: none"></button>
</div>
</div>
</div>
</div>
<div class="upload_bar">
<button id="submit" class="btn basic-style" v-on:click.prevent="createMedia">
<span>Transférer</span>
</button>
<button
id="close_upload_form"
class="btn btn-red basic-style"
v-on:click.prevent="closeUploadFrom"
>
<span>Fermer</span>
</button>
</div>
<br />
<input style="display: none" ref="fileupload" type="file" name="files[]" multiple />
</div>
<div id="ListUploadedFiles" style="display: none">
<h3>
<font-awesome-icon icon="user-cog" /><span> Gestion des médias téléversés</span>
</h3>
<hr />
<div class="list_uploaded_files">
<p class="list_uploaded_files_p" v-for="file in uploadedFilesErrors">
<span> {{ file.libelle }}</span>
<span> {{ file.extension }}</span>
<span> {{ file.message }}</span>
</p>
<p class="list_uploaded_files_p" v-for="file in uploadedFiles">
{{ file.libelle }}.{{ file.extension }}
<button class="btn btn-sm btn-primary" v-on:click.prevent="openMedia(file)">
<span>Editer</span>
</button>
</p>
</div>
<hr />
<div style="margin-top: 20px; text-align: center">
<button v-on:click.prevent="CloseListUploadedFiles" class="btn">
<span>Fermer</span>
</button>
</div>
</div>
</div>
</template>
<script>
import Resumable from "resumablejs";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
export default {
name: "MmActionsComponent",
components: { FontAwesomeIcon },
mounted() {
const data = JSON.parse(this.$parent.$options.json);
this.csrf = data.csrf;
this.etiquettes = data.etiquettes;
},
computed: {
storeRole() {
return this.$store.state.role;
},
storeFolder() {
return this.$store.state.folder;
},
storeGrabbed() {
return this.$store.state.grabbed;
},
storeFormats() {
return this.$store.state.formats;
},
storeSujet() {
return this.$store.state.sujet;
},
storeMedia() {
return this.$store.state.media;
},
},
data: function () {
return {
csrf: "",
etiquettes: [],
files: [],
uploadedFiles: [],
uploadedFilesErrors: [],
selectionContainsLockedMedias: true,
format_id: null,
waitingRequest: false,
resumable: null,
};
},
methods: {
duplicateMedia() {
if (Object.keys(this.storeGrabbed).length === 0) {
$.fancyMessage({
title: "Dupliquer un média",
message: "Veuillez sélectionner un média.",
type: "info",
});
} else if (Object.keys(this.storeGrabbed).length > 1) {
$.fancyMessage({
title: "Dupliquer un média",
message: "Vous ne pouvez dupliquer qu'un média à la fois.",
type: "info",
});
} else {
this.$loading.show({ delay: 0 });
axios
.post(`/ajax/media/${this.storeGrabbed[0].id}/duplicate`)
.then((response) => {
this.$loading.hide();
if (response.data.status === true) {
this.$store.commit({
type: "updateMedia",
media: response.data.datas,
});
//switch to edit tab
this.$store.commit({
type: "changeMediaTab",
tab: "edit",
});
} else {
$.fancyMessage({
title: "Dupliquer un média",
message: response.data.error,
type: "error",
});
}
})
.catch((error) => {
if (error?.response?.status === 419) {
__DAM.methods.sessionTimedOut();
return;
}
this.$loading.hide();
$.fancyMessage({
title: "Dupliquer un média",
message: error,
type: "error",
});
console.log(error);
});
}
},
deleteMedia() {
const self = this,
mediaList = this.storeGrabbed;
if (Object.keys(mediaList).length === 0) {
$.fancyMessage({
title: "Supprimer un média",
message: "Veuillez sélectionner un média.",
type: "info",
});
} else {
$.fancyConfirm({
title: "Suppression de panier",
message: "Etes-vous sûr de vouloir supprimer ces média ?",
okButton: "Supprimer",
noButton: "Annuler",
callback: function (value) {
if (!value) {
return;
}
self.$store.commit({
type: "Loading",
loading: true,
});
$.ajax({
url: "/ajax/remove-media",
method: "POST",
dataType: "json",
data: {
mediaList: mediaList.map(function (obj) {
return obj.id;
}),
},
success: function (result) {
self.$store.commit({
type: "Loading",
loading: false,
});
let reload = function () {
self.$store.commit({
type: "Reload",
reload: Math.random(),
});
};
if (result.length != mediaList.length) {
$.fancybox.close();
if (mediaList.length == 1) {
$.fancyMessage({
title: "Attention",
message: "Ce média est lié à Arcadia. Suppression refusée. ",
type: "error",
});
} else {
$.fancyMessage({
title: "Attention",
message:
"Votre sélection contient des médias liés à Arcadia. Ces médias ne seront pas supprimés.",
type: "info",
callback: reload,
});
}
} else {
$.fancyMessage({
title: "Suppression de média",
message: "Le média a été supprimé.",
type: "info",
callback: reload,
});
}
},
error: function (jqXHR, textStatus, errorThrown) {
self.$store.commit({
type: "Loading",
loading: false,
});
$.fancybox.close();
$.fancyMessage({
title: "Attention",
message:
"Erreur lors de la suppression du média, merci d'actualiser la page.",
type: "error",
});
},
});
},
});
}
},
applySticker() {
if (Object.keys(this.storeGrabbed).length === 0) {
$.fancyMessage({
title: "Appliquer une étiquette",
message: "Veuillez sélectionner au moins un média.",
type: "info",
});
} else {
$("#form_etiquette")
.fancybox({
type: "inline",
opts: {
animationDuration: 350,
animationEffect: "material",
},
})
.trigger("click");
}
},
selectSticker(sticker_id) {
this.waitingRequest = true;
axios
.post("/ajax/apply-sticker", {
mediaList: this.storeGrabbed,
etiquette_id: sticker_id,
})
.then((response) => {
this.$store.commit({
type: "updateGrabbed",
grabbed: [],
});
this.$store.commit({
type: "Reload",
reload: Math.random(),
});
$.fancybox.close();
$.fancyMessage({
title: "Changé",
message: "Les étiquettes ont été changés",
type: "info",
});
})
.catch((e) => {
let message = "Erreur lors de l'opération, merci d'actualiser la page.";
if (e?.response?.status === 419) {
__DAM.methods.sessionTimedOut();
return;
}
if (e.response?.status === 422) {
const errors = e.response?.data?.errors;
if (errors instanceof String) {
message = errors;
}
if (errors instanceof Object) {
message = Object.values(errors).reduce(function (previous, current) {
return String(previous) + String(current);
});
}
console.warn(errors);
}
$.fancybox.close();
$.fancyMessage({
title: "Erreur",
message: message,
type: "error",
});
})
.then(() => (this.waitingRequest = false));
},
download() {
if (Object.keys(this.storeGrabbed).length === 0) {
$.fancyMessage({
title: "Télécharger des médias",
message: "Veuillez sélectionner au moins un média.",
type: "info",
});
} else {
$("#form_download")
.fancybox({
type: "inline",
opts: {
animationDuration: 350,
animationEffect: "material",
},
})
.trigger("click");
}
},
openUploadFrom() {
if (this.storeFolder < 0) {
$.fancyMessage({
title: "Ajout de média",
message:
"Pour ajouter des médias, veuillez d'abord sélectionner un dossier de destination.",
type: "error",
});
} else {
if (!this.resumable) this.setupResumable();
$(".upload_container").show("fast");
}
},
closeUploadFrom() {
this.files = [];
this.resumable.files = [];
$(".upload_container").hide("fast");
},
addFiles() {
this.$refs.fileupload.click();
},
removeFile(file) {
this.resumable.removeFile(file);
this.files = this.resumable.files;
},
/**
* @return {string}
*/
FileConvertSize(aSize) {
aSize = Math.abs(parseInt(aSize, 10));
let def = [
[1, "octets"],
[1024, "ko"],
[1024 * 1024, "Mo"],
[1024 * 1024 * 1024, "Go"],
[1024 * 1024 * 1024 * 1024, "To"],
];
for (let i = 0; i < def.length; i++) {
if (aSize < def[i][0])
return (aSize / def[i - 1][0]).toFixed(2) + " " + def[i - 1][1];
}
},
setupResumable() {
this.resumable = new Resumable({
target: `/ajax/upload-media/${this.storeSujet}/${this.storeFolder}`,
simultaneousUploads: 3,
maxFiles: 8,
testChunks: false,
fileParameterName: "file",
headers: {
"X-CSRF-TOKEN": document
.querySelector('meta[name="csrf-token"]')
.getAttribute("content"),
},
});
this.resumable.on("fileAdded", this.uploadFileAdded);
this.resumable.on("fileSuccess", this.uploadFileSuccess);
this.resumable.on("fileError", this.uploadFileError);
this.resumable.on("complete", this.uploadFileComplete);
this.resumable.assignBrowse(this.$refs.fileupload);
},
uploadFileAdded(file, event) {
const acceptFileTypes = /^(gif|jpe?g|png|mp4|mp3|psd|ai|svg|pdf)$/i;
if (
file.fileName.split(".").pop().length &&
!acceptFileTypes.test(file.fileName.split(".").pop())
) {
this.resumable.removeFile(file);
$.fancyMessage({
title: "Attention",
message: file.fileName + " ce type de fichier n'est pas pris en charge.",
type: "warning",
});
}
if (file.size.length && file.size > 5000000) {
this.resumable.removeFile(file);
$.fancyMessage({
title: "Attention",
message: file.fileName + " ce type de fichier est trop grand.",
type: "warning",
});
}
this.files = this.resumable.files;
},
uploadFileSuccess(file, message) {
this.uploadedFiles.push(JSON.parse(message));
this.removeFile(file);
$.fancybox.close();
$.fancybox.open({
src: "#ListUploadedFiles",
type: "inline",
opts: {
modal: true,
animationDuration: 350,
animationEffect: "material",
},
});
console.log("file success");
},
uploadFileComplete() {
this.closeUploadFrom();
this.$loading.hide();
$.fancybox.close();
$.fancybox.open({
src: "#ListUploadedFiles",
type: "inline",
opts: {
modal: true,
animationDuration: 350,
animationEffect: "material",
},
});
console.log("complete");
},
uploadFileError(file, httpMessage) {
let message = "Erreur lors de l'opération, merci d'actualiser la page.";
this.closeUploadFrom();
this.$loading.hide();
$.fancybox.close();
const error = JSON.parse(httpMessage);
if (error.file) {
const errors = error.file;
if (errors instanceof String) {
message = errors;
}
if (errors instanceof Object) {
message = Object.values(errors).reduce(function (previous, current) {
return String(previous) + String(current);
});
}
this.uploadedFilesErrors.push({
libelle: file.fileName,
extension: file.file.type,
message: message,
});
console.warn(errors);
}
$.fancyMessage({
title: "Erreur",
message: message,
type: "error",
});
},
createMedia() {
this.$loading.show({ delay: 0 });
this.resumable.upload();
},
openMedia(media) {
$.fancybox.close();
this.$store.commit({
type: "updateMedia",
media: media,
});
},
CloseListUploadedFiles() {
if (
!this.uploadedFiles.length ||
confirm(
"En cliquant sur OK, vous confirmez que vous avez édité tous vos fichiers."
)
) {
$.fancybox.close();
this.uploadedFiles = [];
this.uploadedFilesErrors = [];
// * Reset input file.
this.$refs.fileupload.files = new DataTransfer().files;
this.$refs.fileupload.value = "";
this.$store.commit({
type: "Reload",
reload: Math.random(),
});
}
},
performDownload() {
this.$refs.downloadMedias.submit();
},
},
watch: {
storeMedia() {
if (Object.keys(this.storeMedia).length === 0 && this.uploadedFiles.length > 0) {
$.fancybox.open({
src: "#ListUploadedFiles",
type: "inline",
opts: {
modal: true,
animationDuration: 350,
animationEffect: "material",
},
});
}
},
storeGrabbed() {
let self = this;
self.selectionContainsLockedMedias = false;
this.storeGrabbed.map((obj) => {
if (obj.isLocked) {
self.selectionContainsLockedMedias = true;
}
});
if (!this.storeGrabbed.length) {
// * Hide if empty selection
self.selectionContainsLockedMedias = true;
}
},
},
};
</script>
<style scoped>
.basic-style {
font-size: inherit !important;
padding: 9px 19px !important;
display: inline-flex !important;
border: 0 !important;
float: unset !important;
transition: none !important;
}
</style>