@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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isPresent } from "@manta-eu/lib/present";
|
|
2
2
|
import { addAll } from "@manta-eu/lib/set";
|
|
3
|
-
import { CircleCheck, Clock, Hand, MessageSquareWarning, RotateCcw, type LucideIcon } from "lucide-react";
|
|
3
|
+
import { BadgeCheck, CircleCheck, Clock, Hand, MessageSquareWarning, RotateCcw, type LucideIcon } from "lucide-react";
|
|
4
|
+
import { Fragment } from "react";
|
|
4
5
|
import { match } from "ts-pattern";
|
|
5
6
|
import { Badge, type BadgeVariant } from "#components/badge/index";
|
|
6
7
|
import { Button } from "#components/button/index";
|
|
@@ -30,10 +31,25 @@ export type ManualActionCardProps = {
|
|
|
30
31
|
onResolve: (resolution: ManualActionResolution) => void;
|
|
31
32
|
canResolve?: boolean;
|
|
32
33
|
disabledReason?: string;
|
|
34
|
+
/** Offered when the action is about something a person can approve despite the checks, such as a creative. */
|
|
35
|
+
onApproveAnyway?: () => void;
|
|
36
|
+
approvingAnyway?: boolean;
|
|
37
|
+
approvedAnyway?: boolean;
|
|
33
38
|
};
|
|
34
39
|
|
|
35
40
|
export function ManualActionCard(props: ManualActionCardProps) {
|
|
36
|
-
const {
|
|
41
|
+
const {
|
|
42
|
+
manualAction,
|
|
43
|
+
entities = [],
|
|
44
|
+
description,
|
|
45
|
+
resolving,
|
|
46
|
+
onResolve,
|
|
47
|
+
canResolve = true,
|
|
48
|
+
disabledReason,
|
|
49
|
+
onApproveAnyway,
|
|
50
|
+
approvingAnyway = false,
|
|
51
|
+
approvedAnyway = false,
|
|
52
|
+
} = props;
|
|
37
53
|
|
|
38
54
|
const instruction = description ?? manualAction.description ?? null;
|
|
39
55
|
const title = manualAction.label ?? instruction ?? buildManualActionTitle(manualAction);
|
|
@@ -67,6 +83,9 @@ export function ManualActionCard(props: ManualActionCardProps) {
|
|
|
67
83
|
onResolve={onResolve}
|
|
68
84
|
canResolve={canResolve}
|
|
69
85
|
disabledReason={disabledReason}
|
|
86
|
+
onApproveAnyway={onApproveAnyway}
|
|
87
|
+
approvingAnyway={approvingAnyway}
|
|
88
|
+
approvedAnyway={approvedAnyway}
|
|
70
89
|
/>
|
|
71
90
|
)}
|
|
72
91
|
|
|
@@ -274,28 +293,61 @@ type CardFooterProps = {
|
|
|
274
293
|
onResolve: (resolution: ManualActionResolution) => void;
|
|
275
294
|
canResolve: boolean;
|
|
276
295
|
disabledReason?: string;
|
|
296
|
+
onApproveAnyway?: () => void;
|
|
297
|
+
approvingAnyway: boolean;
|
|
298
|
+
approvedAnyway: boolean;
|
|
277
299
|
};
|
|
278
300
|
|
|
279
301
|
function CardFooter(props: CardFooterProps) {
|
|
280
|
-
const {
|
|
302
|
+
const {
|
|
303
|
+
isResolving,
|
|
304
|
+
resolvingChoice,
|
|
305
|
+
retryable,
|
|
306
|
+
defaultResolution,
|
|
307
|
+
onResolve,
|
|
308
|
+
canResolve,
|
|
309
|
+
disabledReason,
|
|
310
|
+
onApproveAnyway,
|
|
311
|
+
approvingAnyway,
|
|
312
|
+
approvedAnyway,
|
|
313
|
+
} = props;
|
|
281
314
|
const choices = resolutionChoices(retryable, defaultResolution);
|
|
315
|
+
const busy = isResolving || approvingAnyway || approvedAnyway;
|
|
282
316
|
|
|
283
317
|
return (
|
|
284
318
|
<div className="flex items-center bg-muted px-3 py-3">
|
|
285
319
|
<DisabledActionTooltip reason={canResolve ? undefined : disabledReason}>
|
|
286
320
|
<div className="flex flex-wrap items-center gap-2">
|
|
287
321
|
{choices.map((choice, index) => (
|
|
288
|
-
<
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
322
|
+
<Fragment key={choice}>
|
|
323
|
+
{choice === "REJECTED" && approvedAnyway && (
|
|
324
|
+
<span className="typography-tiny text-muted-foreground">
|
|
325
|
+
Approved. This review closes when the plan next runs.
|
|
326
|
+
</span>
|
|
327
|
+
)}
|
|
328
|
+
{choice === "REJECTED" && onApproveAnyway && !approvedAnyway && (
|
|
329
|
+
<Button
|
|
330
|
+
size="sm"
|
|
331
|
+
rounded="lg"
|
|
332
|
+
variant="secondary"
|
|
333
|
+
icon={BadgeCheck}
|
|
334
|
+
label="Approve anyway"
|
|
335
|
+
disabled={!canResolve || busy}
|
|
336
|
+
isLoading={approvingAnyway}
|
|
337
|
+
onClick={onApproveAnyway}
|
|
338
|
+
/>
|
|
339
|
+
)}
|
|
340
|
+
<Button
|
|
341
|
+
size="sm"
|
|
342
|
+
rounded="lg"
|
|
343
|
+
variant={index === 0 ? "primary" : "tertiary"}
|
|
344
|
+
icon={choiceIcons[choice]}
|
|
345
|
+
label={choiceLabels[choice]}
|
|
346
|
+
disabled={!canResolve || busy}
|
|
347
|
+
isLoading={isResolving && resolvingChoice === choice}
|
|
348
|
+
onClick={() => onResolve(choice)}
|
|
349
|
+
/>
|
|
350
|
+
</Fragment>
|
|
299
351
|
))}
|
|
300
352
|
</div>
|
|
301
353
|
</DisabledActionTooltip>
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
type ManualActionResolution,
|
|
9
9
|
type ManualActionResolving,
|
|
10
10
|
} from "#hooks/use-manual-actions";
|
|
11
|
+
import { approvalReviewKey } from "#lib/manual-actions";
|
|
11
12
|
|
|
12
13
|
export type ManualActionListViewProps = {
|
|
13
14
|
actions: ManualAction[];
|
|
@@ -19,6 +20,10 @@ export type ManualActionListViewProps = {
|
|
|
19
20
|
isLoading?: boolean;
|
|
20
21
|
failed?: boolean;
|
|
21
22
|
emptyFallback?: ReactNode;
|
|
23
|
+
approvableAnalyses?: Map<string, string>;
|
|
24
|
+
onApproveAnyway?: (analysisIri: string, reviewKey: string) => void;
|
|
25
|
+
approvingAnyway?: ReadonlySet<string>;
|
|
26
|
+
approvedAnyway?: ReadonlySet<string>;
|
|
22
27
|
};
|
|
23
28
|
|
|
24
29
|
const skeletonShapes = [
|
|
@@ -38,6 +43,10 @@ export function ManualActionListView(props: ManualActionListViewProps) {
|
|
|
38
43
|
isLoading = false,
|
|
39
44
|
failed = false,
|
|
40
45
|
emptyFallback,
|
|
46
|
+
approvableAnalyses,
|
|
47
|
+
onApproveAnyway,
|
|
48
|
+
approvingAnyway,
|
|
49
|
+
approvedAnyway,
|
|
41
50
|
} = props;
|
|
42
51
|
|
|
43
52
|
if (isLoading) {
|
|
@@ -75,17 +84,27 @@ export function ManualActionListView(props: ManualActionListViewProps) {
|
|
|
75
84
|
|
|
76
85
|
return (
|
|
77
86
|
<div className="flex flex-col">
|
|
78
|
-
{actions.map((action) =>
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
{actions.map((action) => {
|
|
88
|
+
const analysisIri = approvableAnalyses?.get(action.subjectIri);
|
|
89
|
+
return (
|
|
90
|
+
<ManualActionCard
|
|
91
|
+
key={action.subjectIri}
|
|
92
|
+
manualAction={action}
|
|
93
|
+
entities={targetsBySubject?.get(action.subjectIri) ?? []}
|
|
94
|
+
resolving={resolving}
|
|
95
|
+
onResolve={(resolution) => onResolve(action, resolution)}
|
|
96
|
+
canResolve={canResolve}
|
|
97
|
+
disabledReason={disabledReason}
|
|
98
|
+
onApproveAnyway={
|
|
99
|
+
isPresent(analysisIri) && onApproveAnyway
|
|
100
|
+
? () => onApproveAnyway(analysisIri, approvalReviewKey(action))
|
|
101
|
+
: undefined
|
|
102
|
+
}
|
|
103
|
+
approvingAnyway={isPresent(analysisIri) && (approvingAnyway?.has(analysisIri) ?? false)}
|
|
104
|
+
approvedAnyway={approvedAnyway?.has(approvalReviewKey(action)) ?? false}
|
|
105
|
+
/>
|
|
106
|
+
);
|
|
107
|
+
})}
|
|
89
108
|
</div>
|
|
90
109
|
);
|
|
91
110
|
}
|
|
@@ -1,9 +1,35 @@
|
|
|
1
1
|
import { GQLActionPlanState } from "@manta-eu/client";
|
|
2
|
+
import { isPresent } from "@manta-eu/lib/present";
|
|
2
3
|
import { match } from "ts-pattern";
|
|
3
|
-
|
|
4
|
+
|
|
5
|
+
export function parseTimestampMs(timestamp: string | null | undefined): number | null {
|
|
6
|
+
if (!timestamp) return null;
|
|
7
|
+
const value = new Date(timestamp).getTime();
|
|
8
|
+
return Number.isFinite(value) ? value : null;
|
|
9
|
+
}
|
|
4
10
|
|
|
5
11
|
export type ExecutionStatus = "idle" | "running" | "completed" | "failed" | "needs-approval";
|
|
6
12
|
|
|
13
|
+
export type RunSurface = "completed-changes" | "run" | "starting-run" | "loading" | "none";
|
|
14
|
+
|
|
15
|
+
export type DeriveRunSurfaceArgs = {
|
|
16
|
+
executionStatus: ExecutionStatus;
|
|
17
|
+
runIri: string | null;
|
|
18
|
+
hasCompletedChangesSlot: boolean;
|
|
19
|
+
isLoading: boolean;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export function deriveRunSurface(args: DeriveRunSurfaceArgs): RunSurface {
|
|
23
|
+
const { executionStatus, runIri, hasCompletedChangesSlot, isLoading } = args;
|
|
24
|
+
|
|
25
|
+
if (executionStatus === "completed" && hasCompletedChangesSlot) return "completed-changes";
|
|
26
|
+
if (isPresent(runIri)) return "run";
|
|
27
|
+
if (executionStatus === "running" || executionStatus === "needs-approval") return "starting-run";
|
|
28
|
+
if (isLoading) return "loading";
|
|
29
|
+
|
|
30
|
+
return "none";
|
|
31
|
+
}
|
|
32
|
+
|
|
7
33
|
export type DeriveExecutionStatusArgs = {
|
|
8
34
|
provenance: {
|
|
9
35
|
planErrorMessage: string | null;
|
|
@@ -108,6 +108,7 @@ export function formatIntegration(integration: GQLIntegration | null): string {
|
|
|
108
108
|
.with(GQLIntegration.Slack, () => "Slack")
|
|
109
109
|
.with(GQLIntegration.Figma, () => "Figma")
|
|
110
110
|
.with(GQLIntegration.Dash, () => "Dash")
|
|
111
|
+
.with(GQLIntegration.Canva, () => "Canva")
|
|
111
112
|
.exhaustive();
|
|
112
113
|
}
|
|
113
114
|
|
|
@@ -123,6 +124,7 @@ export function integrationToChannel(integration: GQLIntegration): Channel | nul
|
|
|
123
124
|
[GQLIntegration.Slack]: null,
|
|
124
125
|
[GQLIntegration.Figma]: null,
|
|
125
126
|
[GQLIntegration.Dash]: null,
|
|
127
|
+
[GQLIntegration.Canva]: null,
|
|
126
128
|
} as const satisfies Record<GQLIntegration, Channel | null>;
|
|
127
129
|
|
|
128
130
|
return integrationChannelMap[integration];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { GetRulesToolResult } from "./types";
|
|
2
2
|
|
|
3
3
|
type ListRulesResultDisplayProps = {
|
|
4
|
-
result:
|
|
4
|
+
result: GetRulesToolResult;
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
export function ListRulesResultDisplay(_props: ListRulesResultDisplayProps) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { withDatastoreQueryParam } from "@manta-eu/client/shared/datastore-path";
|
|
1
2
|
import { isShowEntitiesResult } from "@manta-eu/client/shared/tools";
|
|
2
3
|
import {
|
|
3
4
|
isWorkspaceArtifactInlineMediaType,
|
|
@@ -17,7 +18,7 @@ import type {
|
|
|
17
18
|
ChartToolResult,
|
|
18
19
|
ErrorToolResult,
|
|
19
20
|
ExplainFactToolResult,
|
|
20
|
-
|
|
21
|
+
GetRulesToolResult,
|
|
21
22
|
ManageRulesResult,
|
|
22
23
|
ShowcaseToolResult,
|
|
23
24
|
ShowEntitiesToolResult,
|
|
@@ -26,8 +27,8 @@ import type {
|
|
|
26
27
|
import {
|
|
27
28
|
isChartToolResult,
|
|
28
29
|
isErrorToolResult,
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
isExplainFactToolResult,
|
|
31
|
+
isGetRulesToolResult,
|
|
31
32
|
isManageRulesResult,
|
|
32
33
|
isShowcaseToolResult,
|
|
33
34
|
isWorkspaceArtifactResult,
|
|
@@ -45,6 +46,7 @@ import {
|
|
|
45
46
|
import { decodeChartEntities } from "#lib/decode-chart-entities";
|
|
46
47
|
import { cn } from "#lib/utils";
|
|
47
48
|
import { useChatManagerConnection } from "#providers/ChatManagerProvider";
|
|
49
|
+
import { useMantaClient } from "#providers/MantaClientProvider";
|
|
48
50
|
|
|
49
51
|
type ErrorResultDisplayProps = {
|
|
50
52
|
result: ErrorToolResult;
|
|
@@ -126,11 +128,13 @@ type WorkspaceArtifactResultDisplayProps = {
|
|
|
126
128
|
function WorkspaceArtifactResultDisplay(props: WorkspaceArtifactResultDisplayProps) {
|
|
127
129
|
const { result } = props;
|
|
128
130
|
|
|
131
|
+
const { datastoreId } = useMantaClient();
|
|
132
|
+
|
|
129
133
|
return (
|
|
130
134
|
<FileMessagePart
|
|
131
135
|
part={{
|
|
132
136
|
type: "file",
|
|
133
|
-
url: result.url,
|
|
137
|
+
url: withDatastoreQueryParam(result.url, datastoreId),
|
|
134
138
|
mediaType: result.mediaType,
|
|
135
139
|
filename: result.filename,
|
|
136
140
|
}}
|
|
@@ -151,10 +155,8 @@ export function ToolOutputRenderer(props: ToolOutputRendererProps) {
|
|
|
151
155
|
.when(isErrorToolResult, (errorResult: ErrorToolResult) => <ErrorResultDisplay result={errorResult} />)
|
|
152
156
|
.when(isChartToolResult, (chartResult: ChartToolResult) => <ChartResultDisplay result={chartResult} />)
|
|
153
157
|
.when(isManageRulesResult, (rulesResult: ManageRulesResult) => <ManageRulesResultDisplay result={rulesResult} />)
|
|
154
|
-
.when(
|
|
155
|
-
|
|
156
|
-
))
|
|
157
|
-
.when(isExplainRDFoxRulesResult, (explainResult: ExplainFactToolResult) => (
|
|
158
|
+
.when(isGetRulesToolResult, (rulesResult: GetRulesToolResult) => <ListRulesResultDisplay result={rulesResult} />)
|
|
159
|
+
.when(isExplainFactToolResult, (explainResult: ExplainFactToolResult) => (
|
|
158
160
|
<ExplainFactResultDisplay result={explainResult} toolUIPart={toolUIPart} />
|
|
159
161
|
))
|
|
160
162
|
.when(isShowcaseToolResult, (showcaseResult: ShowcaseToolResult) => (
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
type ActionPlanShowcaseOutput,
|
|
4
4
|
type ShowEntitiesOutput,
|
|
5
5
|
} from "@manta-eu/client/shared/tools";
|
|
6
|
-
import type {
|
|
6
|
+
import type { GetRulesOutputSuccess } from "@manta-eu/client/shared/tools/types";
|
|
7
7
|
import { workspaceArtifactSchema, type WorkspaceArtifact } from "@manta-eu/client/shared/workspace-artifacts";
|
|
8
8
|
import { isJsonLdDocument } from "@manta-eu/client/types/jsonld";
|
|
9
9
|
import type { DatalogRule, InferenceVerificationResult } from "@manta-eu/datalog-parser";
|
|
@@ -45,7 +45,7 @@ export type StagedManageRulesResult = ManageRulesResult & {
|
|
|
45
45
|
|
|
46
46
|
export type ShowcaseToolResult = Extract<ActionPlanShowcaseOutput, { planIri: string }>;
|
|
47
47
|
export type ShowEntitiesToolResult = Extract<ShowEntitiesOutput, { entityIris: string[] }>;
|
|
48
|
-
export type
|
|
48
|
+
export type GetRulesToolResult = GetRulesOutputSuccess;
|
|
49
49
|
export type ExplainFactToolResult = ExplainFactOutput;
|
|
50
50
|
|
|
51
51
|
export type ToolResult =
|
|
@@ -54,7 +54,7 @@ export type ToolResult =
|
|
|
54
54
|
| ManageRulesResult
|
|
55
55
|
| ShowcaseToolResult
|
|
56
56
|
| ShowEntitiesToolResult
|
|
57
|
-
|
|
|
57
|
+
| GetRulesToolResult
|
|
58
58
|
| ExplainFactToolResult
|
|
59
59
|
| WorkspaceArtifact
|
|
60
60
|
| { content: Array<{ type: string; text: string }> }
|
|
@@ -95,11 +95,11 @@ export function isShowcaseToolResult(result: unknown): result is ShowcaseToolRes
|
|
|
95
95
|
return isObjectWithProps(result, ["planIri"]);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
export function
|
|
98
|
+
export function isGetRulesToolResult(result: unknown): result is GetRulesOutputSuccess {
|
|
99
99
|
return isObjectWithProps(result, ["rules"]) && Array.isArray(result.rules);
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
export function
|
|
102
|
+
export function isExplainFactToolResult(result: unknown): result is ExplainFactToolResult {
|
|
103
103
|
if (typeof result !== "object" || result === null || Array.isArray(result)) return false;
|
|
104
104
|
if ("is_error" in result || "rules" in result || "type" in result) return false;
|
|
105
105
|
|
|
@@ -120,8 +120,8 @@ export function hasVisualOutput(output: unknown): boolean {
|
|
|
120
120
|
isManageRulesResult(output) ||
|
|
121
121
|
isShowcaseToolResult(output) ||
|
|
122
122
|
isShowEntitiesResult(output) ||
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
isGetRulesToolResult(output) ||
|
|
124
|
+
isExplainFactToolResult(output) ||
|
|
125
125
|
isWorkspaceArtifactResult(output))
|
|
126
126
|
);
|
|
127
127
|
}
|
|
@@ -129,7 +129,7 @@ export function hasVisualOutput(output: unknown): boolean {
|
|
|
129
129
|
export function hasInlineVisualOutput(output: unknown): boolean {
|
|
130
130
|
return (
|
|
131
131
|
isChartToolResult(output) ||
|
|
132
|
-
|
|
132
|
+
isExplainFactToolResult(output) ||
|
|
133
133
|
isShowEntitiesResult(output) ||
|
|
134
134
|
isWorkspaceArtifactResult(output)
|
|
135
135
|
);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
4
|
-
import type { ComponentPropsWithoutRef, ElementRef } from "react";
|
|
5
|
-
import { forwardRef } from "react";
|
|
4
|
+
import type { ComponentPropsWithoutRef, ElementRef, ReactNode } from "react";
|
|
5
|
+
import { forwardRef, useState } from "react";
|
|
6
6
|
import { cn } from "#style";
|
|
7
7
|
|
|
8
8
|
export const TooltipProvider = TooltipPrimitive.Provider;
|
|
@@ -43,3 +43,36 @@ export const TooltipContent = forwardRef<ElementRef<typeof TooltipPrimitive.Cont
|
|
|
43
43
|
),
|
|
44
44
|
);
|
|
45
45
|
TooltipContent.displayName = "TooltipContent";
|
|
46
|
+
|
|
47
|
+
export type TruncateTooltipProps = { text: string; className: string; children?: ReactNode };
|
|
48
|
+
|
|
49
|
+
export function TruncateTooltip(props: TruncateTooltipProps) {
|
|
50
|
+
const { text, className, children } = props;
|
|
51
|
+
|
|
52
|
+
const [isTruncated, setIsTruncated] = useState(false);
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<Tooltip>
|
|
56
|
+
<TooltipTrigger asChild>
|
|
57
|
+
<span
|
|
58
|
+
className={className}
|
|
59
|
+
onMouseEnter={(event) => {
|
|
60
|
+
const element = event.currentTarget;
|
|
61
|
+
// Line height can round a single line 1px taller than its box, so only a real clamp counts.
|
|
62
|
+
setIsTruncated(
|
|
63
|
+
element.scrollWidth > element.clientWidth || element.scrollHeight > element.clientHeight + 1,
|
|
64
|
+
);
|
|
65
|
+
}}
|
|
66
|
+
>
|
|
67
|
+
{children ?? text}
|
|
68
|
+
</span>
|
|
69
|
+
</TooltipTrigger>
|
|
70
|
+
|
|
71
|
+
{isTruncated && (
|
|
72
|
+
<TooltipContent showArrow={false} className="max-h-64 max-w-sm overflow-y-auto break-words text-left">
|
|
73
|
+
<p className="typography-tiny">{text}</p>
|
|
74
|
+
</TooltipContent>
|
|
75
|
+
)}
|
|
76
|
+
</Tooltip>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
@@ -362,7 +362,7 @@ function ruleNameTermFromHeadText(headText: string): string {
|
|
|
362
362
|
return predicate.trim();
|
|
363
363
|
}
|
|
364
364
|
|
|
365
|
-
// Explain payloads echo
|
|
365
|
+
// Explain payloads echo rules as the datastore serializes them (bare ON, atom-free aggregates),
|
|
366
366
|
// so authored text falls through to the expanded grammar when the strict parse fails.
|
|
367
367
|
function explainRuleAst(rule: string): DatalogRule | undefined {
|
|
368
368
|
return parseDatalogRuleCached(rule).ast ?? parseGroundedDatalogRuleCached(rule).ast ?? undefined;
|
|
@@ -415,7 +415,7 @@ function collectFormulaBindings(
|
|
|
415
415
|
.with({ type: "aggregate" }, (aggregate) => {
|
|
416
416
|
if (groundedFormula?.type !== "aggregate") return;
|
|
417
417
|
|
|
418
|
-
// AS targets first, then the aggregate's inner atoms —
|
|
418
|
+
// AS targets first, then the aggregate's inner atoms — the datastore grounds those too
|
|
419
419
|
// (e.g. `:clicks[?c, ?x]` → `:clicks[:C_1, 10]`), and first-wins keeps a head binding.
|
|
420
420
|
if (groundedFormula.bindings?.length === aggregate.bindings?.length) {
|
|
421
421
|
aggregate.bindings?.forEach((binding, index) => {
|
|
@@ -380,7 +380,7 @@ function flattenFacts(output: ExplainFactOutput): FactEntry[] {
|
|
|
380
380
|
const values = Array.isArray(value) ? value : [value];
|
|
381
381
|
|
|
382
382
|
return values.flatMap((fact, index) => {
|
|
383
|
-
if (!
|
|
383
|
+
if (!isExplainedFact(fact)) return [];
|
|
384
384
|
|
|
385
385
|
return [
|
|
386
386
|
{
|
|
@@ -393,7 +393,7 @@ function flattenFacts(output: ExplainFactOutput): FactEntry[] {
|
|
|
393
393
|
});
|
|
394
394
|
}
|
|
395
395
|
|
|
396
|
-
function
|
|
396
|
+
function isExplainedFact(value: unknown): value is ExplainedFact {
|
|
397
397
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
398
398
|
}
|
|
399
399
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ComponentType, createContext, type ReactNode, useContext } from "react";
|
|
2
|
+
|
|
3
|
+
export type EntityLinkProps = { iri: string; className?: string; children: ReactNode };
|
|
4
|
+
|
|
5
|
+
export type EntityLinkComponent = ComponentType<EntityLinkProps>;
|
|
6
|
+
|
|
7
|
+
// The host app supplies how an entity opens (its router and record route); without one, entities render unlinked.
|
|
8
|
+
const EntityLinkContext = createContext<EntityLinkComponent | undefined>(undefined);
|
|
9
|
+
|
|
10
|
+
export type EntityLinkProviderProps = { component: EntityLinkComponent; children: ReactNode };
|
|
11
|
+
|
|
12
|
+
export function EntityLinkProvider(props: EntityLinkProviderProps) {
|
|
13
|
+
const { component, children } = props;
|
|
14
|
+
|
|
15
|
+
return <EntityLinkContext.Provider value={component}>{children}</EntityLinkContext.Provider>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function useEntityLink(): EntityLinkComponent | undefined {
|
|
19
|
+
return useContext(EntityLinkContext);
|
|
20
|
+
}
|
|
@@ -87,6 +87,7 @@ export type NodePropertyChange = {
|
|
|
87
87
|
|
|
88
88
|
export type NodePropertyPreview = {
|
|
89
89
|
id: string;
|
|
90
|
+
predicate?: string;
|
|
90
91
|
label: string;
|
|
91
92
|
value: string;
|
|
92
93
|
changeType?: PropertyChangeType;
|
|
@@ -162,6 +163,7 @@ export function selectPriorityPreviewFields(
|
|
|
162
163
|
|
|
163
164
|
return {
|
|
164
165
|
id: `${property.key}-${index}`,
|
|
166
|
+
predicate: property.iri,
|
|
165
167
|
label: property.label ?? propertyLabelFromKey(property.key),
|
|
166
168
|
value,
|
|
167
169
|
rawValue: String(property.value),
|
package/src/graph/graph-model.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isFullIri } from "@manta-eu/client/shared/rdf-namespaces";
|
|
1
2
|
import { labelPredicateSuffixes } from "@manta-eu/rdf-lib/detail-view-types";
|
|
2
3
|
import { expandPrefix, wellKnownPredicates } from "@manta-eu/rdf-lib/namespaces";
|
|
3
4
|
import type { RdfGraph } from "../lib/rdf-helpers";
|
|
@@ -10,7 +11,7 @@ import {
|
|
|
10
11
|
import { humanizePredicateName, type NodesAndEdges, type RDFEdge, shortenUri } from "./graph-utils";
|
|
11
12
|
import { readVocabValue } from "./nodes/typed-node-helpers";
|
|
12
13
|
import { mantaLightTheme } from "./themes";
|
|
13
|
-
import type { LayoutDirection, NodeProperty, RDFNode } from "./types";
|
|
14
|
+
import type { LayoutDirection, NodeProperty, NodeRelation, RDFNode } from "./types";
|
|
14
15
|
|
|
15
16
|
const labelPredicate = wellKnownPredicates.label;
|
|
16
17
|
const rdfType = wellKnownPredicates.type;
|
|
@@ -44,6 +45,7 @@ type NodeAccumulator = {
|
|
|
44
45
|
label?: string;
|
|
45
46
|
type?: string;
|
|
46
47
|
data: Record<string, unknown>;
|
|
48
|
+
relations: NodeRelation[];
|
|
47
49
|
};
|
|
48
50
|
|
|
49
51
|
type GraphEdgeRecord = {
|
|
@@ -60,7 +62,7 @@ function createOrGetNodeAccumulator(
|
|
|
60
62
|
): NodeAccumulator {
|
|
61
63
|
let node = nodeData.get(subjectId);
|
|
62
64
|
if (!node) {
|
|
63
|
-
node = { data: {} };
|
|
65
|
+
node = { data: {}, relations: [] };
|
|
64
66
|
nodeData.set(subjectId, node);
|
|
65
67
|
connectionCounts.set(subjectId, 0);
|
|
66
68
|
}
|
|
@@ -159,7 +161,7 @@ function buildNodesAndEdges(
|
|
|
159
161
|
const allNodeIds = new Set(nodeData.keys());
|
|
160
162
|
const hubThreshold = computeHubThreshold(connectionCounts);
|
|
161
163
|
|
|
162
|
-
const graphNodes: RDFNode[] = Array.from(nodeData).map(([id, { label, type, data }]) => {
|
|
164
|
+
const graphNodes: RDFNode[] = Array.from(nodeData).map(([id, { label, type, data, relations }]) => {
|
|
163
165
|
const childIds = (parentChildMap.get(id) || []).filter((childId) => allNodeIds.has(childId));
|
|
164
166
|
const parentId = childParentMap.get(id);
|
|
165
167
|
const depth = nodeDepths.get(id) || 0;
|
|
@@ -193,6 +195,7 @@ function buildNodesAndEdges(
|
|
|
193
195
|
isHub: connCount >= hubThreshold,
|
|
194
196
|
jsonLd: { "@id": id, "@type": type, ...data },
|
|
195
197
|
properties,
|
|
198
|
+
relations,
|
|
196
199
|
childIds,
|
|
197
200
|
parentId,
|
|
198
201
|
isCollapsed: false,
|
|
@@ -334,11 +337,15 @@ export function rdfGraphToNodesAndEdges(
|
|
|
334
337
|
const longNumericPattern = /\d{10,}/;
|
|
335
338
|
const leafValueSchemes = ["http://", "https://", "s3://"];
|
|
336
339
|
|
|
340
|
+
// A stored file or web address is a value to render, not a neighbor (without `s3:`, a long digit run reads as a ref).
|
|
341
|
+
function isLeafValue(targetId: string): boolean {
|
|
342
|
+
const isNamespacedIri = targetId.includes("#") || targetId.includes("vocab");
|
|
343
|
+
return !isNamespacedIri && leafValueSchemes.some((scheme) => targetId.startsWith(scheme));
|
|
344
|
+
}
|
|
345
|
+
|
|
337
346
|
function isEnumLikeRef(targetId: string): boolean {
|
|
338
347
|
if (definedSubjects.has(targetId)) return false;
|
|
339
|
-
|
|
340
|
-
// A stored file is a value to render, not a neighbor: without `s3:` a key with a long digit run reads as a ref.
|
|
341
|
-
if (!isNamespacedIri && leafValueSchemes.some((scheme) => targetId.startsWith(scheme))) return true;
|
|
348
|
+
if (isLeafValue(targetId)) return true;
|
|
342
349
|
const localName = targetId.split(/[#/]/).pop() ?? targetId;
|
|
343
350
|
if (uuidPattern.test(localName) || longNumericPattern.test(localName)) return false;
|
|
344
351
|
return true;
|
|
@@ -379,10 +386,12 @@ export function rdfGraphToNodesAndEdges(
|
|
|
379
386
|
|
|
380
387
|
if (isEnumLikeRef(targetId)) {
|
|
381
388
|
mergeNodeValue(node.data, predicate, targetId);
|
|
389
|
+
if (!isLeafValue(targetId) && isFullIri(targetId)) node.relations.push({ predicate, target: targetId });
|
|
382
390
|
continue;
|
|
383
391
|
}
|
|
384
392
|
|
|
385
393
|
createOrGetNodeAccumulator(nodeData, connectionCounts, targetId);
|
|
394
|
+
if (isFullIri(targetId)) node.relations.push({ predicate, target: targetId });
|
|
386
395
|
connectionCounts.set(subjectId, (connectionCounts.get(subjectId) || 0) + 1);
|
|
387
396
|
connectionCounts.set(targetId, (connectionCounts.get(targetId) || 0) + 1);
|
|
388
397
|
|
|
@@ -13,6 +13,7 @@ import { useRedirectEndpoint } from "#hooks/use-redirect-endpoint";
|
|
|
13
13
|
const filePredicate = `${namespaces.brand}file`;
|
|
14
14
|
const mimePredicate = `${namespaces.nmo}contentMimeType`;
|
|
15
15
|
const descriptionPredicate = `${namespaces.brand}assetDescription`;
|
|
16
|
+
const listedElsewhere = [filePredicate, mimePredicate, descriptionPredicate];
|
|
16
17
|
|
|
17
18
|
// The generated schema requires `m:file`, which only the planned request carries, so a lens read never matches.
|
|
18
19
|
export const BrandAssetAnalysisView = memo(function BrandAssetAnalysisView(props: EntityViewProps) {
|
|
@@ -46,8 +47,9 @@ export const BrandAssetAnalysisView = memo(function BrandAssetAnalysisView(props
|
|
|
46
47
|
|
|
47
48
|
<NodePropertyTable
|
|
48
49
|
properties={data.properties}
|
|
50
|
+
relations={data.relations}
|
|
49
51
|
jsonLd={data.jsonLd}
|
|
50
|
-
omitPredicates={
|
|
52
|
+
omitPredicates={listedElsewhere}
|
|
51
53
|
/>
|
|
52
54
|
</BrandNodeBody>
|
|
53
55
|
</EntityCardShell>
|
|
@@ -23,6 +23,7 @@ import { useFontFace } from "#hooks/use-font-face";
|
|
|
23
23
|
import { useRedirectEndpoint } from "#hooks/use-redirect-endpoint";
|
|
24
24
|
|
|
25
25
|
const weightPredicate = `${namespaces.brand}hasSuggestedWeight`;
|
|
26
|
+
const listedElsewhere = [weightPredicate];
|
|
26
27
|
const specimenText = "Aa Bb Cc Qq Rr 0123456789 — The quick brown fox jumps over the lazy dog";
|
|
27
28
|
|
|
28
29
|
function useSuggestedWeights(iris: string[]): SuggestedWeight[] {
|
|
@@ -118,7 +119,12 @@ export const BrandFontSuggestionView = memo(function BrandFontSuggestionView(pro
|
|
|
118
119
|
</ul>
|
|
119
120
|
)}
|
|
120
121
|
|
|
121
|
-
<NodePropertyTable
|
|
122
|
+
<NodePropertyTable
|
|
123
|
+
properties={data.properties}
|
|
124
|
+
jsonLd={data.jsonLd}
|
|
125
|
+
relations={data.relations}
|
|
126
|
+
omitPredicates={listedElsewhere}
|
|
127
|
+
/>
|
|
122
128
|
</BrandNodeBody>
|
|
123
129
|
</EntityCardShell>
|
|
124
130
|
);
|
|
@@ -18,7 +18,7 @@ export const BrandGuidelinesView = memo(function BrandGuidelinesView(props: Enti
|
|
|
18
18
|
onContextMenu={onContextMenu}
|
|
19
19
|
>
|
|
20
20
|
<BrandNodeBody>
|
|
21
|
-
<NodePropertyTable properties={data.properties} jsonLd={data.jsonLd} />
|
|
21
|
+
<NodePropertyTable properties={data.properties} jsonLd={data.jsonLd} relations={data.relations} />
|
|
22
22
|
</BrandNodeBody>
|
|
23
23
|
</EntityCardShell>
|
|
24
24
|
);
|