@taskforcehq/taskforce 0.3.327 → 0.3.329
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/Taskforce.module.css +257 -87
- package/dist/TaskforceCore.js +237 -230
- package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +1 -1
- package/dist/cli.js +34 -0
- package/dist/cliCloudTargetGuard.d.ts +5 -0
- package/dist/cliCloudTargetGuard.js +11 -0
- package/dist/components/activity/EntityActivityTimeline.js +15 -5
- package/dist/components/context/AttachmentPreviewHost.js +1 -1
- package/dist/components/context/ContextAttachmentManager.d.ts +3 -0
- package/dist/components/context/ContextAttachmentManager.js +116 -20
- package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
- package/dist/components/features/TaskSettings.d.ts +12 -1
- package/dist/components/features/TaskSettings.js +147 -40
- package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
- package/dist/components/features/planning/PlanningEntitySummary.d.ts +3 -1
- package/dist/components/features/planning/PlanningEntitySummary.js +3 -2
- package/dist/components/features/planning/PlanningLinkPicker.d.ts +3 -1
- package/dist/components/features/planning/PlanningLinkPicker.js +5 -3
- package/dist/components/features/planning/PlanningModule.js +28 -14
- package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
- package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
- package/dist/components/features/planning/PlanningVisualIdentity.d.ts +14 -0
- package/dist/components/features/planning/PlanningVisualIdentity.js +106 -0
- package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
- package/dist/components/features/planning/planningTaskArrangement.js +5 -5
- package/dist/components/features/planning/planningWorkspaceModel.d.ts +11 -0
- package/dist/components/features/taskforceAgentEditorModel.js +3 -1
- package/dist/components/task/TaskActionHeader.d.ts +2 -1
- package/dist/components/task/TaskActionHeader.js +2 -2
- package/dist/components/task/TaskCard.d.ts +5 -0
- package/dist/components/task/TaskCard.js +101 -13
- package/dist/components/task/TaskContextUpload.d.ts +3 -0
- package/dist/components/task/TaskContextUpload.js +2 -2
- package/dist/components/task/TaskForm.d.ts +4 -0
- package/dist/components/task/TaskForm.js +32 -7
- package/dist/components/task/TaskImageReviews.js +28 -19
- package/dist/components/task/TaskKanban.d.ts +6 -1
- package/dist/components/task/TaskKanban.js +152 -6
- package/dist/components/task/TaskList.d.ts +5 -0
- package/dist/components/task/TaskList.js +3 -3
- package/dist/components/task/TaskStatusActions.js +11 -2
- package/dist/components/task/TaskWorkstreamPicker.js +2 -1
- package/dist/components/ui/DocumentTypeIcon.d.ts +7 -0
- package/dist/components/ui/DocumentTypeIcon.js +8 -0
- package/dist/components/ui/PasswordInput.d.ts +6 -0
- package/dist/components/ui/PasswordInput.js +11 -0
- package/dist/components/ui/TaxonomyDropdown.d.ts +9 -1
- package/dist/components/ui/TaxonomyDropdown.js +30 -3
- package/dist/components/ui/TopNoticeLayer.js +1 -1
- package/dist/components/views/AppShellHeader.js +32 -11
- package/dist/components/views/PlanComparisonPage.js +12 -0
- package/dist/components/views/StandaloneLayout.js +68 -39
- package/dist/components/views/WidgetView.js +10 -7
- package/dist/components/views/panels/PlanningDrawer.d.ts +7 -1
- package/dist/components/views/panels/PlanningDrawer.js +51 -54
- package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
- package/dist/config/envSchema.js +13 -0
- package/dist/config/localServiceCloudTarget.d.ts +10 -0
- package/dist/config/localServiceCloudTarget.js +76 -0
- package/dist/config/localServiceRuntimeContract.d.ts +13 -0
- package/dist/config/localServiceRuntimeContract.js +135 -0
- package/dist/core/AiProfileService.d.ts +1 -0
- package/dist/core/AiProfileService.js +48 -9
- package/dist/core/AttachmentLinkService.js +7 -4
- package/dist/core/DeletedTaskLifecycleService.d.ts +5 -0
- package/dist/core/DeletedTaskLifecycleService.js +55 -3
- package/dist/core/McpTokenService.d.ts +4 -0
- package/dist/core/McpTokenService.js +52 -0
- package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +8 -2
- package/dist/core/TaskAttachmentLinksDurableMutationService.js +51 -18
- package/dist/core/Taskforce.d.ts +124 -2
- package/dist/core/Taskforce.js +1175 -87
- package/dist/core/types.d.ts +8 -1
- package/dist/documentReviews/DocumentReviewCommentStore.d.ts +11 -0
- package/dist/documentReviews/DocumentReviewCommentStore.js +35 -2
- package/dist/documentReviews/service.d.ts +4 -0
- package/dist/documentReviews/service.js +141 -46
- package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
- package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
- package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
- package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
- package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
- package/dist/hooks/tasks/taskHttpMutation.js +1 -0
- package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
- package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
- package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
- package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
- package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
- package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
- package/dist/hooks/tasks/useTaskFormActions.d.ts +9 -0
- package/dist/hooks/tasks/useTaskFormActions.js +96 -17
- package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
- package/dist/hooks/ui/useSettingsModel.js +13 -2
- package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
- package/dist/hooks/ui/useSettingsPersistence.js +74 -47
- package/dist/hooks/useFilterSort.d.ts +7 -3
- package/dist/hooks/useFilterSort.js +15 -5
- package/dist/hooks/useTaskData.d.ts +10 -1
- package/dist/hooks/useTaskData.js +216 -7
- package/dist/hooks/useTaskMutations.d.ts +10 -2
- package/dist/hooks/useTaskMutations.js +223 -43
- package/dist/hooks/useTaskforce.d.ts +94 -57
- package/dist/hooks/useTaskforce.js +428 -16
- package/dist/hooks/useUiNotice.d.ts +4 -0
- package/dist/hooks/useUiNotice.js +4 -0
- package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
- package/dist/mcp/canonicalAssetHelpers.d.ts +13 -0
- package/dist/mcp/canonicalAssetHelpers.js +39 -5
- package/dist/mcp/collaborationRegistrar.js +15 -13
- package/dist/mcp/documentAssetRegistrar.js +60 -44
- package/dist/mcp/documentHelpers.d.ts +1 -0
- package/dist/mcp/documentHelpers.js +7 -3
- package/dist/mcp/localServiceProxy.js +4 -1
- package/dist/mcp/runtime.d.ts +16 -0
- package/dist/mcp/runtime.js +735 -210
- package/dist/mcp/taskAttachmentCommandAdapter.d.ts +2 -0
- package/dist/mcp/taskAttachmentCommandAdapter.js +14 -8
- package/dist/mcp/taskPlanningRegistrar.js +78 -67
- package/dist/mcp/toolCallCompatibility.js +38 -1
- package/dist/mcp/toolCatalog.d.ts +1 -0
- package/dist/mcp/toolRegistry.js +2 -2
- package/dist/migrations/taskSchemaMigrations.js +47 -0
- package/dist/runtime/appGateDefinitions.d.ts +30 -6
- package/dist/runtime/appGateDefinitions.js +6 -6
- package/dist/runtime/appGates.d.ts +12 -13
- package/dist/runtime/appGates.js +29 -13
- package/dist/runtime/nodeAppGates.d.ts +8 -0
- package/dist/runtime/nodeAppGates.js +27 -0
- package/dist/server/appAccess.d.ts +12 -0
- package/dist/server/appAccess.js +21 -0
- package/dist/server/authorizedWorkspaceAccess.d.ts +12 -0
- package/dist/server/authorizedWorkspaceAccess.js +40 -0
- package/dist/server/cloudCollectionRead.d.ts +25 -0
- package/dist/server/cloudCollectionRead.js +120 -0
- package/dist/server/cloudCollectionReadPool.d.ts +52 -0
- package/dist/server/cloudCollectionReadPool.js +140 -0
- package/dist/server/cloudCollectionReadWorker.d.ts +1 -0
- package/dist/server/cloudCollectionReadWorker.js +36 -0
- package/dist/server/index.d.ts +6 -11
- package/dist/server/index.js +67 -42
- package/dist/server/localServiceLease.d.ts +6 -0
- package/dist/server/localServiceLease.js +17 -1
- package/dist/server/localWorkspaceSyncServerRuntime.js +10 -3
- package/dist/server/rateLimit.d.ts +1 -0
- package/dist/server/rateLimit.js +4 -0
- package/dist/server/realtimeSyncWs.js +36 -12
- package/dist/server/routes/admin.js +1 -0
- package/dist/server/routes/agentRoles.js +3 -2
- package/dist/server/routes/agentSkills.js +3 -2
- package/dist/server/routes/agents.js +118 -16
- package/dist/server/routes/annotatedAttachments.js +3 -2
- package/dist/server/routes/auth.js +3 -1
- package/dist/server/routes/documents.d.ts +5 -2
- package/dist/server/routes/documents.js +160 -13
- package/dist/server/routes/durableTaskHttpRouters.d.ts +11 -2
- package/dist/server/routes/durableTaskHttpRouters.js +2 -2
- package/dist/server/routes/localService.js +4 -0
- package/dist/server/routes/primitives.d.ts +4 -0
- package/dist/server/routes/shared.d.ts +24 -0
- package/dist/server/routes/shared.js +114 -18
- package/dist/server/routes/sync.js +22 -0
- package/dist/server/routes/syncAuxRoutes.js +5 -2
- package/dist/server/routes/syncPullApplyRoutes.js +23 -4
- package/dist/server/routes/syncV3FeedRoutes.js +22 -18
- package/dist/server/routes/syncV3LocalCaptureRoutes.js +48 -4
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
- package/dist/server/routes/syncV3OperationRoutes.js +27 -2
- package/dist/server/routes/tasks.js +299 -97
- package/dist/server/routes/workspaces.js +43 -1
- package/dist/server/routes.js +35 -7
- package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
- package/dist/server/workspaceDeletionAdmission.js +50 -0
- package/dist/service/localServiceCli.js +52 -25
- package/dist/service/localServiceClientLifecycle.js +93 -6
- package/dist/services/codexAppServerModelGateway.d.ts +112 -0
- package/dist/services/codexAppServerModelGateway.js +438 -0
- package/dist/services/taskforceAgentMcpBridge.d.ts +7 -1
- package/dist/services/taskforceAgentMcpBridge.js +23 -3
- package/dist/shared/planningIdentity.d.ts +20 -0
- package/dist/shared/planningIdentity.js +79 -0
- package/dist/shared/taskforceAgentDefinition.js +7 -1
- package/dist/shared/taskforceAgentModels.d.ts +1 -0
- package/dist/shared/taskforceAgentModels.js +30 -1
- package/dist/storage/postgresAdapter.d.ts +20 -3
- package/dist/storage/postgresAdapter.js +110 -14
- package/dist/storage/postgresRequestDiagnostics.d.ts +8 -0
- package/dist/storage/postgresRequestDiagnostics.js +24 -0
- package/dist/storage/postgresWorker.js +13 -4
- package/dist/storage/postgresWorkerProtocol.d.ts +29 -0
- package/dist/storage/postgresWorkerProtocol.js +30 -0
- package/dist/storage/workspaceAssetStore.d.ts +32 -0
- package/dist/storage/workspaceAssetStore.js +70 -0
- package/dist/sync/cloudSyncApi.d.ts +4 -1
- package/dist/sync/cloudSyncApi.js +7 -2
- package/dist/sync/contentSyncState.d.ts +1 -1
- package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +17 -0
- package/dist/sync/coordinator/localSyncExecutionPermitStore.js +77 -23
- package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
- package/dist/sync/coordinator/workspaceSyncTransportGateway.js +4 -2
- package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
- package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
- package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +16 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
- package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.d.ts +1 -1
- package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +46 -4
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +51 -11
- package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
- package/dist/sync/engine/workspaceSyncEngineTransfers.js +8 -3
- package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +2 -0
- package/dist/sync/syncApplyHandlers.d.ts +3 -1
- package/dist/sync/syncApplyHandlers.js +29 -0
- package/dist/sync/syncService.d.ts +2 -0
- package/dist/sync/syncService.js +13 -1
- package/dist/sync/taskSyncPayload.d.ts +1 -0
- package/dist/sync/taskSyncPayload.js +6 -0
- package/dist/sync/v3/combinedFeedCapability.js +4 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +3 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +31 -3
- package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -0
- package/dist/sync/v3/durableTaskChecklistMutationRouter.js +4 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +47 -12
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +27 -2
- package/dist/sync/v3/localInitiativeOutboxService.js +4 -2
- package/dist/sync/v3/localOutboxDispatcher.js +5 -1
- package/dist/sync/v3/localTaskAttachmentLinksOutboxHandler.js +12 -2
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +3 -0
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +62 -10
- package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
- package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
- package/dist/sync/v3/localTaskMetadataClient.js +1 -0
- package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
- package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
- package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
- package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
- package/dist/sync/v3/localTaskStatusClient.js +6 -1
- package/dist/sync/v3/localTaskStatusOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskStatusOutboxService.js +54 -13
- package/dist/sync/v3/localWorkstreamOutboxService.js +4 -2
- package/dist/sync/v3/syncDurabilityStore.d.ts +15 -0
- package/dist/sync/v3/syncDurabilityStore.js +201 -43
- package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +7 -4
- package/dist/sync/v3/taskAttachmentLinksMutationService.js +37 -12
- package/dist/sync/v3/taskChecklistMutationService.d.ts +4 -2
- package/dist/sync/v3/taskChecklistMutationService.js +4 -0
- package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
- package/dist/sync/v3/taskCreateMutationService.js +7 -4
- package/dist/sync/v3/taskMetadataCoexistence.js +4 -0
- package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
- package/dist/sync/v3/taskMetadataMutationService.js +4 -0
- package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
- package/dist/sync/v3/taskRestoreMutationService.js +7 -4
- package/dist/sync/v3/taskStatusMutationService.d.ts +2 -0
- package/dist/sync/v3/taskStatusMutationService.js +4 -0
- package/dist/sync/v3/workflowAssignmentSync.d.ts +1 -0
- package/dist/sync/v3/workflowAssignmentSync.js +3 -0
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +14 -12
- package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
- package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
- package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
- package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +10 -1
- package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +15 -4
- package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +66 -13
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +11 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +57 -22
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +10 -4
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +124 -51
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +120 -28
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +3 -1
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +18 -0
- package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
- package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
- package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
- package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
- package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
- package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +3 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +2 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +19 -7
- package/dist/sync/v3/workspaceSyncV3RepairSqlBatching.d.ts +2 -0
- package/dist/sync/v3/workspaceSyncV3RepairSqlBatching.js +10 -0
- package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
- package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
- package/dist/sync/v3/workspaceSyncV3TaskRootProjection.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV3TaskRootProjection.js +1 -1
- package/dist/sync/workspacePullFeed.d.ts +6 -1
- package/dist/sync/workspacePullFeed.js +174 -162
- package/dist/sync/workspaceRepair.d.ts +3 -0
- package/dist/sync/workspaceRepair.js +67 -6
- package/dist/sync/workspaceSyncModel.d.ts +11 -0
- package/dist/sync/workspaceSyncModel.js +27 -2
- package/dist/types.d.ts +55 -1
- package/dist/types.js +6 -0
- package/dist/ui/assets/{AiIdentityRosterCard-DB1BLO_j.js → AiIdentityRosterCard-BZM4aQnM.js} +1 -1
- package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-B68Wg-RV.js +3 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
- package/dist/ui/assets/AssetTraySortControl-C8Rztyal.js +1 -0
- package/dist/ui/assets/ContextAttachmentManager-Cj3c7X9y.js +3 -0
- package/dist/ui/assets/{DocumentWorkspace-BC7sy5TG.js → DocumentWorkspace-B5uvzems.js} +4 -4
- package/dist/ui/assets/EntityActivityTimeline-BVFvCB5R.js +1 -0
- package/dist/ui/assets/PlanningModule-B5DWQOGz.js +1 -0
- package/dist/ui/assets/PlanningModule-CoIR9hbV.css +1 -0
- package/dist/ui/assets/PlansPage-AY4cGWco.js +1 -0
- package/dist/ui/assets/TaskContextUpload-DZxTVesW.js +1 -0
- package/dist/ui/assets/TaskContextUpload-qmBeUw3u.css +1 -0
- package/dist/ui/assets/TaskSettings-BeWAuyZj.js +12 -0
- package/dist/ui/assets/{TaskforceAgentsModule-CkAxW19K.js → TaskforceAgentsModule-BifCYtjR.js} +6 -6
- package/dist/ui/assets/WorkflowManagerModule-DEr5di_r.js +1 -0
- package/dist/ui/assets/index-I5zhdtgt.js +7 -0
- package/dist/ui/assets/index-VRFsx3wz.css +1 -0
- package/dist/ui/assets/{vendor-icons-B8ZNsH1g.js → vendor-icons-D9Lpw-j4.js} +1 -1
- package/dist/ui/index.html +3 -3
- package/dist/utils/constants.d.ts +2 -2
- package/dist/utils/constants.js +1 -1
- package/dist/utils/contextAttachmentUpload.d.ts +2 -0
- package/dist/utils/contextAttachmentUpload.js +7 -0
- package/dist/utils/contextFiles.d.ts +1 -1
- package/dist/utils/contextFiles.js +4 -4
- package/dist/utils/taskActivity.d.ts +3 -2
- package/dist/utils/taskActivity.js +19 -2
- package/dist/utils/taskEditorReconciliation.d.ts +40 -0
- package/dist/utils/taskEditorReconciliation.js +217 -0
- package/dist/utils/taskNormalization.d.ts +1 -0
- package/dist/utils/taskNormalization.js +39 -0
- package/dist/utils/taskSearch.js +2 -2
- package/dist/utils/uiNotice.d.ts +4 -0
- package/package.json +21 -4
- package/dist/ui/assets/AiProfilesModule-DPxQeF9N.js +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-DHNYaNg6.js +0 -3
- package/dist/ui/assets/AssetTraySortControl-DphbyHVc.js +0 -1
- package/dist/ui/assets/ContextAttachmentManager-CMxSzHqc.js +0 -3
- package/dist/ui/assets/EntityActivityTimeline-pJ2ZjZ-k.js +0 -1
- package/dist/ui/assets/PlanningModule-CeTqXMMz.css +0 -1
- package/dist/ui/assets/PlanningModule-t5GbvVR9.js +0 -1
- package/dist/ui/assets/PlansPage-BVH_NfgT.js +0 -1
- package/dist/ui/assets/TaskContextUpload-Ds4LnDzV.css +0 -1
- package/dist/ui/assets/TaskContextUpload-bl4fOOUz.js +0 -1
- package/dist/ui/assets/TaskSettings-xVsxSa0g.js +0 -12
- package/dist/ui/assets/WorkflowManagerModule-BKqIGVnF.js +0 -1
- package/dist/ui/assets/index-BzJlVnNS.css +0 -1
- package/dist/ui/assets/index-Cx7vZJHL.js +0 -7
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { useDndContext, useDraggable, useDroppable } from '@dnd-kit/core';
|
|
4
4
|
import { CSS } from '@dnd-kit/utilities';
|
|
5
|
-
import { ArrowUpDown, Archive, ChevronDown, ChevronLeft, ChevronRight, Eye, EyeOff, Filter, GripVertical, Kanban,
|
|
5
|
+
import { ArrowUpDown, Archive, ChevronDown, ChevronLeft, ChevronRight, Eye, EyeOff, Filter, GripVertical, Kanban, Pencil, Plus, RotateCcw, Search, Star, Unlink, X, } from 'lucide-react';
|
|
6
6
|
import styles from '../../../Taskforce.module.css';
|
|
7
7
|
import panelStyles from './PlanningDrawer.module.css';
|
|
8
8
|
import { HierarchyActionBadge } from '../../ui/HierarchyActionBadge';
|
|
@@ -16,6 +16,7 @@ import { getPlanningFavoriteKey, } from '../../../utils/planningFavorites';
|
|
|
16
16
|
import { TASK_ASSIGNEE_UNASSIGNED_COLOR, TASK_ASSIGNEE_UNASSIGNED_ICON, } from '../../../utils/assignees';
|
|
17
17
|
import { PlanningEntityActivity, PlanningEntityContext, PlanningEntityDescription, } from '../../features/planning/PlanningEntityDetails';
|
|
18
18
|
import { PlanningEntitySummary, PlanningNoTasks, PlanningProgress, PlanningReferenceBadge, PlanningSummaryMeta, } from '../../features/planning/PlanningEntitySummary';
|
|
19
|
+
import { PlanningVisualIdentity } from '../../features/planning/PlanningVisualIdentity';
|
|
19
20
|
import { PlanningTaskCard } from '../../features/planning/PlanningTaskCard';
|
|
20
21
|
import { PlanningTaskArrangeControl } from '../../features/planning/PlanningTaskArrangeControl';
|
|
21
22
|
import planningDropdownStyles from '../../features/planning/PlanningDropdownControl.module.css';
|
|
@@ -72,11 +73,10 @@ function countArchivedDetailChildren(detail) {
|
|
|
72
73
|
}
|
|
73
74
|
return (detail.item.tasks || []).filter((task) => Boolean(task.isArchived)).length;
|
|
74
75
|
}
|
|
75
|
-
function PlanningRow({ rowId, rowType, referenceLabel, item, ownerOption, ownerOptions, workstreamCount, active, isArchived = false, detailOpen = false, canExpand = false, expanded = false, controlsId, onToggleExpand, onToggleScope, onOpenDetails, onChangeOwner, initiativeLinkOptions = [], onLinkInitiative, favorite, favoriteReady, onToggleFavorite, onArchiveReady, hierarchyInteractions = true, }) {
|
|
76
|
+
function PlanningRow({ rowId, rowType, referenceLabel, item, ownerOption, ownerOptions, workstreamCount, active, isArchived = false, detailOpen = false, canExpand = false, expanded = false, controlsId, onToggleExpand, onToggleScope, onOpenDetails, onChangeOwner, onChangeIdentity, initiativeLinkOptions = [], onLinkInitiative, favorite, favoriteReady, onToggleFavorite, onArchiveReady, hierarchyInteractions = true, }) {
|
|
76
77
|
const { title } = item;
|
|
77
78
|
const [archiveConfirmationVisible, setArchiveConfirmationVisible] = React.useState(false);
|
|
78
79
|
const [archiveBusy, setArchiveBusy] = React.useState(false);
|
|
79
|
-
const [initiativePickerVisible, setInitiativePickerVisible] = React.useState(false);
|
|
80
80
|
const [initiativeLinkBusy, setInitiativeLinkBusy] = React.useState(false);
|
|
81
81
|
const { active: dndActive } = useDndContext();
|
|
82
82
|
const dragType = String(dndActive?.data?.current?.type || '');
|
|
@@ -91,7 +91,7 @@ function PlanningRow({ rowId, rowType, referenceLabel, item, ownerOption, ownerO
|
|
|
91
91
|
disabled: !hierarchyInteractions,
|
|
92
92
|
});
|
|
93
93
|
const draggable = hierarchyInteractions && rowType === 'workstream';
|
|
94
|
-
const { attributes, listeners, setNodeRef: setDragRef, transform, isDragging, } = useDraggable({
|
|
94
|
+
const { attributes, listeners, setNodeRef: setDragRef, setActivatorNodeRef, transform, isDragging, } = useDraggable({
|
|
95
95
|
id: `planning-workstream:${rowId}`,
|
|
96
96
|
data: { type: 'planning-workstream', workstreamId: rowId },
|
|
97
97
|
disabled: !draggable,
|
|
@@ -163,9 +163,7 @@ function PlanningRow({ rowId, rowType, referenceLabel, item, ownerOption, ownerO
|
|
|
163
163
|
return;
|
|
164
164
|
setInitiativeLinkBusy(true);
|
|
165
165
|
try {
|
|
166
|
-
|
|
167
|
-
if (result !== false)
|
|
168
|
-
setInitiativePickerVisible(false);
|
|
166
|
+
await onLinkInitiative(option);
|
|
169
167
|
}
|
|
170
168
|
finally {
|
|
171
169
|
setInitiativeLinkBusy(false);
|
|
@@ -178,29 +176,26 @@ function PlanningRow({ rowId, rowType, referenceLabel, item, ownerOption, ownerO
|
|
|
178
176
|
: initiativeLinkOptions.length === 0
|
|
179
177
|
? 'No initiatives available'
|
|
180
178
|
: 'Link initiative';
|
|
181
|
-
return (
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
event.preventDefault();
|
|
202
|
-
onOpenDetails();
|
|
203
|
-
}, "aria-label": `View ${rowType} details for ${title}`, "aria-pressed": detailOpen, children: _jsx(PlanningEntitySummary, { item: item, entityType: rowType, workstreamCount: workstreamCount, ownerOption: ownerOption ? toPlanningAssigneeOption(ownerOption) : undefined, ownerOptions: ownerOptions.map(toPlanningAssigneeOption), onChangeOwner: onChangeOwner }) })] }), archiveConfirmationVisible ? (_jsx(PlanningArchiveConfirmation, { entityType: rowType, title: title, activeTaskCount: item.archiveActiveTaskCount, activeWorkstreamCount: item.archiveActiveWorkstreamCount, busy: archiveBusy, onCancel: () => setArchiveConfirmationVisible(false), onConfirm: () => void handleConfirmArchive() })) : null] }) }));
|
|
179
|
+
return (_jsxs("div", { ref: setDragRef, style: dragStyle, className: `${panelStyles.treeRowShell} ${draggable ? panelStyles.treeRowShellDraggable : ''} ${isDragging ? panelStyles.treeRowDragging : ''} ${showDropReady ? panelStyles.treeRowShellDropMode : ''}`.trim(), "data-planning-draggable-row": draggable || undefined, children: [draggable ? (_jsx("div", { className: panelStyles.rowDragGutter, "data-planning-drag-gutter": "true", children: _jsx("button", { type: "button", ref: setActivatorNodeRef, className: panelStyles.dragHandle, title: "Drag onto an initiative to move this workstream", "aria-label": `Move workstream ${title} to an initiative`, "data-planning-drag-handle": "true", ...attributes, ...listeners, children: _jsx(GripVertical, { size: 15, "aria-hidden": "true" }) }) })) : null, _jsx("div", { ref: setDropRef, className: `${panelStyles.treeRow} ${isArchived ? panelStyles.treeRowArchived : ''} ${detailOpen ? panelStyles.treeRowDetailOpen : ''} ${showDropReady ? panelStyles.treeRowDropReady : ''} ${isOver ? panelStyles.treeRowDropActive : ''} ${showDropReady ? panelStyles.treeRowDropMode : ''}`, "data-board-scoped": active || undefined, children: _jsxs("div", { className: panelStyles.rowContent, children: [_jsxs("div", { className: panelStyles.rowTopRow, children: [_jsxs("div", { className: panelStyles.rowReferenceActions, children: [canLinkInitiative ? (_jsx(PlanningLinkPicker, { options: initiativeLinkOptions, entityLabel: "initiative", onSelect: (option) => void handleLinkInitiative(option), disabled: initiativeLinkDisabled, iconTrigger: true, triggerTitle: initiativeLinkTitle })) : null, _jsx(PlanningReferenceBadge, { label: referenceLabel || 'Reference pending', entityType: rowType, entityName: title, pending: !referenceLabel })] }), _jsxs("div", { className: panelStyles.rowActions, role: "toolbar", "aria-label": `${rowType === 'initiative' ? 'Initiative' : 'Workstream'} actions for ${title}`, "aria-orientation": "horizontal", onKeyDown: handleRowActionKeyDown, children: [_jsx("button", { type: "button", ref: (node) => {
|
|
180
|
+
rowActionRefs.current.favorite = node;
|
|
181
|
+
}, className: `tf-control-icon tf-control-icon-compact ${panelStyles.favoriteButton} ${favorite ? 'tf-control-icon-active' : ''}`.trim(), onClick: onToggleFavorite, onFocus: () => handleRowActionFocus('favorite'), disabled: !favoriteReady, tabIndex: effectiveActiveRowActionId === 'favorite' ? 0 : -1, "data-planning-row-action": "favorite", title: !favoriteReady
|
|
182
|
+
? 'Loading Favorites'
|
|
183
|
+
: favorite ? `Remove ${rowType} from Favorites` : `Add ${rowType} to Favorites`, "aria-label": !favoriteReady
|
|
184
|
+
? `Loading Favorites for ${rowType} ${title}`
|
|
185
|
+
: favorite ? `Remove ${rowType} ${title} from Favorites` : `Add ${rowType} ${title} to Favorites`, "aria-pressed": favorite, children: _jsx(Star, { size: 14, fill: favorite ? 'currentColor' : 'none', "aria-hidden": "true" }) }), archiveActionVisible ? (_jsx("button", { type: "button", ref: (node) => {
|
|
186
|
+
rowActionRefs.current.archive = node;
|
|
187
|
+
}, className: "tf-control-icon tf-control-icon-compact", onClick: () => setArchiveConfirmationVisible(true), onFocus: () => handleRowActionFocus('archive'), tabIndex: effectiveActiveRowActionId === 'archive' ? 0 : -1, "data-planning-row-action": "archive", title: `Archive completed ${rowType}`, "aria-label": `Archive completed ${rowType} ${title}`, "aria-expanded": archiveConfirmationVisible, children: _jsx(Archive, { size: 14, "aria-hidden": "true" }) })) : null, _jsx("button", { type: "button", ref: (node) => {
|
|
188
|
+
rowActionRefs.current.scope = node;
|
|
189
|
+
}, className: `tf-control-icon tf-control-icon-compact ${panelStyles.scopeButton} ${active ? 'tf-control-icon-active' : ''}`.trim(), onClick: onToggleScope, onFocus: () => handleRowActionFocus('scope'), tabIndex: effectiveActiveRowActionId === 'scope' ? 0 : -1, "data-planning-row-action": "scope", title: active ? 'Clear board scope' : 'Scope board to this item', "aria-label": active ? `Clear board scope for ${title}` : `Scope board to ${title}`, "aria-pressed": active, children: _jsx(Kanban, { size: 14, "aria-hidden": "true" }) }), _jsx("button", { type: "button", ref: (node) => {
|
|
190
|
+
rowActionRefs.current.disclosure = node;
|
|
191
|
+
}, className: `tf-control-icon tf-control-icon-compact ${panelStyles.treeChevron}`.trim(), onClick: expansionEnabled ? onToggleExpand : undefined, onFocus: () => handleRowActionFocus('disclosure'), tabIndex: effectiveActiveRowActionId === 'disclosure' ? 0 : -1, "data-planning-row-action": "disclosure", title: expansionLabel, "aria-label": expansionLabel, "aria-expanded": expansionEnabled ? expanded : false, "aria-controls": expansionEnabled && expanded ? controlsId : undefined, disabled: !expansionEnabled, children: expanded && expansionEnabled
|
|
192
|
+
? _jsx(ChevronDown, { size: 14, "aria-hidden": "true" })
|
|
193
|
+
: _jsx(ChevronRight, { size: 14, "aria-hidden": "true" }) })] })] }), _jsx("div", { className: panelStyles.rowBody, children: _jsx("div", { role: "button", tabIndex: 0, className: panelStyles.rowButton, onClick: onOpenDetails, onKeyDown: (event) => {
|
|
194
|
+
if (event.key !== 'Enter' && event.key !== ' ')
|
|
195
|
+
return;
|
|
196
|
+
event.preventDefault();
|
|
197
|
+
onOpenDetails();
|
|
198
|
+
}, "aria-label": `View ${rowType} details for ${title}`, "aria-pressed": detailOpen, children: _jsx(PlanningEntitySummary, { item: item, entityType: rowType, workstreamCount: workstreamCount, ownerOption: ownerOption ? toPlanningAssigneeOption(ownerOption) : undefined, ownerOptions: ownerOptions.map(toPlanningAssigneeOption), onChangeOwner: onChangeOwner, onChangeIdentity: onChangeIdentity }) }) }), archiveConfirmationVisible ? (_jsx(PlanningArchiveConfirmation, { entityType: rowType, title: title, activeTaskCount: item.archiveActiveTaskCount, activeWorkstreamCount: item.archiveActiveWorkstreamCount, busy: archiveBusy, onCancel: () => setArchiveConfirmationVisible(false), onConfirm: () => void handleConfirmArchive() })) : null] }) })] }));
|
|
204
199
|
}
|
|
205
200
|
function PlanningTreeTaskCard({ task, assigneeOption, assigneeOptions, showTaskCardStatusLabel, onOpenTaskById, onChangeTaskAssignee, onSetTaskStatus, onArchivePlanningTask, }) {
|
|
206
201
|
const [archiveBusy, setArchiveBusy] = React.useState(false);
|
|
@@ -233,7 +228,7 @@ function RelationshipPane({ label, title, description, onCollapse, action, paneR
|
|
|
233
228
|
maxWidth: `${PLANNING_DRAWER_DETAIL_WIDTH_PX}px`,
|
|
234
229
|
}, children: [_jsxs("div", { className: panelStyles.paneHeader, children: [_jsx("h2", { className: panelStyles.paneHeaderLabel, tabIndex: -1, "data-planning-pane-heading": true, children: label }), _jsx("button", { type: "button", className: "tf-control-icon", onClick: onCollapse, "aria-label": `Collapse ${label} pane`, title: `Collapse ${label} pane`, children: _jsx(ChevronLeft, { size: 16, "aria-hidden": "true" }) })] }), _jsx("div", { className: `${panelStyles.paneContent} ${isEmptyState ? panelStyles.relationshipPaneContentEmpty : ''}`.trim(), children: _jsxs("div", { className: `${panelStyles.relationshipState} ${isEmptyState ? panelStyles.relationshipStateEmpty : ''}`.trim(), "data-relationship-display": isEmptyState ? 'empty' : 'detail', children: [_jsx("span", { className: panelStyles.relationshipStateTitle, children: title }), description ? _jsx("p", { className: panelStyles.relationshipStateText, children: description }) : null, action ? (_jsx("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: action.onClick, children: action.label })) : null] }) })] }));
|
|
235
230
|
}
|
|
236
|
-
function PlanningDrawerList({ initiatives, standaloneWorkstreams, planningLoadState, taskScope, showArchivedPlanning, currentOwnerId, assigneeOptions, showTaskCardStatusLabel = false, taskArrangeMode = 'execution', activeInitiativeId, activeWorkstreamId, navigatorSort, navigatorSortReady, onNavigatorSortChange, planningFavorites, onTogglePlanningFavorite, favoritesSectionCollapsed, initiativesSectionCollapsed, workstreamsSectionCollapsed, onToggleFavoritesSection, onToggleInitiativesSection, onToggleWorkstreamsSection, expandedInitiativeIds, detail, secondaryPane, onCreateInitiative, onCreateWorkstream, onToggleInitiative, onSelectInitiative, onSelectWorkstream, onOpenInitiativeDetails, onOpenWorkstreamDetails, onOpenNestedWorkstreamDetails, onOpenTaskById, onSetTaskStatus, onChangePlanningOwner, onChangeTaskAssignee, onArchivePlanningTask, onArchiveResolvedWorkstream, onArchiveResolvedInitiative, linkOptions, onAssignInitiativeToWorkstream, onRetryPlanning, }) {
|
|
231
|
+
function PlanningDrawerList({ initiatives, standaloneWorkstreams, planningLoadState, taskScope, showArchivedPlanning, currentOwnerId, assigneeOptions, showTaskCardStatusLabel = false, taskArrangeMode = 'execution', activeInitiativeId, activeWorkstreamId, navigatorSort, navigatorSortReady, onNavigatorSortChange, planningFavorites, onTogglePlanningFavorite, favoritesSectionCollapsed, initiativesSectionCollapsed, workstreamsSectionCollapsed, onToggleFavoritesSection, onToggleInitiativesSection, onToggleWorkstreamsSection, expandedInitiativeIds, detail, secondaryPane, onCreateInitiative, onCreateWorkstream, onToggleInitiative, onSelectInitiative, onSelectWorkstream, onOpenInitiativeDetails, onOpenWorkstreamDetails, onOpenNestedWorkstreamDetails, onOpenTaskById, onSetTaskStatus, onChangePlanningOwner, onChangePlanningIdentity = () => { }, onChangeTaskAssignee, onArchivePlanningTask, onArchiveResolvedWorkstream, onArchiveResolvedInitiative, linkOptions, onAssignInitiativeToWorkstream, onRetryPlanning, }) {
|
|
237
232
|
const [searchQuery, setSearchQuery] = React.useState('');
|
|
238
233
|
const [ownerFilter, setOwnerFilter] = React.useState('all');
|
|
239
234
|
const [filtersExpanded, setFiltersExpanded] = React.useState(false);
|
|
@@ -435,7 +430,7 @@ function PlanningDrawerList({ initiatives, standaloneWorkstreams, planningLoadSt
|
|
|
435
430
|
const favoriteControlsId = `planning-${favoriteBranchKey.replaceAll(':', '-')}-children`;
|
|
436
431
|
return (_jsxs("li", { children: [_jsx(PlanningRow, { rowId: `favorite:${favorite.type}:${item.id}`, rowType: favorite.type, referenceLabel: favorite.type === 'initiative'
|
|
437
432
|
? formatInitiativeReference(item)
|
|
438
|
-
: formatWorkstreamReference(item), item: item, ownerOption: item.ownerId ? assigneeOptionByValue.get(item.ownerId) : undefined, ownerOptions: assigneeOptions, onChangeOwner: (ownerId) => onChangePlanningOwner(favorite.type, item.id, ownerId === 'unassigned' ? '' : ownerId), workstreamCount: favoriteInitiative
|
|
433
|
+
: formatWorkstreamReference(item), item: item, ownerOption: item.ownerId ? assigneeOptionByValue.get(item.ownerId) : undefined, ownerOptions: assigneeOptions, onChangeOwner: (ownerId) => onChangePlanningOwner(favorite.type, item.id, ownerId === 'unassigned' ? '' : ownerId), onChangeIdentity: (patch) => onChangePlanningIdentity(favorite.type, item.id, patch), workstreamCount: favoriteInitiative
|
|
439
434
|
? visibleInitiativeWorkstreams.length
|
|
440
435
|
: undefined, active: favorite.type === 'initiative'
|
|
441
436
|
? activeInitiativeId === item.id && !activeWorkstreamId
|
|
@@ -476,7 +471,7 @@ function PlanningDrawerList({ initiatives, standaloneWorkstreams, planningLoadSt
|
|
|
476
471
|
const childControlsId = `planning-${childBranchKey.replaceAll(':', '-')}-children`;
|
|
477
472
|
return (_jsxs("li", { children: [_jsx(PlanningRow, { rowId: childBranchKey, rowType: "workstream", referenceLabel: formatWorkstreamReference(workstream), item: workstream, ownerOption: workstream.ownerId
|
|
478
473
|
? assigneeOptionByValue.get(workstream.ownerId)
|
|
479
|
-
: undefined, ownerOptions: assigneeOptions, onChangeOwner: (ownerId) => onChangePlanningOwner('workstream', workstream.id, ownerId === 'unassigned' ? '' : ownerId), active: activeWorkstreamId === workstream.id, isArchived: Boolean(workstream.isArchived), detailOpen: (detail?.type === 'workstream' && detail.item.id === workstream.id)
|
|
474
|
+
: undefined, ownerOptions: assigneeOptions, onChangeOwner: (ownerId) => onChangePlanningOwner('workstream', workstream.id, ownerId === 'unassigned' ? '' : ownerId), onChangeIdentity: (patch) => onChangePlanningIdentity('workstream', workstream.id, patch), active: activeWorkstreamId === workstream.id, isArchived: Boolean(workstream.isArchived), detailOpen: (detail?.type === 'workstream' && detail.item.id === workstream.id)
|
|
480
475
|
|| (secondaryPane?.kind === 'detail'
|
|
481
476
|
&& secondaryPane.detail.item.id === workstream.id), canExpand: Boolean(workstream.tasks?.length), expanded: childExpanded, controlsId: childControlsId, onToggleExpand: () => toggleFavoriteBranch(childBranchKey), onToggleScope: () => onSelectWorkstream(workstream.id, favoriteInitiative.id), onOpenDetails: () => {
|
|
482
477
|
onOpenInitiativeDetails(favoriteInitiative.id);
|
|
@@ -503,16 +498,16 @@ function PlanningDrawerList({ initiatives, standaloneWorkstreams, planningLoadSt
|
|
|
503
498
|
const expanded = navigatorResults.hasCriteria
|
|
504
499
|
? displayedWorkstreams.length > 0
|
|
505
500
|
: expandedInitiativeIds.has(initiative.id);
|
|
506
|
-
return (_jsxs("li", { children: [_jsx(PlanningRow, { rowId: initiative.id, rowType: "initiative", referenceLabel: formatInitiativeReference(initiative), item: initiative, ownerOption: initiative.ownerId ? assigneeOptionByValue.get(initiative.ownerId) : undefined, ownerOptions: assigneeOptions, onChangeOwner: (ownerId) => onChangePlanningOwner('initiative', initiative.id, ownerId === 'unassigned' ? '' : ownerId), workstreamCount: treeWorkstreams.length, active: activeInitiativeId === initiative.id && !activeWorkstreamId, isArchived: Boolean(initiative.isArchived), detailOpen: detail?.type === 'initiative' && detail.item.id === initiative.id, canExpand: allWorkstreams.length > 0, expanded: expanded, controlsId: `planning-children-${initiative.id}`, onToggleExpand: () => onToggleInitiative(initiative.id), onToggleScope: () => onSelectInitiative(initiative.id), onOpenDetails: () => onOpenInitiativeDetails(initiative.id), favorite: planningFavoriteKeys.has(getPlanningFavoriteKey({ type: 'initiative', id: initiative.id })), favoriteReady: navigatorSortReady, onToggleFavorite: () => onTogglePlanningFavorite({ type: 'initiative', id: initiative.id }), onArchiveReady: onArchiveResolvedInitiative
|
|
501
|
+
return (_jsxs("li", { children: [_jsx(PlanningRow, { rowId: initiative.id, rowType: "initiative", referenceLabel: formatInitiativeReference(initiative), item: initiative, ownerOption: initiative.ownerId ? assigneeOptionByValue.get(initiative.ownerId) : undefined, ownerOptions: assigneeOptions, onChangeOwner: (ownerId) => onChangePlanningOwner('initiative', initiative.id, ownerId === 'unassigned' ? '' : ownerId), onChangeIdentity: (patch) => onChangePlanningIdentity('initiative', initiative.id, patch), workstreamCount: treeWorkstreams.length, active: activeInitiativeId === initiative.id && !activeWorkstreamId, isArchived: Boolean(initiative.isArchived), detailOpen: detail?.type === 'initiative' && detail.item.id === initiative.id, canExpand: allWorkstreams.length > 0, expanded: expanded, controlsId: `planning-children-${initiative.id}`, onToggleExpand: () => onToggleInitiative(initiative.id), onToggleScope: () => onSelectInitiative(initiative.id), onOpenDetails: () => onOpenInitiativeDetails(initiative.id), favorite: planningFavoriteKeys.has(getPlanningFavoriteKey({ type: 'initiative', id: initiative.id })), favoriteReady: navigatorSortReady, onToggleFavorite: () => onTogglePlanningFavorite({ type: 'initiative', id: initiative.id }), onArchiveReady: onArchiveResolvedInitiative
|
|
507
502
|
? () => onArchiveResolvedInitiative(initiative.id)
|
|
508
|
-
: undefined }), expanded && displayedWorkstreams.length > 0 && (_jsx("ul", { id: `planning-children-${initiative.id}`, className: panelStyles.treeChildren, "aria-label": `Workstreams in ${initiative.title}`, children: displayedWorkstreams.map((workstream) => (_jsxs("li", { children: [_jsx(PlanningRow, { rowId: workstream.id, rowType: "workstream", referenceLabel: formatWorkstreamReference(workstream), item: workstream, ownerOption: workstream.ownerId ? assigneeOptionByValue.get(workstream.ownerId) : undefined, ownerOptions: assigneeOptions, onChangeOwner: (ownerId) => onChangePlanningOwner('workstream', workstream.id, ownerId === 'unassigned' ? '' : ownerId), active: activeWorkstreamId === workstream.id, isArchived: Boolean(workstream.isArchived), detailOpen: (detail?.type === 'workstream' && detail.item.id === workstream.id)
|
|
503
|
+
: undefined }), expanded && displayedWorkstreams.length > 0 && (_jsx("ul", { id: `planning-children-${initiative.id}`, className: `${panelStyles.treeChildren} ${panelStyles.treeWorkstreamChildren}`.trim(), "aria-label": `Workstreams in ${initiative.title}`, children: displayedWorkstreams.map((workstream) => (_jsxs("li", { children: [_jsx(PlanningRow, { rowId: workstream.id, rowType: "workstream", referenceLabel: formatWorkstreamReference(workstream), item: workstream, ownerOption: workstream.ownerId ? assigneeOptionByValue.get(workstream.ownerId) : undefined, ownerOptions: assigneeOptions, onChangeOwner: (ownerId) => onChangePlanningOwner('workstream', workstream.id, ownerId === 'unassigned' ? '' : ownerId), onChangeIdentity: (patch) => onChangePlanningIdentity('workstream', workstream.id, patch), active: activeWorkstreamId === workstream.id, isArchived: Boolean(workstream.isArchived), detailOpen: (detail?.type === 'workstream' && detail.item.id === workstream.id)
|
|
509
504
|
|| (secondaryPane?.kind === 'detail' && secondaryPane.detail.item.id === workstream.id), canExpand: (workstream.tasks || []).length > 0, expanded: expandedWorkstreamIds.has(workstream.id), controlsId: `planning-tasks-${workstream.id}`, onToggleExpand: () => toggleWorkstreamTasks(workstream.id), onToggleScope: () => onSelectWorkstream(workstream.id, initiative.id), onOpenDetails: () => {
|
|
510
505
|
onOpenInitiativeDetails(initiative.id);
|
|
511
506
|
onOpenNestedWorkstreamDetails(workstream.id);
|
|
512
507
|
}, favorite: planningFavoriteKeys.has(getPlanningFavoriteKey({ type: 'workstream', id: workstream.id })), favoriteReady: navigatorSortReady, onToggleFavorite: () => onTogglePlanningFavorite({ type: 'workstream', id: workstream.id }), onArchiveReady: onArchiveResolvedWorkstream
|
|
513
508
|
? () => onArchiveResolvedWorkstream(workstream.id)
|
|
514
509
|
: undefined }), renderWorkstreamTasks(workstream)] }, workstream.id))) }))] }, initiative.id));
|
|
515
|
-
}) })) : null] }), _jsxs("div", { className: panelStyles.sectionGroup, children: [_jsx(DisclosureSectionHeader, { label: "Workstreams", count: navigatorResults.standaloneWorkstreams.length, showZeroCount: true, actions: (planningLoadState.collections.workstreams === 'ready' ? (_jsx("button", { type: "button", className: "tf-control-icon", title: "Create workstream", "aria-label": "Create workstream", onClick: onCreateWorkstream, children: _jsx(Plus, { size: 15 }) })) : null), expanded: !workstreamsSectionCollapsed, expandedTitle: "Collapse workstreams", collapsedTitle: "Expand workstreams", onToggle: onToggleWorkstreamsSection, controlsId: !workstreamsSectionCollapsed ? 'planning-workstreams-section' : undefined }), !workstreamsSectionCollapsed ? (_jsx("ul", { id: "planning-workstreams-section", className: panelStyles.treeList, "aria-label": "Standalone workstreams", children: planningLoadState.collections.workstreams === 'error' ? (_jsx("li", { children: _jsx(PlanningFailureState, { compact: true, title: "Workstreams unavailable", message: "Workstreams could not be loaded.", retrying: planningLoadState.isRefreshing, onRetry: onRetryPlanning }) })) : navigatorResults.standaloneWorkstreams.length === 0 ? (_jsxs("li", { className: panelStyles.emptyPanel, children: [_jsx("div", { className: panelStyles.emptyPanelTitle, children: workstreamEmptyTitle }), _jsx("div", { className: panelStyles.emptyPanelText, children: workstreamEmptyText })] })) : navigatorResults.standaloneWorkstreams.map((workstream) => (_jsxs("li", { children: [_jsx(PlanningRow, { rowId: workstream.id, rowType: "workstream", referenceLabel: formatWorkstreamReference(workstream), item: workstream, ownerOption: workstream.ownerId ? assigneeOptionByValue.get(workstream.ownerId) : undefined, ownerOptions: assigneeOptions, onChangeOwner: (ownerId) => onChangePlanningOwner('workstream', workstream.id, ownerId === 'unassigned' ? '' : ownerId), active: activeWorkstreamId === workstream.id, isArchived: Boolean(workstream.isArchived), detailOpen: (detail?.type === 'workstream' && detail.item.id === workstream.id)
|
|
510
|
+
}) })) : null] }), _jsxs("div", { className: panelStyles.sectionGroup, children: [_jsx(DisclosureSectionHeader, { label: "Workstreams", count: navigatorResults.standaloneWorkstreams.length, showZeroCount: true, actions: (planningLoadState.collections.workstreams === 'ready' ? (_jsx("button", { type: "button", className: "tf-control-icon", title: "Create workstream", "aria-label": "Create workstream", onClick: onCreateWorkstream, children: _jsx(Plus, { size: 15 }) })) : null), expanded: !workstreamsSectionCollapsed, expandedTitle: "Collapse workstreams", collapsedTitle: "Expand workstreams", onToggle: onToggleWorkstreamsSection, controlsId: !workstreamsSectionCollapsed ? 'planning-workstreams-section' : undefined }), !workstreamsSectionCollapsed ? (_jsx("ul", { id: "planning-workstreams-section", className: panelStyles.treeList, "aria-label": "Standalone workstreams", children: planningLoadState.collections.workstreams === 'error' ? (_jsx("li", { children: _jsx(PlanningFailureState, { compact: true, title: "Workstreams unavailable", message: "Workstreams could not be loaded.", retrying: planningLoadState.isRefreshing, onRetry: onRetryPlanning }) })) : navigatorResults.standaloneWorkstreams.length === 0 ? (_jsxs("li", { className: panelStyles.emptyPanel, children: [_jsx("div", { className: panelStyles.emptyPanelTitle, children: workstreamEmptyTitle }), _jsx("div", { className: panelStyles.emptyPanelText, children: workstreamEmptyText })] })) : navigatorResults.standaloneWorkstreams.map((workstream) => (_jsxs("li", { children: [_jsx(PlanningRow, { rowId: workstream.id, rowType: "workstream", referenceLabel: formatWorkstreamReference(workstream), item: workstream, ownerOption: workstream.ownerId ? assigneeOptionByValue.get(workstream.ownerId) : undefined, ownerOptions: assigneeOptions, onChangeOwner: (ownerId) => onChangePlanningOwner('workstream', workstream.id, ownerId === 'unassigned' ? '' : ownerId), onChangeIdentity: (patch) => onChangePlanningIdentity('workstream', workstream.id, patch), active: activeWorkstreamId === workstream.id, isArchived: Boolean(workstream.isArchived), detailOpen: (detail?.type === 'workstream' && detail.item.id === workstream.id)
|
|
516
511
|
|| (secondaryPane?.kind === 'detail' && secondaryPane.detail.item.id === workstream.id), canExpand: (workstream.tasks || []).length > 0, expanded: expandedWorkstreamIds.has(workstream.id), controlsId: `planning-tasks-${workstream.id}`, onToggleExpand: () => toggleWorkstreamTasks(workstream.id), onToggleScope: () => onSelectWorkstream(workstream.id, null), onOpenDetails: () => onOpenWorkstreamDetails(workstream.id), favorite: planningFavoriteKeys.has(getPlanningFavoriteKey({ type: 'workstream', id: workstream.id })), favoriteReady: navigatorSortReady, onToggleFavorite: () => onTogglePlanningFavorite({ type: 'workstream', id: workstream.id }), onArchiveReady: onArchiveResolvedWorkstream
|
|
517
512
|
? () => onArchiveResolvedWorkstream(workstream.id)
|
|
518
513
|
: undefined, initiativeLinkOptions: linkOptions.initiatives, onLinkInitiative: (option) => onAssignInitiativeToWorkstream(workstream.id, option.referenceLabel) }), renderWorkstreamTasks(workstream)] }, workstream.id))) })) : null] })] }))] }));
|
|
@@ -523,10 +518,9 @@ function PlanningLoadingState() {
|
|
|
523
518
|
function PlanningFailureState({ title, message, retrying, onRetry, compact = false, }) {
|
|
524
519
|
return (_jsxs("div", { className: `${panelStyles.failureState} ${compact ? panelStyles.failureStateCompact : ''} tf-surface-inset`.trim(), role: "alert", children: [_jsxs("div", { className: panelStyles.failureCopy, children: [_jsx("strong", { children: title }), _jsx("span", { children: message })] }), _jsx("button", { type: "button", className: "tf-button-ghost tf-button-compact", disabled: retrying, onClick: onRetry, children: retrying ? 'Retrying…' : 'Retry' })] }));
|
|
525
520
|
}
|
|
526
|
-
function PlanningDrawerDetailView({ detail, showArchivedChildren, inlineEditor, selectedChildWorkstreamId, currentWorkspaceId, currentActorId, theme, onOpenNestedWorkstreamDetails, onArchivePlanningTask, onArchiveResolvedWorkstream, onArchiveResolvedEntity, onEdit, onChangeOwner, onChangePlanningOwner, onArchive, onUnarchive, onCreateTaskInWorkstream, onCreateWorkstreamInInitiative, onOpenTaskById, onChangeTaskAssignee, taskReferences, onAssignTaskToWorkstream, onAssignInitiativeToWorkstream, onAttachTaskToWorkstreamByReference, onAttachWorkstreamToInitiativeByReference, onAddPlanningContextFile, onRemovePlanningContextFile, onUpdatePlanningContextCaption, parentInitiative = null, assigneeOptions, linkOptions, showTaskCardStatusLabel = false, taskArrangeMode = 'execution', onTaskArrangeModeChange = () => { }, onReorderWorkstreamTasks, onSetTaskStatus, hydrationState, onRetryHydration, }) {
|
|
521
|
+
function PlanningDrawerDetailView({ detail, showArchivedChildren, inlineEditor, selectedChildWorkstreamId, currentWorkspaceId, currentActorId, theme, onOpenNestedWorkstreamDetails, onArchivePlanningTask, onArchiveResolvedWorkstream, onArchiveResolvedEntity, onEdit, onChangeOwner, onChangePlanningOwner, onChangePlanningIdentity, onArchive, onUnarchive, onCreateTaskInWorkstream, onCreateWorkstreamInInitiative, onOpenTaskById, onChangeTaskAssignee, taskReferences, onAssignTaskToWorkstream, onAssignInitiativeToWorkstream, onAttachTaskToWorkstreamByReference, onAttachWorkstreamToInitiativeByReference, onAddPlanningContextFile, onRemovePlanningContextFile, onUpdatePlanningContextCaption, parentInitiative = null, assigneeOptions, linkOptions, showTaskCardStatusLabel = false, taskArrangeMode = 'execution', onTaskArrangeModeChange = () => { }, onReorderWorkstreamTasks, onSetTaskStatus, hydrationState, onRetryHydration, }) {
|
|
527
522
|
const inlineEditorFormId = React.useId();
|
|
528
523
|
const [isAttachingReference, setIsAttachingReference] = React.useState(false);
|
|
529
|
-
const [showParentLinkPicker, setShowParentLinkPicker] = React.useState(false);
|
|
530
524
|
const [pendingUnlink, setPendingUnlink] = React.useState(null);
|
|
531
525
|
const [relationshipRecovery, setRelationshipRecovery] = React.useState(null);
|
|
532
526
|
const [isChangingRelationship, setIsChangingRelationship] = React.useState(false);
|
|
@@ -595,7 +589,6 @@ function PlanningDrawerDetailView({ detail, showArchivedChildren, inlineEditor,
|
|
|
595
589
|
: `Archive ${detailLabel.toLowerCase()}`;
|
|
596
590
|
React.useEffect(() => {
|
|
597
591
|
setIsAttachingReference(false);
|
|
598
|
-
setShowParentLinkPicker(false);
|
|
599
592
|
setPendingUnlink(null);
|
|
600
593
|
setRelationshipRecovery(null);
|
|
601
594
|
setIsChangingRelationship(false);
|
|
@@ -663,9 +656,7 @@ function PlanningDrawerDetailView({ detail, showArchivedChildren, inlineEditor,
|
|
|
663
656
|
return;
|
|
664
657
|
setIsChangingRelationship(true);
|
|
665
658
|
try {
|
|
666
|
-
|
|
667
|
-
if (result !== false)
|
|
668
|
-
setShowParentLinkPicker(false);
|
|
659
|
+
await onAssignInitiativeToWorkstream(detail.item.id, option.referenceLabel);
|
|
669
660
|
}
|
|
670
661
|
finally {
|
|
671
662
|
setIsChangingRelationship(false);
|
|
@@ -767,7 +758,7 @@ function PlanningDrawerDetailView({ detail, showArchivedChildren, inlineEditor,
|
|
|
767
758
|
});
|
|
768
759
|
}, title: "Unlink workstream from initiative", ariaLabel: "Unlink workstream from initiative", children: _jsx(Unlink, { size: 14, "aria-hidden": "true" }) })) : null] })) : null })) : null, detail.type === 'workstream'
|
|
769
760
|
&& !parentInitiativeReferenceLabel
|
|
770
|
-
&& !inlineEditor ? (_jsx(
|
|
761
|
+
&& !inlineEditor ? (_jsx(PlanningLinkPicker, { options: linkOptions.initiatives, entityLabel: "initiative", onSelect: handleLinkInitiative, disabled: !onAssignInitiativeToWorkstream || isChangingRelationship, iconTrigger: true, triggerTitle: "Link initiative" })) : null, _jsx(PlanningReferenceBadge, { label: detailReferenceLabel || 'Reference pending', entityType: detail.type, entityName: detail.item.title, pending: !detailReferenceLabel })] }), _jsx("div", { className: panelStyles.detailTopActions, children: inlineEditor ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: "tf-button-ghost tf-button-compact", onClick: inlineEditor.onCancel, disabled: inlineEditor.isSubmitting, children: "Cancel" }), _jsx("button", { type: "submit", form: inlineEditorFormId, className: "tf-button-primary tf-button-compact", disabled: inlineEditor.isSubmitting, children: inlineEditor.isSubmitting ? 'Saving…' : 'Save' })] })) : (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: "tf-control-icon", disabled: archiveDetailState.mode === 'blocked' || archiveDetailState.mode === 'checking', onClick: () => {
|
|
771
762
|
if (archiveDetailState.mode === 'archived') {
|
|
772
763
|
onUnarchive?.();
|
|
773
764
|
}
|
|
@@ -781,10 +772,9 @@ function PlanningDrawerDetailView({ detail, showArchivedChildren, inlineEditor,
|
|
|
781
772
|
? archiveEntityConfirmationVisible
|
|
782
773
|
: undefined, children: archiveDetailState.mode === 'archived'
|
|
783
774
|
? _jsx(RotateCcw, { size: 14, "aria-hidden": "true" })
|
|
784
|
-
: _jsx(Archive, { size: 14, "aria-hidden": "true" }) }), _jsx("button", { type: "button", className: "tf-control-icon", onClick: () => {
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
}, title: `Edit ${detailLabel.toLowerCase()} details`, "aria-label": `Edit ${detailLabel.toLowerCase()} details`, children: _jsx(Pencil, { size: 14, "aria-hidden": "true" }) })] })) })] }), archiveEntityConfirmationVisible && archiveDetailState.mode === 'ready' ? (_jsx(PlanningArchiveConfirmation, { entityType: detail.type, title: detail.item.title, activeTaskCount: detail.item.archiveActiveTaskCount, activeWorkstreamCount: detail.item.archiveActiveWorkstreamCount, busy: archiveEntityBusy, onCancel: () => setArchiveEntityConfirmationVisible(false), onConfirm: () => void handleConfirmArchiveEntity() })) : null, detail.type === 'workstream' ? renderRelationshipFeedback('workstream', detail.item.id) : null, detail.type === 'workstream' && !parentInitiativeReferenceLabel && showParentLinkPicker ? (_jsxs("div", { className: panelStyles.relationshipPickerRow, role: "group", "aria-label": "Link workstream to initiative", children: [_jsx(PlanningLinkPicker, { options: linkOptions.initiatives, entityLabel: "initiative", onSelect: handleLinkInitiative, disabled: !onAssignInitiativeToWorkstream || isChangingRelationship }), _jsx("button", { type: "button", className: "tf-control-icon tf-control-icon-compact", disabled: isChangingRelationship, onClick: () => setShowParentLinkPicker(false), title: "Cancel initiative link", "aria-label": "Cancel initiative link", children: _jsx(X, { size: 14, "aria-hidden": "true" }) })] })) : null, inlineEditor ? (_jsx(PlanningDrawerEditor, { editor: inlineEditor.editor, draftTitle: inlineEditor.draftTitle, draftDescription: inlineEditor.draftDescription, draftOwner: inlineEditor.draftOwner, draftInitiativeId: inlineEditor.draftInitiativeId, assigneeOptions: assigneeOptions, initiativeLinkOptions: linkOptions.initiatives, draftInitiativeSummary: inlineEditor.draftInitiativeSummary, onChangeDraftTitle: inlineEditor.onChangeDraftTitle, onChangeDraftDescription: inlineEditor.onChangeDraftDescription, onChangeDraftOwner: inlineEditor.onChangeDraftOwner, onChangeDraftInitiativeId: inlineEditor.onChangeDraftInitiativeId, onCancel: inlineEditor.onCancel, onSubmit: inlineEditor.onSubmit, isSubmitting: inlineEditor.isSubmitting, inline: true, formId: inlineEditorFormId })) : (_jsxs(_Fragment, { children: [_jsx("h3", { className: panelStyles.detailTitle, children: detail.item.title }), _jsx(PlanningEntityDescription, { description: detail.item.description, label: detailLabel, taskReferences: taskReferences, className: `${panelStyles.detailDescription} ${styles.appScrollbar} tf-scrollbar`.trim(), markdownClassName: panelStyles.detailDescriptionMarkdown })] })), _jsxs("div", { className: panelStyles.detailOwnerField, children: [_jsx("span", { className: panelStyles.detailOwnerLabel, children: "Owner" }), _jsx(PlanningOwnerDropdown, { value: ownerValue, disabled: !onChangeOwner || isSavingOwner, onChange: (nextOwnerId) => void handleOwnerChange(nextOwnerId), ariaLabel: `${detailLabel} owner`, options: assigneeOptions, className: `${planningDropdownStyles.control} ${panelStyles.ownerSelect}` })] }), detail.item.taskCount > 0 ? (_jsx(PlanningProgress, { value: detail.item.progressPercent, label: `${detail.item.progressPercent}% resolved`, statusCounts: detail.item.statusCounts })) : (_jsx(PlanningNoTasks, {})), _jsx(PlanningSummaryMeta, { item: detail.item, workstreamCount: detail.type === 'initiative'
|
|
775
|
+
: _jsx(Archive, { size: 14, "aria-hidden": "true" }) }), _jsx("button", { type: "button", className: "tf-control-icon", onClick: onEdit, title: `Edit ${detailLabel.toLowerCase()} details`, "aria-label": `Edit ${detailLabel.toLowerCase()} details`, children: _jsx(Pencil, { size: 14, "aria-hidden": "true" }) })] })) })] }), archiveEntityConfirmationVisible && archiveDetailState.mode === 'ready' ? (_jsx(PlanningArchiveConfirmation, { entityType: detail.type, title: detail.item.title, activeTaskCount: detail.item.archiveActiveTaskCount, activeWorkstreamCount: detail.item.archiveActiveWorkstreamCount, busy: archiveEntityBusy, onCancel: () => setArchiveEntityConfirmationVisible(false), onConfirm: () => void handleConfirmArchiveEntity() })) : null, detail.type === 'workstream' ? renderRelationshipFeedback('workstream', detail.item.id) : null, inlineEditor ? (_jsx(PlanningDrawerEditor, { editor: inlineEditor.editor, draftTitle: inlineEditor.draftTitle, draftDescription: inlineEditor.draftDescription, draftOwner: inlineEditor.draftOwner, draftInitiativeId: inlineEditor.draftInitiativeId, assigneeOptions: assigneeOptions, initiativeLinkOptions: linkOptions.initiatives, draftInitiativeSummary: inlineEditor.draftInitiativeSummary, onChangeDraftTitle: inlineEditor.onChangeDraftTitle, onChangeDraftDescription: inlineEditor.onChangeDraftDescription, onChangeDraftOwner: inlineEditor.onChangeDraftOwner, onChangeDraftInitiativeId: inlineEditor.onChangeDraftInitiativeId, onCancel: inlineEditor.onCancel, onSubmit: inlineEditor.onSubmit, isSubmitting: inlineEditor.isSubmitting, inline: true, formId: inlineEditorFormId })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: panelStyles.detailTitleRow, children: [_jsx(PlanningVisualIdentity, { entityType: detail.type, entityId: detail.item.id, icon: detail.item.icon, color: detail.item.color, size: "detail", disabled: Boolean(detail.item.isArchived), onChange: onChangePlanningIdentity
|
|
776
|
+
? (patch) => onChangePlanningIdentity(detail.type, detail.item.id, patch)
|
|
777
|
+
: undefined }), _jsx("h3", { className: panelStyles.detailTitle, children: detail.item.title })] }), _jsx(PlanningEntityDescription, { description: detail.item.description, label: detailLabel, taskReferences: taskReferences, className: `${panelStyles.detailDescription} ${styles.appScrollbar} tf-scrollbar`.trim(), markdownClassName: panelStyles.detailDescriptionMarkdown })] })), _jsxs("div", { className: panelStyles.detailOwnerField, children: [_jsx("span", { className: panelStyles.detailOwnerLabel, children: "Owner" }), _jsx(PlanningOwnerDropdown, { value: ownerValue, disabled: !onChangeOwner || isSavingOwner, onChange: (nextOwnerId) => void handleOwnerChange(nextOwnerId), ariaLabel: `${detailLabel} owner`, options: assigneeOptions, className: `${planningDropdownStyles.control} ${panelStyles.ownerSelect}` })] }), detail.item.taskCount > 0 ? (_jsx(PlanningProgress, { value: detail.item.progressPercent, label: `${detail.item.progressPercent}% resolved`, statusCounts: detail.item.statusCounts })) : (_jsx(PlanningNoTasks, {})), _jsx(PlanningSummaryMeta, { item: detail.item, workstreamCount: detail.type === 'initiative'
|
|
788
778
|
? detail.item.workstreamCount ?? detail.item.workstreams.length
|
|
789
779
|
: undefined, className: panelStyles.detailSummaryMeta }), detail.item.taskCount > 0 ? (_jsx("span", { className: panelStyles.passiveGuidance, children: "Lifetime progress includes archived tasks." })) : null] }), _jsxs("div", { ref: setChildDropRef, className: `${panelStyles.listCard} ${canDropTask || canDropWorkstream ? panelStyles.sectionDropReady : ''} ${isChildDropOver ? panelStyles.sectionDropActive : ''} ${canDropTask || canDropWorkstream ? panelStyles.sectionDropMode : ''}`.trim(), children: [_jsxs("div", { className: panelStyles.sectionHeaderRow, children: [_jsxs("div", { className: panelStyles.sectionTitle, children: [childLabel, " (", visibleChildCount, ")"] }), _jsx("div", { className: panelStyles.headerActionGroup, children: detail.type === 'initiative' ? (_jsx("button", { type: "button", className: "tf-control-icon", title: "Create workstream in this initiative", "aria-label": "Create workstream in this initiative", onClick: () => onCreateWorkstreamInInitiative?.(detail.item.id), children: _jsx(Plus, { size: 15 }) })) : (_jsx("button", { type: "button", className: "tf-control-icon", title: "Create task in this workstream", "aria-label": "Create task in this workstream", onClick: () => onCreateTaskInWorkstream?.(detail.item.id), children: _jsx(Plus, { size: 15 }) })) })] }), _jsx("div", { className: panelStyles.linkPickerRow, children: _jsx(PlanningLinkPicker, { options: availableLinkOptions, entityLabel: detail.type === 'initiative' ? 'workstream' : 'task', onSelect: handleAttachReference, disabled: !hasAttachReferenceHandler || isAttachingReference }) }), detail.type === 'workstream' ? (_jsx(PlanningTaskArrangeControl, { value: taskArrangeMode, onChange: onTaskArrangeModeChange })) : null, detail.type === 'initiative' ? (visibleChildItems.length > 0 ? visibleChildItems.map((workstream) => {
|
|
790
780
|
const workstreamReferenceLabel = formatWorkstreamReference(workstream);
|
|
@@ -822,6 +812,8 @@ function PlanningDrawerDetailView({ detail, showArchivedChildren, inlineEditor,
|
|
|
822
812
|
? toPlanningAssigneeOption(assigneeOptionByValue.get(workstream.ownerId))
|
|
823
813
|
: undefined, ownerOptions: assigneeOptions.map(toPlanningAssigneeOption), onChangeOwner: onChangePlanningOwner
|
|
824
814
|
? (ownerId) => onChangePlanningOwner('workstream', workstream.id, ownerId === 'unassigned' ? '' : ownerId)
|
|
815
|
+
: undefined, onChangeIdentity: onChangePlanningIdentity
|
|
816
|
+
? (patch) => onChangePlanningIdentity('workstream', workstream.id, patch)
|
|
825
817
|
: undefined }) })] }) }, workstream.id));
|
|
826
818
|
}) : (_jsx("div", { className: panelStyles.passiveGuidance, children: "No workstreams are linked to this initiative." }))) : (visibleTaskItems.length > 0 ? (_jsx(PlanningTaskOrderList, { tasks: visibleTaskItems, mode: taskArrangeMode, onReorder: onReorderWorkstreamTasks
|
|
827
819
|
? (taskIds) => onReorderWorkstreamTasks(detail.item.id, mergeVisiblePlanningTaskOrder(arrangePlanningTasks(taskItems, 'execution'), taskIds))
|
|
@@ -855,7 +847,7 @@ function PlanningDrawerDetailView({ detail, showArchivedChildren, inlineEditor,
|
|
|
855
847
|
}, title: "Archive task", "aria-label": `Archive task ${referenceLabel || task.title}`, children: _jsx(Archive, { size: 14, "aria-hidden": "true" }) })) : undefined }) }, task.id));
|
|
856
848
|
} })) : (_jsx("div", { className: panelStyles.passiveGuidance, children: "No tasks are linked to this workstream." }))), detachedRelationshipRecovery] }), _jsx("div", { className: panelStyles.listCard, children: _jsx(PlanningEntityContext, { entityType: detail.type, entityId: detail.item.id, referenceLabel: detailReferenceLabel, workspaceId: currentWorkspaceId, attachments: detail.item.attachments, readOnly: Boolean(detail.item.isArchived), onAddAttachment: (file) => onAddPlanningContextFile?.(detail.type, detail.item.id, file), onRemoveAttachment: (index) => onRemovePlanningContextFile?.(detail.type, detail.item.id, index), onUpdateAttachmentCaption: (index, caption) => (onUpdatePlanningContextCaption?.(detail.type, detail.item.id, index, caption)) }) }), _jsx("div", { className: panelStyles.listCard, children: _jsx(PlanningEntityActivity, { entityType: detail.type, item: detail.item, assigneeOptions: assigneeOptions.map(toPlanningAssigneeOption), currentActorId: currentActorId, taskReferences: taskReferences, parentInitiative: parentInitiative, listClassName: panelStyles.activityTimelineList, emptyClassName: panelStyles.activityTimelineEmpty, hydrationState: hydrationState, onRetryHydration: onRetryHydration }) }), _jsx(PlanningUnlinkConfirmation, { item: pendingUnlink, busy: isChangingRelationship, theme: theme, onCancel: () => setPendingUnlink(null), onConfirm: () => void handleConfirmUnlink() })] }));
|
|
857
849
|
}
|
|
858
|
-
function PlanningDrawerEditor({ editor, draftTitle, draftDescription, draftOwner, draftInitiativeId, assigneeOptions, initiativeLinkOptions, draftInitiativeSummary, onChangeDraftTitle, onChangeDraftDescription, onChangeDraftOwner, onChangeDraftInitiativeId, onCancel, onSubmit, isSubmitting, inline = false, formId, }) {
|
|
850
|
+
function PlanningDrawerEditor({ editor, draftTitle, draftDescription, draftOwner, draftInitiativeId, draftIcon, draftColor, assigneeOptions, initiativeLinkOptions, draftInitiativeSummary, onChangeDraftTitle, onChangeDraftDescription, onChangeDraftOwner, onChangeDraftInitiativeId, onChangeDraftIcon, onChangeDraftColor, onCancel, onSubmit, isSubmitting, inline = false, formId, }) {
|
|
859
851
|
const entityLabel = editor.entityType === 'initiative' ? 'Initiative' : 'Workstream';
|
|
860
852
|
const titleInputId = React.useId();
|
|
861
853
|
const titleErrorId = React.useId();
|
|
@@ -881,7 +873,12 @@ function PlanningDrawerEditor({ editor, draftTitle, draftDescription, draftOwner
|
|
|
881
873
|
event.preventDefault();
|
|
882
874
|
onCancel();
|
|
883
875
|
}, [inline, isSubmitting, onCancel]);
|
|
884
|
-
return (_jsxs("form", { id: formId, className: `${panelStyles.editorCard} ${inline ? panelStyles.inlineEditorCard : ''}`.trim(), onSubmit: handleSubmit, onKeyDown: handleKeyDown, noValidate: true, children: [
|
|
876
|
+
return (_jsxs("form", { id: formId, className: `${panelStyles.editorCard} ${inline ? panelStyles.inlineEditorCard : ''}`.trim(), onSubmit: handleSubmit, onKeyDown: handleKeyDown, noValidate: true, children: [editor.mode === 'create' && onChangeDraftIcon && onChangeDraftColor ? (_jsxs("div", { className: panelStyles.editorIdentityField, children: [_jsx(PlanningVisualIdentity, { entityType: editor.entityType, entityId: "create-preview", icon: draftIcon, color: draftColor || 'blue', size: "detail", onChange: (patch) => {
|
|
877
|
+
if (Object.prototype.hasOwnProperty.call(patch, 'icon'))
|
|
878
|
+
onChangeDraftIcon(patch.icon ?? null);
|
|
879
|
+
if (Object.prototype.hasOwnProperty.call(patch, 'color'))
|
|
880
|
+
onChangeDraftColor(patch.color ?? null);
|
|
881
|
+
} }), _jsx("span", { children: "Choose an icon and color" })] })) : null, _jsxs("div", { className: panelStyles.editorField, children: [_jsxs("label", { className: panelStyles.editorLabel, htmlFor: titleInputId, children: [entityLabel, " title"] }), _jsx("input", { ref: titleInputRef, id: titleInputId, "data-planning-editor-title": true, className: styles.input, disabled: isSubmitting, required: true, "aria-invalid": titleError ? 'true' : undefined, "aria-describedby": titleError ? titleErrorId : undefined, value: draftTitle, onChange: (event) => {
|
|
885
882
|
if (titleError)
|
|
886
883
|
setTitleError(null);
|
|
887
884
|
onChangeDraftTitle(event.target.value);
|
|
@@ -889,7 +886,7 @@ function PlanningDrawerEditor({ editor, draftTitle, draftDescription, draftOwner
|
|
|
889
886
|
? 'Describe the broader outcome this initiative is meant to achieve.'
|
|
890
887
|
: 'Describe the lane of work this workstream will coordinate.', rows: 5 })] }), editor.entityType === 'workstream' && (_jsxs("div", { className: panelStyles.editorField, children: [_jsx("span", { className: panelStyles.editorLabel, children: "Initiative" }), _jsxs("div", { className: panelStyles.editorRelationshipRow, children: [_jsx(PlanningLinkPicker, { options: initiativeLinkOptions, selectedId: draftInitiativeSummary?.id || '', entityLabel: "initiative", disabled: isSubmitting, onSelect: (option) => onChangeDraftInitiativeId(option.referenceLabel) }), draftInitiativeId.trim() ? (_jsx("button", { type: "button", className: "tf-button-ghost tf-button-compact", disabled: isSubmitting, onClick: () => onChangeDraftInitiativeId(''), children: "Remove" })) : null] })] })), !inline ? _jsxs("div", { className: panelStyles.editorField, children: [_jsxs("span", { className: panelStyles.editorLabel, children: [entityLabel, " owner"] }), _jsx(PlanningOwnerDropdown, { disabled: isSubmitting, value: draftOwner, onChange: onChangeDraftOwner, ariaLabel: `${entityLabel} owner`, options: assigneeOptions, className: panelStyles.editorSelect })] }) : null, !inline ? _jsxs("div", { className: panelStyles.editorActions, children: [_jsx("button", { type: "button", className: styles.secondaryHeaderBtn, onClick: onCancel, disabled: isSubmitting, children: "Cancel" }), _jsx("button", { type: "submit", className: styles.primaryUpdateBtn, disabled: isSubmitting, children: submitLabel })] }) : null] }));
|
|
891
888
|
}
|
|
892
|
-
export function PlanningDrawer({ open, leftOffset = 0, returnFocusRef, onWidthChange, initiatives, standaloneWorkstreams, planningLoadState, onRetryPlanning, taskScope, activeInitiativeId, activeWorkstreamId, navigatorSort, navigatorSortReady, onNavigatorSortChange, taskArrangeMode = 'execution', onTaskArrangeModeChange = () => { }, onReorderWorkstreamTasks, planningFavorites, onTogglePlanningFavorite, favoritesSectionCollapsed, initiativesSectionCollapsed, workstreamsSectionCollapsed, onToggleFavoritesSection, onToggleInitiativesSection, onToggleWorkstreamsSection, expandedInitiativeIds, detail, editor, secondaryEditor = null, secondaryPane, primaryHydrationState, secondaryHydrationState, onRetryPrimaryHydration, onRetrySecondaryHydration, currentWorkspaceId, currentOwnerId, theme, assigneeOptions, linkOptions, showTaskCardStatusLabel = false, draftInitiativeSummary, draftTitle, draftDescription, draftOwner, draftInitiativeId, onChangeDraftTitle, onChangeDraftDescription, onChangeDraftOwner, onChangeDraftInitiativeId, onCollapseTreePane, onExpandTreePane, onCollapsePrimaryPane, onExpandPrimaryPane, onCollapseSecondaryPane, onExpandSecondaryPane, onBackFromSecondary, treeCollapsed, primaryCollapsed, secondaryCollapsed, onCancelEditor, onCancelSecondaryEditor, onSubmitEditor, isSubmittingEditor, onCreateInitiative, onCreateWorkstream, onToggleInitiative, onSelectInitiative, onSelectWorkstream, onOpenInitiativeDetails, onOpenWorkstreamDetails, onOpenNestedWorkstreamDetails, onEditInitiative, onEditWorkstream, onChangePlanningOwner, onChangeTaskAssignee, onArchiveInitiative, onUnarchiveInitiative, onArchiveWorkstream, onUnarchiveWorkstream, onArchivePlanningTask, onArchiveResolvedWorkstream, onArchiveResolvedInitiative, onCreateTaskInWorkstream, onCreateWorkstreamInInitiative, onAssignInitiativeToWorkstream, onOpenTaskById, onSetTaskStatus, taskReferences, onAssignTaskToWorkstream, onAttachTaskToWorkstreamByReference, onAttachWorkstreamToInitiativeByReference, onAddPlanningContextFile, onRemovePlanningContextFile, onUpdatePlanningContextCaption, }) {
|
|
889
|
+
export function PlanningDrawer({ open, leftOffset = 0, returnFocusRef, onWidthChange, initiatives, standaloneWorkstreams, planningLoadState, onRetryPlanning, taskScope, activeInitiativeId, activeWorkstreamId, navigatorSort, navigatorSortReady, onNavigatorSortChange, taskArrangeMode = 'execution', onTaskArrangeModeChange = () => { }, onReorderWorkstreamTasks, planningFavorites, onTogglePlanningFavorite, favoritesSectionCollapsed, initiativesSectionCollapsed, workstreamsSectionCollapsed, onToggleFavoritesSection, onToggleInitiativesSection, onToggleWorkstreamsSection, expandedInitiativeIds, detail, editor, secondaryEditor = null, secondaryPane, primaryHydrationState, secondaryHydrationState, onRetryPrimaryHydration, onRetrySecondaryHydration, currentWorkspaceId, currentOwnerId, theme, assigneeOptions, linkOptions, showTaskCardStatusLabel = false, draftInitiativeSummary, draftTitle, draftDescription, draftOwner, draftInitiativeId, draftIcon = null, draftColor = null, onChangeDraftTitle, onChangeDraftDescription, onChangeDraftOwner, onChangeDraftInitiativeId, onChangeDraftIcon = () => { }, onChangeDraftColor = () => { }, onCollapseTreePane, onExpandTreePane, onCollapsePrimaryPane, onExpandPrimaryPane, onCollapseSecondaryPane, onExpandSecondaryPane, onBackFromSecondary, treeCollapsed, primaryCollapsed, secondaryCollapsed, onCancelEditor, onCancelSecondaryEditor, onSubmitEditor, isSubmittingEditor, onCreateInitiative, onCreateWorkstream, onToggleInitiative, onSelectInitiative, onSelectWorkstream, onOpenInitiativeDetails, onOpenWorkstreamDetails, onOpenNestedWorkstreamDetails, onEditInitiative, onEditWorkstream, onChangePlanningOwner, onChangePlanningIdentity = () => { }, onChangeTaskAssignee, onArchiveInitiative, onUnarchiveInitiative, onArchiveWorkstream, onUnarchiveWorkstream, onArchivePlanningTask, onArchiveResolvedWorkstream, onArchiveResolvedInitiative, onCreateTaskInWorkstream, onCreateWorkstreamInInitiative, onAssignInitiativeToWorkstream, onOpenTaskById, onSetTaskStatus, taskReferences, onAssignTaskToWorkstream, onAttachTaskToWorkstreamByReference, onAttachWorkstreamToInitiativeByReference, onAddPlanningContextFile, onRemovePlanningContextFile, onUpdatePlanningContextCaption, }) {
|
|
893
890
|
const primaryInlineEditor = editor?.mode === 'edit'
|
|
894
891
|
&& detail
|
|
895
892
|
&& editor.entityType === detail.type
|
|
@@ -1088,7 +1085,7 @@ export function PlanningDrawer({ open, leftOffset = 0, returnFocusRef, onWidthCh
|
|
|
1088
1085
|
pointerEvents: open ? 'auto' : 'none',
|
|
1089
1086
|
transition: 'left 220ms cubic-bezier(0.4, 0, 0.2, 1)',
|
|
1090
1087
|
willChange: 'left',
|
|
1091
|
-
}, children: _jsxs("div", { className: panelStyles.drawerBody, children: [showTreePane && (effectiveTreeCollapsed ? (_jsx(CollapsedPane, { label: "Planning", onExpand: onExpandTreePane })) : (_jsxs("div", { ref: treePaneRef, "data-planning-pane": "tree", className: `${panelStyles.paneShell} ${styles.appScrollbar} tf-scrollbar ${panelStyles.treePane} ${hasPrimaryPane && !primaryCollapsed ? panelStyles.treePaneSplit : ''}`.trim(), style: paneWidthStyle(layoutMode === 'narrow' ? drawerWidth : PLANNING_DRAWER_TREE_WIDTH_PX), children: [_jsxs("div", { className: panelStyles.paneHeader, children: [_jsx("h2", { className: panelStyles.paneHeaderLabel, tabIndex: -1, "data-planning-pane-heading": true, children: "Planning" }), _jsxs("div", { className: panelStyles.headerActionGroup, children: [_jsx(ArchiveVisibilityToggle, { visible: showArchivedPlanning, disabled: taskScope === 'deleted' || archivedPlanningItemCount === 0, disabledLabel: taskScope === 'deleted' ? 'Archive visibility unavailable in Trash' : undefined, itemLabel: "planning items", onToggle: () => setShowArchivedPlanning((current) => !current) }), wideLayout ? (_jsx("button", { type: "button", className: "tf-control-icon", onClick: onCollapseTreePane, "aria-label": "Collapse Planning pane", title: "Collapse Planning pane", children: _jsx(ChevronLeft, { size: 16, "aria-hidden": "true" }) })) : null] })] }), _jsx("div", { className: panelStyles.paneContent, "aria-busy": planningLoadState.status === 'loading' || planningLoadState.isRefreshing, children: _jsx(PlanningDrawerList, { initiatives: initiatives, standaloneWorkstreams: standaloneWorkstreams, planningLoadState: planningLoadState, taskScope: taskScope, showArchivedPlanning: showArchivedPlanning, currentOwnerId: currentOwnerId, assigneeOptions: assigneeOptions, showTaskCardStatusLabel: showTaskCardStatusLabel, taskArrangeMode: taskArrangeMode, activeInitiativeId: activeInitiativeId, activeWorkstreamId: activeWorkstreamId, navigatorSort: navigatorSort, navigatorSortReady: navigatorSortReady, onNavigatorSortChange: onNavigatorSortChange, planningFavorites: planningFavorites, onTogglePlanningFavorite: onTogglePlanningFavorite, favoritesSectionCollapsed: favoritesSectionCollapsed, initiativesSectionCollapsed: initiativesSectionCollapsed, workstreamsSectionCollapsed: workstreamsSectionCollapsed, onToggleFavoritesSection: onToggleFavoritesSection, onToggleInitiativesSection: onToggleInitiativesSection, onToggleWorkstreamsSection: onToggleWorkstreamsSection, expandedInitiativeIds: expandedInitiativeIds, detail: detail, secondaryPane: secondaryPane, onCreateInitiative: onCreateInitiative, onCreateWorkstream: onCreateWorkstream, onToggleInitiative: onToggleInitiative, onSelectInitiative: onSelectInitiative, onSelectWorkstream: onSelectWorkstream, onOpenInitiativeDetails: onOpenInitiativeDetails, onOpenWorkstreamDetails: onOpenWorkstreamDetails, onOpenNestedWorkstreamDetails: onOpenNestedWorkstreamDetails, onOpenTaskById: onOpenTaskById, onSetTaskStatus: onSetTaskStatus, onChangePlanningOwner: onChangePlanningOwner, onChangeTaskAssignee: onChangeTaskAssignee, onArchivePlanningTask: onArchivePlanningTask, onArchiveResolvedWorkstream: onArchiveResolvedWorkstream, onArchiveResolvedInitiative: onArchiveResolvedInitiative, linkOptions: linkOptions, onAssignInitiativeToWorkstream: onAssignInitiativeToWorkstream, onRetryPlanning: onRetryPlanning }) })] }))), wideLayout && !primaryIsInitiative && (initiativeRelationshipExpanded ? (_jsx(RelationshipPane, { label: "Initiative", title: initiativeRelationship.title, description: initiativeRelationship.description, action: initiativeRelationship.action, onCollapse: () => setInitiativeRelationshipExpanded(false), paneRef: initiativeRelationshipPaneRef })) : (_jsx(CollapsedPane, { label: "Initiative", muted: !hasInitiativeRelationship, onExpand: () => setInitiativeRelationshipExpanded(true) }))), showPrimaryPane && (effectivePrimaryCollapsed ? (_jsx(CollapsedPane, { label: primaryEntityType === 'initiative' ? 'Initiative' : 'Workstream', onExpand: onExpandPrimaryPane })) : (_jsxs("div", { ref: primaryPaneRef, "data-planning-pane": "primary", className: `${panelStyles.paneShell} ${styles.appScrollbar} tf-scrollbar ${panelStyles.detailPane}`.trim(), style: paneWidthStyle(wideLayout ? PLANNING_DRAWER_DETAIL_WIDTH_PX : adaptiveDetailWidth), children: [_jsxs("div", { className: panelStyles.paneHeader, children: [layoutMode === 'narrow' ? (_jsx("button", { type: "button", className: "tf-control-icon", onClick: handleBackFromPrimary, "aria-label": "Back to Planning", title: "Back to Planning", children: _jsx(ChevronLeft, { size: 16, "aria-hidden": "true" }) })) : null, _jsx("h2", { className: panelStyles.paneHeaderLabel, tabIndex: -1, "data-planning-pane-heading": true, children: primaryPaneLabel }), _jsxs("div", { className: panelStyles.headerActionGroup, children: [primaryArchiveDetail ? (_jsx(ArchiveVisibilityToggle, { visible: archivedDetailVisibility[primaryArchiveDetail.type], disabled: countArchivedDetailChildren(primaryArchiveDetail) === 0, itemLabel: primaryArchiveDetail.type === 'initiative' ? 'workstreams' : 'tasks', onToggle: () => toggleArchivedDetailVisibility(primaryArchiveDetail.type) })) : null, wideLayout ? (_jsx("button", { type: "button", className: "tf-control-icon", onClick: onCollapsePrimaryPane, "aria-label": `Collapse ${primaryPaneLabel} pane`, title: `Collapse ${primaryPaneLabel} pane`, children: _jsx(ChevronLeft, { size: 16, "aria-hidden": "true" }) })) : null] })] }), _jsx("div", { className: panelStyles.paneContent, "aria-busy": primaryHydrationState?.status === 'loading', children: dedicatedPrimaryEditor ? (_jsx(PlanningDrawerEditor, { editor: dedicatedPrimaryEditor, draftTitle: draftTitle, draftDescription: draftDescription, draftOwner: draftOwner, draftInitiativeId: draftInitiativeId, assigneeOptions: assigneeOptions, initiativeLinkOptions: linkOptions.initiatives, draftInitiativeSummary: draftInitiativeSummary, onChangeDraftTitle: onChangeDraftTitle, onChangeDraftDescription: onChangeDraftDescription, onChangeDraftOwner: onChangeDraftOwner, onChangeDraftInitiativeId: onChangeDraftInitiativeId, onCancel: onCancelEditor, onSubmit: onSubmitEditor, isSubmitting: isSubmittingEditor })) : detail ? (_jsx(PlanningDrawerDetailView, { detail: detail, showArchivedChildren: archivedDetailVisibility[detail.type], inlineEditor: primaryInlineEditor ? {
|
|
1088
|
+
}, children: _jsxs("div", { className: panelStyles.drawerBody, children: [showTreePane && (effectiveTreeCollapsed ? (_jsx(CollapsedPane, { label: "Planning", onExpand: onExpandTreePane })) : (_jsxs("div", { ref: treePaneRef, "data-planning-pane": "tree", className: `${panelStyles.paneShell} ${styles.appScrollbar} tf-scrollbar ${panelStyles.treePane} ${hasPrimaryPane && !primaryCollapsed ? panelStyles.treePaneSplit : ''}`.trim(), style: paneWidthStyle(layoutMode === 'narrow' ? drawerWidth : PLANNING_DRAWER_TREE_WIDTH_PX), children: [_jsxs("div", { className: panelStyles.paneHeader, children: [_jsx("h2", { className: panelStyles.paneHeaderLabel, tabIndex: -1, "data-planning-pane-heading": true, children: "Planning" }), _jsxs("div", { className: panelStyles.headerActionGroup, children: [_jsx(ArchiveVisibilityToggle, { visible: showArchivedPlanning, disabled: taskScope === 'deleted' || archivedPlanningItemCount === 0, disabledLabel: taskScope === 'deleted' ? 'Archive visibility unavailable in Trash' : undefined, itemLabel: "planning items", onToggle: () => setShowArchivedPlanning((current) => !current) }), wideLayout ? (_jsx("button", { type: "button", className: "tf-control-icon", onClick: onCollapseTreePane, "aria-label": "Collapse Planning pane", title: "Collapse Planning pane", children: _jsx(ChevronLeft, { size: 16, "aria-hidden": "true" }) })) : null] })] }), _jsx("div", { className: panelStyles.paneContent, "aria-busy": planningLoadState.status === 'loading' || planningLoadState.isRefreshing, children: _jsx(PlanningDrawerList, { initiatives: initiatives, standaloneWorkstreams: standaloneWorkstreams, planningLoadState: planningLoadState, taskScope: taskScope, showArchivedPlanning: showArchivedPlanning, currentOwnerId: currentOwnerId, assigneeOptions: assigneeOptions, showTaskCardStatusLabel: showTaskCardStatusLabel, taskArrangeMode: taskArrangeMode, activeInitiativeId: activeInitiativeId, activeWorkstreamId: activeWorkstreamId, navigatorSort: navigatorSort, navigatorSortReady: navigatorSortReady, onNavigatorSortChange: onNavigatorSortChange, planningFavorites: planningFavorites, onTogglePlanningFavorite: onTogglePlanningFavorite, favoritesSectionCollapsed: favoritesSectionCollapsed, initiativesSectionCollapsed: initiativesSectionCollapsed, workstreamsSectionCollapsed: workstreamsSectionCollapsed, onToggleFavoritesSection: onToggleFavoritesSection, onToggleInitiativesSection: onToggleInitiativesSection, onToggleWorkstreamsSection: onToggleWorkstreamsSection, expandedInitiativeIds: expandedInitiativeIds, detail: detail, secondaryPane: secondaryPane, onCreateInitiative: onCreateInitiative, onCreateWorkstream: onCreateWorkstream, onToggleInitiative: onToggleInitiative, onSelectInitiative: onSelectInitiative, onSelectWorkstream: onSelectWorkstream, onOpenInitiativeDetails: onOpenInitiativeDetails, onOpenWorkstreamDetails: onOpenWorkstreamDetails, onOpenNestedWorkstreamDetails: onOpenNestedWorkstreamDetails, onOpenTaskById: onOpenTaskById, onSetTaskStatus: onSetTaskStatus, onChangePlanningOwner: onChangePlanningOwner, onChangePlanningIdentity: onChangePlanningIdentity, onChangeTaskAssignee: onChangeTaskAssignee, onArchivePlanningTask: onArchivePlanningTask, onArchiveResolvedWorkstream: onArchiveResolvedWorkstream, onArchiveResolvedInitiative: onArchiveResolvedInitiative, linkOptions: linkOptions, onAssignInitiativeToWorkstream: onAssignInitiativeToWorkstream, onRetryPlanning: onRetryPlanning }) })] }))), wideLayout && !primaryIsInitiative && (initiativeRelationshipExpanded ? (_jsx(RelationshipPane, { label: "Initiative", title: initiativeRelationship.title, description: initiativeRelationship.description, action: initiativeRelationship.action, onCollapse: () => setInitiativeRelationshipExpanded(false), paneRef: initiativeRelationshipPaneRef })) : (_jsx(CollapsedPane, { label: "Initiative", muted: !hasInitiativeRelationship, onExpand: () => setInitiativeRelationshipExpanded(true) }))), showPrimaryPane && (effectivePrimaryCollapsed ? (_jsx(CollapsedPane, { label: primaryEntityType === 'initiative' ? 'Initiative' : 'Workstream', onExpand: onExpandPrimaryPane })) : (_jsxs("div", { ref: primaryPaneRef, "data-planning-pane": "primary", className: `${panelStyles.paneShell} ${styles.appScrollbar} tf-scrollbar ${panelStyles.detailPane}`.trim(), style: paneWidthStyle(wideLayout ? PLANNING_DRAWER_DETAIL_WIDTH_PX : adaptiveDetailWidth), children: [_jsxs("div", { className: panelStyles.paneHeader, children: [layoutMode === 'narrow' ? (_jsx("button", { type: "button", className: "tf-control-icon", onClick: handleBackFromPrimary, "aria-label": "Back to Planning", title: "Back to Planning", children: _jsx(ChevronLeft, { size: 16, "aria-hidden": "true" }) })) : null, _jsx("h2", { className: panelStyles.paneHeaderLabel, tabIndex: -1, "data-planning-pane-heading": true, children: primaryPaneLabel }), _jsxs("div", { className: panelStyles.headerActionGroup, children: [primaryArchiveDetail ? (_jsx(ArchiveVisibilityToggle, { visible: archivedDetailVisibility[primaryArchiveDetail.type], disabled: countArchivedDetailChildren(primaryArchiveDetail) === 0, itemLabel: primaryArchiveDetail.type === 'initiative' ? 'workstreams' : 'tasks', onToggle: () => toggleArchivedDetailVisibility(primaryArchiveDetail.type) })) : null, wideLayout ? (_jsx("button", { type: "button", className: "tf-control-icon", onClick: onCollapsePrimaryPane, "aria-label": `Collapse ${primaryPaneLabel} pane`, title: `Collapse ${primaryPaneLabel} pane`, children: _jsx(ChevronLeft, { size: 16, "aria-hidden": "true" }) })) : null] })] }), _jsx("div", { className: panelStyles.paneContent, "aria-busy": primaryHydrationState?.status === 'loading', children: dedicatedPrimaryEditor ? (_jsx(PlanningDrawerEditor, { editor: dedicatedPrimaryEditor, draftTitle: draftTitle, draftDescription: draftDescription, draftOwner: draftOwner, draftInitiativeId: draftInitiativeId, draftIcon: draftIcon, draftColor: draftColor, assigneeOptions: assigneeOptions, initiativeLinkOptions: linkOptions.initiatives, draftInitiativeSummary: draftInitiativeSummary, onChangeDraftTitle: onChangeDraftTitle, onChangeDraftDescription: onChangeDraftDescription, onChangeDraftOwner: onChangeDraftOwner, onChangeDraftInitiativeId: onChangeDraftInitiativeId, onChangeDraftIcon: onChangeDraftIcon, onChangeDraftColor: onChangeDraftColor, onCancel: onCancelEditor, onSubmit: onSubmitEditor, isSubmitting: isSubmittingEditor })) : detail ? (_jsx(PlanningDrawerDetailView, { detail: detail, showArchivedChildren: archivedDetailVisibility[detail.type], inlineEditor: primaryInlineEditor ? {
|
|
1092
1089
|
editor: primaryInlineEditor,
|
|
1093
1090
|
draftTitle,
|
|
1094
1091
|
draftDescription,
|
|
@@ -1108,13 +1105,13 @@ export function PlanningDrawer({ open, leftOffset = 0, returnFocusRef, onWidthCh
|
|
|
1108
1105
|
? onArchiveResolvedInitiative
|
|
1109
1106
|
: onArchiveResolvedWorkstream, onOpenNestedWorkstreamDetails: detail.type === 'initiative' ? onOpenNestedWorkstreamDetails : undefined, onCreateTaskInWorkstream: detail.type === 'workstream' ? onCreateTaskInWorkstream : undefined, onCreateWorkstreamInInitiative: detail.type === 'initiative' ? onCreateWorkstreamInInitiative : undefined, onOpenTaskById: detail.type === 'workstream' ? onOpenTaskById : undefined, onChangeTaskAssignee: detail.type === 'workstream' ? onChangeTaskAssignee : undefined, taskReferences: taskReferences, onAssignTaskToWorkstream: detail.type === 'workstream' ? onAssignTaskToWorkstream : undefined, onAssignInitiativeToWorkstream: onAssignInitiativeToWorkstream, onAttachTaskToWorkstreamByReference: detail.type === 'workstream' ? onAttachTaskToWorkstreamByReference : undefined, onAttachWorkstreamToInitiativeByReference: detail.type === 'initiative' ? onAttachWorkstreamToInitiativeByReference : undefined, parentInitiative: detail.type === 'workstream' ? resolveParentInitiative(detail.item) : null, onEdit: () => detail.type === 'initiative'
|
|
1110
1107
|
? onEditInitiative(detail.item.id)
|
|
1111
|
-
: onEditWorkstream(detail.item.id), onChangeOwner: (ownerId) => onChangePlanningOwner(detail.type, detail.item.id, ownerId), onChangePlanningOwner: onChangePlanningOwner, onArchive: () => detail.type === 'initiative'
|
|
1108
|
+
: onEditWorkstream(detail.item.id), onChangeOwner: (ownerId) => onChangePlanningOwner(detail.type, detail.item.id, ownerId), onChangePlanningOwner: onChangePlanningOwner, onChangePlanningIdentity: onChangePlanningIdentity, onArchive: () => detail.type === 'initiative'
|
|
1112
1109
|
? onArchiveInitiative(detail.item.id)
|
|
1113
1110
|
: onArchiveWorkstream(detail.item.id), onUnarchive: () => detail.type === 'initiative'
|
|
1114
1111
|
? onUnarchiveInitiative(detail.item.id)
|
|
1115
1112
|
: onUnarchiveWorkstream(detail.item.id), onAddPlanningContextFile: onAddPlanningContextFile, onRemovePlanningContextFile: onRemovePlanningContextFile, onUpdatePlanningContextCaption: onUpdatePlanningContextCaption })) : null })] }))), wideLayout && !primaryIsWorkstream && !hasSecondaryPane && (workstreamRelationshipExpanded ? (_jsx(RelationshipPane, { label: "Workstream", title: workstreamRelationship.title, description: workstreamRelationship.description, action: workstreamRelationship.action, onCollapse: () => setWorkstreamRelationshipExpanded(false), paneRef: workstreamRelationshipPaneRef })) : (_jsx(CollapsedPane, { label: "Workstream", muted: true, onExpand: () => setWorkstreamRelationshipExpanded(true) }))), showSecondaryPane && (effectiveSecondaryCollapsed ? (_jsx(CollapsedPane, { label: "Workstream", onExpand: onExpandSecondaryPane })) : (_jsxs("div", { ref: secondaryPaneRef, "data-planning-pane": "secondary", className: `${panelStyles.paneShell} ${styles.appScrollbar} tf-scrollbar ${panelStyles.detailPane}`.trim(), style: paneWidthStyle(wideLayout ? PLANNING_DRAWER_DETAIL_WIDTH_PX : adaptiveDetailWidth), children: [_jsxs("div", { className: panelStyles.paneHeader, children: [!wideLayout ? (_jsx("button", { type: "button", className: "tf-control-icon", onClick: secondaryInlineEditor
|
|
1116
1113
|
? (onCancelSecondaryEditor || onBackFromSecondary)
|
|
1117
|
-
: onBackFromSecondary, "aria-label": secondaryInlineEditor ? 'Cancel workstream editing' : `Back to ${primaryPaneLabel}`, title: secondaryInlineEditor ? 'Cancel workstream editing' : `Back to ${primaryPaneLabel}`, children: _jsx(ChevronLeft, { size: 16, "aria-hidden": "true" }) })) : null, _jsx("h2", { className: panelStyles.paneHeaderLabel, tabIndex: -1, "data-planning-pane-heading": true, children: secondaryPaneLabel }), _jsxs("div", { className: panelStyles.headerActionGroup, children: [secondaryArchiveDetail ? (_jsx(ArchiveVisibilityToggle, { visible: archivedDetailVisibility.workstream, disabled: countArchivedDetailChildren(secondaryArchiveDetail) === 0, itemLabel: "tasks", onToggle: () => toggleArchivedDetailVisibility('workstream') })) : null, wideLayout ? (_jsx("button", { type: "button", className: "tf-control-icon", onClick: onCollapseSecondaryPane, "aria-label": `Collapse ${secondaryPaneLabel} pane`, title: `Collapse ${secondaryPaneLabel} pane`, children: _jsx(ChevronLeft, { size: 16, "aria-hidden": "true" }) })) : null] })] }), _jsx("div", { className: panelStyles.paneContent, "aria-busy": secondaryHydrationState?.status === 'loading', children: secondaryPane?.kind === 'editor' ? (_jsx(PlanningDrawerEditor, { editor: secondaryPane.editor, draftTitle: draftTitle, draftDescription: draftDescription, draftOwner: draftOwner, draftInitiativeId: draftInitiativeId, assigneeOptions: assigneeOptions, initiativeLinkOptions: linkOptions.initiatives, draftInitiativeSummary: draftInitiativeSummary, onChangeDraftTitle: onChangeDraftTitle, onChangeDraftDescription: onChangeDraftDescription, onChangeDraftOwner: onChangeDraftOwner, onChangeDraftInitiativeId: onChangeDraftInitiativeId, onCancel: onBackFromSecondary, onSubmit: onSubmitEditor, isSubmitting: isSubmittingEditor })) : secondaryPane ? (_jsx(PlanningDrawerDetailView, { detail: secondaryPane.detail, showArchivedChildren: archivedDetailVisibility.workstream, inlineEditor: secondaryInlineEditor ? {
|
|
1114
|
+
: onBackFromSecondary, "aria-label": secondaryInlineEditor ? 'Cancel workstream editing' : `Back to ${primaryPaneLabel}`, title: secondaryInlineEditor ? 'Cancel workstream editing' : `Back to ${primaryPaneLabel}`, children: _jsx(ChevronLeft, { size: 16, "aria-hidden": "true" }) })) : null, _jsx("h2", { className: panelStyles.paneHeaderLabel, tabIndex: -1, "data-planning-pane-heading": true, children: secondaryPaneLabel }), _jsxs("div", { className: panelStyles.headerActionGroup, children: [secondaryArchiveDetail ? (_jsx(ArchiveVisibilityToggle, { visible: archivedDetailVisibility.workstream, disabled: countArchivedDetailChildren(secondaryArchiveDetail) === 0, itemLabel: "tasks", onToggle: () => toggleArchivedDetailVisibility('workstream') })) : null, wideLayout ? (_jsx("button", { type: "button", className: "tf-control-icon", onClick: onCollapseSecondaryPane, "aria-label": `Collapse ${secondaryPaneLabel} pane`, title: `Collapse ${secondaryPaneLabel} pane`, children: _jsx(ChevronLeft, { size: 16, "aria-hidden": "true" }) })) : null] })] }), _jsx("div", { className: panelStyles.paneContent, "aria-busy": secondaryHydrationState?.status === 'loading', children: secondaryPane?.kind === 'editor' ? (_jsx(PlanningDrawerEditor, { editor: secondaryPane.editor, draftTitle: draftTitle, draftDescription: draftDescription, draftOwner: draftOwner, draftInitiativeId: draftInitiativeId, draftIcon: draftIcon, draftColor: draftColor, assigneeOptions: assigneeOptions, initiativeLinkOptions: linkOptions.initiatives, draftInitiativeSummary: draftInitiativeSummary, onChangeDraftTitle: onChangeDraftTitle, onChangeDraftDescription: onChangeDraftDescription, onChangeDraftOwner: onChangeDraftOwner, onChangeDraftInitiativeId: onChangeDraftInitiativeId, onChangeDraftIcon: onChangeDraftIcon, onChangeDraftColor: onChangeDraftColor, onCancel: onBackFromSecondary, onSubmit: onSubmitEditor, isSubmitting: isSubmittingEditor })) : secondaryPane ? (_jsx(PlanningDrawerDetailView, { detail: secondaryPane.detail, showArchivedChildren: archivedDetailVisibility.workstream, inlineEditor: secondaryInlineEditor ? {
|
|
1118
1115
|
editor: secondaryInlineEditor,
|
|
1119
1116
|
draftTitle,
|
|
1120
1117
|
draftDescription,
|
|
@@ -1128,5 +1125,5 @@ export function PlanningDrawer({ open, leftOffset = 0, returnFocusRef, onWidthCh
|
|
|
1128
1125
|
onCancel: onCancelSecondaryEditor || onBackFromSecondary,
|
|
1129
1126
|
onSubmit: onSubmitEditor,
|
|
1130
1127
|
isSubmitting: isSubmittingEditor,
|
|
1131
|
-
} : null, currentWorkspaceId: currentWorkspaceId, currentActorId: currentOwnerId, theme: theme, assigneeOptions: assigneeOptions, linkOptions: linkOptions, showTaskCardStatusLabel: showTaskCardStatusLabel, taskArrangeMode: taskArrangeMode, onTaskArrangeModeChange: onTaskArrangeModeChange, onReorderWorkstreamTasks: onReorderWorkstreamTasks, hydrationState: secondaryHydrationState, onRetryHydration: onRetrySecondaryHydration, onSetTaskStatus: onSetTaskStatus, onArchivePlanningTask: onArchivePlanningTask, onArchiveResolvedEntity: onArchiveResolvedWorkstream, onCreateTaskInWorkstream: onCreateTaskInWorkstream, onOpenTaskById: onOpenTaskById, onChangeTaskAssignee: onChangeTaskAssignee, taskReferences: taskReferences, onAssignTaskToWorkstream: onAssignTaskToWorkstream, onAssignInitiativeToWorkstream: onAssignInitiativeToWorkstream, onAttachTaskToWorkstreamByReference: onAttachTaskToWorkstreamByReference, parentInitiative: resolveParentInitiative(secondaryPane.detail.item), onEdit: () => onEditWorkstream(secondaryPane.detail.item.id), onChangeOwner: (ownerId) => onChangePlanningOwner('workstream', secondaryPane.detail.item.id, ownerId), onChangePlanningOwner: onChangePlanningOwner, onArchive: () => onArchiveWorkstream(secondaryPane.detail.item.id), onUnarchive: () => onUnarchiveWorkstream(secondaryPane.detail.item.id), onAddPlanningContextFile: onAddPlanningContextFile, onRemovePlanningContextFile: onRemovePlanningContextFile, onUpdatePlanningContextCaption: onUpdatePlanningContextCaption })) : null })] })))] }) }));
|
|
1128
|
+
} : null, currentWorkspaceId: currentWorkspaceId, currentActorId: currentOwnerId, theme: theme, assigneeOptions: assigneeOptions, linkOptions: linkOptions, showTaskCardStatusLabel: showTaskCardStatusLabel, taskArrangeMode: taskArrangeMode, onTaskArrangeModeChange: onTaskArrangeModeChange, onReorderWorkstreamTasks: onReorderWorkstreamTasks, hydrationState: secondaryHydrationState, onRetryHydration: onRetrySecondaryHydration, onSetTaskStatus: onSetTaskStatus, onArchivePlanningTask: onArchivePlanningTask, onArchiveResolvedEntity: onArchiveResolvedWorkstream, onCreateTaskInWorkstream: onCreateTaskInWorkstream, onOpenTaskById: onOpenTaskById, onChangeTaskAssignee: onChangeTaskAssignee, taskReferences: taskReferences, onAssignTaskToWorkstream: onAssignTaskToWorkstream, onAssignInitiativeToWorkstream: onAssignInitiativeToWorkstream, onAttachTaskToWorkstreamByReference: onAttachTaskToWorkstreamByReference, parentInitiative: resolveParentInitiative(secondaryPane.detail.item), onEdit: () => onEditWorkstream(secondaryPane.detail.item.id), onChangeOwner: (ownerId) => onChangePlanningOwner('workstream', secondaryPane.detail.item.id, ownerId), onChangePlanningOwner: onChangePlanningOwner, onChangePlanningIdentity: onChangePlanningIdentity, onArchive: () => onArchiveWorkstream(secondaryPane.detail.item.id), onUnarchive: () => onUnarchiveWorkstream(secondaryPane.detail.item.id), onAddPlanningContextFile: onAddPlanningContextFile, onRemovePlanningContextFile: onRemovePlanningContextFile, onUpdatePlanningContextCaption: onUpdatePlanningContextCaption })) : null })] })))] }) }));
|
|
1132
1129
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useState } from 'react';
|
|
2
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
3
3
|
import { CreditCard, KeyRound, Link2, RefreshCw, ShieldCheck, User } from 'lucide-react';
|
|
4
4
|
import { Modal } from '../../../ui/Modal';
|
|
5
5
|
import { EditableAvatarButton } from '../../../ui/EditableAvatarButton';
|
|
@@ -9,6 +9,7 @@ import styles from '../../../../Taskforce.module.css';
|
|
|
9
9
|
import settingsStyles from './AccountSettingsModal.module.css';
|
|
10
10
|
import { resolveCommercialLifecyclePresentation } from '../../../../utils/commercialLifecyclePresentation';
|
|
11
11
|
import { getPasswordPolicyGuidance, validatePasswordPolicy } from '../../../../shared/passwordPolicy';
|
|
12
|
+
import { PasswordInput } from '../../../ui/PasswordInput';
|
|
12
13
|
const PROVIDER_LABELS = {
|
|
13
14
|
password: 'Email & Password',
|
|
14
15
|
google: 'Google',
|
|
@@ -53,11 +54,7 @@ export function AccountSettingsModal({ isOpen, theme, displayName, email, avatar
|
|
|
53
54
|
const linkedProviders = new Set(loginMethods.map((method) => method.provider));
|
|
54
55
|
const hasPassword = linkedProviders.has('password');
|
|
55
56
|
const linkableProviders = availableAuthProviders.filter((provider) => provider !== 'password' && !linkedProviders.has(provider));
|
|
56
|
-
|
|
57
|
-
if (!isOpen)
|
|
58
|
-
return;
|
|
59
|
-
setActiveSection('profile');
|
|
60
|
-
setUnlinkError(null);
|
|
57
|
+
const clearCredentialState = useCallback(() => {
|
|
61
58
|
setShowAddPassword(false);
|
|
62
59
|
setAddPasswordValue('');
|
|
63
60
|
setAddPasswordError(null);
|
|
@@ -68,16 +65,28 @@ export function AccountSettingsModal({ isOpen, theme, displayName, email, avatar
|
|
|
68
65
|
setConfirmPasswordValue('');
|
|
69
66
|
setChangePasswordError(null);
|
|
70
67
|
setChangePasswordDone(false);
|
|
71
|
-
}, [
|
|
68
|
+
}, []);
|
|
69
|
+
const handleClose = () => {
|
|
70
|
+
clearCredentialState();
|
|
71
|
+
onClose();
|
|
72
|
+
};
|
|
73
|
+
const handleSectionChange = (section) => {
|
|
74
|
+
if (section !== 'security')
|
|
75
|
+
clearCredentialState();
|
|
76
|
+
setActiveSection(section);
|
|
77
|
+
};
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
setUnlinkError(null);
|
|
80
|
+
clearCredentialState();
|
|
81
|
+
if (!isOpen)
|
|
82
|
+
return;
|
|
83
|
+
setActiveSection('profile');
|
|
84
|
+
}, [clearCredentialState, isOpen]);
|
|
72
85
|
useEffect(() => {
|
|
73
86
|
if (activeSection === 'security')
|
|
74
87
|
return;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
setNewPasswordValue('');
|
|
78
|
-
setConfirmPasswordValue('');
|
|
79
|
-
setChangePasswordError(null);
|
|
80
|
-
}, [activeSection]);
|
|
88
|
+
clearCredentialState();
|
|
89
|
+
}, [activeSection, clearCredentialState]);
|
|
81
90
|
useEffect(() => {
|
|
82
91
|
if (!isOpen || activeSection !== 'security' || !cloudAuthEnabled)
|
|
83
92
|
return;
|
|
@@ -173,7 +182,7 @@ export function AccountSettingsModal({ isOpen, theme, displayName, email, avatar
|
|
|
173
182
|
setShowChangePassword(true);
|
|
174
183
|
setChangePasswordDone(false);
|
|
175
184
|
setChangePasswordError(null);
|
|
176
|
-
}, children: "Change password" }) })), showChangePassword && (_jsxs("div", { className: settingsStyles.addPasswordForm, children: [_jsxs("
|
|
185
|
+
}, children: "Change password" }) })), showChangePassword && (_jsxs("div", { className: settingsStyles.addPasswordForm, children: [_jsxs("div", { className: settingsStyles.fieldLabel, children: [_jsx("label", { htmlFor: "account-current-password", children: "Current password" }), _jsx(PasswordInput, { id: "account-current-password", className: styles.input, value: currentPasswordValue, onChange: (event) => setCurrentPasswordValue(event.target.value), disabled: changePasswordBusy, autoComplete: "current-password", visibilityLabel: "current password" })] }), _jsxs("div", { className: settingsStyles.fieldLabel, children: [_jsx("label", { htmlFor: "account-new-password", children: "New password" }), _jsx(PasswordInput, { id: "account-new-password", className: styles.input, value: newPasswordValue, onChange: (event) => setNewPasswordValue(event.target.value), disabled: changePasswordBusy, autoComplete: "new-password", visibilityLabel: "new password" })] }), _jsxs("div", { className: settingsStyles.fieldLabel, children: [_jsx("label", { htmlFor: "account-confirm-password", children: "Confirm new password" }), _jsx(PasswordInput, { id: "account-confirm-password", className: styles.input, value: confirmPasswordValue, onChange: (event) => setConfirmPasswordValue(event.target.value), disabled: changePasswordBusy, autoComplete: "new-password", visibilityLabel: "confirm new password" })] }), _jsx("p", { className: "tf-text-helper", children: addPasswordGuidance.join(' ') }), changePasswordError && _jsx("p", { className: "tf-text-error", role: "alert", children: changePasswordError }), _jsxs("div", { className: settingsStyles.inlineActions, children: [_jsx("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: () => {
|
|
177
186
|
setShowChangePassword(false);
|
|
178
187
|
setCurrentPasswordValue('');
|
|
179
188
|
setNewPasswordValue('');
|
|
@@ -183,15 +192,15 @@ export function AccountSettingsModal({ isOpen, theme, displayName, email, avatar
|
|
|
183
192
|
setShowAddPassword(true);
|
|
184
193
|
setAddPasswordDone(false);
|
|
185
194
|
setAddPasswordError(null);
|
|
186
|
-
}, children: "Add password login" }) })), showAddPassword && (_jsxs("div", { className: settingsStyles.addPasswordForm, children: [_jsxs("
|
|
195
|
+
}, children: "Add password login" }) })), showAddPassword && (_jsxs("div", { className: settingsStyles.addPasswordForm, children: [_jsxs("div", { className: settingsStyles.fieldLabel, children: [_jsx("label", { htmlFor: "account-add-password", children: "New password" }), _jsx(PasswordInput, { id: "account-add-password", className: styles.input, placeholder: "Use 12+ characters", value: addPasswordValue, onChange: (event) => setAddPasswordValue(event.target.value), disabled: addPasswordBusy, autoComplete: "new-password", visibilityLabel: "new password" })] }), _jsx("p", { className: "tf-text-helper", children: addPasswordGuidance.join(' ') }), addPasswordError && _jsx("p", { className: "tf-text-error", role: "alert", children: addPasswordError }), _jsxs("div", { className: settingsStyles.inlineActions, children: [_jsx("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: () => {
|
|
187
196
|
setShowAddPassword(false);
|
|
188
197
|
setAddPasswordValue('');
|
|
189
198
|
setAddPasswordError(null);
|
|
190
199
|
}, disabled: addPasswordBusy, children: "Cancel" }), _jsx("button", { type: "button", className: "tf-button-primary tf-button-compact", onClick: () => { void handleAddPassword(); }, disabled: addPasswordBusy || !addPasswordValue, children: addPasswordBusy ? 'Saving…' : 'Save password' })] })] })), !loginMethodsLoading && !loginMethodsError && linkableProviders.length > 0 && (_jsxs("div", { className: settingsStyles.linkProviderBlock, children: [_jsx("p", { className: "tf-label-micro", children: "Link another account" }), _jsx("div", { className: settingsStyles.inlineActions, children: linkableProviders.map((provider) => (_jsxs("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: () => onLinkProvider(provider), children: [_jsx(Link2, { size: 15 }), PROVIDER_LABELS[provider] || provider] }, provider))) })] }))] })] }));
|
|
191
200
|
const renderBillingSection = () => (_jsxs("section", { className: settingsStyles.section, "aria-labelledby": "account-billing-heading", children: [_jsxs("div", { className: settingsStyles.sectionHeader, children: [_jsxs("div", { children: [_jsx("h2", { className: "tf-heading-card", id: "account-billing-heading", children: "Plan & Billing" }), _jsx("p", { className: "tf-text-secondary", children: "Review your plan and open the secure billing portal." })] }), _jsxs("button", { type: "button", className: "tf-button-ghost tf-button-compact", onClick: onRefreshBilling, disabled: billingActionBusy || billingLoading, children: [_jsx(RefreshCw, { size: 14 }), "Refresh"] })] }), _jsxs("div", { className: `${settingsStyles.sectionCard} tf-surface-panel`, children: [billingLoading && _jsx("p", { className: "tf-text-secondary", children: "Loading billing status\u2026" }), billingError && _jsx("p", { className: "tf-text-error", role: "alert", children: billingError }), billingActionError && _jsx("p", { className: "tf-text-error", role: "alert", children: billingActionError }), billingNotice && _jsx("p", { className: "tf-text-secondary", role: "status", children: billingNotice }), _jsxs("div", { className: settingsStyles.planSummary, children: [_jsxs("div", { children: [_jsx("p", { className: "tf-label-micro", children: "Current plan" }), _jsx("strong", { className: settingsStyles.planName, children: resolvedPlanLabel })] }), _jsx("span", { className: `tf-chip ${lifecyclePresentation.isActive ? 'tf-chip-success' : 'tf-chip-neutral'}`, children: formatStatusLabel(accountProfileSummary?.entitlementState) })] }), lifecyclePresentation.message && (_jsx("p", { className: lifecyclePresentation.statusTone === 'error' ? 'tf-text-error' : 'tf-text-secondary', children: lifecyclePresentation.message })), accountProfileSummary?.stripeSubscriptionId && (_jsxs("div", { className: settingsStyles.intervalRow, children: [_jsxs("label", { className: settingsStyles.fieldLabel, children: [_jsx("span", { children: "Billing interval" }), _jsxs("select", { className: styles.input, value: billingIntervalChoice, onChange: (event) => onBillingIntervalChange(event.target.value === 'year' ? 'year' : 'month'), disabled: billingActionBusy, children: [_jsx("option", { value: "month", children: "Monthly" }), _jsx("option", { value: "year", children: "Yearly" })] })] }), _jsx("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: onUpdateInterval, disabled: billingActionBusy, children: "Update interval" })] })), _jsxs("div", { className: settingsStyles.sectionActions, children: [(lifecyclePresentation.primaryAction === 'manage_billing' || lifecyclePresentation.primaryAction === 'none') && (_jsx("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: onOpenPlans, disabled: billingActionBusy, children: "View plans" })), lifecyclePresentation.showManageBilling && lifecyclePresentation.primaryAction !== 'manage_billing' && (_jsx("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: onManageBilling, disabled: billingActionBusy, children: "Manage billing" })), lifecyclePresentation.primaryLabel && (_jsx("button", { type: "button", className: "tf-button-primary tf-button-compact", onClick: handlePrimaryBillingAction, disabled: billingActionBusy, children: billingActionBusy ? 'Working…' : lifecyclePresentation.primaryLabel }))] })] })] }));
|
|
192
|
-
return (_jsx(Modal, { isOpen: isOpen, onClose:
|
|
201
|
+
return (_jsx(Modal, { isOpen: isOpen, onClose: handleClose, title: "Account Settings", size: "mdWide", theme: theme, draggable: true, children: _jsx("div", { className: `${modalStyles.form} ${settingsStyles.modalBody}`, children: _jsxs("div", { className: settingsStyles.layout, children: [_jsx("div", { className: settingsStyles.sectionTabs, role: "tablist", "aria-label": "Account settings sections", "aria-orientation": "vertical", children: SECTION_META.map((section) => {
|
|
193
202
|
const Icon = section.icon;
|
|
194
203
|
const selected = section.id === activeSection;
|
|
195
|
-
return (_jsxs("button", { type: "button", role: "tab", id: `account-settings-tab-${section.id}`, "aria-controls": `account-settings-panel-${section.id}`, "aria-selected": selected, className: settingsStyles.sectionTab, onClick: () =>
|
|
204
|
+
return (_jsxs("button", { type: "button", role: "tab", id: `account-settings-tab-${section.id}`, "aria-controls": `account-settings-panel-${section.id}`, "aria-selected": selected, className: settingsStyles.sectionTab, onClick: () => handleSectionChange(section.id), children: [_jsx(Icon, { size: 16 }), _jsx("span", { children: section.label })] }, section.id));
|
|
196
205
|
}) }), _jsxs("div", { className: settingsStyles.sectionPanel, role: "tabpanel", id: `account-settings-panel-${activeSection}`, "aria-labelledby": `account-settings-tab-${activeSection}`, children: [activeSection === 'profile' && renderProfileSection(), activeSection === 'security' && renderSecuritySection(), activeSection === 'billing' && renderBillingSection()] })] }) }) }));
|
|
197
206
|
}
|