Skip to content

Commit 25745de

Browse files
bybashmadeindjs
andauthored
feat(UI): execution logs details [AB-685] (#1204)
* feat(UI): instance type filter [AB-721] * feat(UI): execution logs details [AB-685] * feat: review changes [AB-721] Co-authored-by: Alexandre Rousseau <alexandre@rsseau.fr> * feat: review changes [AB-685] --------- Co-authored-by: Alexandre Rousseau <alexandre@rsseau.fr>
1 parent e219eec commit 25745de

11 files changed

Lines changed: 661 additions & 62 deletions

src/ui/src/builder/BuilderApp.vue

Lines changed: 40 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -23,46 +23,45 @@
2323
>
2424
<template #top>
2525
<div class="builderMain">
26-
<KeepAlive include="BuilderJournal">
27-
<BuilderVault
28-
v-if="builderMode === 'vault'"
29-
key="vault"
30-
/>
31-
<BuilderJournal
32-
v-else-if="builderMode === 'journal'"
33-
key="journal"
34-
/>
35-
<div
36-
v-else
37-
key="renderer"
38-
ref="rendererWrapperEl"
39-
class="rendererWrapper"
26+
<BuilderVault v-if="builderMode === 'vault'" />
27+
<KeepAlive>
28+
<BuilderJournal v-if="builderMode === 'journal'" />
29+
</KeepAlive>
30+
<div
31+
v-if="
32+
builderMode !== 'vault' &&
33+
builderMode !== 'journal'
34+
"
35+
ref="rendererWrapperEl"
36+
class="rendererWrapper"
37+
:class="{
38+
addNoteCursor:
39+
notesManager.isAnnotating.value &&
40+
ssbm.mode.value !== 'preview',
41+
}"
42+
@scroll="refreshNotesPosition"
43+
>
44+
<ComponentRenderer
45+
ref="rendererEl"
46+
class="componentRenderer"
4047
:class="{
41-
addNoteCursor:
42-
notesManager.isAnnotating.value &&
43-
ssbm.mode.value !== 'preview',
48+
settingsOpen: ssbm.isSingleSelectionActive,
4449
}"
45-
@scroll="refreshNotesPosition"
50+
@dragover="handleRendererDragover"
51+
@dragstart="handleRendererDragStart"
52+
@dragend="handleRendererDragEnd"
53+
@drop="handleRendererDrop"
54+
@click.capture="handleRendererClick"
55+
@dblclick="handleRendererDblClick"
4656
>
47-
<ComponentRenderer
48-
ref="rendererEl"
49-
class="componentRenderer"
50-
:class="{
51-
settingsOpen:
52-
ssbm.isSingleSelectionActive,
53-
}"
54-
@dragover="handleRendererDragover"
55-
@dragstart="handleRendererDragStart"
56-
@dragend="handleRendererDragEnd"
57-
@drop="handleRendererDrop"
58-
@click.capture="handleRendererClick"
59-
@dblclick="handleRendererDblClick"
60-
>
61-
</ComponentRenderer>
62-
</div>
63-
</KeepAlive>
57+
</ComponentRenderer>
58+
</div>
6459
<BuilderSettings
65-
v-if="ssbm.isSingleSelectionActive"
60+
v-if="
61+
ssbm.isSingleSelectionActive &&
62+
builderMode !== 'journal' &&
63+
builderMode !== 'vault'
64+
"
6665
:key="selectedId ?? 'noneSelected'"
6766
/>
6867
</div>
@@ -126,9 +125,11 @@
126125
</template>
127126

128127
<!-- MODAL -->
129-
130128
<div id="modal"></div>
131129

130+
<!-- DRAWER -->
131+
<div id="drawer"></div>
132+
132133
<BuilderAppSocketTimeoutModal />
133134
<!-- TOOLTIP -->
134135

@@ -612,11 +613,11 @@ onUnmounted(() => {
612613
position: absolute;
613614
top: 0;
614615
left: 0;
615-
z-index: 10;
616+
z-index: 100;
616617
}
617618
618619
#tooltip {
619620
position: absolute;
620-
z-index: 11;
621+
z-index: 110;
621622
}
622623
</style>

src/ui/src/builder/BuilderJournal.vue

Lines changed: 63 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,52 @@
1111
v-for="(entry, key) of sortedEntries"
1212
:key="key"
1313
:journal-entry="entry"
14+
@click="openEntryDetails(entry)"
1415
></BuilderJournalEntry>
1516
</div>
17+
18+
<!-- Drawer for entry details -->
19+
<WdsDrawer
20+
v-model="isDrawerOpen"
21+
title="Execution Details"
22+
size="large"
23+
>
24+
<BuilderJournalEntryDetails
25+
v-if="selectedEntry"
26+
:entry="selectedEntry"
27+
@re-run="handleReRun"
28+
@go-to-trigger="handleGoToTrigger"
29+
/>
30+
</WdsDrawer>
1631
</div>
1732
</template>
1833

1934
<script setup lang="ts">
20-
import { computed, inject, onMounted, onActivated, ref } from "vue";
35+
import { computed, inject, ref, shallowRef, onActivated, onMounted } from "vue";
2136
import BuilderJournalHeader from "./journal/BuilderJournalHeader.vue";
2237
import BuilderJournalEntry from "./journal/BuilderJournalEntry.vue";
38+
import BuilderJournalEntryDetails from "./journal/BuilderJournalEntryDetails.vue";
39+
import WdsDrawer from "@/wds/WdsDrawer.vue";
2340
import { convertAbsolutePathtoFullURL } from "@/utils/url";
41+
import { downloadJson } from "@/utils/blob";
2442
import { useToasts } from "./useToast";
2543
import { Component, WriterComponentDefinition } from "@/writerTypes";
2644
import injectionKeys from "@/injectionKeys";
2745
import type { JournalFilters } from "./journal/journalTypes";
46+
import { useComponentActions } from "./useComponentActions";
2847
2948
defineOptions({
3049
name: "BuilderJournal",
3150
});
3251
3352
const { pushToast } = useToasts();
3453
const wf = inject(injectionKeys.core);
54+
const builderManager = inject(injectionKeys.builderManager);
55+
56+
const { goToComponentParentPage, goToChild } = useComponentActions(
57+
wf,
58+
builderManager,
59+
);
3560
3661
type ComponentInfo = {
3762
type: "blueprint" | "block";
@@ -72,6 +97,14 @@ const filters = ref<JournalFilters>({
7297
instanceTypes: [],
7398
});
7499
100+
const selectedEntry = shallowRef<JournalEntry | null>(null);
101+
const isDrawerOpen = computed({
102+
get: () => !!selectedEntry.value,
103+
set: (value) => {
104+
if (!value) selectedEntry.value = null;
105+
},
106+
});
107+
75108
const entries = computed<Record<string, JournalEntry>>(() => {
76109
return Object.fromEntries(
77110
Object.entries(rawEntries.value).map(([key, entry]) => {
@@ -185,20 +218,7 @@ const downloadAsJson = () => {
185218
return [key, rawEntries.value[key]];
186219
}),
187220
);
188-
const jsonString = JSON.stringify(rawFiltered, null, 2);
189-
const blob = new Blob([jsonString], { type: "application/json" });
190-
191-
const url = URL.createObjectURL(blob);
192-
try {
193-
const a = document.createElement("a");
194-
a.href = url;
195-
a.download = "agent-journal.json";
196-
document.body.appendChild(a);
197-
a.click();
198-
document.body.removeChild(a);
199-
} finally {
200-
window.URL.revokeObjectURL(url);
201-
}
221+
downloadJson(rawFiltered, "agent-journal.json");
202222
};
203223
204224
async function deleteEntries() {
@@ -239,6 +259,34 @@ async function deleteEntries() {
239259
rawEntries.value = newRawEntries;
240260
}
241261
262+
function openEntryDetails(entry: JournalEntry) {
263+
selectedEntry.value = entry;
264+
}
265+
266+
function handleReRun(entry: JournalEntry) {
267+
// TODO: Implement re-run logic
268+
// This would trigger the same blueprint/workflow with the same inputs
269+
pushToast({
270+
type: "info",
271+
message: `Re-run functionality for ${entry.title} will be implemented soon`,
272+
});
273+
// Placeholder for re-run implementation
274+
// Will trigger the blueprint/workflow execution with entry data
275+
}
276+
277+
function handleGoToTrigger(entry: JournalEntry) {
278+
// Close the drawer
279+
selectedEntry.value = null;
280+
281+
// Go to the trigger component
282+
goToComponentParentPage(entry.trigger.component.id);
283+
goToChild(entry.trigger.component.id);
284+
pushToast({
285+
type: "success",
286+
message: `Jumped to ${entry.title}`,
287+
});
288+
}
289+
242290
onMounted(() => {
243291
loadEntries();
244292
});

src/ui/src/builder/BuilderToasts.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const { toasts, removeToast } = useToasts();
2929
position: fixed;
3030
bottom: 12px;
3131
right: 12px;
32-
z-index: 5;
32+
z-index: 20;
3333
}
3434
3535
.BuilderToasts__toast {

src/ui/src/builder/journal/BuilderJournalEntry.vue

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<template>
2-
<div class="BuilderJournalEntry">
2+
<div
3+
class="BuilderJournalEntry BuilderJournalEntry--clickable"
4+
@click="$emit('click')"
5+
>
36
<div class="BuilderJournalEntry__summary">
47
<BuilderJournalEntryResult
58
:result="journalEntry.result"
@@ -37,6 +40,10 @@ const props = defineProps({
3740
journalEntry: { type: Object as PropType<JournalEntry>, required: true },
3841
});
3942
43+
defineEmits<{
44+
click: () => true;
45+
}>();
46+
4047
const dateObj = computed(() => new Date(props.journalEntry.timestamp));
4148
4249
const { formattedDate, formattedTime } = useDateTimeFormatter(dateObj, {
@@ -66,6 +73,15 @@ const { formattedDate, formattedTime } = useDateTimeFormatter(dateObj, {
6673
border-bottom: 1px solid #e4e7ed;
6774
}
6875
76+
.BuilderJournalEntry--clickable {
77+
cursor: pointer;
78+
transition: background-color 0.2s;
79+
}
80+
81+
.BuilderJournalEntry--clickable:hover {
82+
background-color: var(--wdsColorBlue1);
83+
}
84+
6985
.BuilderJournalEntry__summary {
7086
padding: 12px 0;
7187
width: fit-content;

0 commit comments

Comments
 (0)