ldc-dam/resources/js/components/media-manager/MmFolderComponent.vue
2022-07-25 12:08:11 +02:00

422 lines
13 KiB
Vue

<template>
<div :class="`folder_container ${isLoading === true ? 'loading' : ''}`">
<div class="loader">
<font-awesome-icon icon="circle-notch" spin />
</div>
<div ref="folder_container" class="dd">
<ol class="dd-list dd3-list root">
<li
v-on:click.prevent="selectFolder({ id: 0, libelle: 'racine' })"
v-on:drop.prevent="moveMedia({ id: 0, libelle: 'racine' })"
ondragstart="return false;"
:class="storeFolder === 0 ? 'root_folder selected' : 'root_folder'"
data-id="0"
>
<span>/racine</span>
<span class="count">{{ racineCount }}</span>
</li>
<li
v-for="item in folders"
:class="
item.parent_id === null ? 'dd-item dd3-item parent' : 'dd-item dd3-item'
"
:data-id="item.id"
:id="`_li${item.id}`"
>
<button
:class="`nestableFolderButton ${implodeClasses(handleClass(item))}`"
v-on:click.prevent="toggle(item)"
>
<span :class="handleClass(item).opened === true ? 'icon' : 'icon d-none'">
<font-awesome-icon icon="caret-down" />
</span>
<span :class="handleClass(item).openable === true ? 'icon' : 'icon d-none'">
<font-awesome-icon icon="caret-right" />
</span>
</button>
<div
v-on:click.prevent="selectFolder(item)"
v-on:drop.prevent="moveMedia(item)"
v-on:dragover.prevent
v-on:dragenter.prevent
:class="item.id === storeFolder ? 'dd3-content selected' : 'dd3-content'"
>
<font-awesome-icon icon="folder" />
<input type="text" value="" class="input_rename" maxlength="100" />
<span>{{ item.libelle | str_limit(25) }}</span>
<div class="count">{{ item.mediacount }}</div>
<button
v-if="item.system === 0"
v-on:click.capture="toggleFav(item)"
class="starButton"
>
<font-awesome-icon
:icon="`${item.favoris === true ? 'fas' : 'far'} fa-star`"
/>
</button>
</div>
<ol
v-if="item.sousdossiers.length > 0"
class="dd-list"
:parent-id="item.id"
style="display: none"
>
<li
v-for="item2 in item.sousdossiers"
:class="
item2.parent_id === null ? 'dd-item dd3-item parent' : 'dd-item dd3-item'
"
:data-id="item2.id"
:id="`_li${item2.id}`"
>
<button
:class="`nestableFolderButton ${implodeClasses(handleClass(item))}`"
v-on:click.prevent="toggle(item2)"
>
<span :class="handleClass(item2).opened ? 'icon' : 'icon d-none'">
<font-awesome-icon icon="caret-down" />
</span>
<span :class="handleClass(item2).openable ? 'icon' : 'icon d-none'">
<font-awesome-icon icon="caret-right" />
</span>
</button>
<div
v-on:click.prevent="selectFolder(item2)"
v-on:drop.prevent="moveMedia(item2)"
v-on:dragover.prevent
v-on:dragenter.prevent
:class="item2.id === storeFolder ? 'dd3-content selected' : 'dd3-content'"
>
<font-awesome-icon icon="folder" />
<input type="text" value="" class="input_rename" maxlength="100" />
<span>{{ item2.libelle | str_limit(25) }}</span>
<div class="count">{{ item2.mediacount }}</div>
<button
v-if="item2.system === 0"
v-on:click.capture="toggleFav(item2)"
class="starButton"
>
<font-awesome-icon
:icon="`${item2.favoris === true ? 'fas' : 'far'} fa-star`"
/>
</button>
</div>
<ol
v-if="item2.sousdossiers.length > 0"
class="dd-list"
:parent-id="item2.id"
style="display: none"
>
<li
v-for="item3 in item2.sousdossiers"
:class="
item3.parent_id === null
? 'dd-item dd3-item parent'
: 'dd-item dd3-item'
"
:data-id="item3.id"
:id="`_li${item3.id}`"
>
<div
:class="
item3.parent_id === null
? 'dd-handle dd3-handle no-handle'
: 'dd-handle dd3-handle'
"
></div>
<div
v-on:click.prevent="selectFolder(item3)"
v-on:drop.prevent="moveMedia(item3)"
v-on:dragover.prevent
v-on:dragenter.prevent
:class="
item3.id === storeFolder ? 'dd3-content selected' : 'dd3-content'
"
>
<input type="text" value="" class="input_rename" maxlength="100" />
<span>{{ item3.libelle | str_limit(25) }}</span>
<div class="count">{{ item3.mediacount }}</div>
<button
v-if="item3.system === 0"
v-on:click.capture="toggleFav(item3)"
class="starButton"
>
<font-awesome-icon
:icon="`${item3.favoris === true ? 'fas' : 'far'} fa-star`"
/>
</button>
</div>
</li>
</ol>
</li>
</ol>
</li>
</ol>
</div>
</div>
</template>
<script>
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
export default {
name: "MmFolderComponent",
components: { FontAwesomeIcon },
computed: {
storeSujet() {
return this.$store.state.sujet;
},
storeFolder() {
return this.$store.state.folder;
},
storeFilters() {
return this.$store.state.filters;
},
storeRole() {
return this.$store.state.role;
},
storeGrabbed() {
return this.$store.state.grabbed;
},
storeReload() {
return this.$store.state.reload;
},
},
data() {
return {
selectedFolder: false,
isLoading: true,
oFolders: [],
racineCount: 0,
folders: [],
};
},
watch: {
storeSujet() {
this.initFolders();
},
storeReload() {
this.reload();
},
isLoading() {
this.$store.commit({
type: "Loading",
loading: this.isLoading,
});
},
},
methods: {
scrollToContent(item, headerOffset = 0) {
const element = document.getElementById("_li" + item.id),
parentElement = element ? element.parentNode.closest("li.dd-item") : 0,
topElement = parentElement
? parentElement.parentNode.closest("li.dd-item") ?? 0
: 0,
elementPosition =
(element ? element.offsetTop : 0) +
(parentElement ? parentElement.offsetTop : parentElement) +
(topElement ? topElement.offsetTop : topElement);
if (element !== null) {
this.$refs.folder_container.scrollTo({
top: elementPosition + headerOffset,
behavior: "smooth",
});
}
},
initFolders(toSelectFolder = false) {
const self = this;
self.isLoading = true;
self.folders = [];
self.racineCount = 0;
axios
.get("/ajax/load-folders", {
params: {
sujet_id: self.storeSujet,
},
})
.then((response) => {
self.oFolders = response.data.data;
self.racineCount = response.data.racineCount;
self.renderItems();
self.isLoading = false;
if (toSelectFolder !== false) {
self.selectFolder(toSelectFolder);
} else {
// ! Reset Current folder to none selected
self.$store.state.folder = -1;
}
})
.catch(function (error) {
if (error?.response?.status === 419) {
__DAM.methods.sessionTimedOut();
return;
}
console.error(error);
});
},
reload() {
this.initFolders(this.selectedFolder);
},
renderItems() {
const favs = this.oFolders.filter((item) => item.favoris === true),
folders = [];
favs.forEach((item) => {
item.__opened = true;
folders.push(item);
});
this.oFolders.forEach((item) => {
item.__opened = true;
if (item.favoris === false) {
folders.push(item);
}
});
folders.forEach((item) => {
this.toggle(item);
});
this.folders = folders;
},
selectFolder(item) {
this.selectedFolder = item;
const filter = this.storeFilters.findIndex((e) => e.type === "dossier_id");
if (filter !== -1) {
this.$delete(this.storeFilters, filter);
}
this.storeFilters.push({
type: "dossier_id",
legend: "Dossier : ",
value: item.id,
libelle: item.libelle,
});
this.$store.commit({
type: "updateFilters",
filters: this.storeFilters,
});
this.$store.commit({
type: "updateFolder",
folder: item.id,
});
this.$nextTick(() => {
this.scrollToContent(item, -75);
});
},
toggleFav(folder) {
const self = this;
this.selectedFolder = folder;
axios
.post(`/ajax/favoris-folder/${folder.id}`, {
favoris: !folder.favoris ? true : false,
})
.then((response) => {
self.reload();
})
.catch((error) => {
if (error?.response?.status === 419) {
__DAM.methods.sessionTimedOut();
return;
}
$.fancyMessage({
title: "Dossiers",
message: "Une erreur est survenue, veuillez recharger la page (Ctrl + F5).",
type: "error",
});
console.error(error);
});
},
moveMedia(folder) {
// Si on déplace dans le même dossier que le dossier actuel du/des media(s) séléctionné(s)
if (this.storeGrabbed[0].dossier_id === folder.id) {
return;
}
// Prevent moving locked medias
for (let media of this.storeGrabbed) {
if (media.isLocked) {
$.fancyMessage({
title: "Attention",
message: "Il n'est pas possible de déplacer des médias verrouillés",
type: "error",
});
return;
}
}
const self = this;
self.isLoading = true;
axios
.post("/ajax/move-media", {
mediaList: this.storeGrabbed,
dossier_id: folder.id ? folder.id : "-1",
})
.then((response) => {
self.isLoading = false;
// On met un timeout pour être sûr qu'Elastic est update lors du reload du DisplayComponent
setTimeout(function () {
self.$nextTick(() => {
self.selectFolder.apply(self, [folder]);
self.$store.commit({
type: "updateGrabbed",
grabbed: [],
});
self.$store.commit({
type: "Reload",
reload: Math.random(),
});
});
}, 1000);
})
.catch((error) => {
if (error?.response?.status === 419) {
__DAM.methods.sessionTimedOut();
return;
}
console.error(error);
$.fancybox.close();
$.fancyMessage({
title: "Attention",
message: "Erreur lors du déplacement, merci d'actualiser la page.",
type: "error",
});
})
.then(() => (self.isLoading = false));
},
handleClass(item) {
let dd3_handle = false,
openable = item.__opened ? false : true,
opened = item.__opened ? true : false,
no_handle = false;
if (item.sousdossiers.length === 0) {
//icone dossier simple sans action
dd3_handle = true;
no_handle = true;
openable = false;
opened = false;
}
return {
id: item.id,
"dd-handle": true,
"dd3-handle": dd3_handle,
"no-handle": no_handle,
openable: openable,
opened: opened,
};
},
implodeClasses(classList) {
return Object.keys(classList).reduce((carry, className) => {
return `${carry} ${classList[className] ? className : ""}`;
});
},
toggle(item) {
const self = this;
item.__opened = item.__opened ? false : true;
$("[parent-id='" + item.id + "']").toggle(300, () => {
// * Force rerender classes on folders
self.$forceUpdate();
});
},
},
};
</script>
<style scoped></style>