From be7f756d727efa8c251fb0576f787818bb0b55ac Mon Sep 17 00:00:00 2001 From: Grzegorz Godlewski Date: Sat, 16 Sep 2023 19:48:49 +0200 Subject: [PATCH] Refactor transform_subdir --- apps/ui/src/components/DriveTools.vue | 4 ++-- apps/ui/src/components/GitSettings.vue | 3 +-- apps/ui/src/components/UserSettings.vue | 22 +++++++++++------- apps/ui/src/pages/FolderView.vue | 23 ++++++++++++++++--- .../action/ActionRunnerContainer.ts | 2 +- src/containers/server/ServerContainer.ts | 2 +- .../server/routes/ConfigController.ts | 22 +++++++++++++++--- .../server/routes/DriveController.ts | 14 ++++++++--- .../server/routes/DriveUiController.ts | 9 ++++++-- .../server/routes/FolderController.ts | 20 ++++++++-------- .../server/routes/GoogleDriveController.ts | 11 ++++++--- .../server/routes/SearchController.ts | 2 +- .../transform/TransformContainer.ts | 4 ++++ src/utils/FileContentService.ts | 8 +++++++ 14 files changed, 106 insertions(+), 40 deletions(-) diff --git a/apps/ui/src/components/DriveTools.vue b/apps/ui/src/components/DriveTools.vue index 951db8ab..46a006f7 100644 --- a/apps/ui/src/components/DriveTools.vue +++ b/apps/ui/src/components/DriveTools.vue @@ -37,11 +37,11 @@ -
  • +
  • Markdown tree empty Sync All
  • -
  • +
  • Markdowns were generated with version: {{treeVersion}}.
    WikiGDrive is now running: {{GIT_SHA}}.
    Update your entire tree now? diff --git a/apps/ui/src/components/GitSettings.vue b/apps/ui/src/components/GitSettings.vue index 29268fca..adda5568 100644 --- a/apps/ui/src/components/GitSettings.vue +++ b/apps/ui/src/components/GitSettings.vue @@ -11,7 +11,6 @@
    -
    @@ -43,7 +42,7 @@
    - +
    diff --git a/apps/ui/src/components/UserSettings.vue b/apps/ui/src/components/UserSettings.vue index b86332ba..b2923d02 100644 --- a/apps/ui/src/components/UserSettings.vue +++ b/apps/ui/src/components/UserSettings.vue @@ -1,13 +1,24 @@ + + + + + + + - + @@ -170,7 +185,9 @@ export default { this.fetch(); this.rootFolder = this.$root.drive; this.emitter.on('tree:changed', () => { - this.fetch(); + this.$nextTick(() => { + this.fetch(); + }); }); }, watch: { @@ -215,7 +232,7 @@ export default { const file = this.files.find(file => (file.realFileName || file.fileName) === baseName) || { path: filePath.replace('/' + driveId + this.contentDir, '') }; - this.selectedFolder = null; + this.selectedFolder = {}; this.selectedFile = file || {}; } else { parts.push(baseName); diff --git a/src/containers/action/ActionRunnerContainer.ts b/src/containers/action/ActionRunnerContainer.ts index b9e4bc99..815c3ae4 100644 --- a/src/containers/action/ActionRunnerContainer.ts +++ b/src/containers/action/ActionRunnerContainer.ts @@ -99,7 +99,7 @@ export class ActionRunnerContainer extends Container { const driveIdTransform: string = path.basename(generatedFileService.getRealPath()); const contentDir = config.transform_subdir ? - `/${driveIdTransform}/${config.transform_subdir}` : + `/${driveIdTransform}${ !config.transform_subdir.startsWith('/') ? '/' : '' }${config.transform_subdir}` : `/${driveIdTransform}`; const docker = new Docker({socketPath: '/var/run/docker.sock'}); diff --git a/src/containers/server/ServerContainer.ts b/src/containers/server/ServerContainer.ts index 1bb43dae..2aaaf308 100644 --- a/src/containers/server/ServerContainer.ts +++ b/src/containers/server/ServerContainer.ts @@ -389,7 +389,7 @@ export class ServerContainer extends Container { const backlinksController = new BackLinksController('/api/backlinks', this.filesService); app.use('/api/backlinks', authenticate(this.logger), await backlinksController.getRouter()); - const configController = new ConfigController('/api/config', this.filesService, this.engine.getContainer('folder_registry')); + const configController = new ConfigController('/api/config', this.filesService, this.engine.getContainer('folder_registry'), this.engine); app.use('/api/config', authenticate(this.logger), await configController.getRouter()); const logsController = new LogsController('/api/logs', this.logger); diff --git a/src/containers/server/routes/ConfigController.ts b/src/containers/server/routes/ConfigController.ts index 7a7492be..86aa6f97 100644 --- a/src/containers/server/routes/ConfigController.ts +++ b/src/containers/server/routes/ConfigController.ts @@ -3,6 +3,7 @@ import {FileContentService} from '../../../utils/FileContentService'; import {GitScanner} from '../../../git/GitScanner'; import {UserConfigService} from '../../google_folder/UserConfigService'; import {FolderRegistryContainer} from '../../folder_registry/FolderRegistryContainer'; +import {ContainerEngine} from "../../../ContainerEngine"; export interface ConfigBody { config: { @@ -38,7 +39,7 @@ async function loadHugoThemes(filesService: FileContentService) { export class ConfigController extends Controller { - constructor(subPath: string, private readonly filesService: FileContentService, private folderRegistryContainer: FolderRegistryContainer) { + constructor(subPath: string, private readonly filesService: FileContentService, private folderRegistryContainer: FolderRegistryContainer, private engine: ContainerEngine) { super(subPath); } @@ -89,8 +90,16 @@ export class ConfigController extends Controller { if (body.config?.config_toml) { userConfigService.config.config_toml = body.config?.config_toml; } - if (body.config?.transform_subdir) { - userConfigService.config.transform_subdir = body.config?.transform_subdir; + let modified = false; + if ('string' === typeof body.config?.transform_subdir) { + let trimmed = body.config?.transform_subdir.trim(); + if (trimmed.length > 0 && !trimmed.startsWith('/')) { + trimmed = '/' + trimmed; + } + if (userConfigService.config.transform_subdir !== trimmed) { + modified = true; + } + userConfigService.config.transform_subdir = trimmed; } if (body.config?.actions_yaml) { userConfigService.config.actions_yaml = body.config?.actions_yaml; @@ -107,6 +116,13 @@ export class ConfigController extends Controller { await gitScanner.setRemoteUrl(''); } + if (modified) { + this.engine.emit(driveId, 'toasts:added', { + title: 'Config modified', + type: 'tree:changed' + }); + } + return { ...await this.returnConfig(userConfigService), remote_url: await gitScanner.getRemoteUrl() diff --git a/src/containers/server/routes/DriveController.ts b/src/containers/server/routes/DriveController.ts index bde2b856..168e7550 100644 --- a/src/containers/server/routes/DriveController.ts +++ b/src/containers/server/routes/DriveController.ts @@ -59,13 +59,21 @@ export class DriveController extends Controller { const tocFile = transformedTree.find(item => item.path === '/toc.md'); const navFile = transformedTree.find(item => item.path === '/.navigation.md' || item.path === '/navigation.md'); - const contentPrefix = userConfigService.config.transform_subdir ? `/${userConfigService.config.transform_subdir}` : ''; + let tocFilePath = null; + let navFilePath = null; + + if (userConfigService.config.transform_subdir && userConfigService.config.transform_subdir.length > 0) { + const contentPrefix = (!userConfigService.config.transform_subdir.startsWith('/') ? '/' : '') + + userConfigService.config.transform_subdir; + tocFilePath = tocFile ? contentPrefix + tocFile.path : null; + navFilePath = navFile ? contentPrefix + navFile.path : null; + } return { ...drive, gitStats: await gitScanner.getStats(userConfig), - tocFilePath: tocFile ? contentPrefix + tocFile.path : null, - navFilePath: navFile ? contentPrefix + navFile.path : null + tocFilePath, + navFilePath }; } diff --git a/src/containers/server/routes/DriveUiController.ts b/src/containers/server/routes/DriveUiController.ts index ea69d31c..ac031043 100644 --- a/src/containers/server/routes/DriveUiController.ts +++ b/src/containers/server/routes/DriveUiController.ts @@ -66,8 +66,13 @@ export class DriveUiController extends Controller { await markdownTreeProcessor.load(); const [file, drivePath] = await markdownTreeProcessor.findById(fileId); if (file && drivePath) { - const transformSubDir = userConfigService.config.transform_subdir ? '/' + userConfigService.config.transform_subdir : ''; - this.res.redirect(`/drive/${driveId}${transformSubDir || ''}/${drivePath}`); + if (userConfigService.config.transform_subdir.length > 0) { + const transformSubDir = (!userConfigService.config.transform_subdir.startsWith('/') ? '/' : '') + + userConfigService.config.transform_subdir; + this.res.redirect(`/drive/${driveId}${transformSubDir}/${drivePath}`); + } else { + this.res.redirect(`/drive/${driveId}`); + } return; } else { this.res.redirect(`/drive/${driveId}`); diff --git a/src/containers/server/routes/FolderController.ts b/src/containers/server/routes/FolderController.ts index ffdef549..36aabb84 100644 --- a/src/containers/server/routes/FolderController.ts +++ b/src/containers/server/routes/FolderController.ts @@ -244,18 +244,16 @@ export default class FolderController extends Controller { this.res.setHeader('wgd-drive-empty', googleTreeProcessor.getTree().length === 0 ? 'true' : 'false'); this.res.setHeader('wgd-tree-empty', markdownTreeProcessor.getTree().length === 0 ? 'true' : 'false'); this.res.setHeader('wgd-tree-version', treeVersion); - const contentDir = userConfigService.config.transform_subdir ? '/' + userConfigService.config.transform_subdir : '/'; - this.res.setHeader('wgd-content-dir', contentDir); + this.res.setHeader('wgd-content-dir', userConfigService.config.transform_subdir || ''); if (!await transformedFileSystem.exists(filePath)) { this.res.status(404).send({ message: 'Not exist in transformedFileSystem' }); return; } - if (!userConfigService.config.transform_subdir || inDir('/' + userConfigService.config.transform_subdir, filePath)) { - const contentFilePath = !userConfigService.config.transform_subdir ? - filePath : - filePath.replace('/' + userConfigService.config.transform_subdir, '') || '/'; + if ((userConfigService.config.transform_subdir || '').startsWith('/') && inDir(userConfigService.config.transform_subdir, filePath)) { + const prefixed_subdir = userConfigService.config.transform_subdir; + const contentFilePath = filePath.replace(prefixed_subdir, '') || '/'; const [treeItem] = contentFilePath === '/' ? await markdownTreeProcessor.getRootItem(driveId) @@ -284,7 +282,7 @@ export default class FolderController extends Controller { const changes = await getCachedChanges(this.logger, transformedFileSystem, contentFileService, googleFileSystem); const subDir = await transformedFileSystem.getSubFileService(filePath); const map1: Map = new Map( - (await this.generateChildren(subDir, driveId, '/' + userConfigService.config.transform_subdir, filePath)) + (await this.generateChildren(subDir, driveId, prefixed_subdir, filePath)) .map(element => [element.realFileName, element]) ); const map2: Map = new Map( @@ -292,7 +290,7 @@ export default class FolderController extends Controller { .map(element => [element.realFileName, element]) ); treeItem.children = Object.values({ ...Object.fromEntries(map1), ...Object.fromEntries(map2) }); - await addGitData(treeItem.children, changes, userConfigService.config.transform_subdir ? '/' + userConfigService.config.transform_subdir + '' : ''); + await addGitData(treeItem.children, changes, prefixed_subdir); await outputDirectory(this.res, treeItem); return; } else { @@ -322,7 +320,7 @@ export default class FolderController extends Controller { realFileName: '', title: '', mimeType: MimeTypes.FOLDER_MIME, - children: await this.generateChildren(subDir, driveId, '/' + userConfigService.config.transform_subdir, filePath) + children: await this.generateChildren(subDir, driveId, userConfigService.config.transform_subdir || '/', filePath) }; const changes = await getCachedChanges(this.logger, transformedFileSystem, contentFileService, googleFileSystem); @@ -347,7 +345,7 @@ export default class FolderController extends Controller { } } - async generateChildren(transformedFileSystem: FileContentService, driveId: FileId, transform_subdir: string, dirPath: string) { + async generateChildren(transformedFileSystem: FileContentService, driveId: FileId, subdir: string, dirPath: string) { const scanner = new DirectoryScanner(); const files = await scanner.scan(transformedFileSystem); @@ -355,7 +353,7 @@ export default class FolderController extends Controller { .map(file => { return { fileName: file.fileName, - id: transform_subdir === dirPath + file.fileName ? driveId : 'UNKNOWN', + id: subdir === dirPath + file.fileName ? driveId : 'UNKNOWN', parentId: 'UNKNOWN', path: dirPath + file.fileName, realFileName: file.fileName, diff --git a/src/containers/server/routes/GoogleDriveController.ts b/src/containers/server/routes/GoogleDriveController.ts index dd748d4e..8cb806e4 100644 --- a/src/containers/server/routes/GoogleDriveController.ts +++ b/src/containers/server/routes/GoogleDriveController.ts @@ -63,9 +63,9 @@ export class GoogleDriveController extends Controller { const treeItem = addPreviewUrl(userConfigService.config.hugo_theme, driveId)(foundTreeItem); - const contentDir = userConfigService.config.transform_subdir ? '/' + userConfigService.config.transform_subdir : '/'; + const contentDir = (userConfigService.config.transform_subdir || '').startsWith('/') ? userConfigService.config.transform_subdir : undefined; - this.res.setHeader('wgd-content-dir', contentDir); + this.res.setHeader('wgd-content-dir', contentDir || ''); this.res.setHeader('wgd-google-parent-id', treeItem.parentId || ''); this.res.setHeader('wgd-google-id', treeItem.id || ''); this.res.setHeader('wgd-google-version', treeItem.version || ''); @@ -76,6 +76,11 @@ export class GoogleDriveController extends Controller { this.res.setHeader('wgd-preview-url', treeItem.previewUrl || ''); this.res.setHeader('wgd-last-author', treeItem.lastAuthor || ''); + if (!contentDir) { + this.res.status(404).send('Content subdirectory must be set and start with /'); + return; + } + const treeProcessor = new GoogleTreeProcessor(googleFileSystem); await treeProcessor.load(); const [leaf] = await treeProcessor.findById(foundTreeItem.id); @@ -86,7 +91,7 @@ export class GoogleDriveController extends Controller { } const changes = await getCachedChanges(this.logger, transformedFileSystem, contentFileService, googleFileSystem); - const change = changes.find(change => change.path === (contentDir + treeItem.path).replace(/^\//, '')); + const change = changes.find(change => change.path === (contentDir.substring(1) + treeItem.path).replace(/^\//, '')); if (change) { if (change.state.isNew) { treeItem['status'] = 'N'; diff --git a/src/containers/server/routes/SearchController.ts b/src/containers/server/routes/SearchController.ts index 88486b5a..a972a0e3 100644 --- a/src/containers/server/routes/SearchController.ts +++ b/src/containers/server/routes/SearchController.ts @@ -23,7 +23,7 @@ export class SearchController extends Controller { const userConfigService = new UserConfigService(googleFileSystem); await userConfigService.load(); - const prefix = userConfigService.config.transform_subdir ? `/${userConfigService.config.transform_subdir}` : ''; + const prefix = (userConfigService.config.transform_subdir || '').startsWith('/') ? `${userConfigService.config.transform_subdir}` : ''; const transformedFileSystem = await this.filesService.getSubFileService(driveId + '_transform', ''); diff --git a/src/containers/transform/TransformContainer.ts b/src/containers/transform/TransformContainer.ts index ce0b7b2f..8f5f38a0 100644 --- a/src/containers/transform/TransformContainer.ts +++ b/src/containers/transform/TransformContainer.ts @@ -309,6 +309,10 @@ export class TransformContainer extends Container { } async run(rootFolderId: FileId) { + if (!this.userConfigService.config.transform_subdir.startsWith('/')) { + this.logger.warn('Content subdirectory must be set and start with /'); + return; + } const contentFileService = await getContentFileService(this.generatedFileService, this.userConfigService); const queueTransformer = new QueueTransformer(this.logger); diff --git a/src/utils/FileContentService.ts b/src/utils/FileContentService.ts index 1652fad3..03b59759 100644 --- a/src/utils/FileContentService.ts +++ b/src/utils/FileContentService.ts @@ -8,6 +8,9 @@ export class FileContentService extends FileService { constructor(protected readonly rootPath: string = '/', virtualPath = '/') { super(rootPath); this.virtualPath = virtualPath || '/'; + if (!this.virtualPath.endsWith('/')) { + this.virtualPath += '/'; + } } async readFile(filePath: string): Promise { @@ -44,6 +47,11 @@ export class FileContentService extends FileService { if (!subPath) { throw new Error('Empty subPath'); } + + if (subPath.startsWith('/')) { // this.virtualPath always ends with '/' + subPath = subPath.substring(1); + } + const subFileService = new FileContentService( pathResolve(this.rootPath, subPath), virtualPath !== undefined ? virtualPath : this.virtualPath + subPath + '/'