Skip to content

Commit e001c9d

Browse files
committed
Cleanup and refinement
1 parent 7d5da48 commit e001c9d

15 files changed

Lines changed: 44 additions & 264 deletions

File tree

client/src/components/Graph/GraphEdges.vue

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
<script setup lang="ts">
22
import { curveBasisPath, orthogonalPath } from "@/utils/connectionPath";
33
4-
import type { GraphEdge } from "./types";
5-
6-
export type EdgeStyle = "orthogonal" | "curved";
4+
import type { EdgeStyle, GraphEdge } from "./types";
75
86
interface Props {
97
edges: GraphEdge[];
@@ -52,10 +50,6 @@ function edgeClass(edge: GraphEdge): Record<string, boolean> {
5250
"edge-collection": !!edge.isCollection,
5351
};
5452
}
55-
56-
function strokeWidth(edge: GraphEdge): number {
57-
return edge.isCollection ? 2 : 2;
58-
}
5953
</script>
6054

6155
<template>
@@ -66,7 +60,6 @@ function strokeWidth(edge: GraphEdge): number {
6660
:key="`${edge.id}-${idx}`"
6761
:d="path"
6862
:class="edgeClass(edge)"
69-
:stroke-width="strokeWidth(edge)"
7063
fill="none" />
7164
</template>
7265
</svg>

client/src/components/Graph/GraphNode.vue

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,6 @@ const iconSpin = computed(() => Boolean(props.node.data?.stateSpin));
6565
border-color 0.15s,
6666
box-shadow 0.15s,
6767
opacity 0.2s ease;
68-
69-
&:hover {
70-
border-color: $brand-primary;
71-
}
7268
}
7369
7470
.node-highlight {
@@ -100,10 +96,6 @@ const iconSpin = computed(() => Boolean(props.node.data?.stateSpin));
10096
padding: 1px 0;
10197
}
10298
103-
.input-data-row {
104-
position: relative;
105-
}
106-
10799
.output-data-row {
108100
text-align: right;
109101
}

client/src/components/Graph/GraphView.vue

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
<script setup lang="ts">
2-
import { useElementBounding, useScroll } from "@vueuse/core";
2+
import { useElementBounding } from "@vueuse/core";
33
import { computed, nextTick, type Ref, ref, watch } from "vue";
44
55
import { useD3Zoom } from "@/composables/d3Zoom";
66
import { useViewportBoundingBox } from "@/composables/viewportBoundingBox";
77
import { maxZoom, minZoom } from "@/utils/zoomLevels";
88
9-
import type { EdgeStyle } from "./GraphEdges.vue";
10-
import type { GraphLayout, GraphNode } from "./types";
9+
import type { EdgeStyle, GraphLayout, GraphNode } from "./types";
1110
1211
import GraphEdges from "./GraphEdges.vue";
1312
import GraphNodeComponent from "./GraphNode.vue";
@@ -19,8 +18,6 @@ interface Props {
1918
edgeStyle?: EdgeStyle;
2019
showZoomControls?: boolean;
2120
showMinimap?: boolean;
22-
showScrollOverlays?: boolean;
23-
showRightOverlay?: boolean;
2421
/** Minimap component — injected by consumer to avoid domain coupling */
2522
minimapComponent?: object | null;
2623
}
@@ -30,8 +27,6 @@ const props = withDefaults(defineProps<Props>(), {
3027
edgeStyle: "orthogonal",
3128
showZoomControls: true,
3229
showMinimap: true,
33-
showScrollOverlays: true,
34-
showRightOverlay: false,
3530
minimapComponent: null,
3631
});
3732
@@ -46,8 +41,7 @@ const scale = ref(1);
4641
// d3 zoom is attached to the inner canvas-container, NOT the outer wrapper.
4742
// This keeps ZoomControl and minimap outside the d3 event target.
4843
const canvasContainer: Ref<HTMLElement | null> = ref(null);
49-
const scroll = useScroll(canvasContainer);
50-
const { transform, setZoom, panBy, moveTo } = useD3Zoom(1, minZoom, maxZoom, canvasContainer, scroll, { x: 50, y: 50 });
44+
const { transform, setZoom, panBy, moveTo } = useD3Zoom(1, minZoom, maxZoom, canvasContainer, { x: 50, y: 50 });
5145
5246
// Element bounding for viewport computation (needed by minimap)
5347
const elementBounding = useElementBounding(canvasContainer, { windowResize: false, windowScroll: false });
@@ -65,7 +59,6 @@ watch(
6559
6660
function onZoom(zoomLevel: number) {
6761
setZoom(zoomLevel);
68-
scale.value = zoomLevel;
6962
}
7063
7164
const canvasStyle = computed(() => ({
@@ -132,7 +125,6 @@ watch(
132125
<template>
133126
<div class="graph-canvas rounded">
134127
<ZoomControl v-if="showZoomControls" :zoom-level="scale" @onZoom="onZoom" />
135-
<div v-if="showScrollOverlays && showRightOverlay" class="scroll-overlay overlay-right" />
136128
<div ref="canvasContainer" class="canvas-container" @pointerdown="onPointerDown" @pointerup="onPointerUp">
137129
<div v-if="layout" class="graph-node-area" :style="canvasStyle">
138130
<GraphEdges
@@ -186,18 +178,4 @@ watch(
186178
left: 0;
187179
transform-origin: 0 0;
188180
}
189-
190-
.scroll-overlay {
191-
position: absolute;
192-
top: 0;
193-
bottom: 0;
194-
width: 1.5rem;
195-
background: $gray-200;
196-
opacity: 0.5;
197-
z-index: 1;
198-
199-
&.overlay-right {
200-
right: 0;
201-
}
202-
}
203181
</style>

client/src/components/Graph/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ export interface GraphEdge {
3636
points: { x: number; y: number }[];
3737
}
3838

39+
/** Edge rendering style */
40+
export type EdgeStyle = "orthogonal" | "curved";
41+
3942
/** Complete layout result ready for rendering */
4043
export interface GraphLayout {
4144
nodes: GraphNode[];

client/src/components/History/Graph/HistoryGraphDetails.vue

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,9 @@ import LoadingSpan from "@/components/LoadingSpan.vue";
1212
1313
interface Props {
1414
node: GraphNode;
15-
details?: { label: string; value: string }[];
1615
}
1716
18-
const props = withDefaults(defineProps<Props>(), {
19-
details: () => [],
20-
});
17+
const props = defineProps<Props>();
2118
2219
const nodeType = computed(() => (props.node?.data?.type as string) ?? null);
2320
const encodedId = computed(() => (props.node?.data?.encodedId as string) ?? null);
@@ -85,14 +82,6 @@ watch(
8582
<BAlert v-else-if="jobError" variant="info" show class="mb-0">{{ jobError }}</BAlert>
8683
<JobInformation v-else-if="jobId" :job-id="jobId" :include-times="true" />
8784
</div>
88-
89-
<!-- Fallback -->
90-
<div v-else class="p-2">
91-
<div v-for="detail in details" :key="detail.label" class="text-muted small">
92-
<span class="font-weight-bold">{{ detail.label }}:</span>
93-
<span class="ml-1">{{ detail.value }}</span>
94-
</div>
95-
</div>
9685
</div>
9786
</div>
9887
</template>
@@ -104,14 +93,4 @@ watch(
10493
height: 100%;
10594
overflow-y: auto;
10695
}
107-
108-
.details-header {
109-
position: sticky;
110-
top: 0;
111-
z-index: 1;
112-
}
113-
114-
.details-body {
115-
overflow-y: auto;
116-
}
11796
</style>

client/src/components/History/Graph/HistoryGraphMinimap.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script setup lang="ts">
22
import type { Ref } from "vue";
3-
import { computed, onMounted, ref, watch } from "vue";
3+
import { computed, onMounted, ref, toRef, watch } from "vue";
44
55
import type { GraphLayout } from "@/components/Graph/types";
66
import { useAnimationFrame } from "@/composables/sensors/animationFrame";
@@ -55,9 +55,9 @@ const contentBounds = computed(() => {
5555
return aabb;
5656
});
5757
58-
const viewportBoundsRef = computed(() => props.viewportBoundingBox);
59-
const parentRightRef = computed(() => props.parentRight);
60-
const parentBottomRef = computed(() => props.parentBottom);
58+
const viewportBoundsRef = toRef(props, "viewportBoundingBox");
59+
const parentRightRef = toRef(props, "parentRight");
60+
const parentBottomRef = toRef(props, "parentBottom");
6161
6262
// ── Shared interaction ──
6363

client/src/components/History/Graph/HistoryGraphView.vue

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@ import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
44
import { BAlert } from "bootstrap-vue";
55
import { computed, ref, toRef } from "vue";
66
7-
import type { GraphNode } from "@/components/Graph/types";
7+
import type { EdgeStyle, GraphNode } from "@/components/Graph/types";
88
import { useHistoryStore } from "@/stores/historyStore";
99
10-
import { buildDetails } from "./historyGraphMapper";
1110
import { useHistoryGraphData } from "./useHistoryGraphData";
12-
import { type EdgeStyle, useHistoryGraphLayout } from "./useHistoryGraphLayout";
11+
import { useHistoryGraphLayout } from "./useHistoryGraphLayout";
1312
1413
import HistoryGraphDetails from "./HistoryGraphDetails.vue";
1514
import HistoryGraphMinimap from "./HistoryGraphMinimap.vue";
@@ -41,12 +40,6 @@ const { layout, layoutLoading } = useHistoryGraphLayout(graphData, edgeStyle);
4140
4241
// Selection
4342
const selectedNode = ref<GraphNode | null>(null);
44-
const selectedDetails = computed(() => {
45-
if (!selectedNode.value) {
46-
return [];
47-
}
48-
return buildDetails(selectedNode.value);
49-
});
5043
5144
function onNodeSelected(node: GraphNode | null) {
5245
selectedNode.value = node;
@@ -102,7 +95,7 @@ const isTruncated = computed(() => {
10295
:edge-style="edgeStyle"
10396
:minimap-component="HistoryGraphMinimap"
10497
@nodeSelected="onNodeSelected" />
105-
<HistoryGraphDetails v-if="selectedNode" :node="selectedNode" :details="selectedDetails" />
98+
<HistoryGraphDetails v-if="selectedNode" :node="selectedNode" />
10699
</div>
107100
<div v-if="isTruncated" class="history-graph-truncation">
108101
Showing a partial graph. Not all connections are visible.
@@ -148,12 +141,4 @@ const isTruncated = computed(() => {
148141
:deep(.node-collection) .graph-node-header {
149142
color: $text-color;
150143
}
151-
152-
:deep(.edge-collection) {
153-
stroke: $brand-primary;
154-
}
155-
156-
:deep(.edge-dataset) {
157-
stroke: $brand-primary;
158-
}
159144
</style>

client/src/components/History/Graph/historyGraphMapper.ts

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ export function mapNodes(apiNodes: ApiGraphNode[], apiEdges: ApiGraphEdge[]): Gr
169169

170170
// Data nodes always have a body (badge + state text)
171171
const hasBody = !isToolRequest;
172-
const label = resolveNodeLabel(node);
172+
const label = nodeLabels.get(node.id)!;
173173
return {
174174
id: node.id,
175175
x: 0,
@@ -213,32 +213,3 @@ export function mapEdges(apiEdges: ApiGraphEdge[]): GraphEdge[] {
213213
points: [],
214214
}));
215215
}
216-
217-
/**
218-
* Build detail lines for the details panel from a selected graph node.
219-
*/
220-
export function buildDetails(node: GraphNode): { label: string; value: string }[] {
221-
const details: { label: string; value: string }[] = [];
222-
const d = node.data ?? {};
223-
224-
details.push({ label: "Type", value: (d.typeLabel as string) ?? "Unknown" });
225-
226-
if (d.toolId) {
227-
details.push({ label: "Tool", value: d.toolId as string });
228-
}
229-
230-
const inputs = (d.inputCount as number) ?? 0;
231-
const outputs = (d.outputCount as number) ?? 0;
232-
const parts: string[] = [];
233-
if (inputs > 0) {
234-
parts.push(`${inputs} input${inputs !== 1 ? "s" : ""}`);
235-
}
236-
if (outputs > 0) {
237-
parts.push(`${outputs} output${outputs !== 1 ? "s" : ""}`);
238-
}
239-
if (parts.length > 0) {
240-
details.push({ label: "Connections", value: parts.join(", ") });
241-
}
242-
243-
return details;
244-
}

client/src/components/History/Graph/useHistoryGraphLayout.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import ELK, { type ElkExtendedEdge, type ElkNode } from "elkjs/lib/elk.bundled";
22
import { type Ref, ref, watch } from "vue";
33

4-
import type { GraphEdge, GraphLayout, GraphNode } from "@/components/Graph/types";
4+
import type { EdgeStyle, GraphEdge, GraphLayout, GraphNode } from "@/components/Graph/types";
55
import { computeControlPoints } from "@/utils/connectionPath";
66

77
import { type HistoryGraphResponse, mapEdges, mapNodes } from "./historyGraphMapper";
88

9-
export type EdgeStyle = "orthogonal" | "curved";
10-
119
const elk = new ELK();
1210

1311
/**

0 commit comments

Comments
 (0)