diff --git a/src/constants/Extension.ts b/src/constants/Extension.ts index 47dec66e..aa935517 100644 --- a/src/constants/Extension.ts +++ b/src/constants/Extension.ts @@ -23,6 +23,7 @@ export const COMMAND_NAME = { createContent: getCommandName('createContent'), createByContentType: getCommandName('createByContentType'), createByTemplate: getCommandName('createByTemplate'), + createContentInFolder: getCommandName('createContentInFolder'), createTemplate: getCommandName('createTemplate'), initTemplate: getCommandName('initTemplate'), collapseSections: getCommandName('collapseSections'), diff --git a/src/dashboardWebView/DashboardMessage.ts b/src/dashboardWebView/DashboardMessage.ts index 4fd51a9d..b0e0304d 100644 --- a/src/dashboardWebView/DashboardMessage.ts +++ b/src/dashboardWebView/DashboardMessage.ts @@ -23,6 +23,7 @@ export enum DashboardMessage { createContent = 'createContent', createByContentType = 'createByContentType', createByTemplate = 'createByTemplate', + createContentInFolder = 'createContentInFolder', refreshPages = 'refreshPages', searchPages = 'searchPages', openFile = 'openFile', diff --git a/src/dashboardWebView/components/Contents/StructureView.tsx b/src/dashboardWebView/components/Contents/StructureView.tsx index b73cc15c..d883c2c8 100644 --- a/src/dashboardWebView/components/Contents/StructureView.tsx +++ b/src/dashboardWebView/components/Contents/StructureView.tsx @@ -1,10 +1,12 @@ import { Disclosure } from '@headlessui/react'; -import { ChevronRightIcon, FolderIcon } from '@heroicons/react/24/solid'; +import { ChevronRightIcon, FolderIcon, PlusIcon } from '@heroicons/react/24/solid'; import * as React from 'react'; import { useMemo } from 'react'; import { Page } from '../../models'; import { StructureItem } from './StructureItem'; import { parseWinPath } from '../../../helpers/parseWinPath'; +import { messageHandler } from '@estruyf/vscode/dist/client'; +import { DashboardMessage } from '../../DashboardMessage'; export interface IStructureViewProps { pages: Page[]; @@ -20,6 +22,31 @@ interface FolderNode { export const StructureView: React.FunctionComponent = ({ pages }: React.PropsWithChildren) => { + + const createContentInFolder = React.useCallback((folderPath: string, nodePagesOnly: Page[]) => { + // Find a page from this folder to get the base content folder information + // First try to find from the specific folder, then from all pages if not found + let samplePage = nodePagesOnly.find(page => page.fmPageFolder); + + if (!samplePage) { + // If no pages in this specific folder, find any page that has the same base folder structure + samplePage = pages.find(page => { + if (!page.fmFolder || !page.fmPageFolder) return false; + const normalizedFmFolder = page.fmFolder.replace(/\\/g, '/').replace(/^\/+|\/+$/g, ''); + return folderPath.startsWith(normalizedFmFolder) || normalizedFmFolder.startsWith(folderPath.split('/')[0]); + }); + } + + if (samplePage && samplePage.fmPageFolder) { + // Construct the full folder path by combining the base content folder with the structure path + const baseFolderPath = samplePage.fmPageFolder.path.replace(/\\/g, '/').replace(/\/+$/, ''); + const relativePath = folderPath.replace(/^\/+|\/+$/g, ''); + const fullFolderPath = `${baseFolderPath}/${relativePath}`; + + messageHandler.send(DashboardMessage.createContentInFolder, { folderPath: fullFolderPath }); + } + }, [pages]); + const folderTree = useMemo(() => { const root: FolderNode = { name: '', @@ -168,24 +195,37 @@ export const StructureView: React.FunctionComponent = ({ {({ open }) => ( <> - - - - - {node.name} - {node.pages.length > 0 && ( - - ({node.pages.length} {node.pages.length === 1 ? 'file' : 'files'}) - - )} - - +
+ + + + + {node.name} + {node.pages.length > 0 && ( + + ({node.pages.length} {node.pages.length === 1 ? 'file' : 'files'}) + + )} + + + + +
{/* Child folders */} diff --git a/src/helpers/ContentType.ts b/src/helpers/ContentType.ts index 14438c26..48040de9 100644 --- a/src/helpers/ContentType.ts +++ b/src/helpers/ContentType.ts @@ -55,6 +55,10 @@ export class ContentType { commands.registerCommand(COMMAND_NAME.createByContentType, ContentType.createContent) ); + subscriptions.push( + commands.registerCommand(COMMAND_NAME.createContentInFolder, ContentType.createContentInFolder) + ); + subscriptions.push( commands.registerCommand(COMMAND_NAME.generateContentType, ContentType.generate) ); @@ -144,6 +148,45 @@ export class ContentType { } } + /** + * Create content in a specific folder based on content types + * @param folderData - Object containing folder path information + * @returns + */ + public static async createContentInFolder(folderData: { folderPath: string }) { + if (!folderData || !folderData.folderPath) { + return; + } + + const contentTypes = ContentType.getAll(); + let folders = await Folders.get(); + folders = folders.filter((f) => !f.disableCreation); + + // Find the folder that matches the provided path + const folder = folders.find((f) => { + const folderPath = Folders.getFolderPath(Uri.file(f.path)); + // Check if the folderData.folderPath is within this content folder + return folderData.folderPath.includes(folderPath || ''); + }); + + if (!folder) { + return; + } + + const selectedContentType = await Questions.SelectContentType(folder.contentTypes || []); + if (!selectedContentType) { + return; + } + + if (contentTypes && folder) { + const contentType = contentTypes.find((ct) => ct.name === selectedContentType); + if (contentType) { + // Use the specific folder path provided instead of the base folder path + ContentType.create(contentType, folderData.folderPath); + } + } + } + /** * Retrieve all content types * @returns diff --git a/src/listeners/dashboard/PagesListener.ts b/src/listeners/dashboard/PagesListener.ts index 407490ca..feafb3eb 100644 --- a/src/listeners/dashboard/PagesListener.ts +++ b/src/listeners/dashboard/PagesListener.ts @@ -45,6 +45,9 @@ export class PagesListener extends BaseListener { case DashboardMessage.createByTemplate: await commands.executeCommand(COMMAND_NAME.createByTemplate); break; + case DashboardMessage.createContentInFolder: + await commands.executeCommand(COMMAND_NAME.createContentInFolder, msg.payload); + break; case DashboardMessage.refreshPages: this.getPagesData(true); break;