diff --git a/frontend/src/lib/i18n/catalogs/en.js b/frontend/src/lib/i18n/catalogs/en.js index a3a652d..d0613de 100644 --- a/frontend/src/lib/i18n/catalogs/en.js +++ b/frontend/src/lib/i18n/catalogs/en.js @@ -160,6 +160,15 @@ export default { 'workspaceTree.createError': 'Could not create the Deal. Please try again.', 'workspaceTree.renameError': 'Could not rename the Deal. Please try again.', 'workspaceTree.trashError': 'Could not move the Deal to trash. Please try again.', + 'workspaceTree.parentFolder': 'Parent folder', + 'workspaceTree.rootFolder': '(vault root)', + 'workspaceTree.folderTitle': 'Folders', + 'workspaceTree.folderEmpty': 'No Deals here', + 'workspaceTree.createFolder': 'Create Folder', + 'workspaceTree.folderNamePlaceholder': 'Folder name', + 'workspaceTree.folderIcon': 'Icon', + 'workspaceTree.folderColor': 'Color', + 'workspaceTree.folderCreateError': 'Could not create the folder. Please try again.', 'pluginManager.loadError': 'Could not load plugins. Please try again.', 'pluginManager.reloadError': 'Could not reload plugins. Please try again.', 'pluginManager.enableError': 'Could not enable the plugin. Please try again.', diff --git a/frontend/src/lib/i18n/catalogs/ru.js b/frontend/src/lib/i18n/catalogs/ru.js index 235d3fe..36295b9 100644 --- a/frontend/src/lib/i18n/catalogs/ru.js +++ b/frontend/src/lib/i18n/catalogs/ru.js @@ -160,6 +160,15 @@ export default { 'workspaceTree.createError': 'Не удалось создать Дело. Повторите попытку.', 'workspaceTree.renameError': 'Не удалось переименовать Дело. Повторите попытку.', 'workspaceTree.trashError': 'Не удалось переместить Дело в корзину. Повторите попытку.', + 'workspaceTree.parentFolder': 'Родительская папка', + 'workspaceTree.rootFolder': '(корень vault)', + 'workspaceTree.folderTitle': 'Папки', + 'workspaceTree.folderEmpty': 'Здесь нет Дел', + 'workspaceTree.createFolder': 'Создать папку', + 'workspaceTree.folderNamePlaceholder': 'Название папки', + 'workspaceTree.folderIcon': 'Иконка', + 'workspaceTree.folderColor': 'Цвет', + 'workspaceTree.folderCreateError': 'Не удалось создать папку. Повторите попытку.', 'pluginManager.loadError': 'Не удалось загрузить плагины. Повторите попытку.', 'pluginManager.reloadError': 'Не удалось перезагрузить плагины. Повторите попытку.', 'pluginManager.enableError': 'Не удалось включить плагин. Повторите попытку.', diff --git a/frontend/src/lib/plugin-host/VerstakPluginAPI.js b/frontend/src/lib/plugin-host/VerstakPluginAPI.js index 361d8d9..2357be0 100644 --- a/frontend/src/lib/plugin-host/VerstakPluginAPI.js +++ b/frontend/src/lib/plugin-host/VerstakPluginAPI.js @@ -584,6 +584,48 @@ export function createPluginAPI(pluginId) { } }, + workspaces: { + list: async function() { + assertActive('workspaces.list'); + return callBackend(pluginId, 'workspaces.list', () => App.ListWorkspaces()); + }, + getCurrent: async function() { + assertActive('workspaces.getCurrent'); + return callBackend(pluginId, 'workspaces.getCurrent', () => App.GetCurrentWorkspace()); + }, + getTree: async function() { + assertActive('workspaces.getTree'); + return callBackend(pluginId, 'workspaces.getTree', () => App.GetWorkspaceTree()); + }, + select: async function(path) { + assertActive('workspaces.select'); + return callBackendErrorString(pluginId, 'workspaces.select', () => App.SetCurrentWorkspace(path)); + }, + create: async function(path, templateId) { + assertActive('workspaces.create'); + return callBackend(pluginId, 'workspaces.create', () => App.CreateWorkspace(path, templateId || 'default')); + }, + trash: async function(path) { + assertActive('workspaces.trash'); + return callBackend(pluginId, 'workspaces.trash', () => App.TrashWorkspace(path)); + }, + move: async function(id, newParentId) { + assertActive('workspaces.move'); + return callBackendErrorString(pluginId, 'workspaces.move', () => App.MoveWorkspace(id, newParentId)); + } + }, + + folders: { + getMetadata: async function(path) { + assertActive('folders.getMetadata'); + return callBackend(pluginId, 'folders.getMetadata', () => App.GetFolderMetadata(path)); + }, + setMetadata: async function(path, meta) { + assertActive('folders.setMetadata'); + return callBackendErrorString(pluginId, 'folders.setMetadata', () => App.SetFolderMetadata(path, meta)); + } + }, + dispose: function() { if (disposed) return; disposed = true; diff --git a/frontend/src/lib/shell/Sidebar.svelte b/frontend/src/lib/shell/Sidebar.svelte index 35178b3..86b6431 100644 --- a/frontend/src/lib/shell/Sidebar.svelte +++ b/frontend/src/lib/shell/Sidebar.svelte @@ -2,6 +2,7 @@ import { onDestroy, onMount } from 'svelte'; import * as App from '../../../wailsjs/go/api/App'; import WorkspaceTree from './WorkspaceTree.svelte'; + import PluginBundleHost from '../plugin-host/PluginBundleHost.svelte'; import GlobalSearch from './GlobalSearch.svelte'; import Icon from '../ui/Icon.svelte'; import { debug } from '../log/debug.js'; @@ -18,6 +19,7 @@ let plugins = []; let vaultStatus = { status: 'unknown', path: '', vaultId: '' }; let sidebarItems = []; + let workspaceTreeProvider = null; let errorMessage = ''; let locale = i18n.getLocale(); let unsubscribeLocale = null; @@ -59,6 +61,19 @@ return plugin.status !== 'disabled' && plugin.status !== 'failed' && plugin.status !== 'incompatible' && plugin.status !== 'missing-required-capability'; }); sidebarItems.sort((a, b) => (a.position || 100) - (b.position || 100)); + + // Check for workspaceTree contribution + const wtContrib = (localizedContributions.workspaceTree || null); + if (wtContrib && wtContrib.pluginId && wtContrib.component) { + const wtPlugin = plugins.find(p => p.manifest?.id === wtContrib.pluginId); + if (wtPlugin && wtPlugin.status !== 'disabled' && wtPlugin.status !== 'failed' && wtPlugin.status !== 'incompatible' && wtPlugin.status !== 'missing-required-capability') { + workspaceTreeProvider = { pluginId: wtContrib.pluginId, component: wtContrib.component }; + } else { + workspaceTreeProvider = null; + } + } else { + workspaceTreeProvider = null; + } debug.log('[Sidebar] onMount: sidebarItems=' + sidebarItems.length); flog('onMount: sidebarItems=' + sidebarItems.length); } catch (e) { @@ -123,7 +138,11 @@ {/if} {#if vaultOpen} - + {#if workspaceTreeProvider} + + {:else} + + {/if} {/if}