@manta-eu/react 0.2.0 → 0.3.0
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/components/channel-icon/index.d.ts +1 -0
- package/dist/components/channel-icon/index.d.ts.map +1 -1
- package/dist/components/channel-icon/index.js +1 -1
- package/dist/components/channel-icon/index.js.map +1 -1
- package/dist/components/datastore-management/tree.d.ts +1 -1
- package/dist/components/datastore-management/tree.d.ts.map +1 -1
- package/dist/components/datastore-management/tree.js +5 -5
- package/dist/components/datastore-management/tree.js.map +1 -1
- package/dist/components/explain-fact/ExplainFact.js +3 -3
- package/dist/components/explain-fact/ExplainFact.js.map +1 -1
- package/dist/components/planning/ActioningView.d.ts +1 -2
- package/dist/components/planning/ActioningView.d.ts.map +1 -1
- package/dist/components/planning/ActioningView.js +19 -44
- package/dist/components/planning/ActioningView.js.map +1 -1
- package/dist/components/planning/ManualActionCard.d.ts +4 -0
- package/dist/components/planning/ManualActionCard.d.ts.map +1 -1
- package/dist/components/planning/ManualActionCard.js +7 -5
- package/dist/components/planning/ManualActionCard.js.map +1 -1
- package/dist/components/planning/ManualActionList.d.ts +4 -0
- package/dist/components/planning/ManualActionList.d.ts.map +1 -1
- package/dist/components/planning/ManualActionList.js +8 -2
- package/dist/components/planning/ManualActionList.js.map +1 -1
- package/dist/components/planning/actioning-view-utils.d.ts +9 -0
- package/dist/components/planning/actioning-view-utils.d.ts.map +1 -1
- package/dist/components/planning/actioning-view-utils.js +19 -1
- package/dist/components/planning/actioning-view-utils.js.map +1 -1
- package/dist/components/planning/plan-detail-utils.d.ts.map +1 -1
- package/dist/components/planning/plan-detail-utils.js +2 -0
- package/dist/components/planning/plan-detail-utils.js.map +1 -1
- package/dist/components/tool-invocation-card/ListRulesResultDisplay.d.ts +2 -2
- package/dist/components/tool-invocation-card/ListRulesResultDisplay.d.ts.map +1 -1
- package/dist/components/tool-invocation-card/ToolOutputRenderer.d.ts.map +1 -1
- package/dist/components/tool-invocation-card/ToolOutputRenderer.js +7 -4
- package/dist/components/tool-invocation-card/ToolOutputRenderer.js.map +1 -1
- package/dist/components/tool-invocation-card/types.d.ts +5 -5
- package/dist/components/tool-invocation-card/types.d.ts.map +1 -1
- package/dist/components/tool-invocation-card/types.js +5 -5
- package/dist/components/tool-invocation-card/types.js.map +1 -1
- package/dist/components/tooltip/index.d.ts +7 -0
- package/dist/components/tooltip/index.d.ts.map +1 -1
- package/dist/components/tooltip/index.js +10 -1
- package/dist/components/tooltip/index.js.map +1 -1
- package/dist/explain-fact/rule-presentation.js +2 -2
- package/dist/explain-fact/rule-presentation.js.map +1 -1
- package/dist/explain-fact/tree-model.js +2 -2
- package/dist/explain-fact/tree-model.js.map +1 -1
- package/dist/globals.css +19 -6
- package/dist/graph/entity-link.d.ts +14 -0
- package/dist/graph/entity-link.d.ts.map +1 -0
- package/dist/graph/entity-link.js +12 -0
- package/dist/graph/entity-link.js.map +1 -0
- package/dist/graph/graph-list-utils.d.ts +1 -0
- package/dist/graph/graph-list-utils.d.ts.map +1 -1
- package/dist/graph/graph-list-utils.js +1 -0
- package/dist/graph/graph-list-utils.js.map +1 -1
- package/dist/graph/graph-model.d.ts.map +1 -1
- package/dist/graph/graph-model.js +14 -5
- package/dist/graph/graph-model.js.map +1 -1
- package/dist/graph/nodes/BrandAssetAnalysisView.d.ts.map +1 -1
- package/dist/graph/nodes/BrandAssetAnalysisView.js +2 -1
- package/dist/graph/nodes/BrandAssetAnalysisView.js.map +1 -1
- package/dist/graph/nodes/BrandFontSuggestionView.d.ts.map +1 -1
- package/dist/graph/nodes/BrandFontSuggestionView.js +2 -1
- package/dist/graph/nodes/BrandFontSuggestionView.js.map +1 -1
- package/dist/graph/nodes/BrandGuidelinesView.js +1 -1
- package/dist/graph/nodes/BrandGuidelinesView.js.map +1 -1
- package/dist/graph/nodes/NodePropertyTable.d.ts +4 -2
- package/dist/graph/nodes/NodePropertyTable.d.ts.map +1 -1
- package/dist/graph/nodes/NodePropertyTable.js +12 -59
- package/dist/graph/nodes/NodePropertyTable.js.map +1 -1
- package/dist/graph/nodes/node-property-row.d.ts +30 -0
- package/dist/graph/nodes/node-property-row.d.ts.map +1 -0
- package/dist/graph/nodes/node-property-row.js +35 -0
- package/dist/graph/nodes/node-property-row.js.map +1 -0
- package/dist/graph/property-formatters.d.ts +1 -0
- package/dist/graph/property-formatters.d.ts.map +1 -1
- package/dist/graph/property-formatters.js +4 -1
- package/dist/graph/property-formatters.js.map +1 -1
- package/dist/graph/special-nodes/AttributeList.d.ts +27 -0
- package/dist/graph/special-nodes/AttributeList.d.ts.map +1 -0
- package/dist/graph/special-nodes/AttributeList.js +57 -0
- package/dist/graph/special-nodes/AttributeList.js.map +1 -0
- package/dist/graph/special-nodes/EntityPreview.d.ts +5 -0
- package/dist/graph/special-nodes/EntityPreview.d.ts.map +1 -0
- package/dist/graph/special-nodes/EntityPreview.js +19 -0
- package/dist/graph/special-nodes/EntityPreview.js.map +1 -0
- package/dist/graph/special-nodes/EntityValueChip.d.ts +11 -0
- package/dist/graph/special-nodes/EntityValueChip.d.ts.map +1 -0
- package/dist/graph/special-nodes/EntityValueChip.js +40 -0
- package/dist/graph/special-nodes/EntityValueChip.js.map +1 -0
- package/dist/graph/special-nodes/GenericView.d.ts +2 -1
- package/dist/graph/special-nodes/GenericView.d.ts.map +1 -1
- package/dist/graph/special-nodes/GenericView.js +23 -69
- package/dist/graph/special-nodes/GenericView.js.map +1 -1
- package/dist/graph/special-nodes/card-facts.d.ts +52 -0
- package/dist/graph/special-nodes/card-facts.d.ts.map +1 -0
- package/dist/graph/special-nodes/card-facts.js +189 -0
- package/dist/graph/special-nodes/card-facts.js.map +1 -0
- package/dist/graph/special-nodes/property-icons.d.ts +9 -0
- package/dist/graph/special-nodes/property-icons.d.ts.map +1 -0
- package/dist/graph/special-nodes/property-icons.js +39 -0
- package/dist/graph/special-nodes/property-icons.js.map +1 -0
- package/dist/graph/status-utils.d.ts +16 -0
- package/dist/graph/status-utils.d.ts.map +1 -1
- package/dist/graph/status-utils.js +35 -0
- package/dist/graph/status-utils.js.map +1 -1
- package/dist/graph/types.d.ts +5 -0
- package/dist/graph/types.d.ts.map +1 -1
- package/dist/hooks/use-approve-anyway.d.ts +12 -0
- package/dist/hooks/use-approve-anyway.d.ts.map +1 -0
- package/dist/hooks/use-approve-anyway.js +81 -0
- package/dist/hooks/use-approve-anyway.js.map +1 -0
- package/dist/hooks/use-connection-problems.d.ts.map +1 -1
- package/dist/hooks/useValidateActionPlan.d.ts.map +1 -1
- package/dist/ldo-ui.d.ts +2 -1
- package/dist/ldo-ui.d.ts.map +1 -1
- package/dist/ldo-ui.js +1 -0
- package/dist/ldo-ui.js.map +1 -1
- package/dist/lib/find-latest-staged-rule.js +1 -1
- package/dist/lib/find-latest-staged-rule.js.map +1 -1
- package/dist/lib/manual-actions.d.ts +2 -1
- package/dist/lib/manual-actions.d.ts.map +1 -1
- package/dist/lib/manual-actions.js +3 -2
- package/dist/lib/manual-actions.js.map +1 -1
- package/dist/lib/tool-icons.js +6 -6
- package/dist/lib/tool-icons.js.map +1 -1
- package/dist/lib/tool-names.d.ts.map +1 -1
- package/dist/lib/tool-names.js +0 -1
- package/dist/lib/tool-names.js.map +1 -1
- package/dist/ontology/skolem.js +2 -2
- package/dist/ontology/skolem.js.map +1 -1
- package/dist/providers/ActiveChatProvider.js +3 -1
- package/dist/providers/ActiveChatProvider.js.map +1 -1
- package/dist/providers/ChatManagerProvider.d.ts.map +1 -1
- package/dist/providers/ChatManagerProvider.js +3 -1
- package/dist/providers/ChatManagerProvider.js.map +1 -1
- package/dist/providers/KnowledgeGraphStateProvider.js +1 -1
- package/dist/providers/KnowledgeGraphStateProvider.js.map +1 -1
- package/dist/providers/chat-socket-auth.d.ts +7 -2
- package/dist/providers/chat-socket-auth.d.ts.map +1 -1
- package/dist/providers/chat-socket-auth.js +87 -16
- package/dist/providers/chat-socket-auth.js.map +1 -1
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +8 -1
- package/dist/providers/index.js.map +1 -1
- package/dist/routes/activity/detail/ActivityChanges.d.ts +2 -0
- package/dist/routes/activity/detail/ActivityChanges.d.ts.map +1 -1
- package/dist/routes/activity/detail/ActivityChanges.js +8 -7
- package/dist/routes/activity/detail/ActivityChanges.js.map +1 -1
- package/dist/routes/activity/detail/ActivityDetail.d.ts +1 -0
- package/dist/routes/activity/detail/ActivityDetail.d.ts.map +1 -1
- package/dist/routes/activity/detail/ActivityDetail.js +5 -4
- package/dist/routes/activity/detail/ActivityDetail.js.map +1 -1
- package/dist/routes/activity/detail/ActivityStepsRail.d.ts +1 -0
- package/dist/routes/activity/detail/ActivityStepsRail.d.ts.map +1 -1
- package/dist/routes/activity/detail/ActivityStepsRail.js +3 -2
- package/dist/routes/activity/detail/ActivityStepsRail.js.map +1 -1
- package/dist/routes/activity/detail/ActivityTimeline.js +2 -2
- package/dist/routes/activity/detail/ActivityTimeline.js.map +1 -1
- package/dist/routes/activity/detail/NoChangesMessage.d.ts +6 -0
- package/dist/routes/activity/detail/NoChangesMessage.d.ts.map +1 -0
- package/dist/routes/activity/detail/NoChangesMessage.js +10 -0
- package/dist/routes/activity/detail/NoChangesMessage.js.map +1 -0
- package/dist/routes/data-explorer/class-properties.js +2 -2
- package/dist/routes/data-explorer/class-properties.js.map +1 -1
- package/dist/routes/data-explorer/classes.js +2 -2
- package/dist/routes/data-explorer/classes.js.map +1 -1
- package/dist/routes/data-explorer/components/RawTriples.js +1 -1
- package/dist/routes/data-explorer/components/RawTriples.js.map +1 -1
- package/dist/routes/data-explorer/components/RecentTypes.js +1 -1
- package/dist/routes/data-explorer/components/RecentTypes.js.map +1 -1
- package/dist/routes/data-explorer/components/class-detail/Instances.js +1 -1
- package/dist/routes/data-explorer/components/class-detail/Instances.js.map +1 -1
- package/dist/routes/data-explorer/components/namespace-detail/NamespaceClassRow.js +1 -1
- package/dist/routes/data-explorer/components/namespace-detail/NamespaceClassRow.js.map +1 -1
- package/dist/routes/data-explorer/components/ontology-coverage/CoverageTermColumns.js +1 -1
- package/dist/routes/data-explorer/components/ontology-coverage/CoverageTermColumns.js.map +1 -1
- package/dist/routes/data-explorer/components/ontology-coverage/UnobservedRuleVocabulary.js +1 -1
- package/dist/routes/data-explorer/components/ontology-coverage/UnobservedRuleVocabulary.js.map +1 -1
- package/dist/routes/data-explorer/components/record-detail/ChatPreview.js +2 -2
- package/dist/routes/data-explorer/components/record-detail/ChatPreview.js.map +1 -1
- package/dist/routes/data-explorer/recents.js +1 -1
- package/dist/routes/data-explorer/recents.js.map +1 -1
- package/dist/routes/data-explorer/shapes.js +2 -2
- package/dist/routes/data-explorer/shapes.js.map +1 -1
- package/dist/routes/integrations/components/connect-forms/CanvaConnectForm.d.ts +3 -0
- package/dist/routes/integrations/components/connect-forms/CanvaConnectForm.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/CanvaConnectForm.js +12 -0
- package/dist/routes/integrations/components/connect-forms/CanvaConnectForm.js.map +1 -0
- package/dist/routes/integrations/components/connect-forms/DataConnectionConnectForm.d.ts.map +1 -1
- package/dist/routes/integrations/components/connect-forms/DataConnectionConnectForm.js +13 -6
- package/dist/routes/integrations/components/connect-forms/DataConnectionConnectForm.js.map +1 -1
- package/dist/routes/integrations/components/connect-forms/data-connection-fields.d.ts +3 -0
- package/dist/routes/integrations/components/connect-forms/data-connection-fields.d.ts.map +1 -1
- package/dist/routes/integrations/components/connect-forms/data-connection-fields.js +9 -2
- package/dist/routes/integrations/components/connect-forms/data-connection-fields.js.map +1 -1
- package/dist/routes/integrations/connect-forms.d.ts +1 -0
- package/dist/routes/integrations/connect-forms.d.ts.map +1 -1
- package/dist/routes/integrations/connect-forms.js +1 -0
- package/dist/routes/integrations/connect-forms.js.map +1 -1
- package/dist/routes/integrations/connection-view.d.ts.map +1 -1
- package/dist/routes/integrations/connection-view.js +1 -0
- package/dist/routes/integrations/connection-view.js.map +1 -1
- package/dist/routes/integrations/types.d.ts +2 -1
- package/dist/routes/integrations/types.d.ts.map +1 -1
- package/dist/routes/integrations/types.js +1 -0
- package/dist/routes/integrations/types.js.map +1 -1
- package/dist/routes/plans/components/ActionPlanPage.d.ts.map +1 -1
- package/dist/routes/plans/components/ActionPlanPage.js +4 -7
- package/dist/routes/plans/components/ActionPlanPage.js.map +1 -1
- package/dist/routes/plans/components/PlanDetailRouteContent.d.ts.map +1 -1
- package/dist/routes/plans/components/PlanDetailRouteContent.js +2 -1
- package/dist/routes/plans/components/PlanDetailRouteContent.js.map +1 -1
- package/dist/routes/rules/hooks/useRuleFactsPreview.js +4 -4
- package/dist/routes/rules/hooks/useRuleFactsPreview.js.map +1 -1
- package/dist/shacl/form-appearance.d.ts +1 -1
- package/dist/shacl/form-appearance.d.ts.map +1 -1
- package/dist/shacl/form-appearance.js +1 -1
- package/dist/shacl/form-appearance.js.map +1 -1
- package/dist/shared/graph-derived-queries.js +2 -2
- package/dist/shared/graph-derived-queries.js.map +1 -1
- package/package.json +12 -7
- package/src/app-subpaths.json +1 -0
- package/src/components/channel-icon/index.tsx +1 -1
- package/src/components/datastore-management/tree.ts +5 -5
- package/src/components/explain-fact/ExplainFact.tsx +3 -3
- package/src/components/planning/ActioningView.tsx +62 -70
- package/src/components/planning/ManualActionCard.tsx +66 -14
- package/src/components/planning/ManualActionList.tsx +30 -11
- package/src/components/planning/actioning-view-utils.ts +27 -1
- package/src/components/planning/plan-detail-utils.tsx +2 -0
- package/src/components/tool-invocation-card/ListRulesResultDisplay.tsx +2 -2
- package/src/components/tool-invocation-card/ToolOutputRenderer.tsx +10 -8
- package/src/components/tool-invocation-card/types.ts +8 -8
- package/src/components/tooltip/index.tsx +35 -2
- package/src/explain-fact/rule-presentation.ts +2 -2
- package/src/explain-fact/tree-model.ts +2 -2
- package/src/graph/entity-link.tsx +20 -0
- package/src/graph/graph-list-utils.ts +2 -0
- package/src/graph/graph-model.ts +15 -6
- package/src/graph/nodes/BrandAssetAnalysisView.tsx +3 -1
- package/src/graph/nodes/BrandFontSuggestionView.tsx +7 -1
- package/src/graph/nodes/BrandGuidelinesView.tsx +1 -1
- package/src/graph/nodes/NodePropertyTable.tsx +32 -143
- package/src/graph/nodes/node-property-row.tsx +154 -0
- package/src/graph/property-formatters.ts +5 -1
- package/src/graph/special-nodes/AttributeList.tsx +177 -0
- package/src/graph/special-nodes/EntityPreview.tsx +27 -0
- package/src/graph/special-nodes/EntityValueChip.tsx +85 -0
- package/src/graph/special-nodes/GenericView.tsx +49 -139
- package/src/graph/special-nodes/card-facts.ts +278 -0
- package/src/graph/special-nodes/property-icons.ts +59 -0
- package/src/graph/status-utils.ts +40 -0
- package/src/graph/types.ts +4 -0
- package/src/hooks/use-approve-anyway.ts +100 -0
- package/src/ldo-ui.ts +8 -0
- package/src/lib/find-latest-staged-rule.ts +1 -1
- package/src/lib/manual-actions.ts +3 -2
- package/src/lib/tool-icons.ts +6 -6
- package/src/lib/tool-names.ts +0 -1
- package/src/ontology/skolem.ts +2 -2
- package/src/providers/ActiveChatProvider.tsx +3 -1
- package/src/providers/ChatManagerProvider.tsx +3 -1
- package/src/providers/KnowledgeGraphStateProvider.tsx +1 -1
- package/src/providers/chat-socket-auth.ts +95 -16
- package/src/providers/index.tsx +16 -1
- package/src/routes/activity/detail/ActivityChanges.tsx +21 -5
- package/src/routes/activity/detail/ActivityDetail.tsx +24 -5
- package/src/routes/activity/detail/ActivityStepsRail.tsx +4 -2
- package/src/routes/activity/detail/ActivityTimeline.tsx +2 -2
- package/src/routes/activity/detail/NoChangesMessage.tsx +20 -0
- package/src/routes/data-explorer/class-properties.ts +2 -2
- package/src/routes/data-explorer/classes.ts +2 -2
- package/src/routes/data-explorer/components/RawTriples.tsx +1 -1
- package/src/routes/data-explorer/components/RecentTypes.tsx +1 -1
- package/src/routes/data-explorer/components/class-detail/Instances.tsx +1 -1
- package/src/routes/data-explorer/components/namespace-detail/NamespaceClassRow.tsx +1 -1
- package/src/routes/data-explorer/components/ontology-coverage/CoverageTermColumns.tsx +1 -1
- package/src/routes/data-explorer/components/ontology-coverage/UnobservedRuleVocabulary.tsx +1 -1
- package/src/routes/data-explorer/components/record-detail/ChatPreview.tsx +2 -2
- package/src/routes/data-explorer/recents.ts +1 -1
- package/src/routes/data-explorer/shapes.ts +2 -2
- package/src/routes/datastores/flatten.ts +1 -1
- package/src/routes/integrations/components/connect-forms/CanvaConnectForm.tsx +26 -0
- package/src/routes/integrations/components/connect-forms/DataConnectionConnectForm.tsx +38 -12
- package/src/routes/integrations/components/connect-forms/data-connection-fields.ts +11 -2
- package/src/routes/integrations/connect-forms.ts +1 -0
- package/src/routes/integrations/connection-view.ts +1 -0
- package/src/routes/integrations/types.ts +2 -0
- package/src/routes/plans/components/ActionPlanPage.tsx +9 -8
- package/src/routes/plans/components/PlanDetailRouteContent.tsx +4 -3
- package/src/routes/rules/hooks/useRuleFactsPreview.ts +4 -4
- package/src/shacl/form-appearance.ts +1 -1
- package/src/shared/graph-derived-queries.ts +2 -2
- package/dist/components/planning/ExecutionActivityRow.d.ts +0 -9
- package/dist/components/planning/ExecutionActivityRow.d.ts.map +0 -1
- package/dist/components/planning/ExecutionActivityRow.js +0 -53
- package/dist/components/planning/ExecutionActivityRow.js.map +0 -1
- package/dist/components/planning/ExecutionSectionItem.d.ts +0 -20
- package/dist/components/planning/ExecutionSectionItem.d.ts.map +0 -1
- package/dist/components/planning/ExecutionSectionItem.js +0 -66
- package/dist/components/planning/ExecutionSectionItem.js.map +0 -1
- package/dist/components/planning/ExecutionSections.d.ts +0 -16
- package/dist/components/planning/ExecutionSections.d.ts.map +0 -1
- package/dist/components/planning/ExecutionSections.js +0 -32
- package/dist/components/planning/ExecutionSections.js.map +0 -1
- package/dist/components/planning/action-plan-icons.d.ts +0 -3
- package/dist/components/planning/action-plan-icons.d.ts.map +0 -1
- package/dist/components/planning/action-plan-icons.js +0 -25
- package/dist/components/planning/action-plan-icons.js.map +0 -1
- package/dist/components/planning/execution-section-model.d.ts +0 -24
- package/dist/components/planning/execution-section-model.d.ts.map +0 -1
- package/dist/components/planning/execution-section-model.js +0 -150
- package/dist/components/planning/execution-section-model.js.map +0 -1
- package/dist/routes/data-explorer/components/TruncateTooltip.d.ts +0 -7
- package/dist/routes/data-explorer/components/TruncateTooltip.d.ts.map +0 -1
- package/dist/routes/data-explorer/components/TruncateTooltip.js +0 -9
- package/dist/routes/data-explorer/components/TruncateTooltip.js.map +0 -1
- package/src/components/planning/ExecutionActivityRow.tsx +0 -89
- package/src/components/planning/ExecutionSectionItem.tsx +0 -184
- package/src/components/planning/ExecutionSections.tsx +0 -97
- package/src/components/planning/action-plan-icons.tsx +0 -27
- package/src/components/planning/execution-section-model.ts +0 -190
- package/src/routes/data-explorer/components/TruncateTooltip.tsx +0 -25
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { useExecuteAgentActionAdditionMutation } from "@manta-eu/client";
|
|
2
|
+
import { isPresent } from "@manta-eu/lib/present";
|
|
3
|
+
import { isValidFullIri, namespaces } from "@manta-eu/rdf-lib/namespaces";
|
|
4
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
5
|
+
import { DataFactory } from "ldkit/rdf";
|
|
6
|
+
import { sparql } from "ldkit/sparql";
|
|
7
|
+
import { useCallback, useMemo, useRef, useState } from "react";
|
|
8
|
+
import { toast } from "sonner";
|
|
9
|
+
import type { ManualAction } from "./use-manual-actions";
|
|
10
|
+
import { useSparqlSelect } from "./use-sparql-construct";
|
|
11
|
+
import { buildActionDocument, mintSubjectIri } from "#lib/action-document";
|
|
12
|
+
import { useMantaClient } from "#providers/MantaClientProvider";
|
|
13
|
+
import { invalidateActionPlanQueries } from "#shared/query-keys";
|
|
14
|
+
|
|
15
|
+
const df = new DataFactory();
|
|
16
|
+
const assetAnalysis = `${namespaces.brand}AssetAnalysis`;
|
|
17
|
+
const assetDecision = `${namespaces.brand}AssetDecision`;
|
|
18
|
+
const decideAssetShape = `${namespaces.brand}DecideAssetShape`;
|
|
19
|
+
|
|
20
|
+
export type ApproveAnywayHandle = {
|
|
21
|
+
/** Sends the approval; `reviewKey` names the review it answers, so a later review of the same analysis asks again. */
|
|
22
|
+
approve: (analysisIri: string, reviewKey: string) => void;
|
|
23
|
+
approving: ReadonlySet<string>;
|
|
24
|
+
approved: ReadonlySet<string>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** Maps each manual action about a brand analysis to that analysis, the one a person can approve anyway. */
|
|
28
|
+
export function useApprovableAnalyses(actions: readonly ManualAction[]): Map<string, string> {
|
|
29
|
+
const aboutIris = useMemo(() => {
|
|
30
|
+
const iris = actions.flatMap(({ aboutIri }) => (isPresent(aboutIri) && isValidFullIri(aboutIri) ? [aboutIri] : []));
|
|
31
|
+
return [...new Set(iris)].sort();
|
|
32
|
+
}, [actions]);
|
|
33
|
+
|
|
34
|
+
const values = aboutIris.map((iri) => sparql`${df.namedNode(iri)}`).join(" ");
|
|
35
|
+
const query = isPresent(aboutIris)
|
|
36
|
+
? `SELECT ?about WHERE { VALUES ?about { ${values} } ?about a ${sparql`${df.namedNode(assetAnalysis)}`} . }`
|
|
37
|
+
: "";
|
|
38
|
+
|
|
39
|
+
const { data } = useSparqlSelect({
|
|
40
|
+
query,
|
|
41
|
+
queryKey: ["ldo-ui", "approvable-analyses", aboutIris],
|
|
42
|
+
enabled: isPresent(aboutIris),
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return useMemo(() => {
|
|
46
|
+
const analyses = new Set((data ?? []).flatMap((row) => row.get("about")?.value ?? []));
|
|
47
|
+
const approvable = new Map<string, string>();
|
|
48
|
+
for (const action of actions) {
|
|
49
|
+
if (isPresent(action.aboutIri) && analyses.has(action.aboutIri)) {
|
|
50
|
+
approvable.set(action.subjectIri, action.aboutIri);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return approvable;
|
|
54
|
+
}, [actions, data]);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Records a person's approval of an analysis that was not confirmed on-brand, so the rules publish it anyway. */
|
|
58
|
+
export function useApproveAnyway(planGraphIri: string): ApproveAnywayHandle {
|
|
59
|
+
const queryClient = useQueryClient();
|
|
60
|
+
const { mantaClient } = useMantaClient();
|
|
61
|
+
const { mutateAsync: startAddition } = useExecuteAgentActionAdditionMutation(mantaClient);
|
|
62
|
+
const inFlight = useRef(new Set<string>());
|
|
63
|
+
const [approving, setApproving] = useState<ReadonlySet<string>>(() => new Set());
|
|
64
|
+
const [approved, setApproved] = useState<ReadonlySet<string>>(() => new Set());
|
|
65
|
+
|
|
66
|
+
const approve = useCallback(
|
|
67
|
+
(analysisIri: string, reviewKey: string) => {
|
|
68
|
+
if (inFlight.current.has(analysisIri)) return;
|
|
69
|
+
inFlight.current.add(analysisIri);
|
|
70
|
+
setApproving(new Set(inFlight.current));
|
|
71
|
+
const subjectIri = mintSubjectIri(assetDecision);
|
|
72
|
+
const properties = buildActionDocument(
|
|
73
|
+
{ subjectIri, rdfType: assetDecision },
|
|
74
|
+
{
|
|
75
|
+
[`${namespaces.brand}decisionOnAsset`]: { "@id": analysisIri },
|
|
76
|
+
[`${namespaces.brand}decision`]: "approved",
|
|
77
|
+
},
|
|
78
|
+
);
|
|
79
|
+
void startAddition({
|
|
80
|
+
input: { subjectIri, rdfType: assetDecision, actionShape: decideAssetShape, properties },
|
|
81
|
+
})
|
|
82
|
+
.then(({ executeActionAddition }) => {
|
|
83
|
+
if (!executeActionAddition.success) throw new Error(executeActionAddition.error ?? "The approval failed");
|
|
84
|
+
setApproved((previous) => new Set(previous).add(reviewKey));
|
|
85
|
+
toast.success("Approved. It is uploaded, and this review closes, when the plan next runs.");
|
|
86
|
+
void invalidateActionPlanQueries(queryClient, planGraphIri);
|
|
87
|
+
})
|
|
88
|
+
.catch((error: unknown) => {
|
|
89
|
+
toast.error(error instanceof Error ? error.message : "The approval failed");
|
|
90
|
+
})
|
|
91
|
+
.finally(() => {
|
|
92
|
+
inFlight.current.delete(analysisIri);
|
|
93
|
+
setApproving(new Set(inFlight.current));
|
|
94
|
+
});
|
|
95
|
+
},
|
|
96
|
+
[startAddition, queryClient, planGraphIri],
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
return { approve, approving, approved };
|
|
100
|
+
}
|
package/src/ldo-ui.ts
CHANGED
|
@@ -268,6 +268,7 @@ export type {
|
|
|
268
268
|
EntityView,
|
|
269
269
|
EntityViewProps,
|
|
270
270
|
LayoutDirection,
|
|
271
|
+
NodeRelation,
|
|
271
272
|
OnNodeContextMenu,
|
|
272
273
|
RDFNode,
|
|
273
274
|
RDFNodeData,
|
|
@@ -275,6 +276,13 @@ export type {
|
|
|
275
276
|
SampleInstance,
|
|
276
277
|
} from "./graph/types";
|
|
277
278
|
export { jsonLdToRdfGraph } from "./graph/jsonld-bridge";
|
|
279
|
+
export {
|
|
280
|
+
EntityLinkProvider,
|
|
281
|
+
useEntityLink,
|
|
282
|
+
type EntityLinkComponent,
|
|
283
|
+
type EntityLinkProps,
|
|
284
|
+
type EntityLinkProviderProps,
|
|
285
|
+
} from "./graph/entity-link";
|
|
278
286
|
export { rdfGraphToNodesAndEdges, rdfGraphToSummaryNodesAndEdges } from "./graph/graph-model";
|
|
279
287
|
export {
|
|
280
288
|
applyDagreLayout,
|
|
@@ -3,5 +3,5 @@ import { isStagedManageRulesResult } from "../components/tool-invocation-card/ty
|
|
|
3
3
|
import { findLatestToolOutput } from "./find-latest-tool-output";
|
|
4
4
|
|
|
5
5
|
export function findLatestStagedRuleIri(messages: ChatUIMessage[]): string | null {
|
|
6
|
-
return findLatestToolOutput(messages, "tool-
|
|
6
|
+
return findLatestToolOutput(messages, "tool-manageRules", isStagedManageRulesResult)?.ruleIri ?? null;
|
|
7
7
|
}
|
|
@@ -16,6 +16,7 @@ export function getPendingManualActions(actions: readonly ManualAction[] | undef
|
|
|
16
16
|
return (actions ?? []).filter(isPendingManualAction);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
/** Names the review an approval answers: the step, as of the analysis it currently reports. */
|
|
20
|
+
export function approvalReviewKey(action: Pick<ManualAction, "subjectIri" | "observedValue">): string {
|
|
21
|
+
return `${action.subjectIri}|${action.observedValue ?? ""}`;
|
|
21
22
|
}
|
package/src/lib/tool-icons.ts
CHANGED
|
@@ -27,12 +27,12 @@ import {
|
|
|
27
27
|
import { match } from "ts-pattern";
|
|
28
28
|
|
|
29
29
|
const toolIconMap: Record<ToolName, LucideIcon> = {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
queryKnowledgeGraph: Database,
|
|
31
|
+
addFacts: Database,
|
|
32
|
+
manageFacts: Database,
|
|
33
|
+
getRules: Brain,
|
|
34
|
+
explainFact: Brain,
|
|
35
|
+
manageRules: Brain,
|
|
36
36
|
generateChart: TrendingUp,
|
|
37
37
|
scheduleTask: Clock,
|
|
38
38
|
listScheduledTasks: Clock,
|
package/src/lib/tool-names.ts
CHANGED
package/src/ontology/skolem.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type SkolemPart = { type: "iri"; value: string } | { type: "literal"; val
|
|
|
5
5
|
const blankNodePrefixes = ["_:", "_."];
|
|
6
6
|
const segmentTagLength = 2;
|
|
7
7
|
|
|
8
|
-
//
|
|
8
|
+
// The datastore datatype tags: "02" = IRI, "05" = string; other datatypes are binary-encoded.
|
|
9
9
|
const segmentTypeByTag: Record<string, SkolemPart["type"]> = {
|
|
10
10
|
"02": "iri",
|
|
11
11
|
"05": "literal",
|
|
@@ -29,7 +29,7 @@ function decodeSegment(segment: string): string | undefined {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
//
|
|
32
|
+
// The datastore skolem labels: dot-separated base64 segments, each prefixed with a 2-char type tag.
|
|
33
33
|
export function decodeSkolem(term: string): SkolemPart[] | undefined {
|
|
34
34
|
const prefix = blankNodePrefixes.find((candidate) => term.startsWith(candidate));
|
|
35
35
|
|
|
@@ -109,7 +109,9 @@ function ThinkChatSession(props: ThinkChatSessionProps) {
|
|
|
109
109
|
sub: [{ agent: "ThinkChat", name: conversationId }],
|
|
110
110
|
host,
|
|
111
111
|
query: socketAuth.query,
|
|
112
|
-
...("
|
|
112
|
+
...("enabled" in socketAuth
|
|
113
|
+
? { enabled: socketAuth.enabled, shouldReconnectOnClose: socketAuth.shouldReconnectOnClose }
|
|
114
|
+
: {}),
|
|
113
115
|
onClose: handleAgentClose,
|
|
114
116
|
onMessage: handleAgentMessage,
|
|
115
117
|
});
|
|
@@ -97,7 +97,9 @@ export function ChatManagerProvider(props: ChatManagerProviderProps) {
|
|
|
97
97
|
basePath: chatManagerBasePath,
|
|
98
98
|
host: mantaBaseUrl.host,
|
|
99
99
|
query: socketAuth.query,
|
|
100
|
-
...("
|
|
100
|
+
...("enabled" in socketAuth
|
|
101
|
+
? { enabled: socketAuth.enabled, shouldReconnectOnClose: socketAuth.shouldReconnectOnClose }
|
|
102
|
+
: {}),
|
|
101
103
|
});
|
|
102
104
|
|
|
103
105
|
const listConversations = useCallback(
|
|
@@ -135,7 +135,7 @@ export function KnowledgeGraphStateProvider(props: KnowledgeGraphStateProviderPr
|
|
|
135
135
|
|
|
136
136
|
if (currentDataVersion && isPresent(previousDataVersion) && previousDataVersion !== currentDataVersion) {
|
|
137
137
|
void invalidateGraphDerivedQueries(queryClient);
|
|
138
|
-
console.debug("Knowledge graph dataVersion changed, invalidating
|
|
138
|
+
console.debug("Knowledge graph dataVersion changed, invalidating the knowledge graph queries");
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
if (currentDataVersion && currentDataVersion !== previousDataVersion) {
|
|
@@ -1,44 +1,123 @@
|
|
|
1
1
|
import { chatTicketPath, chatTicketQueryParam } from "@manta-eu/client/shared/chat-manager";
|
|
2
2
|
import { datastoreHeader, datastoreQueryParam } from "@manta-eu/client/shared/datastore-path";
|
|
3
3
|
import { isPresent } from "@manta-eu/lib/present";
|
|
4
|
-
import {
|
|
4
|
+
import { isTerminalCloseEvent } from "agents/client";
|
|
5
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
5
6
|
import { providerFetch } from "./manta-client-context";
|
|
6
7
|
import { useMantaClient } from "./MantaClientProvider";
|
|
7
8
|
|
|
8
|
-
// A reconnect always fetches a new ticket, and an expiring cache entry would replace a live socket.
|
|
9
|
-
const ticketCacheTtlMs = 24 * 60 * 60 * 1000;
|
|
10
9
|
const tokenRefreshCheckMs = 30_000;
|
|
10
|
+
const reconnectDelaysMs = [0, 1_000, 2_000, 5_000, 10_000];
|
|
11
|
+
const dropCountResetMs = 60_000;
|
|
12
|
+
const stableConnectionMs = 5_000;
|
|
13
|
+
// Any other 4xx is Manta refusing this person or datastore for good, so asking again cannot help.
|
|
14
|
+
const retriedRefusals = new Set([401, 408, 429]);
|
|
11
15
|
|
|
12
16
|
export type ChatSocketAuth =
|
|
13
17
|
| { query: Record<string, string>; credentials: "include" }
|
|
14
|
-
| {
|
|
18
|
+
| {
|
|
19
|
+
query: Record<string, string>;
|
|
20
|
+
enabled: boolean;
|
|
21
|
+
shouldReconnectOnClose: (event: CloseEvent) => boolean;
|
|
22
|
+
credentials: "omit";
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
type Ticketed = { datastoreKey: string; query: Record<string, string> };
|
|
15
26
|
|
|
16
27
|
function ticketFrom(body: unknown): string | undefined {
|
|
17
28
|
if (typeof body !== "object" || body === null || !("ticket" in body)) return undefined;
|
|
18
29
|
return typeof body.ticket === "string" ? body.ticket : undefined;
|
|
19
30
|
}
|
|
20
31
|
|
|
32
|
+
// partysocket clears shouldReconnect before a close it was asked for: an unmount, or a socket being replaced.
|
|
33
|
+
function isRequestedClose(event: CloseEvent): boolean {
|
|
34
|
+
const target: unknown = event.target;
|
|
35
|
+
return typeof target === "object" && target !== null && "shouldReconnect" in target && !target.shouldReconnect;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* A ticket is spent on its first connect, and partysocket would reconnect to the same URL, so the socket never
|
|
40
|
+
* reconnects by itself: each connect waits for a new ticket, and a dropped socket asks for one.
|
|
41
|
+
*/
|
|
21
42
|
export function useChatSocketAuth(datastoreQuery: Record<string, string>): ChatSocketAuth {
|
|
22
43
|
const client = useMantaClient();
|
|
23
44
|
const { getAccessToken, mantaBaseUrl } = client;
|
|
24
45
|
const authorizedFetch = providerFetch(client);
|
|
46
|
+
const authorizedFetchRef = useRef(authorizedFetch);
|
|
47
|
+
authorizedFetchRef.current = authorizedFetch;
|
|
48
|
+
const hasAccessToken = getAccessToken !== undefined;
|
|
49
|
+
const datastoreKey = JSON.stringify(datastoreQuery);
|
|
50
|
+
const datastoreQueryRef = useRef(datastoreQuery);
|
|
51
|
+
datastoreQueryRef.current = datastoreQuery;
|
|
52
|
+
const [ticketed, setTicketed] = useState<Ticketed>();
|
|
53
|
+
const [connectRequest, setConnectRequest] = useState(0);
|
|
54
|
+
const drops = useRef({ count: 0, lastAt: 0 });
|
|
55
|
+
const ticketedAt = useRef<number>(undefined);
|
|
25
56
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
57
|
+
// A socket that stayed up starts the backoff over; one dropped at once, as a server refusing it would, does not.
|
|
58
|
+
const recordDrop = useCallback((socketClosed = false) => {
|
|
59
|
+
const now = Date.now();
|
|
60
|
+
const stayedUp = socketClosed && ticketedAt.current !== undefined && now - ticketedAt.current >= stableConnectionMs;
|
|
61
|
+
const fresh = stayedUp || now - drops.current.lastAt > dropCountResetMs;
|
|
62
|
+
drops.current = { count: fresh ? 1 : drops.current.count + 1, lastAt: now };
|
|
63
|
+
setConnectRequest((request) => request + 1);
|
|
64
|
+
}, []);
|
|
65
|
+
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (!hasAccessToken) return;
|
|
68
|
+
setTicketed((held) => (held?.datastoreKey === datastoreKey ? held : undefined));
|
|
69
|
+
let cancelled = false;
|
|
70
|
+
const delay = reconnectDelaysMs[Math.min(Math.max(drops.current.count - 1, 0), reconnectDelaysMs.length - 1)];
|
|
71
|
+
const timer = setTimeout(() => {
|
|
72
|
+
const query = datastoreQueryRef.current;
|
|
73
|
+
authorizedFetchRef
|
|
74
|
+
.current(new URL(`/${chatTicketPath}`, mantaBaseUrl), {
|
|
75
|
+
method: "POST",
|
|
76
|
+
headers: datastoreHeader(query[datastoreQueryParam]),
|
|
77
|
+
})
|
|
78
|
+
.then(async (response) => {
|
|
79
|
+
if (response.status >= 400 && response.status < 500 && !retriedRefusals.has(response.status)) {
|
|
80
|
+
if (!cancelled) console.warn(`Manta refused a chat ticket (${response.status}); not asking again`);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const ticket = response.ok ? ticketFrom(await response.json()) : undefined;
|
|
84
|
+
if (!isPresent(ticket)) throw new Error(`Manta refused a chat ticket (${response.status})`);
|
|
85
|
+
if (cancelled) return;
|
|
86
|
+
ticketedAt.current = Date.now();
|
|
87
|
+
setTicketed({ datastoreKey, query: { ...query, [chatTicketQueryParam]: ticket } });
|
|
88
|
+
})
|
|
89
|
+
.catch((error: unknown) => {
|
|
90
|
+
if (cancelled) return;
|
|
91
|
+
console.warn("Could not get a chat ticket", error);
|
|
92
|
+
recordDrop();
|
|
93
|
+
});
|
|
94
|
+
}, delay);
|
|
95
|
+
return () => {
|
|
96
|
+
cancelled = true;
|
|
97
|
+
clearTimeout(timer);
|
|
98
|
+
};
|
|
99
|
+
}, [hasAccessToken, mantaBaseUrl, datastoreKey, connectRequest, recordDrop]);
|
|
100
|
+
|
|
101
|
+
const shouldReconnectOnClose = useCallback(
|
|
102
|
+
(event: CloseEvent) => {
|
|
103
|
+
if (!isRequestedClose(event) && !isTerminalCloseEvent(event)) recordDrop(true);
|
|
104
|
+
return false;
|
|
105
|
+
},
|
|
106
|
+
[recordDrop],
|
|
107
|
+
);
|
|
35
108
|
|
|
109
|
+
const ticketQuery = ticketed?.datastoreKey === datastoreKey ? ticketed.query : undefined;
|
|
36
110
|
return useMemo(
|
|
37
111
|
() =>
|
|
38
|
-
|
|
39
|
-
? {
|
|
112
|
+
hasAccessToken
|
|
113
|
+
? {
|
|
114
|
+
query: ticketQuery ?? datastoreQuery,
|
|
115
|
+
enabled: ticketQuery !== undefined,
|
|
116
|
+
shouldReconnectOnClose,
|
|
117
|
+
credentials: "omit" as const,
|
|
118
|
+
}
|
|
40
119
|
: { query: datastoreQuery, credentials: "include" as const },
|
|
41
|
-
[
|
|
120
|
+
[hasAccessToken, ticketQuery, datastoreQuery, shouldReconnectOnClose],
|
|
42
121
|
);
|
|
43
122
|
}
|
|
44
123
|
|
package/src/providers/index.tsx
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { defaultDeployment } from "@manta-eu/auth/default-deployment";
|
|
2
2
|
import type { AccessTokenSource } from "@manta-eu/client";
|
|
3
|
+
import { entityPath } from "@manta-eu/client/shared/explorer-paths";
|
|
3
4
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
4
5
|
import { NuqsAdapter } from "nuqs/adapters/react-router/v7";
|
|
5
6
|
import type { ReactNode } from "react";
|
|
6
7
|
import { useState } from "react";
|
|
8
|
+
import { Link } from "react-router";
|
|
9
|
+
import { EntityLinkProvider, type EntityLinkProps } from "../graph/entity-link";
|
|
7
10
|
import { ActiveDatastoreProvider, ActiveDatastoreRouter, useActiveDatastore } from "./ActiveDatastoreProvider";
|
|
8
11
|
import { GenerateStructuredDataProvider } from "./GenerateStructuredDataProvider";
|
|
9
12
|
import { KnowledgeGraphPollingProvider } from "./KnowledgeGraphPollingProvider";
|
|
@@ -89,6 +92,16 @@ function CoreProviders(props: ProvidersProps) {
|
|
|
89
92
|
);
|
|
90
93
|
}
|
|
91
94
|
|
|
95
|
+
function RecordEntityLink(props: EntityLinkProps) {
|
|
96
|
+
const { iri, className, children } = props;
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<Link to={entityPath(iri)} className={className} onClick={(event) => event.stopPropagation()}>
|
|
100
|
+
{children}
|
|
101
|
+
</Link>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
92
105
|
export function Providers(props: ProvidersProps) {
|
|
93
106
|
const { children, ...coreProps } = props;
|
|
94
107
|
|
|
@@ -97,7 +110,9 @@ export function Providers(props: ProvidersProps) {
|
|
|
97
110
|
<ThemeProvider>
|
|
98
111
|
<CoreProviders {...coreProps}>
|
|
99
112
|
<ActiveDatastoreRouter>
|
|
100
|
-
<NuqsAdapter>
|
|
113
|
+
<NuqsAdapter>
|
|
114
|
+
<EntityLinkProvider component={RecordEntityLink}>{children}</EntityLinkProvider>
|
|
115
|
+
</NuqsAdapter>
|
|
101
116
|
</ActiveDatastoreRouter>
|
|
102
117
|
</CoreProviders>
|
|
103
118
|
</ThemeProvider>
|
|
@@ -8,6 +8,7 @@ import { useIntersectionObserver } from "usehooks-ts";
|
|
|
8
8
|
import { DiffRow } from "../change-display";
|
|
9
9
|
import { EntityNodeView, subsumesChangeRows } from "./EntityNodeView";
|
|
10
10
|
import { LazyMount, viewportOverscan } from "./LazyMount";
|
|
11
|
+
import { NoChangesMessage } from "./NoChangesMessage";
|
|
11
12
|
import { useEntityNodes, type ActivityChangeGroup, type EntityNode } from "#ldo-ui";
|
|
12
13
|
import { cn } from "#lib/utils";
|
|
13
14
|
import { entityPath } from "#routes/data-explorer/namespaces";
|
|
@@ -52,10 +53,11 @@ type ChangeGroupProps = {
|
|
|
52
53
|
node?: EntityNode;
|
|
53
54
|
nodesLoading: boolean;
|
|
54
55
|
scrollRoot: HTMLElement | null;
|
|
56
|
+
showLinks: boolean;
|
|
55
57
|
};
|
|
56
58
|
|
|
57
59
|
function ChangeGroup(props: ChangeGroupProps) {
|
|
58
|
-
const { group, selected, onJumpTo, node, nodesLoading, scrollRoot } = props;
|
|
60
|
+
const { group, selected, onJumpTo, node, nodesLoading, scrollRoot, showLinks } = props;
|
|
59
61
|
|
|
60
62
|
// Answered from the change's own triples until the fetch lands, so the rows do not show then vanish.
|
|
61
63
|
const typedCard = useMemo(
|
|
@@ -87,7 +89,7 @@ function ChangeGroup(props: ChangeGroupProps) {
|
|
|
87
89
|
>
|
|
88
90
|
{group.entityLabel}
|
|
89
91
|
</button>
|
|
90
|
-
{isFullIri(group.entityIri) && (
|
|
92
|
+
{showLinks && isFullIri(group.entityIri) && (
|
|
91
93
|
<Link
|
|
92
94
|
to={entityPath(group.entityIri)}
|
|
93
95
|
aria-label={`Open ${group.entityLabel} in the data explorer`}
|
|
@@ -145,10 +147,11 @@ type ChangeBlockProps = {
|
|
|
145
147
|
activeIri: string | null;
|
|
146
148
|
onJumpTo: (entityIri: string) => void;
|
|
147
149
|
scrollRoot: HTMLElement | null;
|
|
150
|
+
showLinks: boolean;
|
|
148
151
|
};
|
|
149
152
|
|
|
150
153
|
function ChangeBlock(props: ChangeBlockProps) {
|
|
151
|
-
const { groups, activeIri, onJumpTo, scrollRoot } = props;
|
|
154
|
+
const { groups, activeIri, onJumpTo, scrollRoot, showLinks } = props;
|
|
152
155
|
|
|
153
156
|
const { ref, isIntersecting } = useIntersectionObserver({
|
|
154
157
|
root: scrollRoot,
|
|
@@ -173,6 +176,7 @@ function ChangeBlock(props: ChangeBlockProps) {
|
|
|
173
176
|
.find(isPresent)}
|
|
174
177
|
nodesLoading={isLoading}
|
|
175
178
|
scrollRoot={scrollRoot}
|
|
179
|
+
showLinks={showLinks}
|
|
176
180
|
/>
|
|
177
181
|
))}
|
|
178
182
|
</div>
|
|
@@ -188,10 +192,21 @@ export type ActivityChangesProps = {
|
|
|
188
192
|
scrollTarget: { iri: string; nonce: number } | null;
|
|
189
193
|
// Embedded runs in a short box, where the full-page scroll-room spacer would over-scroll.
|
|
190
194
|
inline?: boolean;
|
|
195
|
+
running?: boolean;
|
|
196
|
+
showLinks?: boolean;
|
|
191
197
|
};
|
|
192
198
|
|
|
193
199
|
export function ActivityChanges(props: ActivityChangesProps) {
|
|
194
|
-
const {
|
|
200
|
+
const {
|
|
201
|
+
groups,
|
|
202
|
+
activeIri,
|
|
203
|
+
onActivate,
|
|
204
|
+
onJumpTo,
|
|
205
|
+
scrollTarget,
|
|
206
|
+
inline = false,
|
|
207
|
+
running = false,
|
|
208
|
+
showLinks = true,
|
|
209
|
+
} = props;
|
|
195
210
|
|
|
196
211
|
const blocks = useMemo(
|
|
197
212
|
() =>
|
|
@@ -260,7 +275,7 @@ export function ActivityChanges(props: ActivityChangesProps) {
|
|
|
260
275
|
if (!isPresent(groups)) {
|
|
261
276
|
return (
|
|
262
277
|
<div className="rounded-xl border border-muted-border bg-card p-5">
|
|
263
|
-
<
|
|
278
|
+
<NoChangesMessage running={running} />
|
|
264
279
|
</div>
|
|
265
280
|
);
|
|
266
281
|
}
|
|
@@ -291,6 +306,7 @@ export function ActivityChanges(props: ActivityChangesProps) {
|
|
|
291
306
|
activeIri={activeIri}
|
|
292
307
|
onJumpTo={onJumpTo}
|
|
293
308
|
scrollRoot={scrollRoot}
|
|
309
|
+
showLinks={showLinks}
|
|
294
310
|
/>
|
|
295
311
|
))}
|
|
296
312
|
|
|
@@ -41,10 +41,20 @@ export type ActivityDetailProps = {
|
|
|
41
41
|
variant?: "page" | "embedded";
|
|
42
42
|
// Embedded only — lead-in above the run, rendered after it loads.
|
|
43
43
|
caption?: ReactNode;
|
|
44
|
+
// Off when the host has no route for the run page or the data explorer.
|
|
45
|
+
showLinks?: boolean;
|
|
44
46
|
};
|
|
45
47
|
|
|
46
48
|
export function ActivityDetail(props: ActivityDetailProps) {
|
|
47
|
-
const {
|
|
49
|
+
const {
|
|
50
|
+
activityIri,
|
|
51
|
+
leading,
|
|
52
|
+
layout: controlledLayout,
|
|
53
|
+
onLayoutChange,
|
|
54
|
+
variant = "page",
|
|
55
|
+
caption,
|
|
56
|
+
showLinks = true,
|
|
57
|
+
} = props;
|
|
48
58
|
const embedded = variant === "embedded";
|
|
49
59
|
|
|
50
60
|
const [internalLayout, setInternalLayout] = useState<ActivityLayout>("timeline");
|
|
@@ -107,9 +117,13 @@ export function ActivityDetail(props: ActivityDetailProps) {
|
|
|
107
117
|
/>
|
|
108
118
|
) : null;
|
|
109
119
|
|
|
120
|
+
const isRunning = activity?.status === "running";
|
|
121
|
+
|
|
110
122
|
const changes = (
|
|
111
123
|
<ActivityChanges
|
|
112
124
|
inline={embedded}
|
|
125
|
+
running={isRunning}
|
|
126
|
+
showLinks={showLinks}
|
|
113
127
|
groups={groups}
|
|
114
128
|
activeIri={activeIri}
|
|
115
129
|
onActivate={activate}
|
|
@@ -140,7 +154,7 @@ export function ActivityDetail(props: ActivityDetailProps) {
|
|
|
140
154
|
<div className="flex h-full min-h-0 flex-col gap-3">
|
|
141
155
|
{isPresent(caption) && <p className="typography-small text-muted-foreground shrink-0">{caption}</p>}
|
|
142
156
|
<div className="flex shrink-0 flex-wrap items-center gap-2">
|
|
143
|
-
{isPresent(activityIri) ? (
|
|
157
|
+
{showLinks && isPresent(activityIri) ? (
|
|
144
158
|
<Link
|
|
145
159
|
to={buildActivityHref(activityIri)}
|
|
146
160
|
title={`Open ${activity.planLabel} run detail`}
|
|
@@ -160,7 +174,7 @@ export function ActivityDetail(props: ActivityDetailProps) {
|
|
|
160
174
|
<Banner label={activity.errorMessage} className="max-h-40 shrink-0 overflow-y-auto" />
|
|
161
175
|
)}
|
|
162
176
|
|
|
163
|
-
{isChangeSetLoading ? (
|
|
177
|
+
{isChangeSetLoading && !isRunning ? (
|
|
164
178
|
<div className="flex items-center justify-center py-10">
|
|
165
179
|
<Loader className="size-5" />
|
|
166
180
|
</div>
|
|
@@ -234,7 +248,7 @@ export function ActivityDetail(props: ActivityDetailProps) {
|
|
|
234
248
|
) : layout === "steps" ? (
|
|
235
249
|
<>
|
|
236
250
|
<div className="min-h-0 flex-1 overflow-y-auto sm:hidden">
|
|
237
|
-
<ActivityStepsRail groups={groups} activeIri={activeIri} onSelect={activate} />
|
|
251
|
+
<ActivityStepsRail groups={groups} activeIri={activeIri} onSelect={activate} running={isRunning} />
|
|
238
252
|
<div className="border-t border-muted-border">
|
|
239
253
|
<ActivityStepDetail group={activeGroup} />
|
|
240
254
|
</div>
|
|
@@ -243,7 +257,12 @@ export function ActivityDetail(props: ActivityDetailProps) {
|
|
|
243
257
|
<ResizablePanelGroup direction="horizontal" className="min-h-0 flex-1">
|
|
244
258
|
<ResizablePanel defaultSize={26} minSize={18} maxSize={50} className="min-h-0">
|
|
245
259
|
<div className="h-full overflow-y-auto">
|
|
246
|
-
<ActivityStepsRail
|
|
260
|
+
<ActivityStepsRail
|
|
261
|
+
groups={groups}
|
|
262
|
+
activeIri={activeIri}
|
|
263
|
+
onSelect={activate}
|
|
264
|
+
running={isRunning}
|
|
265
|
+
/>
|
|
247
266
|
</div>
|
|
248
267
|
</ResizablePanel>
|
|
249
268
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { humanCount } from "@manta-eu/lib/humanize";
|
|
2
2
|
import { isPresent } from "@manta-eu/lib/present";
|
|
3
3
|
import { formatStepTime } from "../format";
|
|
4
|
+
import { NoChangesMessage } from "./NoChangesMessage";
|
|
4
5
|
import type { ActivityChangeGroup } from "#ldo-ui";
|
|
5
6
|
import { cn } from "#lib/utils";
|
|
6
7
|
|
|
@@ -8,15 +9,16 @@ export type ActivityStepsRailProps = {
|
|
|
8
9
|
groups: ActivityChangeGroup[];
|
|
9
10
|
activeIri: string | null;
|
|
10
11
|
onSelect: (entityIri: string) => void;
|
|
12
|
+
running?: boolean;
|
|
11
13
|
};
|
|
12
14
|
|
|
13
15
|
export function ActivityStepsRail(props: ActivityStepsRailProps) {
|
|
14
|
-
const { groups, activeIri, onSelect } = props;
|
|
16
|
+
const { groups, activeIri, onSelect, running = false } = props;
|
|
15
17
|
|
|
16
18
|
if (!isPresent(groups)) {
|
|
17
19
|
return (
|
|
18
20
|
<div className="p-4">
|
|
19
|
-
<
|
|
21
|
+
<NoChangesMessage running={running} />
|
|
20
22
|
</div>
|
|
21
23
|
);
|
|
22
24
|
}
|
|
@@ -42,7 +42,7 @@ export function ActivityTimeline(props: ActivityTimelineProps) {
|
|
|
42
42
|
|
|
43
43
|
if (!isPresent(bars)) {
|
|
44
44
|
return (
|
|
45
|
-
<div className="rounded-xl border border-muted-border bg-card px-5 py-4">
|
|
45
|
+
<div className="shrink-0 rounded-xl border border-muted-border bg-card px-5 py-4">
|
|
46
46
|
<p className="typography-small text-muted-foreground">No timestamps to plot.</p>
|
|
47
47
|
</div>
|
|
48
48
|
);
|
|
@@ -57,7 +57,7 @@ export function ActivityTimeline(props: ActivityTimelineProps) {
|
|
|
57
57
|
const trackHeightPx = Math.max(laneCount, 1) * rowHeightPx;
|
|
58
58
|
|
|
59
59
|
return (
|
|
60
|
-
<div className="overflow-auto rounded-xl border border-muted-border bg-card">
|
|
60
|
+
<div className="shrink-0 overflow-auto rounded-xl border border-muted-border bg-card">
|
|
61
61
|
<div className="px-5 pb-3 pt-3" style={{ minWidth: `${trackMinWidthPx}px` }}>
|
|
62
62
|
<div className="relative h-4">
|
|
63
63
|
{ticks.map((tick, index) => (
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Loader } from "#components/loader/index";
|
|
2
|
+
|
|
3
|
+
type NoChangesMessageProps = {
|
|
4
|
+
running?: boolean;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export function NoChangesMessage(props: NoChangesMessageProps) {
|
|
8
|
+
const { running = false } = props;
|
|
9
|
+
|
|
10
|
+
if (!running) {
|
|
11
|
+
return <p className="typography-small text-muted-foreground">No recorded changes.</p>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<p role="status" className="flex items-center gap-2 typography-small text-muted-foreground">
|
|
16
|
+
<Loader className="size-4 shrink-0" />
|
|
17
|
+
Running. Changes appear as each step completes.
|
|
18
|
+
</p>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ontologyGraphIri,
|
|
1
|
+
import { ontologyGraphIri, shaclGraph } from "@manta-eu/client/shared/rdf-namespaces";
|
|
2
2
|
import { isPresent } from "@manta-eu/lib/present";
|
|
3
3
|
import { DataFactory } from "ldkit/rdf";
|
|
4
4
|
import { SELECT } from "ldkit/sparql";
|
|
@@ -32,7 +32,7 @@ function classPropertiesQuery(classIri: string): string {
|
|
|
32
32
|
|
|
33
33
|
function shapeConstraintsQuery(classIri: string): string {
|
|
34
34
|
return `${prefixes}${SELECT`?path ?minCount ?allowedValue`.WHERE`
|
|
35
|
-
VALUES ?shapeGraph { ${df.namedNode(ontologyGraphIri)} ${df.namedNode(
|
|
35
|
+
VALUES ?shapeGraph { ${df.namedNode(ontologyGraphIri)} ${df.namedNode(shaclGraph)} }
|
|
36
36
|
GRAPH ?shapeGraph {
|
|
37
37
|
?shape sh:targetClass ${df.namedNode(safeIri(classIri))} ; sh:property ?propertyShape .
|
|
38
38
|
?propertyShape sh:path ?path .
|