From e492371ce2f17e32bc72f576c5126ff7b5aace26 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Fri, 30 Jun 2023 06:24:35 +0000 Subject: [PATCH] feat: file manager open to current folder --- server/models/pages.mjs | 4 +-- server/models/tree.mjs | 4 +-- ux/src/components/FileManager.vue | 38 +++++++++++++++++++++---- ux/src/components/TreeBrowserDialog.vue | 18 ++++++++---- 4 files changed, 50 insertions(+), 14 deletions(-) diff --git a/server/models/pages.mjs b/server/models/pages.mjs index c24a8cdc..da5746ce 100644 --- a/server/models/pages.mjs +++ b/server/models/pages.mjs @@ -18,8 +18,8 @@ import { PageLink } from './pageLinks.mjs' import { Tag } from './tags.mjs' import { User } from './users.mjs' -const pageRegex = /^[a-zA0-90-9-_/]*$/ -const aliasRegex = /^[a-zA0-90-9-_]*$/ +const pageRegex = /^[a-zA-Z0-9-_/]*$/ +const aliasRegex = /^[a-zA-Z0-9-_]*$/ const frontmatterRegex = { html: /^()?(?:\n|\r)*([\w\W]*)*/, diff --git a/server/models/tree.mjs b/server/models/tree.mjs index 61091ab1..c8e7ff10 100644 --- a/server/models/tree.mjs +++ b/server/models/tree.mjs @@ -132,8 +132,8 @@ export class Tree extends Model { */ static async addPage ({ id, parentId, parentPath, fileName, title, locale, siteId, meta = {} }) { const folder = (parentId || parentPath) ? await WIKI.db.tree.getFolder({ - parentId, - parentPath, + id: parentId, + path: parentPath, locale, siteId, createIfMissing: true diff --git a/ux/src/components/FileManager.vue b/ux/src/components/FileManager.vue index 503eff01..1cc0d072 100644 --- a/ux/src/components/FileManager.vue +++ b/ux/src/components/FileManager.vue @@ -320,7 +320,7 @@ import { computed, defineAsyncComponent, nextTick, onMounted, reactive, ref, toR import { filesize } from 'filesize' import { useQuasar } from 'quasar' import { DateTime } from 'luxon' -import { cloneDeep, find } from 'lodash-es' +import { cloneDeep, dropRight, find, findKey, initial, last, nth } from 'lodash-es' import { useRoute, useRouter } from 'vue-router' import gql from 'graphql-tag' import Fuse from 'fuse.js/dist/fuse.basic.esm' @@ -622,8 +622,14 @@ async function loadTree ({ parentId = null, parentPath = null, types, initLoad = // -> Set Ancestors / Tree Roots if (item.folderPath) { - if (item.id !== parentId && !state.treeNodes[parentId].children.includes(item.id)) { - state.treeNodes[parentId].children.push(item.id) + let folderParentId = parentId + if (!folderParentId) { + const parentFolderParts = item.folderPath.split('/') + const parentFolder = find(items, { folderPath: parentFolderParts.length > 1 ? initial(parentFolderParts).join('/') : '', fileName: last(parentFolderParts) }) + folderParentId = parentFolder.id + } + if (item.id !== folderParentId && !state.treeNodes[folderParentId]?.children?.includes(item.id)) { + state.treeNodes[folderParentId]?.children?.push(item.id) } } else { newTreeRoots.push(item.id) @@ -990,8 +996,30 @@ function delItem (item) { // MOUNTED -onMounted(() => { - loadTree({}) +onMounted(async () => { + const pathParts = pageStore.path.split('/') + const parentPath = initial(pathParts).join('/') + + await loadTree({ + parentPath, + initLoad: true + }) + + // -> Open tree up to current folder + const folderFolderPath = dropRight(pathParts, 2).join('/') + const folderFileName = nth(pathParts, -2) + + for (const [id, node] of Object.entries(state.treeNodes)) { + if (parentPath.startsWith(node.folderPath ? `${node.folderPath}/${node.fileName}` : node.fileName)) { + treeComp.value.setOpened(id) + } + } + + // -> Switch to current folder (from page path) + const currentNodeId = findKey(state.treeNodes, n => n.folderPath === folderFolderPath && n.fileName === folderFileName) + if (currentNodeId) { + state.currentFolderId = currentNodeId + } }) diff --git a/ux/src/components/TreeBrowserDialog.vue b/ux/src/components/TreeBrowserDialog.vue index d0e1c5f2..8e3be6d0 100644 --- a/ux/src/components/TreeBrowserDialog.vue +++ b/ux/src/components/TreeBrowserDialog.vue @@ -114,7 +114,7 @@ q-dialog(ref='dialogRef', @hide='onDialogHide') import { useI18n } from 'vue-i18n' import { computed, onMounted, reactive } from 'vue' import { useDialogPluginComponent, useQuasar } from 'quasar' -import { cloneDeep, find, last } from 'lodash-es' +import { cloneDeep, find, initial, last } from 'lodash-es' import gql from 'graphql-tag' import fileTypes from '../helpers/fileTypes' @@ -233,7 +233,7 @@ const files = computed(() => { async function save () { onDialogOK({ title: state.title, - path: state.path + path: currentFolderPath.value.length > 1 ? `${currentFolderPath.value.substring(1)}${state.path}` : state.path }) } @@ -307,10 +307,18 @@ async function loadTree ({ parentId = null, parentPath = null, types, initLoad = title: item.title, children: [] } - if (!item.folderPath) { - newTreeRoots.push(item.id) + if (item.folderPath) { + let folderParentId = parentId + if (!folderParentId) { + const parentFolderParts = item.folderPath.split('/') + const parentFolder = find(items, { folderPath: parentFolderParts.length > 1 ? initial(parentFolderParts).join('/') : '', fileName: last(parentFolderParts) }) + folderParentId = parentFolder.id + } + if (item.id !== folderParentId && !state.treeNodes[folderParentId]?.children?.includes(item.id)) { + state.treeNodes[folderParentId].children.push(item.id) + } } else { - state.treeNodes[parentId].children.push(item.id) + newTreeRoots.push(item.id) } break }