diff --git a/frontend/src/views/files/Editor.vue b/frontend/src/views/files/Editor.vue index 3dbabc74..6ee0db48 100644 --- a/frontend/src/views/files/Editor.vue +++ b/frontend/src/views/files/Editor.vue @@ -4,6 +4,25 @@ {{ req.name }} + + + preview + preview +
+ + @@ -33,6 +67,7 @@ import "ace-builds/webpack-resolver"; import HeaderBar from "@/components/header/HeaderBar"; import Action from "@/components/header/Action"; import Breadcrumbs from "@/components/Breadcrumbs"; +import * as upload from "@/utils/upload"; export default { name: "editor", @@ -46,6 +81,16 @@ export default { }, computed: { ...mapState(["req", "user"]), + previewLink() { + return this.$route.path + .replace(/^\/files\//, "/") + .replace(/[^/]*$/, ""); + }, + headerButtons() { + return { + upload: this.user.perm.create, + }; + }, breadcrumbs() { let parts = this.$route.path.split("/"); @@ -78,8 +123,12 @@ export default { }, created() { window.addEventListener("keydown", this.keyEvent); + window.addEventListener("drop", this.drop); + window.addEventListener("paste", this.drop); }, beforeDestroy() { + window.removeEventListener("paste", this.drop); + window.removeEventListener("drop", this.drop); window.removeEventListener("keydown", this.keyEvent); this.editor.destroy(); }, @@ -104,6 +153,129 @@ export default { let uri = url.removeLastDir(this.$route.path) + "/"; this.$router.push({ path: uri }); }, + dragEnter() { + this.dragCounter++; + + // When the user starts dragging an item, put every + // file on the listing with 50% opacity. + let items = document.getElementsByClassName("item"); + + Array.from(items).forEach((file) => { + file.style.opacity = 0.5; + }); + }, + dragLeave() { + this.dragCounter--; + + if (this.dragCounter == 0) { + this.resetOpacity(); + } + }, + drop: async function (event) { + event.preventDefault(); + this.dragCounter = 0; + this.resetOpacity(); + + let dt = event.dataTransfer ?? event.clipboardData; + let el = event.target; + + if (dt.files.length <= 0) return; + + for (let i = 0; i < 5; i++) { + if (el !== null && !el.classList.contains("item")) { + el = el.parentElement; + } + } + + let files = await upload.scanFiles(dt); + let items = this.req.items; + let path = this.$route.path.replace(/\/[^/]*$/, "/"); + + if ( + el !== null && + el.classList.contains("item") && + el.dataset.dir === "true" + ) { + // Get url from ListingItem instance + path = el.__vue__.url; + + try { + items = (await api.fetch(path)).items; + } catch (error) { + this.$showError(error); + } + } + + let conflict = upload.checkConflict(files, items); + + if (conflict) { + this.$store.commit("showHover", { + prompt: "replace", + confirm: (event) => { + event.preventDefault(); + this.$store.commit("closeHovers"); + upload.handleFiles(files, path, true); + }, + }); + + return; + } + + upload.handleFiles(files, path); + const alt = files[0].name; + const link = files[0].name; + this.editor.insert(`![${alt}](${link})`); + }, + uploadInput(event) { + this.$store.commit("closeHovers"); + + let files = event.currentTarget.files; + let folder_upload = + files[0].webkitRelativePath !== undefined && + files[0].webkitRelativePath !== ""; + + if (folder_upload) { + for (let i = 0; i < files.length; i++) { + let file = files[i]; + files[i].fullPath = file.webkitRelativePath; + } + } + + let path = this.$route.path.replace(/\/[^/]*$/, "/"); + let conflict = upload.checkConflict(files, this.req.items); + + if (conflict) { + this.$store.commit("showHover", { + prompt: "replace", + confirm: (event) => { + event.preventDefault(); + this.$store.commit("closeHovers"); + upload.handleFiles(files, path, true); + }, + }); + + return; + } + + upload.handleFiles(files, path); + }, + resetOpacity() { + let items = document.getElementsByClassName("item"); + + Array.from(items).forEach((file) => { + file.style.opacity = 1; + }); + }, + upload: function () { + if ( + typeof window.DataTransferItem !== "undefined" && + typeof DataTransferItem.prototype.webkitGetAsEntry !== "undefined" + ) { + this.$store.commit("showHover", "upload"); + } else { + document.getElementById("upload-input").click(); + } + }, keyEvent(event) { if (!event.ctrlKey && !event.metaKey) { return;