attach duration element
3clyp50 committed
Jan 29, 2026 at 20:35 UTC
499b7625b7b4976b898f8720a50c6b242bfdc250
1 file changed
+45
-20
webui/js/messages.js
+45
-20
@@ -239,6 +239,11 @@ function drawProcessStep({
239
const isNewStep = !step;
240
const isGroupComplete = isProcessGroupComplete(group);
241
242
+ // Set start timestamp on group when first step is created
243
+ if (isNewStep && !group.hasAttribute("data-start-timestamp") && log.timestamp) {
244
+ group.setAttribute("data-start-timestamp", String(log.timestamp));
245
+ }
246
+
247
if (isNewStep) {
248
// create the base DOM element for the step
249
step = document.createElement("div");
@@ -249,6 +254,11 @@ function drawProcessStep({
254
step.setAttribute("data-log-type", log.type);
255
step.setAttribute("data-step-id", id);
256
step.setAttribute("data-agent-number", log.agentno);
257
+
258
+ // set timestamp attribute (convert to milliseconds for duration calculation)
259
+ if (log.timestamp) {
260
+ step.setAttribute("data-timestamp", String(Math.round(log.timestamp * 1000)));
261
+ }
262
263
// apply step classes
264
if (classes) step.classList.add(...classes);
@@ -1647,7 +1657,6 @@ function createProcessGroup(id) {
1657
<span class="metric-time" title="Start time"><span class="material-symbols-outlined">schedule</span><span class="metric-value">--:--</span></span>
1658
<span class="metric-steps" title="Steps"><span class="material-symbols-outlined">footprint</span><span class="metric-value">0</span></span>
1659
<span class="metric-notifications" title="Warnings/Info/Hint" hidden><span class="material-symbols-outlined">priority_high</span><span class="metric-value">0</span></span>
1650
- <span class="metric-duration" title="Duration"><span class="material-symbols-outlined">timer</span><span class="metric-value">0s</span></span>
1660
</span>
1661
`;
1662
@@ -1918,26 +1927,42 @@ function updateProcessGroupHeader(group) {
1927
timeMetricEl.textContent = `${hours}:${minutes}`;
1928
}
1929
1921
- // Update duration metric
1922
- const durationMetricEl = metricsEl?.querySelector(
1923
- ".metric-duration .metric-value",
1930
+ const firstTimestampMs = parseInt(
1931
+ steps[0]?.getAttribute("data-timestamp") || "0",
1932
+ 10,
1933
);
1925
- if (durationMetricEl && steps.length > 0) {
1926
- const firstTimestampMs = parseInt(
1927
- steps[0]?.getAttribute("data-timestamp") || "0",
1928
- 10,
1929
- );
1930
-
1931
- const lastStep = steps[steps.length - 1];
1932
- const lastTimestampMs = parseInt(
1933
- lastStep.getAttribute("data-timestamp") || "0",
1934
- 10,
1935
- );
1936
-
1937
- const totalDurationMs = Math.max(0, lastTimestampMs - firstTimestampMs);
1938
-
1939
- durationMetricEl.textContent = formatDuration(totalDurationMs);
1940
- }
1934
+ const lastTimestampMs = parseInt(
1935
+ steps[steps.length - 1]?.getAttribute("data-timestamp") || "0",
1936
+ 10,
1937
+ );
1938
+ const durationText =
1939
+ isCompleted &&
1940
+ metricsEl &&
1941
+ steps.length > 0 &&
1942
+ firstTimestampMs > 0 &&
1943
+ lastTimestampMs > 0 &&
1944
+ formatDuration(Math.max(0, lastTimestampMs - firstTimestampMs));
1945
+
1946
+ const durationMetricEl =
1947
+ durationText &&
1948
+ (() => {
1949
+ const container = ensureChild(
1950
+ metricsEl,
1951
+ ".metric-duration",
1952
+ "span",
1953
+ "metric-duration",
1954
+ );
1955
+ container.title = "Duration";
1956
+ const icon = ensureChild(
1957
+ container,
1958
+ ".material-symbols-outlined",
1959
+ "span",
1960
+ "material-symbols-outlined",
1961
+ );
1962
+ icon.textContent = "timer";
1963
+ return ensureChild(container, ".metric-value", "span", "metric-value");
1964
+ })();
1965
+ durationMetricEl && (durationMetricEl.textContent = durationText);
1966
1967
if (notificationsEl) {
1968
const counts = { warning: 0, info: 0, hint: 0 };