diff --git a/filemanager/package-lock.json b/filemanager/package-lock.json index 2ec0e9b58..de0e0c749 100644 --- a/filemanager/package-lock.json +++ b/filemanager/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "combokeys": "^3.0.1", "filesize": "^10.0.7", - "pankow": "^0.1.0", + "pankow": "^0.1.1", "primeicons": "^6.0.1", "primevue": "^3.27.0", "superagent": "^8.0.9", @@ -18,8 +18,8 @@ "vue-router": "^4.1.6" }, "devDependencies": { - "@vitejs/plugin-vue": "^4.1.0", - "vite": "^4.3.1" + "@vitejs/plugin-vue": "^4.2.0", + "vite": "^4.3.2" } }, "node_modules/@babel/parser": { @@ -394,9 +394,9 @@ "peer": true }, "node_modules/@vitejs/plugin-vue": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.1.0.tgz", - "integrity": "sha512-++9JOAFdcXI3lyer9UKUV4rfoQ3T1RN8yDqoCLar86s0xQct5yblxAE+yWgRnU5/0FOlVCpTZpYSBV/bGWrSrQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.2.0.tgz", + "integrity": "sha512-hYaXFvEKEwyTmwHq2ft7GGeLBvyYLwTM3E5R1jpvzxg9gO4m5PQcTVvj1wEPKoPL8PAt+KAlxo3gyJWnmwzaWQ==", "dev": true, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -838,9 +838,9 @@ } }, "node_modules/pankow": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/pankow/-/pankow-0.1.0.tgz", - "integrity": "sha512-XDLrmtg9pRx5q4kvefnRHYQsDk4dyilqfIB9ZlBs1HdxNNyu4Lp6THh2WkbmVkKJlIf+fA+UIl3LR+U95fQdog==", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pankow/-/pankow-0.1.1.tgz", + "integrity": "sha512-l06TNXKxmwBxCZGtOb7zzX2sdBx/12lU3IYBPD0EDTsuFmnR+a3A+OizaXxPqhFlClH1hmTXcMszGIiqxOzpbg==", "dependencies": { "filesize": "^10.0.7", "monaco-editor": "^0.37.1", @@ -904,9 +904,9 @@ } }, "node_modules/rollup": { - "version": "3.20.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.2.tgz", - "integrity": "sha512-3zwkBQl7Ai7MFYQE0y1MeQ15+9jsi7XxfrqwTb/9EK8D9C9+//EBR4M+CuA1KODRaNbFez/lWxA5vhEGZp4MUg==", + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.21.0.tgz", + "integrity": "sha512-ANPhVcyeHvYdQMUyCbczy33nbLzI7RzrBje4uvNiTDJGIMtlKoOStmympwr9OtS1LZxiDmE2wvxHyVhoLtf1KQ==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -989,14 +989,14 @@ } }, "node_modules/vite": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.1.tgz", - "integrity": "sha512-EPmfPLAI79Z/RofuMvkIS0Yr091T2ReUoXQqc5ppBX/sjFRhHKiPPF/R46cTdoci/XgeQpB23diiJxq5w30vdg==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.2.tgz", + "integrity": "sha512-9R53Mf+TBoXCYejcL+qFbZde+eZveQLDYd9XgULILLC1a5ZwPaqgmdVpL8/uvw2BM/1TzetWjglwm+3RO+xTyw==", "dev": true, "dependencies": { "esbuild": "^0.17.5", "postcss": "^8.4.21", - "rollup": "^3.20.2" + "rollup": "^3.21.0" }, "bin": { "vite": "bin/vite.js" diff --git a/filemanager/package.json b/filemanager/package.json index 0e118de41..c38812e48 100644 --- a/filemanager/package.json +++ b/filemanager/package.json @@ -11,7 +11,7 @@ "dependencies": { "combokeys": "^3.0.1", "filesize": "^10.0.7", - "pankow": "^0.1.0", + "pankow": "^0.1.1", "primeicons": "^6.0.1", "primevue": "^3.27.0", "superagent": "^8.0.9", @@ -19,7 +19,7 @@ "vue-router": "^4.1.6" }, "devDependencies": { - "@vitejs/plugin-vue": "^4.1.0", - "vite": "^4.3.1" + "@vitejs/plugin-vue": "^4.2.0", + "vite": "^4.3.2" } } diff --git a/filemanager/src/models/DirectoryModel.js b/filemanager/src/models/DirectoryModel.js index e330c905b..14580634d 100644 --- a/filemanager/src/models/DirectoryModel.js +++ b/filemanager/src/models/DirectoryModel.js @@ -1,6 +1,6 @@ import superagent from 'superagent'; -import { sanitize } from 'pankow/utils'; +import { buildFilePath, sanitize } from 'pankow/utils'; const BASE_URL = import.meta.env.BASE_URL || '/'; @@ -17,6 +17,8 @@ export function createDirectoryModel(origin, accessToken, api) { } if (error || result.statusCode !== 200) { + if (error.status === 404) return []; + console.error('Failed to list files', error || result.statusCode); return []; } @@ -69,6 +71,11 @@ export function createDirectoryModel(origin, accessToken, api) { .send({ action: 'rename', newFilePath: sanitize(toFilePath) }) .query({ access_token: accessToken }); }, + async copy(fromFilePath, toFilePath) { + await superagent.put(`${origin}/api/v1/${api}/files/${fromFilePath}`) + .send({ action: 'copy', newFilePath: sanitize(toFilePath) }) + .query({ access_token: accessToken }); + }, async chown(filePath, uid) { await superagent.put(`${origin}/api/v1/${api}/files/${filePath}`) .send({ action: 'chown', uid: uid, recursive: true }) @@ -93,6 +100,12 @@ export function createDirectoryModel(origin, accessToken, api) { const text = await result.text(); return text; }, + async paste(targetDir, action, files) { + for (let f in files) { + if (action === 'cut') await this.rename(buildFilePath(files[f].folderPath, files[f].name), targetDir + '/' + files[f].name); + if (action === 'copy') await this.copy(buildFilePath(files[f].folderPath, files[f].name), targetDir + '/' + files[f].name); + } + }, getFileUrl(path) { return `${origin}/api/v1/${api}/files/${path}?access_token=${accessToken}`; } diff --git a/filemanager/src/views/Home.vue b/filemanager/src/views/Home.vue index 0523bf16f..5f22c99db 100644 --- a/filemanager/src/views/Home.vue +++ b/filemanager/src/views/Home.vue @@ -54,11 +54,13 @@ :change-owner-handler="changeOwnerHandler" :copy-handler="copyHandler" :cut-handler="cutHandler" + :paste-handler="pasteHandler" :new-file-handler="onNewFile" :new-folder-handler="onNewFolder" :upload-file-handler="onUploadFile" :upload-folder-handler="onUploadFolder" :items="items" + :clipboard="clipboard" :owners-model="ownersModel" /> @@ -122,7 +124,10 @@ export default { activeDirectoryItem: {}, items: [], selectedItems: [], - clipboard: {}, + clipboard: { + action: '', // copy or cut + files: [] + }, accessToken: localStorage.token, apiOrigin: API_ORIGIN || '', apps: [], @@ -280,6 +285,15 @@ export default { files }; }, + async pasteHandler(target) { + if (!this.clipboard.files || !this.clipboard.files.length) return; + + const targetPath = target ? sanitize(this.cwd + '/' + target.fileName) : this.cwd; + + await this.directoryModel.paste(targetPath, this.clipboard.action, this.clipboard.files); + this.clipboard = {}; + await this.loadCwd(); + }, async uploadHandler(targetDir, file, progressHandler) { await this.directoryModel.upload(targetDir, file, progressHandler); await this.loadCwd();