422 lines
13 KiB
Vue
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>
|