@parhelia/core 0.1.12911 → 0.1.12917
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents-view/AgentGalleryCard.js +1 -1
- package/dist/agents-view/AgentGalleryCard.js.map +1 -1
- package/dist/agents-view/AgentGalleryView.d.ts +1 -1
- package/dist/agents-view/AgentGalleryView.js +3 -2
- package/dist/agents-view/AgentGalleryView.js.map +1 -1
- package/dist/agents-view/AgentsView.js +1 -1
- package/dist/agents-view/AgentsView.js.map +1 -1
- package/dist/agents-view/AgentsWorkspaceView.js +15 -2
- package/dist/agents-view/AgentsWorkspaceView.js.map +1 -1
- package/dist/components/MarkdownViewerPopover.d.ts +73 -0
- package/dist/components/MarkdownViewerPopover.js +109 -0
- package/dist/components/MarkdownViewerPopover.js.map +1 -0
- package/dist/components/PageHeader.d.ts +11 -2
- package/dist/components/PageHeader.js +8 -3
- package/dist/components/PageHeader.js.map +1 -1
- package/dist/components/SearchInput.js +1 -1
- package/dist/components/ui/UserPicker.d.ts +5 -1
- package/dist/components/ui/UserPicker.js +17 -3
- package/dist/components/ui/UserPicker.js.map +1 -1
- package/dist/components/ui/button.js +1 -1
- package/dist/components/ui/button.js.map +1 -1
- package/dist/components/ui/command.js +1 -1
- package/dist/components/ui/delete-button.d.ts +1 -1
- package/dist/components/ui/delete-button.js +2 -2
- package/dist/components/ui/delete-button.js.map +1 -1
- package/dist/components/ui/dropdown-menu.js +3 -3
- package/dist/components/ui/input.js +1 -1
- package/dist/components/ui/input.js.map +1 -1
- package/dist/components/ui/label.js +1 -1
- package/dist/components/ui/select.d.ts +2 -0
- package/dist/components/ui/select.js +8 -6
- package/dist/components/ui/select.js.map +1 -1
- package/dist/components/ui/textarea.js +1 -3
- package/dist/components/ui/textarea.js.map +1 -1
- package/dist/config/config.js +22 -2
- package/dist/config/config.js.map +1 -1
- package/dist/config/types/workspace.d.ts +6 -2
- package/dist/editor/ConfirmationDialog.d.ts +3 -0
- package/dist/editor/ConfirmationDialog.js +5 -1
- package/dist/editor/ConfirmationDialog.js.map +1 -1
- package/dist/editor/ContentTree.d.ts +9 -2
- package/dist/editor/ContentTree.js +16 -4
- package/dist/editor/ContentTree.js.map +1 -1
- package/dist/editor/ContextMenu.js +6 -2
- package/dist/editor/ContextMenu.js.map +1 -1
- package/dist/editor/EditorWarning.js +1 -1
- package/dist/editor/EditorWarning.js.map +1 -1
- package/dist/editor/FieldHistory.js +8 -5
- package/dist/editor/FieldHistory.js.map +1 -1
- package/dist/editor/FieldListField.js +4 -3
- package/dist/editor/FieldListField.js.map +1 -1
- package/dist/editor/GlobalMenuBar.js +5 -2
- package/dist/editor/GlobalMenuBar.js.map +1 -1
- package/dist/editor/MobileLayout.js +4 -1
- package/dist/editor/MobileLayout.js.map +1 -1
- package/dist/editor/ScrollingContentTree.d.ts +2 -1
- package/dist/editor/ScrollingContentTree.js +2 -2
- package/dist/editor/ScrollingContentTree.js.map +1 -1
- package/dist/editor/Titlebar.d.ts +2 -1
- package/dist/editor/Titlebar.js +4 -9
- package/dist/editor/Titlebar.js.map +1 -1
- package/dist/editor/WorkspaceTitleSwitcher.d.ts +2 -1
- package/dist/editor/WorkspaceTitleSwitcher.js +4 -3
- package/dist/editor/WorkspaceTitleSwitcher.js.map +1 -1
- package/dist/editor/ai/AgentProfileSelector.js +3 -3
- package/dist/editor/ai/AgentProfileSelector.js.map +1 -1
- package/dist/editor/ai/Agents.js +15 -4
- package/dist/editor/ai/Agents.js.map +1 -1
- package/dist/editor/ai/ContentInspectorPopover.js +2 -1
- package/dist/editor/ai/ContentInspectorPopover.js.map +1 -1
- package/dist/editor/ai/InlineAiTrigger.js +5 -1
- package/dist/editor/ai/InlineAiTrigger.js.map +1 -1
- package/dist/editor/ai/agentActivitySummary.js +17 -9
- package/dist/editor/ai/agentActivitySummary.js.map +1 -1
- package/dist/editor/ai/dialogs/capturePageScreenshot.d.ts +18 -1
- package/dist/editor/ai/dialogs/capturePageScreenshot.js +60 -13
- package/dist/editor/ai/dialogs/capturePageScreenshot.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentDocumentList.js +6 -3
- package/dist/editor/ai/terminal/components/AgentDocumentList.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentFullPromptControls.d.ts +2 -1
- package/dist/editor/ai/terminal/components/AgentFullPromptControls.js +9 -6
- package/dist/editor/ai/terminal/components/AgentFullPromptControls.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentModeSelector.js +8 -7
- package/dist/editor/ai/terminal/components/AgentModeSelector.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentPromptTrayPopovers.js +4 -1
- package/dist/editor/ai/terminal/components/AgentPromptTrayPopovers.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentSummaryPromptActions.d.ts +2 -1
- package/dist/editor/ai/terminal/components/AgentSummaryPromptActions.js +7 -2
- package/dist/editor/ai/terminal/components/AgentSummaryPromptActions.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentTerminalSummaryLayout.d.ts +2 -1
- package/dist/editor/ai/terminal/components/AgentTerminalSummaryLayout.js +2 -2
- package/dist/editor/ai/terminal/components/AgentTerminalSummaryLayout.js.map +1 -1
- package/dist/editor/ai/terminal/components/ContextInfoBar.js +35 -8
- package/dist/editor/ai/terminal/components/ContextInfoBar.js.map +1 -1
- package/dist/editor/ai/terminal/components/EditOperationsPanel.js +3 -3
- package/dist/editor/ai/terminal/components/EditOperationsPanel.js.map +1 -1
- package/dist/editor/ai/terminal/components/UserMessage.js +4 -4
- package/dist/editor/ai/terminal/components/UserMessage.js.map +1 -1
- package/dist/editor/ai/terminal/projectTemplateContext.d.ts +11 -0
- package/dist/editor/ai/terminal/projectTemplateContext.js +64 -0
- package/dist/editor/ai/terminal/projectTemplateContext.js.map +1 -0
- package/dist/editor/ai/terminal/useAgentLoadPipeline.js +1 -0
- package/dist/editor/ai/terminal/useAgentLoadPipeline.js.map +1 -1
- package/dist/editor/ai/terminal/useAgentLoader.d.ts +1 -0
- package/dist/editor/ai/terminal/useAgentLoader.js +14 -2
- package/dist/editor/ai/terminal/useAgentLoader.js.map +1 -1
- package/dist/editor/ai/terminal/useAgentSettingsData.js +1 -0
- package/dist/editor/ai/terminal/useAgentSettingsData.js.map +1 -1
- package/dist/editor/ai/terminal/useAgentSubmitHandlers.d.ts +1 -0
- package/dist/editor/ai/terminal/useAgentSubmitHandlers.js +19 -1
- package/dist/editor/ai/terminal/useAgentSubmitHandlers.js.map +1 -1
- package/dist/editor/ai/terminal/useAgentTerminalController.js +4 -1
- package/dist/editor/ai/terminal/useAgentTerminalController.js.map +1 -1
- package/dist/editor/ai/useInlineAiPosition.d.ts +2 -1
- package/dist/editor/ai/useInlineAiPosition.js +10 -3
- package/dist/editor/ai/useInlineAiPosition.js.map +1 -1
- package/dist/editor/bridge/protocol.d.ts +35 -1
- package/dist/editor/bridge/protocol.js +4 -1
- package/dist/editor/bridge/protocol.js.map +1 -1
- package/dist/editor/client/EditorShell.js +47 -33
- package/dist/editor/client/EditorShell.js.map +1 -1
- package/dist/editor/client/editContext.d.ts +3 -4
- package/dist/editor/client/errorToast.d.ts +12 -0
- package/dist/editor/client/errorToast.js +67 -0
- package/dist/editor/client/errorToast.js.map +1 -0
- package/dist/editor/client/helpers.d.ts +2 -4
- package/dist/editor/client/helpers.js +3 -2
- package/dist/editor/client/helpers.js.map +1 -1
- package/dist/editor/client/hooks/useSocketMessageHandler.js +5 -3
- package/dist/editor/client/hooks/useSocketMessageHandler.js.map +1 -1
- package/dist/editor/client/operations.d.ts +2 -4
- package/dist/editor/client/operations.js +11 -2
- package/dist/editor/client/operations.js.map +1 -1
- package/dist/editor/client/pageModelBuilder.d.ts +1 -0
- package/dist/editor/client/pageModelBuilder.js +9 -2
- package/dist/editor/client/pageModelBuilder.js.map +1 -1
- package/dist/editor/client/ui/FullscreenControls.d.ts +0 -1
- package/dist/editor/client/ui/FullscreenControls.js +4 -17
- package/dist/editor/client/ui/FullscreenControls.js.map +1 -1
- package/dist/editor/commands/componentCommands.d.ts +1 -0
- package/dist/editor/commands/componentCommands.js +139 -2
- package/dist/editor/commands/componentCommands.js.map +1 -1
- package/dist/editor/content-tree/TreeSettingsMenu.js +1 -1
- package/dist/editor/content-tree/TreeSettingsMenu.js.map +1 -1
- package/dist/editor/field-types/DateFieldEditor.js +1 -1
- package/dist/editor/field-types/DateFieldEditor.js.map +1 -1
- package/dist/editor/field-types/DateTimeFieldEditor.js +1 -1
- package/dist/editor/field-types/DateTimeFieldEditor.js.map +1 -1
- package/dist/editor/field-types/useTextCompletion.js +12 -43
- package/dist/editor/field-types/useTextCompletion.js.map +1 -1
- package/dist/editor/fieldTypeConfiguration.d.ts +2 -0
- package/dist/editor/fieldTypeConfiguration.js +7 -0
- package/dist/editor/fieldTypeConfiguration.js.map +1 -0
- package/dist/editor/menubar/PageSelector.js +8 -1
- package/dist/editor/menubar/PageSelector.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/DeviceSwitchToolbar.d.ts +7 -1
- package/dist/editor/menubar/toolbar-sections/DeviceSwitchToolbar.js +22 -14
- package/dist/editor/menubar/toolbar-sections/DeviceSwitchToolbar.js.map +1 -1
- package/dist/editor/page-editor-chrome/BridgeInlineFormatOverlay.js +7 -1
- package/dist/editor/page-editor-chrome/BridgeInlineFormatOverlay.js.map +1 -1
- package/dist/editor/page-editor-chrome/DragInsertionOverlay.js +53 -19
- package/dist/editor/page-editor-chrome/DragInsertionOverlay.js.map +1 -1
- package/dist/editor/page-editor-chrome/FrameMenu.js +11 -3
- package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
- package/dist/editor/page-editor-chrome/InsertComponentMenu.js +1 -1
- package/dist/editor/page-editor-chrome/InsertComponentMenu.js.map +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +4 -3
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -1
- package/dist/editor/page-editor-chrome/bridgeInlineFormatToolbarLayout.d.ts +2 -1
- package/dist/editor/page-editor-chrome/bridgeInlineFormatToolbarLayout.js +2 -0
- package/dist/editor/page-editor-chrome/bridgeInlineFormatToolbarLayout.js.map +1 -1
- package/dist/editor/page-editor-chrome/insertTargetLabel.d.ts +1 -0
- package/dist/editor/page-editor-chrome/insertTargetLabel.js +14 -1
- package/dist/editor/page-editor-chrome/insertTargetLabel.js.map +1 -1
- package/dist/editor/page-editor-chrome/overlay/placeholderZones.js +13 -3
- package/dist/editor/page-editor-chrome/overlay/placeholderZones.js.map +1 -1
- package/dist/editor/page-editor-chrome/useComponentDragHandle.js +11 -5
- package/dist/editor/page-editor-chrome/useComponentDragHandle.js.map +1 -1
- package/dist/editor/page-viewer/PageViewer.js +5 -4
- package/dist/editor/page-viewer/PageViewer.js.map +1 -1
- package/dist/editor/page-viewer/PageViewerFrame.js +342 -5
- package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
- package/dist/editor/page-viewer/RenderingParametersSection.js +1 -1
- package/dist/editor/page-viewer/RenderingParametersSection.js.map +1 -1
- package/dist/editor/page-viewer/bridgeFieldPatch.d.ts +3 -1
- package/dist/editor/page-viewer/bridgeFieldPatch.js +26 -2
- package/dist/editor/page-viewer/bridgeFieldPatch.js.map +1 -1
- package/dist/editor/page-viewer/pageViewContext.d.ts +4 -1
- package/dist/editor/page-viewer/pageViewContext.js +4 -1
- package/dist/editor/page-viewer/pageViewContext.js.map +1 -1
- package/dist/editor/page-viewer/parentBridgeInjection.d.ts +23 -0
- package/dist/editor/page-viewer/parentBridgeInjection.js +251 -0
- package/dist/editor/page-viewer/parentBridgeInjection.js.map +1 -0
- package/dist/editor/page-viewer/renderUrl.js +4 -2
- package/dist/editor/page-viewer/renderUrl.js.map +1 -1
- package/dist/editor/pageModel.d.ts +1 -0
- package/dist/editor/reviews/DecisionsMatrix.js +1 -1
- package/dist/editor/reviews/DecisionsMatrix.js.map +1 -1
- package/dist/editor/reviews/MultiReviewManager.js +3 -22
- package/dist/editor/reviews/MultiReviewManager.js.map +1 -1
- package/dist/editor/reviews/openCommentsFeedback.js +2 -0
- package/dist/editor/reviews/openCommentsFeedback.js.map +1 -1
- package/dist/editor/services/agentService.js +6 -2
- package/dist/editor/services/agentService.js.map +1 -1
- package/dist/editor/services/editService.d.ts +15 -0
- package/dist/editor/services/editService.js +3 -0
- package/dist/editor/services/editService.js.map +1 -1
- package/dist/editor/services/textCompletionService.d.ts +14 -0
- package/dist/editor/services/textCompletionService.js +45 -0
- package/dist/editor/services/textCompletionService.js.map +1 -0
- package/dist/editor/settings/About.js +40 -263
- package/dist/editor/settings/About.js.map +1 -1
- package/dist/editor/settings/SettingsBreadcrumb.js +8 -1
- package/dist/editor/settings/SettingsBreadcrumb.js.map +1 -1
- package/dist/editor/settings/SettingsHeaderActionsContext.d.ts +4 -0
- package/dist/editor/settings/SettingsHeaderActionsContext.js.map +1 -1
- package/dist/editor/settings/SettingsTitlebar.d.ts +1 -0
- package/dist/editor/settings/SettingsTitlebar.js +18 -0
- package/dist/editor/settings/SettingsTitlebar.js.map +1 -0
- package/dist/editor/settings/SettingsView.js +64 -18
- package/dist/editor/settings/SettingsView.js.map +1 -1
- package/dist/editor/settings/panels/AgentToolsPanel.js +3 -7
- package/dist/editor/settings/panels/AgentToolsPanel.js.map +1 -1
- package/dist/editor/settings/panels/AgentsPanel.js +2 -3
- package/dist/editor/settings/panels/AgentsPanel.js.map +1 -1
- package/dist/editor/settings/panels/ClusterInstancesPanel.js +2 -3
- package/dist/editor/settings/panels/ClusterInstancesPanel.js.map +1 -1
- package/dist/editor/settings/panels/FieldTypeSerializersPanel.js +2 -4
- package/dist/editor/settings/panels/FieldTypeSerializersPanel.js.map +1 -1
- package/dist/editor/settings/panels/JavaScriptToolsPanel.js +2 -3
- package/dist/editor/settings/panels/JavaScriptToolsPanel.js.map +1 -1
- package/dist/editor/settings/panels/McpToolsPanel.js +3 -4
- package/dist/editor/settings/panels/McpToolsPanel.js.map +1 -1
- package/dist/editor/settings/panels/ModelsPanel.js +4 -3
- package/dist/editor/settings/panels/ModelsPanel.js.map +1 -1
- package/dist/editor/settings/panels/ProjectTemplateAgentPanel.d.ts +8 -1
- package/dist/editor/settings/panels/ProjectTemplateAgentPanel.js +75 -9
- package/dist/editor/settings/panels/ProjectTemplateAgentPanel.js.map +1 -1
- package/dist/editor/settings/panels/ProjectTemplateSelectorList.js +1 -1
- package/dist/editor/settings/panels/ProjectTemplateSelectorList.js.map +1 -1
- package/dist/editor/settings/panels/ProjectTemplatesPanel.js +516 -52
- package/dist/editor/settings/panels/ProjectTemplatesPanel.js.map +1 -1
- package/dist/editor/settings/panels/ProvidersPanel.js +1 -1
- package/dist/editor/settings/panels/ProvidersPanel.js.map +1 -1
- package/dist/editor/settings/settingsNavigationStore.d.ts +12 -0
- package/dist/editor/settings/settingsNavigationStore.js +32 -0
- package/dist/editor/settings/settingsNavigationStore.js.map +1 -0
- package/dist/editor/setup-wizard/steps/LicenseActivationStep.d.ts +3 -1
- package/dist/editor/setup-wizard/steps/LicenseActivationStep.js +9 -5
- package/dist/editor/setup-wizard/steps/LicenseActivationStep.js.map +1 -1
- package/dist/editor/setup-wizard/steps/LicenseEmailStep.d.ts +2 -1
- package/dist/editor/setup-wizard/steps/LicenseEmailStep.js +6 -3
- package/dist/editor/setup-wizard/steps/LicenseEmailStep.js.map +1 -1
- package/dist/editor/setup-wizard/steps/ProviderStep.js +6 -2
- package/dist/editor/setup-wizard/steps/ProviderStep.js.map +1 -1
- package/dist/editor/sidebar/ComponentPalette.js +10 -4
- package/dist/editor/sidebar/ComponentPalette.js.map +1 -1
- package/dist/editor/sidebar/ComponentTree.js +12 -12
- package/dist/editor/sidebar/ComponentTree.js.map +1 -1
- package/dist/editor/sidebar/ContentTreePanel.js +1 -1
- package/dist/editor/sidebar/ContentTreePanel.js.map +1 -1
- package/dist/editor/sidebar/SidebarPanel.js +1 -1
- package/dist/editor/sidebar/SidebarPanel.js.map +1 -1
- package/dist/editor/sidebar/WorkspaceRailMobile.d.ts +0 -1
- package/dist/editor/sidebar/WorkspaceRailMobile.js +4 -16
- package/dist/editor/sidebar/WorkspaceRailMobile.js.map +1 -1
- package/dist/editor/ui/ComponentThumbnailDialog.d.ts +14 -0
- package/dist/editor/ui/ComponentThumbnailDialog.js +75 -0
- package/dist/editor/ui/ComponentThumbnailDialog.js.map +1 -0
- package/dist/editor/ui/ItemCollectionEditor.d.ts +6 -2
- package/dist/editor/ui/ItemCollectionEditor.js +163 -84
- package/dist/editor/ui/ItemCollectionEditor.js.map +1 -1
- package/dist/editor/ui/PerfectTree.d.ts +5 -1
- package/dist/editor/ui/PerfectTree.js +10 -6
- package/dist/editor/ui/PerfectTree.js.map +1 -1
- package/dist/editor/ui/PublishRestrictionsDialog.js +77 -9
- package/dist/editor/ui/PublishRestrictionsDialog.js.map +1 -1
- package/dist/editor/ui/SimpleIconButton.js +1 -1
- package/dist/editor/ui/Splitter.d.ts +3 -0
- package/dist/editor/ui/Splitter.js +30 -16
- package/dist/editor/ui/Splitter.js.map +1 -1
- package/dist/editor/ui/TreeListSelector.d.ts +6 -2
- package/dist/editor/ui/TreeListSelector.js +2 -2
- package/dist/editor/ui/TreeListSelector.js.map +1 -1
- package/dist/editor/utils/itemutils.js +2 -0
- package/dist/editor/utils/itemutils.js.map +1 -1
- package/dist/editor/views/ItemEditorPane.js +1 -1
- package/dist/editor/views/ItemEditorPane.js.map +1 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/task-board/TaskBoardWorkspace.js +73 -5
- package/dist/task-board/TaskBoardWorkspace.js.map +1 -1
- package/dist/task-board/components/CreateProjectDialog.d.ts +0 -1
- package/dist/task-board/components/CreateProjectDialog.js +1 -4
- package/dist/task-board/components/CreateProjectDialog.js.map +1 -1
- package/dist/task-board/components/GoalDialog.d.ts +9 -0
- package/dist/task-board/components/GoalDialog.js +149 -0
- package/dist/task-board/components/GoalDialog.js.map +1 -0
- package/dist/task-board/components/ProjectDashboard.d.ts +10 -0
- package/dist/task-board/components/ProjectDashboard.js +5 -4
- package/dist/task-board/components/ProjectDashboard.js.map +1 -1
- package/dist/task-board/components/ProjectGoalsPanel.d.ts +16 -0
- package/dist/task-board/components/ProjectGoalsPanel.js +310 -0
- package/dist/task-board/components/ProjectGoalsPanel.js.map +1 -0
- package/dist/task-board/components/ProjectPropertiesPanel.js +6 -4
- package/dist/task-board/components/ProjectPropertiesPanel.js.map +1 -1
- package/dist/task-board/components/TaskAssigneeBadge.d.ts +1 -1
- package/dist/task-board/components/TaskAssigneeBadge.js +1 -1
- package/dist/task-board/components/TaskAssigneeBadge.js.map +1 -1
- package/dist/task-board/components/TaskAssigneePicker.js +1 -1
- package/dist/task-board/components/TaskAssigneePicker.js.map +1 -1
- package/dist/task-board/components/TaskAttachmentDropZone.d.ts +1 -0
- package/dist/task-board/components/TaskAttachmentDropZone.js +5 -3
- package/dist/task-board/components/TaskAttachmentDropZone.js.map +1 -1
- package/dist/task-board/components/TaskAttachmentsSection.js +8 -1
- package/dist/task-board/components/TaskAttachmentsSection.js.map +1 -1
- package/dist/task-board/components/TaskRow.js +1 -1
- package/dist/task-board/components/TaskRow.js.map +1 -1
- package/dist/task-board/components/WizardCommunicationCenter.js +1 -10
- package/dist/task-board/components/WizardCommunicationCenter.js.map +1 -1
- package/dist/task-board/services/goalService.d.ts +65 -0
- package/dist/task-board/services/goalService.js +37 -0
- package/dist/task-board/services/goalService.js.map +1 -0
- package/dist/task-board/types.d.ts +68 -3
- package/dist/task-board/views/DependencyGraphView.js +121 -31
- package/dist/task-board/views/DependencyGraphView.js.map +1 -1
- package/package.json +2 -2
- package/dist/editor/sidebar/MobileWorkspacePopover.d.ts +0 -16
- package/dist/editor/sidebar/MobileWorkspacePopover.js +0 -35
- package/dist/editor/sidebar/MobileWorkspacePopover.js.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { ChevronLeft, CopyPlus, CornerDownRight, GitBranch, LayoutTemplate, Link2, Plus, RefreshCw, Settings2, Shield, X, } from "lucide-react";
|
|
2
|
+
import { ChevronLeft, CopyPlus, CornerDownRight, GitBranch, LayoutTemplate, Link2, PanelRightOpen, Plus, RefreshCw, Settings2, Shield, Trash2, X, } from "lucide-react";
|
|
3
3
|
import { useCallback, useEffect, useMemo, useRef, useState, Suspense, lazy, } from "react";
|
|
4
4
|
import { toast } from "sonner";
|
|
5
5
|
import { Badge } from "../../../components/ui/badge";
|
|
6
6
|
import { Button } from "../../../components/ui/button";
|
|
7
|
-
import {
|
|
7
|
+
import { CloseButton } from "../../../components/ui/close-button";
|
|
8
8
|
import { DeleteIcon } from "../../../components/ui/delete-icon";
|
|
9
9
|
import { Dialog, DialogContent, DialogFooter, } from "../../../components/ui/dialog";
|
|
10
10
|
import { Input } from "../../../components/ui/input";
|
|
@@ -22,7 +22,7 @@ const DependencyGraphView = lazy(() => import("../../../task-board/views/Depende
|
|
|
22
22
|
})));
|
|
23
23
|
import { useEditContext } from "../../client/editContext";
|
|
24
24
|
import { useSearchParams } from "../../client/navigation";
|
|
25
|
-
import { updateAgentContext } from "../../services/agentService";
|
|
25
|
+
import { updateAgentContext, } from "../../services/agentService";
|
|
26
26
|
import { getAiProfilesErrorMessage, loadAiProfiles, } from "../../services/aiService";
|
|
27
27
|
import { localStorageService } from "../../services/localStorageService";
|
|
28
28
|
import { ItemNameDialog, } from "../../ui/ItemNameDialogNew";
|
|
@@ -94,6 +94,9 @@ function normalizeTaskTemplate(task) {
|
|
|
94
94
|
const rawAssigneeId = task.assigneeId?.trim() || null;
|
|
95
95
|
const rawAgentProfileId = task.agentProfileId?.trim() || null;
|
|
96
96
|
const rawParentTaskId = task.parentTaskId?.trim() || null;
|
|
97
|
+
const dependencyIds = Array.from(new Set((task.dependencyIds ?? [])
|
|
98
|
+
.map((dependencyId) => dependencyId?.trim())
|
|
99
|
+
.filter((dependencyId) => !!dependencyId)));
|
|
97
100
|
const disabled = task.disabled === true;
|
|
98
101
|
const taskType = String(task.taskType ?? "").toLowerCase() === "decisionpoint"
|
|
99
102
|
? "DecisionPoint"
|
|
@@ -115,6 +118,7 @@ function normalizeTaskTemplate(task) {
|
|
|
115
118
|
assigneeId: canonicalAgentId,
|
|
116
119
|
agentProfileId: canonicalAgentId,
|
|
117
120
|
parentTaskId: rawParentTaskId,
|
|
121
|
+
dependencyIds,
|
|
118
122
|
};
|
|
119
123
|
}
|
|
120
124
|
if (assigneeType === "user" || assigneeType === "Role") {
|
|
@@ -127,6 +131,7 @@ function normalizeTaskTemplate(task) {
|
|
|
127
131
|
assigneeId: rawAssigneeId,
|
|
128
132
|
agentProfileId: null,
|
|
129
133
|
parentTaskId: rawParentTaskId,
|
|
134
|
+
dependencyIds,
|
|
130
135
|
};
|
|
131
136
|
}
|
|
132
137
|
return {
|
|
@@ -138,6 +143,7 @@ function normalizeTaskTemplate(task) {
|
|
|
138
143
|
assigneeId: rawAssigneeId,
|
|
139
144
|
agentProfileId: null,
|
|
140
145
|
parentTaskId: rawParentTaskId,
|
|
146
|
+
dependencyIds,
|
|
141
147
|
};
|
|
142
148
|
}
|
|
143
149
|
function normalizeGraphOrientation(orientation) {
|
|
@@ -147,7 +153,6 @@ function normalizeProjectTemplate(template) {
|
|
|
147
153
|
return {
|
|
148
154
|
...template,
|
|
149
155
|
hideFromCreateDialog: template.hideFromCreateDialog === true,
|
|
150
|
-
openInWizardMode: template.openInWizardMode === true,
|
|
151
156
|
graphLayout: template.graphLayout
|
|
152
157
|
? {
|
|
153
158
|
...template.graphLayout,
|
|
@@ -155,6 +160,10 @@ function normalizeProjectTemplate(template) {
|
|
|
155
160
|
}
|
|
156
161
|
: null,
|
|
157
162
|
taskTemplates: (template.taskTemplates ?? []).map(normalizeTaskTemplate),
|
|
163
|
+
goalTemplates: (template.goalTemplates ?? []).map((goal) => ({
|
|
164
|
+
...goal,
|
|
165
|
+
disabled: goal.disabled === true,
|
|
166
|
+
})),
|
|
158
167
|
};
|
|
159
168
|
}
|
|
160
169
|
function createEmptyTemplate() {
|
|
@@ -164,11 +173,11 @@ function createEmptyTemplate() {
|
|
|
164
173
|
description: "",
|
|
165
174
|
disabled: false,
|
|
166
175
|
hideFromCreateDialog: false,
|
|
167
|
-
openInWizardMode: false,
|
|
168
176
|
isSystem: false,
|
|
169
177
|
defaultCostLimit: null,
|
|
170
178
|
graphLayout: null,
|
|
171
179
|
taskTemplates: [],
|
|
180
|
+
goalTemplates: [],
|
|
172
181
|
};
|
|
173
182
|
}
|
|
174
183
|
function createEmptyTaskTemplate(taskCount, title) {
|
|
@@ -188,6 +197,17 @@ function createEmptyTaskTemplate(taskCount, title) {
|
|
|
188
197
|
dependencyIds: [],
|
|
189
198
|
};
|
|
190
199
|
}
|
|
200
|
+
function createEmptyGoalDefinition(goalCount, title) {
|
|
201
|
+
return {
|
|
202
|
+
id: crypto.randomUUID(),
|
|
203
|
+
title: title?.trim() || `Goal ${goalCount + 1}`,
|
|
204
|
+
description: "",
|
|
205
|
+
disabled: false,
|
|
206
|
+
sortOrder: goalCount * 100,
|
|
207
|
+
defaultScopeJson: null,
|
|
208
|
+
dataShape: null,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
191
211
|
function sortTemplates(templates) {
|
|
192
212
|
return [...templates].sort((left, right) => left.name.localeCompare(right.name, undefined, { sensitivity: "base" }));
|
|
193
213
|
}
|
|
@@ -195,10 +215,9 @@ function buildUpsertTemplateRequest(template) {
|
|
|
195
215
|
return {
|
|
196
216
|
projectTemplateId: template.id,
|
|
197
217
|
name: template.name.trim(),
|
|
198
|
-
description: template.description
|
|
218
|
+
description: template.description || null,
|
|
199
219
|
disabled: template.disabled === true,
|
|
200
220
|
hideFromCreateDialog: template.hideFromCreateDialog === true,
|
|
201
|
-
openInWizardMode: template.openInWizardMode === true,
|
|
202
221
|
defaultCostLimit: template.defaultCostLimit == null ||
|
|
203
222
|
Number.isNaN(template.defaultCostLimit)
|
|
204
223
|
? null
|
|
@@ -216,7 +235,7 @@ function buildUpsertTemplateRequest(template) {
|
|
|
216
235
|
return {
|
|
217
236
|
...normalizedTask,
|
|
218
237
|
title: normalizedTask.title.trim(),
|
|
219
|
-
description: normalizedTask.description
|
|
238
|
+
description: normalizedTask.description || null,
|
|
220
239
|
disabled: normalizedTask.disabled === true,
|
|
221
240
|
taskType: normalizedTask.taskType ?? "Task",
|
|
222
241
|
decisionMode: normalizedTask.taskType === "DecisionPoint"
|
|
@@ -231,10 +250,35 @@ function buildUpsertTemplateRequest(template) {
|
|
|
231
250
|
dependencyIds: Array.from(new Set(normalizedTask.dependencyIds || [])),
|
|
232
251
|
};
|
|
233
252
|
}),
|
|
253
|
+
goalTemplates: (template.goalTemplates ?? []).map((goal, index) => ({
|
|
254
|
+
id: goal.id,
|
|
255
|
+
title: goal.title.trim(),
|
|
256
|
+
description: goal.description || null,
|
|
257
|
+
disabled: goal.disabled === true,
|
|
258
|
+
sortOrder: goal.sortOrder || index * 100,
|
|
259
|
+
defaultScopeJson: goal.defaultScopeJson?.trim() || null,
|
|
260
|
+
dataShape: goal.dataShape?.trim() || null,
|
|
261
|
+
})),
|
|
234
262
|
};
|
|
235
263
|
}
|
|
236
264
|
function mergeTemplateResponseWithRequest(serverTemplate, request) {
|
|
237
265
|
const requestedTaskById = new Map((request.taskTemplates ?? []).map((task) => [task.id, task]));
|
|
266
|
+
const requestedGoalById = new Map((request.goalTemplates ?? []).map((goal) => [goal.id, goal]));
|
|
267
|
+
// Server re-reads goals after BeginEdit/EndEdit; if a just-written goal is
|
|
268
|
+
// briefly missing from the response, keep it from the request so the next
|
|
269
|
+
// autosave does not delete it.
|
|
270
|
+
const serverGoals = serverTemplate.goalTemplates ?? [];
|
|
271
|
+
const serverGoalIds = new Set(serverGoals.map((goal) => goal.id));
|
|
272
|
+
const mergedGoalTemplates = [
|
|
273
|
+
...serverGoals.map((goal) => {
|
|
274
|
+
const requested = requestedGoalById.get(goal.id);
|
|
275
|
+
return {
|
|
276
|
+
...goal,
|
|
277
|
+
description: requested?.description ?? goal.description,
|
|
278
|
+
};
|
|
279
|
+
}),
|
|
280
|
+
...(request.goalTemplates ?? []).filter((goal) => !serverGoalIds.has(goal.id)),
|
|
281
|
+
];
|
|
238
282
|
const mergedGraphLayout = request.graphLayout === undefined
|
|
239
283
|
? serverTemplate.graphLayout
|
|
240
284
|
: request.graphLayout === null
|
|
@@ -247,7 +291,9 @@ function mergeTemplateResponseWithRequest(serverTemplate, request) {
|
|
|
247
291
|
};
|
|
248
292
|
return normalizeProjectTemplate({
|
|
249
293
|
...serverTemplate,
|
|
294
|
+
description: request.description ?? serverTemplate.description,
|
|
250
295
|
graphLayout: mergedGraphLayout,
|
|
296
|
+
goalTemplates: mergedGoalTemplates,
|
|
251
297
|
taskTemplates: (serverTemplate.taskTemplates ?? []).map((task) => {
|
|
252
298
|
const requested = requestedTaskById.get(task.id);
|
|
253
299
|
// Sitecore item-cache reads after BeginEdit/EndEdit can briefly omit
|
|
@@ -258,6 +304,7 @@ function mergeTemplateResponseWithRequest(serverTemplate, request) {
|
|
|
258
304
|
const requestedDeps = requested?.dependencyIds ?? [];
|
|
259
305
|
return {
|
|
260
306
|
...task,
|
|
307
|
+
description: requested?.description ?? task.description,
|
|
261
308
|
parentTaskId: task.parentTaskId ?? requested?.parentTaskId ?? null,
|
|
262
309
|
dependencyIds: serverDeps.length === 0 && requestedDeps.length > 0
|
|
263
310
|
? Array.from(new Set(requestedDeps))
|
|
@@ -266,6 +313,61 @@ function mergeTemplateResponseWithRequest(serverTemplate, request) {
|
|
|
266
313
|
}),
|
|
267
314
|
});
|
|
268
315
|
}
|
|
316
|
+
function getActiveDescriptionDraftField(selectedTaskId, selectedGoalId) {
|
|
317
|
+
if (typeof document === "undefined") {
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
const activeElement = document.activeElement;
|
|
321
|
+
if (!(activeElement instanceof HTMLElement)) {
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
switch (activeElement.dataset.testid) {
|
|
325
|
+
case "project-template-description-input":
|
|
326
|
+
return { kind: "template" };
|
|
327
|
+
case "project-template-task-description-input":
|
|
328
|
+
return { kind: "task", id: selectedTaskId };
|
|
329
|
+
case "project-template-goal-description-input":
|
|
330
|
+
return { kind: "goal", id: selectedGoalId };
|
|
331
|
+
default:
|
|
332
|
+
return null;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
function preserveActiveDescriptionDraft(template, draft, activeField) {
|
|
336
|
+
if (!draft || template.id !== draft.id || !activeField) {
|
|
337
|
+
return template;
|
|
338
|
+
}
|
|
339
|
+
if (activeField.kind === "template") {
|
|
340
|
+
return {
|
|
341
|
+
...template,
|
|
342
|
+
description: draft.description,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
if (activeField.kind === "task" && activeField.id) {
|
|
346
|
+
const draftTask = draft.taskTemplates.find((task) => task.id === activeField.id);
|
|
347
|
+
if (!draftTask) {
|
|
348
|
+
return template;
|
|
349
|
+
}
|
|
350
|
+
return {
|
|
351
|
+
...template,
|
|
352
|
+
taskTemplates: template.taskTemplates.map((task) => task.id === activeField.id
|
|
353
|
+
? { ...task, description: draftTask.description }
|
|
354
|
+
: task),
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
if (activeField.kind === "goal" && activeField.id) {
|
|
358
|
+
const draftGoal = (draft.goalTemplates ?? []).find((goal) => goal.id === activeField.id);
|
|
359
|
+
if (!draftGoal) {
|
|
360
|
+
return template;
|
|
361
|
+
}
|
|
362
|
+
return {
|
|
363
|
+
...template,
|
|
364
|
+
goalTemplates: (template.goalTemplates ?? []).map((goal) => goal.id === activeField.id
|
|
365
|
+
? { ...goal, description: draftGoal.description }
|
|
366
|
+
: goal),
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
return template;
|
|
370
|
+
}
|
|
269
371
|
function isValidGuid(value) {
|
|
270
372
|
return (!!value &&
|
|
271
373
|
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value));
|
|
@@ -362,12 +464,28 @@ function canAddTemplateDependency(template, taskId, dependencyId) {
|
|
|
362
464
|
}
|
|
363
465
|
return task.parentTaskId !== dependencyId;
|
|
364
466
|
}
|
|
365
|
-
function buildProjectTemplateAgentContext(template, selectedTaskTemplateId) {
|
|
467
|
+
function buildProjectTemplateAgentContext(template, selectedTaskTemplateId, selectedGoalTemplateId = null) {
|
|
366
468
|
const dependencyCount = template.taskTemplates.reduce((count, task) => count + (task.dependencyIds?.length ?? 0), 0);
|
|
367
469
|
const agentAssignedTaskCount = template.taskTemplates.filter((task) => task.agentProfileId || (task.assigneeType === "Agent" && task.assigneeId)).length;
|
|
368
470
|
const selectedTask = selectedTaskTemplateId
|
|
369
471
|
? (template.taskTemplates.find((task) => task.id === selectedTaskTemplateId) ?? null)
|
|
370
472
|
: null;
|
|
473
|
+
const goalDefinitions = [...(template.goalTemplates ?? [])]
|
|
474
|
+
.sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0))
|
|
475
|
+
.map((goal) => ({
|
|
476
|
+
id: goal.id,
|
|
477
|
+
title: goal.title?.trim() || "Untitled goal",
|
|
478
|
+
description: goal.description?.trim() || null,
|
|
479
|
+
disabled: goal.disabled === true,
|
|
480
|
+
sortOrder: goal.sortOrder ?? 0,
|
|
481
|
+
defaultScopeJson: goal.defaultScopeJson?.trim() || null,
|
|
482
|
+
dataShape: goal.dataShape?.trim() || null,
|
|
483
|
+
}));
|
|
484
|
+
const selectedGoal = selectedGoalTemplateId
|
|
485
|
+
? (goalDefinitions.find((goal) => goal.id === selectedGoalTemplateId) ??
|
|
486
|
+
null)
|
|
487
|
+
: null;
|
|
488
|
+
const enabledGoalCount = goalDefinitions.filter((goal) => goal.disabled !== true).length;
|
|
371
489
|
return {
|
|
372
490
|
activeWorkspace: "settings",
|
|
373
491
|
additionalData: {
|
|
@@ -383,10 +501,22 @@ function buildProjectTemplateAgentContext(template, selectedTaskTemplateId) {
|
|
|
383
501
|
selectedTaskTemplate: selectedTask
|
|
384
502
|
? normalizeTaskTemplate(selectedTask)
|
|
385
503
|
: null,
|
|
504
|
+
selectedGoalTemplateId: selectedGoal ? selectedGoal.id : null,
|
|
505
|
+
selectedGoalTemplateTitle: selectedGoal?.title ?? null,
|
|
506
|
+
selectedGoalTemplate: selectedGoal,
|
|
507
|
+
projectTemplateGoalDefinitions: goalDefinitions,
|
|
508
|
+
projectTemplateGoalSummary: {
|
|
509
|
+
goalCount: goalDefinitions.length,
|
|
510
|
+
enabledGoalCount,
|
|
511
|
+
disabledGoalCount: goalDefinitions.length - enabledGoalCount,
|
|
512
|
+
},
|
|
386
513
|
projectTemplateSummary: {
|
|
387
514
|
taskCount: template.taskTemplates.length,
|
|
388
515
|
dependencyCount,
|
|
389
516
|
agentAssignedTaskCount,
|
|
517
|
+
goalCount: goalDefinitions.length,
|
|
518
|
+
enabledGoalCount,
|
|
519
|
+
disabledGoalCount: goalDefinitions.length - enabledGoalCount,
|
|
390
520
|
defaultCostLimit: template.defaultCostLimit ?? null,
|
|
391
521
|
disabled: template.disabled === true,
|
|
392
522
|
},
|
|
@@ -415,6 +545,10 @@ export function ProjectTemplatesPanel() {
|
|
|
415
545
|
const [newTaskTitle, setNewTaskTitle] = useState("");
|
|
416
546
|
const [newTaskDependencySourceId, setNewTaskDependencySourceId] = useState(null);
|
|
417
547
|
const [creatingTask, setCreatingTask] = useState(false);
|
|
548
|
+
const [selectedGoalId, setSelectedGoalId] = useState(null);
|
|
549
|
+
const [isCreateGoalDialogOpen, setIsCreateGoalDialogOpen] = useState(false);
|
|
550
|
+
const [newGoalTitle, setNewGoalTitle] = useState("");
|
|
551
|
+
const [creatingGoal, setCreatingGoal] = useState(false);
|
|
418
552
|
const [isAddChildTaskDialogOpen, setIsAddChildTaskDialogOpen] = useState(false);
|
|
419
553
|
const [newChildTaskTitle, setNewChildTaskTitle] = useState("");
|
|
420
554
|
const [creatingChildTask, setCreatingChildTask] = useState(false);
|
|
@@ -430,6 +564,12 @@ export function ProjectTemplatesPanel() {
|
|
|
430
564
|
const [editingAgentProfile, setEditingAgentProfile] = useState(null);
|
|
431
565
|
const [isTaskEditorMaximized, setIsTaskEditorMaximized] = useState(false);
|
|
432
566
|
const [taskEditorOverlayBounds, setTaskEditorOverlayBounds] = useState(null);
|
|
567
|
+
const [settingsMainContentBounds, setSettingsMainContentBounds] = useState(null);
|
|
568
|
+
const [agentPanelBounds, setAgentPanelBounds] = useState(null);
|
|
569
|
+
const [isAgentPanelCollapsed, setIsAgentPanelCollapsed] = useState(() => {
|
|
570
|
+
const stored = localStorageService.getItem(PROJECT_TEMPLATE_SPLITTER_STORAGE_KEY);
|
|
571
|
+
return stored?.lastCollapsed ?? true;
|
|
572
|
+
});
|
|
433
573
|
const [forceCollapseAgentPanelKey, setForceCollapseAgentPanelKey] = useState(0);
|
|
434
574
|
const [forceExpandAgentPanelKey, setForceExpandAgentPanelKey] = useState(0);
|
|
435
575
|
const settingsMainContentRef = useRequiredSettingsMainContentRef();
|
|
@@ -442,6 +582,7 @@ export function ProjectTemplatesPanel() {
|
|
|
442
582
|
const draftTemplateRef = useRef(null);
|
|
443
583
|
const selectedTemplateIdRef = useRef(selectedTemplateId);
|
|
444
584
|
const selectedTaskIdRef = useRef(selectedTaskId);
|
|
585
|
+
const selectedGoalIdRef = useRef(selectedGoalId);
|
|
445
586
|
const selectedDependencyIdRef = useRef(selectedDependencyId);
|
|
446
587
|
const isDirtyRef = useRef(isDirty);
|
|
447
588
|
const savingRef = useRef(saving);
|
|
@@ -456,6 +597,7 @@ export function ProjectTemplatesPanel() {
|
|
|
456
597
|
};
|
|
457
598
|
const restoreAgentPanelAfterMaximize = () => {
|
|
458
599
|
if (agentPanelWasExpandedBeforeMaximizeRef.current === true) {
|
|
600
|
+
setIsAgentPanelCollapsed(false);
|
|
459
601
|
setForceExpandAgentPanelKey((value) => value + 1);
|
|
460
602
|
}
|
|
461
603
|
agentPanelWasExpandedBeforeMaximizeRef.current = null;
|
|
@@ -478,11 +620,114 @@ export function ProjectTemplatesPanel() {
|
|
|
478
620
|
const agentPanelCollapsed = wasAgentPanelCollapsed();
|
|
479
621
|
agentPanelWasExpandedBeforeMaximizeRef.current = !agentPanelCollapsed;
|
|
480
622
|
if (!agentPanelCollapsed) {
|
|
623
|
+
setIsAgentPanelCollapsed(true);
|
|
481
624
|
setForceCollapseAgentPanelKey((value) => value + 1);
|
|
482
625
|
}
|
|
483
626
|
setTaskEditorOverlayBounds(nextBounds);
|
|
484
627
|
setIsTaskEditorMaximized(true);
|
|
485
628
|
};
|
|
629
|
+
useEffect(() => {
|
|
630
|
+
const settingsMainContent = settingsMainContentRef.current;
|
|
631
|
+
const updateBounds = () => {
|
|
632
|
+
const nextBounds = measureOverlayBounds(settingsMainContentRef.current);
|
|
633
|
+
if (nextBounds) {
|
|
634
|
+
setSettingsMainContentBounds(nextBounds);
|
|
635
|
+
}
|
|
636
|
+
};
|
|
637
|
+
updateBounds();
|
|
638
|
+
if (typeof window === "undefined") {
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
let frameId = null;
|
|
642
|
+
const scheduleUpdate = () => {
|
|
643
|
+
if (frameId != null) {
|
|
644
|
+
window.cancelAnimationFrame(frameId);
|
|
645
|
+
}
|
|
646
|
+
frameId = window.requestAnimationFrame(() => {
|
|
647
|
+
frameId = null;
|
|
648
|
+
updateBounds();
|
|
649
|
+
});
|
|
650
|
+
};
|
|
651
|
+
const resizeObserver = typeof ResizeObserver !== "undefined" && settingsMainContent
|
|
652
|
+
? new ResizeObserver(scheduleUpdate)
|
|
653
|
+
: null;
|
|
654
|
+
if (resizeObserver && settingsMainContent) {
|
|
655
|
+
resizeObserver.observe(settingsMainContent);
|
|
656
|
+
}
|
|
657
|
+
window.addEventListener("resize", scheduleUpdate);
|
|
658
|
+
window.addEventListener("scroll", scheduleUpdate, true);
|
|
659
|
+
return () => {
|
|
660
|
+
if (frameId != null) {
|
|
661
|
+
window.cancelAnimationFrame(frameId);
|
|
662
|
+
}
|
|
663
|
+
resizeObserver?.disconnect();
|
|
664
|
+
window.removeEventListener("resize", scheduleUpdate);
|
|
665
|
+
window.removeEventListener("scroll", scheduleUpdate, true);
|
|
666
|
+
};
|
|
667
|
+
}, [settingsMainContentRef]);
|
|
668
|
+
useEffect(() => {
|
|
669
|
+
if (isMobile) {
|
|
670
|
+
setAgentPanelBounds(null);
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
const updateBounds = () => {
|
|
674
|
+
const element = document.querySelector('[data-testid="splitter-panel-project-template-agent"]');
|
|
675
|
+
const nextBounds = measureOverlayBounds(element);
|
|
676
|
+
setAgentPanelBounds((currentBounds) => {
|
|
677
|
+
if (!nextBounds) {
|
|
678
|
+
return currentBounds === null ? currentBounds : null;
|
|
679
|
+
}
|
|
680
|
+
if (currentBounds &&
|
|
681
|
+
Math.abs(currentBounds.top - nextBounds.top) < 0.5 &&
|
|
682
|
+
Math.abs(currentBounds.left - nextBounds.left) < 0.5 &&
|
|
683
|
+
Math.abs(currentBounds.width - nextBounds.width) < 0.5 &&
|
|
684
|
+
Math.abs(currentBounds.height - nextBounds.height) < 0.5) {
|
|
685
|
+
return currentBounds;
|
|
686
|
+
}
|
|
687
|
+
return nextBounds;
|
|
688
|
+
});
|
|
689
|
+
};
|
|
690
|
+
updateBounds();
|
|
691
|
+
if (typeof window === "undefined") {
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
let frameId = null;
|
|
695
|
+
const scheduleUpdate = () => {
|
|
696
|
+
if (frameId != null) {
|
|
697
|
+
window.cancelAnimationFrame(frameId);
|
|
698
|
+
}
|
|
699
|
+
frameId = window.requestAnimationFrame(() => {
|
|
700
|
+
frameId = null;
|
|
701
|
+
updateBounds();
|
|
702
|
+
});
|
|
703
|
+
};
|
|
704
|
+
const settingsMainContent = settingsMainContentRef.current;
|
|
705
|
+
const agentPanelElement = document.querySelector('[data-testid="splitter-panel-project-template-agent"]');
|
|
706
|
+
const resizeObserver = typeof ResizeObserver !== "undefined" && settingsMainContent
|
|
707
|
+
? new ResizeObserver(scheduleUpdate)
|
|
708
|
+
: null;
|
|
709
|
+
if (resizeObserver && settingsMainContent) {
|
|
710
|
+
resizeObserver.observe(settingsMainContent);
|
|
711
|
+
}
|
|
712
|
+
if (resizeObserver && agentPanelElement) {
|
|
713
|
+
resizeObserver.observe(agentPanelElement);
|
|
714
|
+
}
|
|
715
|
+
window.addEventListener("resize", scheduleUpdate);
|
|
716
|
+
window.addEventListener("scroll", scheduleUpdate, true);
|
|
717
|
+
return () => {
|
|
718
|
+
if (frameId != null) {
|
|
719
|
+
window.cancelAnimationFrame(frameId);
|
|
720
|
+
}
|
|
721
|
+
resizeObserver?.disconnect();
|
|
722
|
+
window.removeEventListener("resize", scheduleUpdate);
|
|
723
|
+
window.removeEventListener("scroll", scheduleUpdate, true);
|
|
724
|
+
};
|
|
725
|
+
}, [
|
|
726
|
+
isAgentPanelCollapsed,
|
|
727
|
+
isMobile,
|
|
728
|
+
selectedTemplateId,
|
|
729
|
+
settingsMainContentRef,
|
|
730
|
+
]);
|
|
486
731
|
useEffect(() => {
|
|
487
732
|
if (!isTaskEditorMaximized) {
|
|
488
733
|
setTaskEditorOverlayBounds(null);
|
|
@@ -623,8 +868,14 @@ export function ProjectTemplatesPanel() {
|
|
|
623
868
|
setMobileView("detail");
|
|
624
869
|
return;
|
|
625
870
|
}
|
|
871
|
+
setIsAgentPanelCollapsed(true);
|
|
626
872
|
setForceCollapseAgentPanelKey((value) => value + 1);
|
|
627
873
|
}, [isMobile]);
|
|
874
|
+
const handleShowTemplateAssistant = useCallback(() => {
|
|
875
|
+
setEditingAgentProfile(null);
|
|
876
|
+
setIsAgentPanelCollapsed(false);
|
|
877
|
+
setForceExpandAgentPanelKey((value) => value + 1);
|
|
878
|
+
}, []);
|
|
628
879
|
useEffect(() => {
|
|
629
880
|
if (!isMobile) {
|
|
630
881
|
setMobileView("detail");
|
|
@@ -643,7 +894,8 @@ export function ProjectTemplatesPanel() {
|
|
|
643
894
|
if (result.type !== "success") {
|
|
644
895
|
throw new Error(result.summary || "Failed to load project templates");
|
|
645
896
|
}
|
|
646
|
-
const
|
|
897
|
+
const activeDescriptionDraftField = getActiveDescriptionDraftField(selectedTaskIdRef.current, selectedGoalIdRef.current);
|
|
898
|
+
const loadedTemplates = (result.data ?? []).map((template) => preserveActiveDescriptionDraft(template, draftTemplateRef.current, activeDescriptionDraftField));
|
|
647
899
|
setTemplates(loadedTemplates);
|
|
648
900
|
setState("success");
|
|
649
901
|
const preferredTemplateExists = !!preferredTemplateId &&
|
|
@@ -713,6 +965,9 @@ export function ProjectTemplatesPanel() {
|
|
|
713
965
|
}, [aiProfiles]);
|
|
714
966
|
const selectedTask = useMemo(() => draftTemplate?.taskTemplates.find((task) => task.id === selectedTaskId) ??
|
|
715
967
|
null, [draftTemplate, selectedTaskId]);
|
|
968
|
+
const templateAgentInitialMetadata = useMemo(() => draftTemplate
|
|
969
|
+
? buildProjectTemplateAgentContext(draftTemplate, selectedTaskId, selectedGoalId)
|
|
970
|
+
: undefined, [draftTemplate, selectedGoalId, selectedTaskId]);
|
|
716
971
|
const dependencyTasks = useMemo(() => {
|
|
717
972
|
if (!draftTemplate || !selectedTask)
|
|
718
973
|
return [];
|
|
@@ -782,9 +1037,9 @@ export function ProjectTemplatesPanel() {
|
|
|
782
1037
|
setMobileView("detail");
|
|
783
1038
|
}
|
|
784
1039
|
}, [isMobile]);
|
|
785
|
-
const syncProjectTemplateAgentContext = useCallback(async (agentId, template, selectedTaskTemplateId) => {
|
|
1040
|
+
const syncProjectTemplateAgentContext = useCallback(async (agentId, template, selectedTaskTemplateId, selectedGoalTemplateId) => {
|
|
786
1041
|
try {
|
|
787
|
-
await updateAgentContext(agentId, buildProjectTemplateAgentContext(template, selectedTaskTemplateId));
|
|
1042
|
+
await updateAgentContext(agentId, buildProjectTemplateAgentContext(template, selectedTaskTemplateId, selectedGoalTemplateId));
|
|
788
1043
|
}
|
|
789
1044
|
catch (error) {
|
|
790
1045
|
setTemplateAgentError(error instanceof Error
|
|
@@ -837,8 +1092,9 @@ export function ProjectTemplatesPanel() {
|
|
|
837
1092
|
const currentTemplate = draftTemplateRef.current;
|
|
838
1093
|
if (!currentTemplate || currentTemplate.id !== selectedTemplateId)
|
|
839
1094
|
return;
|
|
840
|
-
void syncProjectTemplateAgentContext(templateAgentId, currentTemplate, selectedTaskId);
|
|
1095
|
+
void syncProjectTemplateAgentContext(templateAgentId, currentTemplate, selectedTaskId, selectedGoalId);
|
|
841
1096
|
}, [
|
|
1097
|
+
selectedGoalId,
|
|
842
1098
|
selectedTaskId,
|
|
843
1099
|
templateAgentId,
|
|
844
1100
|
templateAgentLoading,
|
|
@@ -869,6 +1125,14 @@ export function ProjectTemplatesPanel() {
|
|
|
869
1125
|
taskTemplates: currentTemplate.taskTemplates.map((task) => task.id === selectedTaskId ? updater({ ...task }) : task),
|
|
870
1126
|
}));
|
|
871
1127
|
}, [applyDraftChange, selectedTaskId]);
|
|
1128
|
+
const updateSelectedGoal = useCallback((updater) => {
|
|
1129
|
+
if (!selectedGoalId)
|
|
1130
|
+
return;
|
|
1131
|
+
applyDraftChange((currentTemplate) => ({
|
|
1132
|
+
...currentTemplate,
|
|
1133
|
+
goalTemplates: (currentTemplate.goalTemplates ?? []).map((goal) => goal.id === selectedGoalId ? updater({ ...goal }) : goal),
|
|
1134
|
+
}));
|
|
1135
|
+
}, [applyDraftChange, selectedGoalId]);
|
|
872
1136
|
const handleDuplicateAssignedAgentProfile = useCallback(async () => {
|
|
873
1137
|
if (!editContext || !selectedAgentProfileId)
|
|
874
1138
|
return;
|
|
@@ -1000,7 +1264,10 @@ export function ProjectTemplatesPanel() {
|
|
|
1000
1264
|
}
|
|
1001
1265
|
if (templateAgentId && savedTemplate.id === selectedTemplateId) {
|
|
1002
1266
|
const nextSelectedTaskId = getSelectedTaskIdForTemplate(savedTemplate, selectedTaskIdRef.current);
|
|
1003
|
-
|
|
1267
|
+
const nextSelectedGoalId = savedTemplate.goalTemplates?.some((goal) => goal.id === selectedGoalId) === true
|
|
1268
|
+
? selectedGoalId
|
|
1269
|
+
: null;
|
|
1270
|
+
void syncProjectTemplateAgentContext(templateAgentId, savedTemplate, nextSelectedTaskId, nextSelectedGoalId);
|
|
1004
1271
|
}
|
|
1005
1272
|
return true;
|
|
1006
1273
|
}
|
|
@@ -1009,7 +1276,12 @@ export function ProjectTemplatesPanel() {
|
|
|
1009
1276
|
setSaving(false);
|
|
1010
1277
|
}
|
|
1011
1278
|
}
|
|
1012
|
-
}, [
|
|
1279
|
+
}, [
|
|
1280
|
+
selectedGoalId,
|
|
1281
|
+
selectedTemplateId,
|
|
1282
|
+
syncProjectTemplateAgentContext,
|
|
1283
|
+
templateAgentId,
|
|
1284
|
+
]);
|
|
1013
1285
|
const applyDraftChangeAndPersist = useCallback((updater) => {
|
|
1014
1286
|
let nextTemplate = null;
|
|
1015
1287
|
let nextSignature = null;
|
|
@@ -1134,6 +1406,9 @@ export function ProjectTemplatesPanel() {
|
|
|
1134
1406
|
useEffect(() => {
|
|
1135
1407
|
selectedTaskIdRef.current = selectedTaskId;
|
|
1136
1408
|
}, [selectedTaskId]);
|
|
1409
|
+
useEffect(() => {
|
|
1410
|
+
selectedGoalIdRef.current = selectedGoalId;
|
|
1411
|
+
}, [selectedGoalId]);
|
|
1137
1412
|
useEffect(() => {
|
|
1138
1413
|
selectedDependencyIdRef.current = selectedDependencyId;
|
|
1139
1414
|
}, [selectedDependencyId]);
|
|
@@ -1244,6 +1519,7 @@ export function ProjectTemplatesPanel() {
|
|
|
1244
1519
|
setSelectedTemplateId(nextTemplate.id);
|
|
1245
1520
|
setDraftTemplate(cloneTemplate(nextTemplate));
|
|
1246
1521
|
setSelectedTaskId(null);
|
|
1522
|
+
setSelectedGoalId(null);
|
|
1247
1523
|
setIsDirty(true);
|
|
1248
1524
|
setSaveError(null);
|
|
1249
1525
|
lastPersistedSignatureRef.current = null;
|
|
@@ -1349,7 +1625,7 @@ export function ProjectTemplatesPanel() {
|
|
|
1349
1625
|
setTemplateAgentId(result.data.agentId);
|
|
1350
1626
|
const currentTemplate = draftTemplateRef.current;
|
|
1351
1627
|
if (currentTemplate?.id === selectedTemplateId) {
|
|
1352
|
-
await syncProjectTemplateAgentContext(result.data.agentId, currentTemplate, selectedTaskIdRef.current);
|
|
1628
|
+
await syncProjectTemplateAgentContext(result.data.agentId, currentTemplate, selectedTaskIdRef.current, selectedGoalId);
|
|
1353
1629
|
}
|
|
1354
1630
|
}
|
|
1355
1631
|
catch (error) {
|
|
@@ -1362,7 +1638,12 @@ export function ProjectTemplatesPanel() {
|
|
|
1362
1638
|
finally {
|
|
1363
1639
|
setTemplateAgentResetting(false);
|
|
1364
1640
|
}
|
|
1365
|
-
}, [
|
|
1641
|
+
}, [
|
|
1642
|
+
flushPendingSave,
|
|
1643
|
+
selectedGoalId,
|
|
1644
|
+
selectedTemplateId,
|
|
1645
|
+
syncProjectTemplateAgentContext,
|
|
1646
|
+
]);
|
|
1366
1647
|
const handleOpenCreateTaskDialog = useCallback(async () => {
|
|
1367
1648
|
if (!draftTemplate)
|
|
1368
1649
|
return;
|
|
@@ -1450,6 +1731,56 @@ export function ProjectTemplatesPanel() {
|
|
|
1450
1731
|
setCreatingTask(false);
|
|
1451
1732
|
}
|
|
1452
1733
|
}, [draftTemplate, newTaskDependencySourceId, newTaskTitle, persistTemplate]);
|
|
1734
|
+
const handleConfirmCreateGoal = useCallback(async () => {
|
|
1735
|
+
if (!draftTemplate)
|
|
1736
|
+
return;
|
|
1737
|
+
const trimmedTitle = newGoalTitle.trim();
|
|
1738
|
+
if (!trimmedTitle) {
|
|
1739
|
+
toast.error("Goal title is required");
|
|
1740
|
+
return;
|
|
1741
|
+
}
|
|
1742
|
+
if (!draftTemplate.name.trim()) {
|
|
1743
|
+
const message = "Project template name is required before it can be saved";
|
|
1744
|
+
setSaveError(message);
|
|
1745
|
+
toast.error(message);
|
|
1746
|
+
return;
|
|
1747
|
+
}
|
|
1748
|
+
if (autosaveTimeoutRef.current !== null) {
|
|
1749
|
+
window.clearTimeout(autosaveTimeoutRef.current);
|
|
1750
|
+
autosaveTimeoutRef.current = null;
|
|
1751
|
+
}
|
|
1752
|
+
const nextGoal = createEmptyGoalDefinition((draftTemplate.goalTemplates ?? []).length, trimmedTitle);
|
|
1753
|
+
const nextTemplate = cloneTemplate(draftTemplate);
|
|
1754
|
+
nextTemplate.goalTemplates = [
|
|
1755
|
+
...(nextTemplate.goalTemplates ?? []),
|
|
1756
|
+
nextGoal,
|
|
1757
|
+
];
|
|
1758
|
+
const request = buildUpsertTemplateRequest(nextTemplate);
|
|
1759
|
+
const signature = JSON.stringify(request);
|
|
1760
|
+
latestDraftSignatureRef.current = signature;
|
|
1761
|
+
setDraftTemplate(cloneTemplate(nextTemplate));
|
|
1762
|
+
setTemplates((existingTemplates) => sortTemplates([
|
|
1763
|
+
...existingTemplates.filter((template) => template.id !== nextTemplate.id),
|
|
1764
|
+
cloneTemplate(nextTemplate),
|
|
1765
|
+
]));
|
|
1766
|
+
setSelectedGoalId(nextGoal.id);
|
|
1767
|
+
setIsDirty(true);
|
|
1768
|
+
setSaveError(null);
|
|
1769
|
+
setCreatingGoal(true);
|
|
1770
|
+
try {
|
|
1771
|
+
const saved = await persistTemplate(request, signature, {
|
|
1772
|
+
showErrorToast: true,
|
|
1773
|
+
});
|
|
1774
|
+
if (saved) {
|
|
1775
|
+
setIsCreateGoalDialogOpen(false);
|
|
1776
|
+
setNewGoalTitle("");
|
|
1777
|
+
toast.success("Goal definition created");
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
finally {
|
|
1781
|
+
setCreatingGoal(false);
|
|
1782
|
+
}
|
|
1783
|
+
}, [draftTemplate, newGoalTitle, persistTemplate]);
|
|
1453
1784
|
const handleOpenAddChildTaskDialog = useCallback(async () => {
|
|
1454
1785
|
if (!draftTemplate || !selectedTaskId)
|
|
1455
1786
|
return;
|
|
@@ -1486,7 +1817,7 @@ export function ProjectTemplatesPanel() {
|
|
|
1486
1817
|
...existingTemplates.filter((template) => template.id !== nextTemplate.id),
|
|
1487
1818
|
cloneTemplate(nextTemplate),
|
|
1488
1819
|
]));
|
|
1489
|
-
// Keep the parent task selected so the new
|
|
1820
|
+
// Keep the parent task selected so the new subtask appears immediately.
|
|
1490
1821
|
setIsDirty(true);
|
|
1491
1822
|
setSaveError(null);
|
|
1492
1823
|
setCreatingChildTask(true);
|
|
@@ -1497,7 +1828,7 @@ export function ProjectTemplatesPanel() {
|
|
|
1497
1828
|
if (saved) {
|
|
1498
1829
|
setIsAddChildTaskDialogOpen(false);
|
|
1499
1830
|
setNewChildTaskTitle("");
|
|
1500
|
-
toast.success("
|
|
1831
|
+
toast.success("Subtask template created");
|
|
1501
1832
|
}
|
|
1502
1833
|
}
|
|
1503
1834
|
finally {
|
|
@@ -1532,6 +1863,12 @@ export function ProjectTemplatesPanel() {
|
|
|
1532
1863
|
setSelectedDependencyId(null);
|
|
1533
1864
|
setSelectedTaskId(taskId);
|
|
1534
1865
|
}, []);
|
|
1866
|
+
const handleCloseTaskDetailsPane = useCallback(() => {
|
|
1867
|
+
selectedTaskIdRef.current = null;
|
|
1868
|
+
selectedDependencyIdRef.current = null;
|
|
1869
|
+
setSelectedTaskId(null);
|
|
1870
|
+
setSelectedDependencyId(null);
|
|
1871
|
+
}, []);
|
|
1535
1872
|
const handleSelectDependencyFromGraph = useCallback((taskId, dependencyId) => {
|
|
1536
1873
|
selectedDependencyIdRef.current = dependencyId;
|
|
1537
1874
|
setSelectedTaskId(taskId);
|
|
@@ -1662,6 +1999,43 @@ export function ProjectTemplatesPanel() {
|
|
|
1662
1999
|
}
|
|
1663
2000
|
runDelete();
|
|
1664
2001
|
}, [applyDraftChange, editContext]);
|
|
2002
|
+
const removeGoalDefinitionById = useCallback((goalId) => {
|
|
2003
|
+
const template = draftTemplateRef.current;
|
|
2004
|
+
const goals = template?.goalTemplates ?? [];
|
|
2005
|
+
if (!goals.some((goal) => goal.id === goalId))
|
|
2006
|
+
return;
|
|
2007
|
+
const goalTitle = goals.find((goal) => goal.id === goalId)?.title ?? "Untitled goal";
|
|
2008
|
+
const runDelete = () => {
|
|
2009
|
+
const current = draftTemplateRef.current;
|
|
2010
|
+
const currentGoals = current?.goalTemplates ?? [];
|
|
2011
|
+
if (!currentGoals.some((goal) => goal.id === goalId))
|
|
2012
|
+
return;
|
|
2013
|
+
const remainingGoals = currentGoals.filter((goal) => goal.id !== goalId);
|
|
2014
|
+
applyDraftChange((currentTemplate) => ({
|
|
2015
|
+
...currentTemplate,
|
|
2016
|
+
goalTemplates: (currentTemplate.goalTemplates ?? []).filter((goal) => goal.id !== goalId),
|
|
2017
|
+
}));
|
|
2018
|
+
setSelectedGoalId((prev) => {
|
|
2019
|
+
if (prev === goalId) {
|
|
2020
|
+
return remainingGoals[0]?.id ?? null;
|
|
2021
|
+
}
|
|
2022
|
+
return remainingGoals.some((goal) => goal.id === prev)
|
|
2023
|
+
? prev
|
|
2024
|
+
: (remainingGoals[0]?.id ?? null);
|
|
2025
|
+
});
|
|
2026
|
+
};
|
|
2027
|
+
if (editContext?.confirm) {
|
|
2028
|
+
editContext.confirm({
|
|
2029
|
+
header: "Remove goal definition",
|
|
2030
|
+
message: `Are you sure you want to remove "${goalTitle}"?`,
|
|
2031
|
+
acceptLabel: "Remove",
|
|
2032
|
+
showCancel: true,
|
|
2033
|
+
accept: runDelete,
|
|
2034
|
+
});
|
|
2035
|
+
return;
|
|
2036
|
+
}
|
|
2037
|
+
runDelete();
|
|
2038
|
+
}, [applyDraftChange, editContext]);
|
|
1665
2039
|
const handleDeleteSelectedTask = useCallback(() => {
|
|
1666
2040
|
if (!selectedTaskId)
|
|
1667
2041
|
return;
|
|
@@ -1713,30 +2087,41 @@ export function ProjectTemplatesPanel() {
|
|
|
1713
2087
|
const breadcrumbTaskCount = draftTemplate?.taskTemplates.length ?? 0;
|
|
1714
2088
|
const breadcrumbItems = useMemo(() => breadcrumbDraftName
|
|
1715
2089
|
? [
|
|
1716
|
-
{
|
|
1717
|
-
title: "Workflow Project Templates",
|
|
1718
|
-
subtitle: "Create project templates",
|
|
1719
|
-
onClick: () => {
|
|
1720
|
-
void handleNavigateToOverview();
|
|
1721
|
-
},
|
|
1722
|
-
},
|
|
1723
2090
|
{
|
|
1724
2091
|
title: breadcrumbDraftName,
|
|
1725
2092
|
subtitle: `${breadcrumbTaskCount} task templates`,
|
|
2093
|
+
backLink: {
|
|
2094
|
+
label: "Back to project templates overview",
|
|
2095
|
+
onClick: () => {
|
|
2096
|
+
void handleNavigateToOverview();
|
|
2097
|
+
},
|
|
2098
|
+
},
|
|
1726
2099
|
},
|
|
1727
2100
|
]
|
|
1728
2101
|
: null, [breadcrumbDraftName, breadcrumbTaskCount, handleNavigateToOverview]);
|
|
1729
2102
|
const desktopHeaderActions = useMemo(() => {
|
|
1730
2103
|
if (isMobile)
|
|
1731
2104
|
return null;
|
|
2105
|
+
const showCreate = !draftTemplate;
|
|
1732
2106
|
const showDelete = draftTemplate && !draftTemplate.isSystem;
|
|
1733
|
-
|
|
2107
|
+
const agentPanelHeaderOffset = draftTemplate &&
|
|
2108
|
+
!isTaskEditorMaximized &&
|
|
2109
|
+
!isAgentPanelCollapsed &&
|
|
2110
|
+
agentPanelBounds
|
|
2111
|
+
? Math.round(agentPanelBounds.width + 8)
|
|
2112
|
+
: 0;
|
|
2113
|
+
return (_jsxs("div", { className: "mt-2 flex items-center gap-2", style: agentPanelHeaderOffset > 0
|
|
2114
|
+
? { marginRight: agentPanelHeaderOffset }
|
|
2115
|
+
: undefined, children: [headerStatusBadge, showCreate ? (_jsxs(Button, { size: "sm", onClick: () => void handleCreateTemplate(), "data-testid": "project-template-create-button", children: [_jsx(Plus, { className: "h-4 w-4", strokeWidth: 1.5 }), "Create template"] })) : null, showDelete ? (_jsxs(Button, { variant: "outline", size: "sm", onClick: () => handleDeleteTemplate(), disabled: deleting, "data-testid": "project-template-delete-button", children: [_jsx(DeleteIcon, { size: "lg" }), deleting ? "Deleting..." : "Delete"] })) : null] }));
|
|
1734
2116
|
}, [
|
|
2117
|
+
agentPanelBounds,
|
|
1735
2118
|
deleting,
|
|
1736
2119
|
draftTemplate,
|
|
1737
2120
|
handleCreateTemplate,
|
|
1738
2121
|
handleDeleteTemplate,
|
|
1739
2122
|
headerStatusBadge,
|
|
2123
|
+
isAgentPanelCollapsed,
|
|
2124
|
+
isTaskEditorMaximized,
|
|
1740
2125
|
isMobile,
|
|
1741
2126
|
]);
|
|
1742
2127
|
useEffect(() => {
|
|
@@ -1774,7 +2159,7 @@ export function ProjectTemplatesPanel() {
|
|
|
1774
2159
|
}));
|
|
1775
2160
|
return nextLayout;
|
|
1776
2161
|
} }) }) }));
|
|
1777
|
-
const taskPane = (_jsx("div", { className: "flex h-full min-h-0 flex-col overflow-hidden", "data-testid": "project-template-task-detail-pane", children: !selectedTask ? (_jsx("div", { className: "min-h-0 flex-1 overflow-y-auto p-4", children: _jsx("div", { className: "border-border-default bg-neutral-grey-5 text-neutral-grey-50 rounded-lg border border-dashed p-6 text-center text-xs", children: "Select a task node to edit its details." }) })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "border-border-default shrink-0 border-b bg-white px-4 pt-4 pb-3", children: _jsxs("div", { className: "flex items-
|
|
2162
|
+
const taskPane = (_jsx("div", { className: "flex h-full min-h-0 flex-col overflow-hidden", "data-testid": "project-template-task-detail-pane", children: !selectedTask ? (_jsx("div", { className: "min-h-0 flex-1 overflow-y-auto p-4", children: _jsx("div", { className: "border-border-default bg-neutral-grey-5 text-neutral-grey-50 rounded-lg border border-dashed p-6 text-center text-xs", children: "Select a task node to edit its details." }) })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "border-border-default shrink-0 border-b bg-white px-4 pt-4 pb-3", children: _jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "text-neutral-grey-100 text-xs font-medium", "data-testid": "project-template-selected-task-title", children: selectedTask.title || "Untitled Task" }), selectedTask.taskType === "DecisionPoint" ? (_jsx(Badge, { variant: "outline", className: "border-highlight-100 bg-highlight-10 text-2xs text-highlight-100", children: "Decision Point" })) : null, selectedTask.disabled ? (_jsx(Badge, { variant: "outline", className: "text-2xs", children: "Disabled" })) : null] }), _jsx("div", { className: "text-neutral-grey-50 text-xs", children: "Configure task details, assignment, and dependencies." })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: handleDeleteSelectedTask, "data-testid": "project-template-remove-task-button", children: [_jsx(DeleteIcon, { size: "lg" }), "Remove Task"] }), _jsx(CloseButton, { onClick: handleCloseTaskDetailsPane, label: "Close task details", "data-testid": "project-template-close-task-details-button" })] })] }) }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto px-4 pt-3 pb-4", children: _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [_jsxs("div", { className: "grid gap-1.5 md:col-span-2", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-task-title-input", children: "Task title" }), _jsx(Input, { id: "project-template-task-title-input", value: selectedTask.title, onChange: (event) => updateSelectedTask((currentTask) => ({
|
|
1778
2163
|
...currentTask,
|
|
1779
2164
|
title: event.target.value,
|
|
1780
2165
|
})), placeholder: "Task title", className: "text-xs md:text-xs", "data-testid": "project-template-task-title-input" })] }), _jsxs("div", { className: "grid gap-1.5 md:col-span-2", children: [_jsx(Label, { className: "text-xs", children: "Description" }), _jsx(Textarea, { className: "text-xs", value: selectedTask.description ?? "", onChange: (event) => updateSelectedTask((currentTask) => ({
|
|
@@ -1803,7 +2188,7 @@ export function ProjectTemplatesPanel() {
|
|
|
1803
2188
|
agentProfileId: next?.assigneeType === "Agent"
|
|
1804
2189
|
? next.assigneeId
|
|
1805
2190
|
: null,
|
|
1806
|
-
})), placeholder: "Assign user or agent", buttonClassName: "h-
|
|
2191
|
+
})), placeholder: "Assign user or agent", buttonClassName: "h-8 min-h-0 w-full justify-between rounded-md bg-white text-xs", buttonTestId: "project-template-task-assignee-picker" }) }), selectedTask.assigneeType === "Agent" ? (_jsxs(Button, { type: "button", size: "sm", variant: "outline", className: "h-8 shrink-0 gap-1 px-2 text-xs", onClick: () => void handleEditAssignedAgentProfile(), disabled: !selectedAgentProfileId, "data-testid": "project-template-task-edit-agent-profile-button", children: [_jsx(Settings2, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }), "Edit Profile"] })) : null] }), profilesError ? (_jsx("div", { className: "text-feedback-orange text-xs", children: profilesError })) : null] })] }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "border-border-default bg-neutral-grey-5 rounded-lg border p-3", "data-testid": "project-template-dependencies-section", children: [_jsxs("div", { className: "mb-2 flex items-center justify-between gap-2", children: [_jsxs("div", { className: "text-neutral-grey-100 flex items-center gap-2 text-xs font-medium", children: [_jsx(Shield, { className: "text-neutral-grey-50 h-4 w-4", strokeWidth: 1.5 }), "Dependencies"] }), _jsxs(Popover, { open: dependencyPickerOpen, onOpenChange: setDependencyPickerOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(Button, { type: "button", size: "sm", variant: "outline", className: "h-7 gap-1 px-2", disabled: dependencyAddCandidates.length === 0, "aria-label": "Add dependency", "data-testid": "project-template-add-dependency-button", children: _jsx(Plus, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }) }) }), _jsxs(PopoverContent, { align: "end", className: "w-72 p-0", sideOffset: 6, "data-testid": "project-template-dependency-popover", children: [_jsx("div", { className: "border-border-default text-neutral-grey-100 border-b px-3 py-2 text-xs font-medium", children: "Depends on" }), _jsx("div", { className: "max-h-56 overflow-y-auto p-1", children: dependencyAddCandidates.length === 0 ? (_jsx("div", { className: "text-neutral-grey-50 px-2 py-3 text-center text-xs", children: "All other tasks are already linked." })) : (dependencyAddCandidates.map((task) => (_jsxs("button", { type: "button", className: "hover:bg-neutral-grey-5 flex w-full items-center gap-2 rounded-md px-2 py-2 text-left text-xs", onClick: () => handleAddDependency(task.id), "data-testid": `project-template-dependency-option-${task.id}`, children: [_jsx(Link2, { className: "text-neutral-grey-50 h-3.5 w-3.5 shrink-0", strokeWidth: 1.5 }), _jsx("span", { className: "text-neutral-grey-100 min-w-0 truncate font-medium", children: task.title || "Untitled Task" })] }, task.id)))) })] })] })] }), _jsx("p", { className: "text-neutral-grey-50 mb-2 text-[11px] leading-snug", children: "This task must wait for these tasks to finish first." }), dependencyTasks.length === 0 ? (_jsx("div", { className: "text-neutral-grey-50 text-xs", children: draftTemplate.taskTemplates.filter((t) => t.id !== selectedTask.id).length === 0
|
|
1807
2192
|
? "Add more task templates to create dependencies."
|
|
1808
2193
|
: "No dependencies yet. Use + to add one." })) : (_jsx("ul", { className: "space-y-1.5", children: dependencyTasks.map((task) => (_jsxs("li", { tabIndex: 0, className: cn("flex items-center justify-between gap-2 rounded-md border bg-white px-3 py-2 text-xs transition-colors outline-none", selectedDependencyId === task.id
|
|
1809
2194
|
? "border-feedback-orange bg-feedback-orange-light ring-feedback-orange ring-1"
|
|
@@ -1819,23 +2204,28 @@ export function ProjectTemplatesPanel() {
|
|
|
1819
2204
|
event.preventDefault();
|
|
1820
2205
|
event.stopPropagation();
|
|
1821
2206
|
handleRemoveDependency(task.id);
|
|
1822
|
-
}, "data-testid": `project-template-dependency-row-${task.id}`, children: [_jsx("span", { className: "text-neutral-grey-100 min-w-0 truncate font-medium", children: task.title || "Untitled Task" }), _jsx("button", { type: "button", className: "text-neutral-grey-50 hover:bg-neutral-grey-5 hover:text-neutral-grey-100 shrink-0 rounded p-0.5", "aria-label": `Remove dependency on ${task.title}`, onClick: () => handleRemoveDependency(task.id), "data-testid": `project-template-remove-dependency-${task.id}`, children: _jsx(X, { className: "h-4 w-4", strokeWidth: 1.5 }) })] }, task.id))) }))] }), _jsxs("div", { className: "border-border-default bg-neutral-grey-5 rounded-lg border p-3", "data-testid": "project-template-child-tasks-section", children: [_jsxs("div", { className: "mb-2 flex items-center justify-between gap-2", children: [_jsxs("div", { className: "text-neutral-grey-100 flex items-center gap-2 text-xs font-medium", children: [_jsx(CornerDownRight, { className: "text-neutral-grey-50 h-4 w-4", strokeWidth: 1.5 }), "
|
|
2207
|
+
}, "data-testid": `project-template-dependency-row-${task.id}`, children: [_jsx("span", { className: "text-neutral-grey-100 min-w-0 truncate font-medium", children: task.title || "Untitled Task" }), _jsx("button", { type: "button", className: "text-neutral-grey-50 hover:bg-neutral-grey-5 hover:text-neutral-grey-100 shrink-0 rounded p-0.5", "aria-label": `Remove dependency on ${task.title}`, onClick: () => handleRemoveDependency(task.id), "data-testid": `project-template-remove-dependency-${task.id}`, children: _jsx(X, { className: "h-4 w-4", strokeWidth: 1.5 }) })] }, task.id))) }))] }), _jsxs("div", { className: "border-border-default bg-neutral-grey-5 rounded-lg border p-3", "data-testid": "project-template-child-tasks-section", children: [_jsxs("div", { className: "mb-2 flex items-center justify-between gap-2", children: [_jsxs("div", { className: "text-neutral-grey-100 flex items-center gap-2 text-xs font-medium", children: [_jsx(CornerDownRight, { className: "text-neutral-grey-50 h-4 w-4", strokeWidth: 1.5 }), "Subtasks"] }), _jsx(Button, { type: "button", size: "sm", variant: "outline", className: "h-7 gap-1 px-2", onClick: () => void handleOpenAddChildTaskDialog(), disabled: creatingChildTask, "aria-label": "Add subtask", "data-testid": "project-template-add-child-task-button", children: _jsx(Plus, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }) })] }), _jsx("p", { className: "text-neutral-grey-50 mb-2 text-[11px] leading-snug", children: "Subtasks must be completed before this task is done." }), childTaskTemplates.length === 0 ? (_jsx("div", { className: "text-neutral-grey-50 text-xs", children: "No subtasks yet. Use + to add one." })) : (_jsx("ul", { className: "space-y-1.5", children: childTaskTemplates.map((task) => (_jsxs("li", { className: "border-border-default flex items-center justify-between gap-2 rounded-md border bg-white px-3 py-2 text-xs", "data-testid": `project-template-child-task-row-${task.id}`, children: [_jsx("span", { className: "text-neutral-grey-100 min-w-0 truncate font-medium", children: task.title || "Untitled Task" }), _jsx("button", { type: "button", className: "text-neutral-grey-50 hover:bg-neutral-grey-5 hover:text-neutral-grey-100 shrink-0 rounded p-0.5", "aria-label": `Unlink subtask ${task.title}`, onClick: () => handleUnlinkChildTask(task.id), "data-testid": `project-template-unlink-child-task-${task.id}`, children: _jsx(X, { className: "h-4 w-4", strokeWidth: 1.5 }) })] }, task.id))) }))] })] })] }) })] })) }));
|
|
1823
2208
|
if (isMobile) {
|
|
1824
2209
|
return (_jsxs("div", { className: "border-border-default flex shrink-0 flex-col border-b", children: [_jsx("div", { className: "border-border-default h-[300px] shrink-0 overflow-hidden border-b", children: graphView }), taskPane] }));
|
|
1825
2210
|
}
|
|
1826
|
-
return (_jsx("div", { className: "border-border-default min-h-[360px] flex-1 overflow-hidden border-b", children: _jsx(Splitter, { direction: "
|
|
2211
|
+
return (_jsx("div", { className: "border-border-default min-h-[360px] flex-1 overflow-hidden border-b", children: _jsx(Splitter, { direction: "horizontal", localStorageKey: "settings-project-template-graph-task-splitter-v2", className: "h-full", panels: [
|
|
1827
2212
|
{
|
|
1828
2213
|
name: "project-template-graph",
|
|
1829
|
-
defaultSize: 400,
|
|
1830
|
-
className: "min-h-0",
|
|
1831
|
-
content: graphView,
|
|
1832
|
-
},
|
|
1833
|
-
{
|
|
1834
|
-
name: "project-template-task-details",
|
|
1835
2214
|
defaultSize: "auto",
|
|
1836
2215
|
className: "min-h-0",
|
|
1837
|
-
content:
|
|
2216
|
+
content: graphView,
|
|
1838
2217
|
},
|
|
2218
|
+
...(selectedTask
|
|
2219
|
+
? [
|
|
2220
|
+
{
|
|
2221
|
+
name: "project-template-task-details",
|
|
2222
|
+
defaultSize: 560,
|
|
2223
|
+
minSize: 360,
|
|
2224
|
+
className: "min-h-0",
|
|
2225
|
+
content: taskPane,
|
|
2226
|
+
},
|
|
2227
|
+
]
|
|
2228
|
+
: []),
|
|
1839
2229
|
] }) }));
|
|
1840
2230
|
};
|
|
1841
2231
|
const detailContent = (_jsxs("div", { className: "bg-neutral-grey-5/40 flex h-full flex-col", "data-testid": "project-template-detail-pane", children: [isMobile && draftTemplate && !draftTemplate.isSystem ? (_jsxs("div", { className: "border-border-default flex min-w-0 items-center gap-3 border-b bg-white px-5 py-2", "data-testid": "project-template-detail-pane-header", children: [_jsx("div", { className: "min-w-0 flex-1", children: templateSelector }), _jsx("div", { className: "flex shrink-0 items-center gap-1.5 self-center", children: _jsx(Button, { variant: "outline", size: "icon", className: "h-9 w-9 shrink-0", onClick: () => handleDeleteTemplate(), disabled: deleting, "aria-label": deleting ? "Deleting template" : "Delete template", title: deleting ? "Deleting…" : "Delete template", "data-testid": "project-template-delete-button", children: deleting ? (_jsx(RefreshCw, { className: "h-4 w-4 animate-spin", strokeWidth: 1.5 })) : (_jsx(DeleteIcon, { size: "lg" })) }) })] })) : null, draftTemplate ? ((() => {
|
|
@@ -1852,6 +2242,12 @@ export function ProjectTemplatesPanel() {
|
|
|
1852
2242
|
content: null,
|
|
1853
2243
|
testId: "project-template-tab-task-editor",
|
|
1854
2244
|
},
|
|
2245
|
+
{
|
|
2246
|
+
id: "project-template-tab-goals",
|
|
2247
|
+
label: "Goals",
|
|
2248
|
+
content: null,
|
|
2249
|
+
testId: "project-template-tab-goals",
|
|
2250
|
+
},
|
|
1855
2251
|
];
|
|
1856
2252
|
const basicSettingsContent = (_jsxs("div", { className: "grid gap-4 overflow-y-auto p-4 md:grid-cols-2", "data-testid": "project-template-basic-settings-panel", children: [_jsxs("div", { className: "grid gap-1.5 md:col-span-2", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-name-input", children: "Template name" }), _jsx(Input, { id: "project-template-name-input", value: draftTemplate.name, onChange: (event) => applyDraftChange((currentTemplate) => ({
|
|
1857
2253
|
...currentTemplate,
|
|
@@ -1870,20 +2266,81 @@ export function ProjectTemplatesPanel() {
|
|
|
1870
2266
|
})), className: "data-[state=checked]:bg-feedback-orange data-[state=checked]:shadow-inner", "aria-label": "Disable this project template", "data-testid": "project-template-disabled-switch" })] }), _jsxs("div", { className: "flex items-center justify-between gap-4 md:col-span-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-neutral-grey-100 text-xs font-medium", children: "Hide from create dialog" }), _jsx("div", { className: "text-neutral-grey-50 mt-0.5 text-xs", children: "Keeps the template active, but removes it from the create project dialog." })] }), _jsx(Switch, { checked: draftTemplate.hideFromCreateDialog === true, onCheckedChange: (checked) => applyDraftChange((currentTemplate) => ({
|
|
1871
2267
|
...currentTemplate,
|
|
1872
2268
|
hideFromCreateDialog: checked,
|
|
1873
|
-
})), "aria-label": "Hide this project template from the create dialog", "data-testid": "project-template-hide-from-create-dialog-switch" })] })
|
|
1874
|
-
...currentTemplate,
|
|
1875
|
-
openInWizardMode: checked,
|
|
1876
|
-
})), "aria-label": "Open new projects from this template in wizard mode", "data-testid": "project-template-open-in-wizard-mode-switch" })] })] }));
|
|
2269
|
+
})), "aria-label": "Hide this project template from the create dialog", "data-testid": "project-template-hide-from-create-dialog-switch" })] })] }));
|
|
1877
2270
|
const taskEditorContent = (_jsx("div", { className: "flex h-full min-h-0 flex-1 flex-col overflow-hidden", children: renderTemplateTaskEditorMain() }));
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
2271
|
+
const goalDefinitions = draftTemplate.goalTemplates ?? [];
|
|
2272
|
+
const selectedGoal = goalDefinitions.find((goal) => goal.id === selectedGoalId) ?? null;
|
|
2273
|
+
const goalsContent = (_jsx("div", { className: "flex h-full min-h-0 flex-1 flex-col gap-3 overflow-y-auto p-4", "data-testid": "project-template-goals-section", children: goalDefinitions.length === 0 ? (_jsx("div", { className: "border-border-default text-neutral-grey-50 rounded-md border border-dashed p-6 text-center text-xs", children: "No goal definitions yet. Use \u201CAdd Goal\u201D to create one \u2014 projects created from this template can pick from these goals." })) : (_jsxs("div", { className: "grid gap-3 md:grid-cols-[220px_1fr]", children: [_jsx("div", { className: "flex flex-col gap-1", children: [...goalDefinitions]
|
|
2274
|
+
.sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0))
|
|
2275
|
+
.map((goal) => (_jsxs("div", { "data-testid": `project-template-goal-row-${goal.id}`, className: cn("flex items-center justify-between gap-2 rounded-md px-3 py-2 text-xs", goal.id === selectedGoalId
|
|
2276
|
+
? "bg-neutral-grey-5"
|
|
2277
|
+
: "hover:bg-neutral-grey-5 bg-transparent"), children: [_jsxs("button", { type: "button", className: "min-w-0 flex-1 truncate text-left", onClick: () => setSelectedGoalId(goal.id), children: [goal.title || "Untitled goal", goal.disabled ? " (disabled)" : ""] }), _jsx("button", { type: "button", "aria-label": `Remove ${goal.title || "goal"}`, "data-testid": `project-template-remove-goal-${goal.id}`, className: "text-neutral-grey-50 hover:text-feedback-red shrink-0", onClick: () => removeGoalDefinitionById(goal.id), children: _jsx(Trash2, { className: "h-3.5 w-3.5", strokeWidth: 1.5 }) })] }, goal.id))) }), selectedGoal ? (_jsxs("div", { className: "border-border-default flex flex-col gap-3 rounded-md border bg-white p-4", children: [_jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-goal-title-input", children: "Title" }), _jsx(Input, { id: "project-template-goal-title-input", "data-testid": "project-template-goal-title-input", className: "text-xs md:text-xs", value: selectedGoal.title, onChange: (event) => updateSelectedGoal((goal) => ({
|
|
2278
|
+
...goal,
|
|
2279
|
+
title: event.target.value,
|
|
2280
|
+
})), placeholder: "Goal title" })] }), _jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-goal-description-input", children: "Description" }), _jsx(Textarea, { id: "project-template-goal-description-input", "data-testid": "project-template-goal-description-input", className: "text-xs", rows: 3, value: selectedGoal.description ?? "", onChange: (event) => updateSelectedGoal((goal) => ({
|
|
2281
|
+
...goal,
|
|
2282
|
+
description: event.target.value,
|
|
2283
|
+
})), placeholder: "What this goal covers" })] }), _jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-goal-sort-order-input", children: "Sort order" }), _jsx(Input, { id: "project-template-goal-sort-order-input", type: "number", className: "text-xs md:text-xs", value: selectedGoal.sortOrder ?? 0, onChange: (event) => updateSelectedGoal((goal) => ({
|
|
2284
|
+
...goal,
|
|
2285
|
+
sortOrder: event.target.value.trim() === ""
|
|
2286
|
+
? 0
|
|
2287
|
+
: Number(event.target.value),
|
|
2288
|
+
})) })] }), _jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-goal-default-scope-input", children: "Default scope (JSON, optional)" }), _jsx(Textarea, { id: "project-template-goal-default-scope-input", className: "font-mono text-xs", rows: 2, value: selectedGoal.defaultScopeJson ?? "", onChange: (event) => updateSelectedGoal((goal) => ({
|
|
2289
|
+
...goal,
|
|
2290
|
+
defaultScopeJson: event.target.value,
|
|
2291
|
+
})), placeholder: '{"rootItemId":"...","pagesOnly":true}' })] }), _jsxs("div", { className: "grid gap-1.5", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-goal-data-shape-input", children: "Data shape hint (optional)" }), _jsx(Input, { id: "project-template-goal-data-shape-input", className: "text-xs md:text-xs", value: selectedGoal.dataShape ?? "", onChange: (event) => updateSelectedGoal((goal) => ({
|
|
2292
|
+
...goal,
|
|
2293
|
+
dataShape: event.target.value,
|
|
2294
|
+
})), placeholder: "e.g. { recommendations: string[] }" })] }), _jsxs("div", { className: "flex items-center justify-between gap-4", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-neutral-grey-100 text-xs font-medium", children: "Disabled" }), _jsx("div", { className: "text-neutral-grey-50 mt-0.5 text-xs", children: "Keeps the definition but hides it from the runtime goal catalog." })] }), _jsx(Switch, { checked: selectedGoal.disabled === true, onCheckedChange: (checked) => updateSelectedGoal((goal) => ({
|
|
2295
|
+
...goal,
|
|
2296
|
+
disabled: checked,
|
|
2297
|
+
})), "aria-label": "Disable this goal definition", "data-testid": "project-template-goal-disabled-switch" })] })] })) : (_jsx("div", { className: "border-border-default text-neutral-grey-50 flex items-center justify-center rounded-md border border-dashed p-6 text-center text-xs", children: "Select a goal to edit its details." }))] })) }));
|
|
2298
|
+
const detailAction = activeDetailTab === "tasks" ? (_jsxs(Button, { size: "sm", variant: "outline", onClick: () => void handleOpenCreateTaskDialog(), disabled: creatingTask, "data-testid": "project-template-add-task-button", children: [_jsx(Plus, { className: "h-4 w-4", strokeWidth: 1.5 }), "Add Task"] })) : activeDetailTab === "goals" ? (_jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
|
|
2299
|
+
setNewGoalTitle("");
|
|
2300
|
+
setIsCreateGoalDialogOpen(true);
|
|
2301
|
+
}, disabled: creatingGoal, "data-testid": "project-template-add-goal-button", children: [_jsx(Plus, { className: "h-4 w-4", strokeWidth: 1.5 }), "Add Goal"] })) : null;
|
|
2302
|
+
return (_jsxs("div", { className: cn("flex min-h-0 flex-1 flex-col overflow-y-auto overscroll-y-contain md:overflow-hidden", isTaskEditorMaximized && "overflow-hidden"), children: [saveError ? (_jsx("div", { className: "flex shrink-0 flex-col pb-3 md:max-h-[50vh] md:min-h-0 md:overflow-y-auto md:overscroll-y-contain", children: _jsx("div", { className: "border-feedback-red bg-feedback-red-light text-feedback-red rounded border px-4 py-3 text-xs", children: saveError }) })) : null, _jsxs("section", { className: cn("border-border-default flex min-h-0 flex-1 flex-col rounded-lg border bg-white md:overflow-hidden", isTaskEditorMaximized &&
|
|
2303
|
+
"overflow-hidden rounded-none shadow-xl"), "data-testid": "project-template-task-editor-shell", children: [_jsxs("div", { className: "border-border-default flex h-[53px] shrink-0 items-center justify-between gap-3 border-b px-4 pt-3", children: [_jsx("div", { className: "min-w-0 flex-1", children: _jsx(SimpleTabs, { tabs: detailTabs, activeTab: activeDetailTab === "basic"
|
|
2304
|
+
? 0
|
|
2305
|
+
: activeDetailTab === "tasks"
|
|
2306
|
+
? 1
|
|
2307
|
+
: 2, setActiveTab: (index) => setActiveDetailTab(index === 0
|
|
2308
|
+
? "basic"
|
|
2309
|
+
: index === 1
|
|
2310
|
+
? "tasks"
|
|
2311
|
+
: "goals"), hideContent: true, className: "w-full translate-y-0.5 justify-start gap-6" }) }), detailAction ? (_jsx("div", { className: "mb-2 flex shrink-0 items-center", children: detailAction })) : null] }), _jsx("div", { className: "flex min-h-0 flex-1 flex-col overflow-hidden", children: activeDetailTab === "basic"
|
|
1882
2312
|
? basicSettingsContent
|
|
1883
|
-
:
|
|
2313
|
+
: activeDetailTab === "tasks"
|
|
2314
|
+
? taskEditorContent
|
|
2315
|
+
: goalsContent })] })] }));
|
|
1884
2316
|
})()) : (_jsx("div", { className: "flex min-h-0 flex-1 items-center justify-center p-5", children: _jsxs("div", { className: "border-border-default max-w-sm rounded-lg border border-dashed bg-white p-8 text-center", children: [_jsx(GitBranch, { className: "text-neutral-grey-50 mx-auto mb-3 h-10 w-10", strokeWidth: 1.2 }), _jsx("h3", { className: "text-neutral-grey-100 text-xs font-medium", children: "Select a project template" }), _jsx("p", { className: "text-neutral-grey-50 mt-1 text-xs", children: "Choose a template from the dropdown or create a new one to start editing." })] }) }))] }));
|
|
1885
|
-
const overviewContent = (_jsx("div", { className: "flex h-full min-h-0 flex-col px-10 pt-0 pb-10", "data-testid": "project-template-overview", children: _jsx(
|
|
1886
|
-
const
|
|
2317
|
+
const overviewContent = (_jsx("div", { className: "flex h-full min-h-0 flex-col px-10 pt-0 pb-10", "data-testid": "project-template-overview", children: _jsx("div", { className: "flex min-h-0 flex-1 flex-col overflow-hidden rounded-lg bg-white", children: _jsx(ProjectTemplateSelectorList, { rootTestId: "project-template-overview-list", templates: templates, selectedTemplateId: selectedTemplateId, error: error, deleting: deleting, loading: state === "loading", onSelectTemplate: handleSelectTemplate, onDeleteTemplate: handleDeleteTemplate }) }) }));
|
|
2318
|
+
const agentFullHeightBounds = useMemo(() => !isMobile && !isTaskEditorMaximized && settingsMainContentBounds
|
|
2319
|
+
? {
|
|
2320
|
+
top: settingsMainContentBounds.top,
|
|
2321
|
+
right: settingsMainContentBounds.left + settingsMainContentBounds.width,
|
|
2322
|
+
height: settingsMainContentBounds.height,
|
|
2323
|
+
}
|
|
2324
|
+
: undefined, [isMobile, isTaskEditorMaximized, settingsMainContentBounds]);
|
|
2325
|
+
const assistantTopToggleStyle = useMemo(() => !isMobile &&
|
|
2326
|
+
!isTaskEditorMaximized &&
|
|
2327
|
+
isAgentPanelCollapsed &&
|
|
2328
|
+
settingsMainContentBounds
|
|
2329
|
+
? {
|
|
2330
|
+
position: "fixed",
|
|
2331
|
+
top: settingsMainContentBounds.top + 8,
|
|
2332
|
+
left: settingsMainContentBounds.left +
|
|
2333
|
+
settingsMainContentBounds.width -
|
|
2334
|
+
88,
|
|
2335
|
+
zIndex: 45,
|
|
2336
|
+
}
|
|
2337
|
+
: undefined, [
|
|
2338
|
+
isAgentPanelCollapsed,
|
|
2339
|
+
isMobile,
|
|
2340
|
+
isTaskEditorMaximized,
|
|
2341
|
+
settingsMainContentBounds,
|
|
2342
|
+
]);
|
|
2343
|
+
const agentPanelContent = (_jsx(ProjectTemplateAgentPanel, { templateName: draftTemplate?.name ?? null, agentId: templateAgentId, loading: templateAgentLoading, resetting: templateAgentResetting, error: templateAgentError, initialMetadata: templateAgentInitialMetadata, fullHeightBounds: agentFullHeightBounds, onStartOver: () => void handleResetTemplateAgent(), onClose: handleHideTemplateAssistant, headerStart: isMobile ? (_jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "gap-1 px-2", onClick: handleMobileBackFromAgent, "data-testid": "project-template-mobile-back-from-agent", children: _jsx(ChevronLeft, { className: "h-5 w-5", strokeWidth: 1.5 }) })) : undefined }));
|
|
1887
2344
|
const rightPanelContent = editingAgentProfile ? (_jsx(AgentProfileEditorPanel, { agent: editingAgentProfile, onClose: handleCloseEditingAgentProfile, actions: _jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => void handleDuplicateAssignedAgentProfile(), disabled: !selectedAgentProfileId ||
|
|
1888
2345
|
!editContext ||
|
|
1889
2346
|
duplicatingAgentProfile ||
|
|
@@ -1900,7 +2357,7 @@ export function ProjectTemplatesPanel() {
|
|
|
1900
2357
|
name: "project-template-agent",
|
|
1901
2358
|
defaultSize: 460,
|
|
1902
2359
|
content: rightPanelContent,
|
|
1903
|
-
className: "overflow-hidden",
|
|
2360
|
+
className: "overflow-hidden bg-white",
|
|
1904
2361
|
collapsible: true,
|
|
1905
2362
|
hidden: isMobile && mobileView !== "agent",
|
|
1906
2363
|
},
|
|
@@ -1911,7 +2368,9 @@ export function ProjectTemplatesPanel() {
|
|
|
1911
2368
|
if (!draftTemplate) {
|
|
1912
2369
|
return overviewContent;
|
|
1913
2370
|
}
|
|
1914
|
-
return (_jsxs(_Fragment, { children: [_jsx("div", { className: cn("h-full", !isTaskEditorMaximized && "px-10 pt-0 pb-
|
|
2371
|
+
return (_jsxs(_Fragment, { children: [assistantTopToggleStyle ? (_jsx(Button, { type: "button", variant: "outline", size: "icon", className: "h-8 w-8 rounded-md bg-white shadow-sm hover:bg-white", style: assistantTopToggleStyle, onClick: handleShowTemplateAssistant, "aria-label": "Show template assistant", title: "Show template assistant", "data-testid": "project-template-assistant-expand-button", children: _jsx(PanelRightOpen, { className: "h-5 w-5", strokeWidth: 1 }) })) : null, _jsx("div", { className: cn("h-full", !isTaskEditorMaximized && "px-10 pt-0 pb-5"), children: _jsx("div", { className: cn("h-full", isTaskEditorMaximized && "fixed overflow-hidden bg-white shadow-xl"), style: projectTemplateEditorStyle, "data-testid": "project-template-editor", onKeyDownCapture: handleProjectTemplateEditorKeyDownCapture, children: _jsx(Splitter, { panels: panels, localStorageKey: PROJECT_TEMPLATE_SPLITTER_STORAGE_KEY, direction: "horizontal", className: "h-full !overflow-visible", expandLabel: _jsx(PanelRightOpen, { className: "h-5 w-5", strokeWidth: 1 }), expandButtonLabel: "Show template assistant", expandButtonTestId: isTaskEditorMaximized
|
|
2372
|
+
? "project-template-assistant-expand-button"
|
|
2373
|
+
: undefined, expandButtonClassName: cn("border-border-default absolute right-4 z-50 h-8 w-8 rounded-md bg-white p-0 text-neutral-grey-100 shadow-sm backdrop-blur-sm hover:bg-white hover:text-neutral-grey-100 md:p-0", isTaskEditorMaximized ? "top-4" : "hidden"), forceCollapseLastPanelKey: forceCollapseLastPanelKey, forceExpandLastPanelKey: forceExpandLastPanelKey, onLastPanelCollapsedChange: setIsAgentPanelCollapsed }) }) }), _jsx(Dialog, { open: isCreateTaskDialogOpen, onOpenChange: (open) => {
|
|
1915
2374
|
setIsCreateTaskDialogOpen(open);
|
|
1916
2375
|
if (!open) {
|
|
1917
2376
|
setNewTaskDependencySourceId(null);
|
|
@@ -1929,7 +2388,12 @@ export function ProjectTemplatesPanel() {
|
|
|
1929
2388
|
? "Creating..."
|
|
1930
2389
|
: newTaskDependencySourceId
|
|
1931
2390
|
? "Create Dependent Task"
|
|
1932
|
-
: "Create Task" })] })] }) }), _jsx(Dialog, { open:
|
|
2391
|
+
: "Create Task" })] })] }) }), _jsx(Dialog, { open: isCreateGoalDialogOpen, onOpenChange: setIsCreateGoalDialogOpen, children: _jsxs(DialogContent, { className: "max-w-md", "data-testid": "project-template-create-goal-dialog", children: [_jsx(StyledDialogTitle, { icon: _jsx(Plus, { strokeWidth: 1.5 }), title: "Add Goal Definition", subtitle: "Create the goal and save it immediately." }), _jsxs("div", { className: "grid gap-2 p-6", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-new-goal-title", children: "Goal title" }), _jsx(Input, { id: "project-template-new-goal-title", value: newGoalTitle, onChange: (event) => setNewGoalTitle(event.target.value), placeholder: "e.g. Review all pages", className: "text-xs md:text-xs", autoFocus: true, onKeyDown: (event) => {
|
|
2392
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
2393
|
+
event.preventDefault();
|
|
2394
|
+
void handleConfirmCreateGoal();
|
|
2395
|
+
}
|
|
2396
|
+
} })] }), _jsxs(DialogFooter, { className: "px-6 pt-0 pb-6", children: [_jsx(Button, { variant: "outline", onClick: () => setIsCreateGoalDialogOpen(false), disabled: creatingGoal, "data-testid": "project-template-create-goal-cancel-button", children: "Cancel" }), _jsx(Button, { onClick: () => void handleConfirmCreateGoal(), disabled: creatingGoal || !newGoalTitle.trim(), "data-testid": "project-template-create-goal-submit-button", children: creatingGoal ? "Creating..." : "Create Goal" })] })] }) }), _jsx(Dialog, { open: isAddChildTaskDialogOpen, onOpenChange: setIsAddChildTaskDialogOpen, children: _jsxs(DialogContent, { className: "max-w-md", "data-testid": "project-template-create-child-task-dialog", children: [_jsx(StyledDialogTitle, { icon: _jsx(Plus, { strokeWidth: 1.5 }), title: "Add Child Task", subtitle: "Creates a new task that depends on the current task." }), _jsxs("div", { className: "grid gap-2 p-6", children: [_jsx(Label, { className: "text-xs", htmlFor: "project-template-new-child-task-title", children: "Task title" }), _jsx(Input, { id: "project-template-new-child-task-title", value: newChildTaskTitle, onChange: (event) => setNewChildTaskTitle(event.target.value), placeholder: "e.g. Review content", className: "text-xs md:text-xs", autoFocus: true, onKeyDown: (event) => {
|
|
1933
2397
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
1934
2398
|
event.preventDefault();
|
|
1935
2399
|
void handleConfirmCreateChildTask();
|