Skip to content

Commit 7ea2dc3

Browse files
authored
Merge pull request #8674 from ProcessMaker/task/FOUR-28707
Task/FOUR-28707: Retrieve and show general session logs in the UI
2 parents 1f6187e + 40875ec commit 7ea2dc3

File tree

4 files changed

+139
-15
lines changed

4 files changed

+139
-15
lines changed

resources/js/admin/logs/components/Logs/BaseTable/BaseTable.vue

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
<template>
22
<div
33
class="
4-
tw-flex-1 tw-overflow-auto tw-rounded-xl tw-border tw-border-gray-200
5-
tw-shadow-md tw-shadow-zinc-200
4+
tw-flex-1 tw-overflow-auto tw-rounded-xl tw-border tw-border-gray-200 tw-shadow-zinc-200
65
"
76
>
87
<table class="tw-w-full tw-text-left tw-text-sm">
@@ -28,7 +27,14 @@
2827
:key="column.key"
2928
class="tw-px-6 tw-py-4 tw-text-gray-600 tw-border-b tw-border-gray-200 tw-whitespace-nowrap"
3029
>
31-
{{ getItemValue(item, column) }}
30+
<slot
31+
:name="`cell-${column.key}`"
32+
:value="getRawValue(item, column)"
33+
:item="item"
34+
:column="column"
35+
>
36+
{{ getItemValue(item, column) }}
37+
</slot>
3238
</td>
3339
</tr>
3440
</tbody>
@@ -43,11 +49,14 @@ export default {
4349
data: { type: Array, required: true },
4450
},
4551
methods: {
46-
getItemValue(item, column) {
47-
// Get value - handle dot-separated keys for nested properties
48-
const value = column.key.includes(".")
52+
getRawValue(item, column) {
53+
// Get raw value - handle dot-separated keys for nested properties
54+
return column.key.includes(".")
4955
? column.key.split(".").reduce((val, part) => (val == null ? undefined : val[part]), item)
5056
: item[column.key];
57+
},
58+
getItemValue(item, column) {
59+
const value = this.getRawValue(item, column);
5160
5261
// Apply format function if provided
5362
if (typeof column.format === "function") {

resources/js/admin/logs/components/Logs/LogContainer/LogContainer.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<template>
2-
<div class="tw-flex tw-gap-6">
3-
<sidebar />
2+
<div class="tw-flex tw-gap-3 tw-px-4 tw-h-full tw-min-h-0 tw-overflow-hidden">
3+
<sidebar class="tw-shrink-0" />
44

5-
<section class="tw-flex-1 tw-overflow-hidden">
6-
<div class="tw-flex tw-flex-col tw-rounded-xl tw-border tw-border-zinc-200 tw-p-4 tw-bg-white tw-h-screen">
5+
<section class="tw-flex-1 tw-min-w-0 tw-min-h-0 tw-overflow-hidden">
6+
<div class="tw-flex tw-flex-col tw-rounded-xl tw-border tw-border-zinc-200 tw-p-4 tw-bg-white tw-h-full">
77
<header-bar
88
v-model="search"
99
@search="onHandleSearch"

resources/js/admin/logs/components/Logs/LogTable/LogTable.vue

Lines changed: 118 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,101 @@
11
<template>
22
<div class="tw-flex tw-flex-col tw-flex-1 tw-min-h-0">
3+
<!-- Loading spinner -->
4+
<div
5+
v-if="loading"
6+
class="tw-flex tw-flex-1 tw-items-center tw-justify-center tw-min-h-[200px]"
7+
>
8+
<div class="tw-flex tw-flex-col tw-items-center tw-gap-3">
9+
<svg
10+
class="tw-animate-spin tw-h-8 tw-w-8 tw-text-blue-500"
11+
xmlns="http://www.w3.org/2000/svg"
12+
fill="none"
13+
viewBox="0 0 24 24"
14+
>
15+
<circle
16+
class="tw-opacity-25"
17+
cx="12"
18+
cy="12"
19+
r="10"
20+
stroke="currentColor"
21+
stroke-width="4"
22+
/>
23+
<path
24+
class="tw-opacity-75"
25+
fill="currentColor"
26+
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
27+
/>
28+
</svg>
29+
<span class="tw-text-sm tw-text-gray-500">{{ $t('Loading...') }}</span>
30+
</div>
31+
</div>
32+
33+
<!-- Table content -->
334
<base-table
35+
v-else
436
:columns="columns"
537
:data="data"
6-
/>
38+
>
39+
<!-- Custom case_number cell with link to case -->
40+
<template #cell-case_number="{ value }">
41+
<a
42+
v-if="value"
43+
:href="`/cases/${value}`"
44+
class="tw-text-blue-600 hover:tw-text-blue-800 hover:tw-underline tw-font-medium"
45+
>
46+
#{{ value }}
47+
</a>
48+
<span v-else class="tw-text-gray-400">-</span>
49+
</template>
50+
51+
<!-- Custom status cell with colored badge -->
52+
<template #cell-status="{ value }">
53+
<span
54+
class="tw-inline-flex tw-items-center tw-px-2.5 tw-py-0.5 tw-rounded-full tw-text-xs tw-font-medium"
55+
:class="getStatusClasses(value)"
56+
>
57+
{{ formatStatus(value) }}
58+
</span>
59+
</template>
60+
61+
<!-- Custom tokens_used cell with hover popover -->
62+
<template #cell-tokens_used="{ value, item }">
63+
<div class="tw-relative tw-group tw-inline-block">
64+
<span class="tw-cursor-help tw-border-b tw-border-dotted tw-border-gray-400">
65+
{{ value }}
66+
</span>
67+
<!-- Popover tooltip -->
68+
<div
69+
class="
70+
tw-absolute tw-z-50 tw-bottom-full tw-left-1/2 tw--translate-x-1/2 tw-mb-2
71+
tw-hidden group-hover:tw-block
72+
tw-bg-gray-900 tw-text-white tw-text-xs tw-rounded-lg tw-py-2 tw-px-3
73+
tw-whitespace-nowrap tw-shadow-lg
74+
"
75+
>
76+
<div class="tw-flex tw-flex-col tw-gap-1">
77+
<div class="tw-flex tw-justify-between tw-gap-4">
78+
<span class="tw-text-gray-400">{{ $t('Input') }}:</span>
79+
<span class="tw-font-medium">{{ item.input_tokens }}</span>
80+
</div>
81+
<div class="tw-flex tw-justify-between tw-gap-4">
82+
<span class="tw-text-gray-400">{{ $t('Output') }}:</span>
83+
<span class="tw-font-medium">{{ item.output_tokens }}</span>
84+
</div>
85+
</div>
86+
<!-- Arrow -->
87+
<div
88+
class="
89+
tw-absolute tw-top-full tw-left-1/2 tw--translate-x-1/2
90+
tw-border-4 tw-border-transparent tw-border-t-gray-900
91+
"
92+
/>
93+
</div>
94+
</div>
95+
</template>
96+
</base-table>
797
<pagination
98+
v-if="!loading"
899
class="tw-mt-3 tw-shrink-0"
9100
:page="page"
10101
:total-pages="totalPages"
@@ -39,6 +130,7 @@ export default {
39130
page: 1,
40131
totalPages: 1,
41132
perPage: 15,
133+
loading: false,
42134
};
43135
},
44136
computed: {
@@ -83,19 +175,23 @@ export default {
83175
design: [
84176
{ key: 'flow_genie_name', label: this.$t('FlowGenie Name') },
85177
{ key: 'user_name', label: this.$t('User') },
178+
{ key: 'model', label: this.$t('Model') },
86179
{ key: 'status', label: this.$t('Status') },
87180
{ key: 'duration', label: this.$t('Execution Time') },
181+
{ key: 'llm_calls', label: this.$t('LLM Calls') },
88182
{ key: 'tools', label: this.$t('Tools') },
89183
{ key: 'tokens_used', label: this.$t('Tokens Used') },
90184
{ key: 'created_at', label: this.$t('Date'), format: dateFormatter },
91185
],
92186
execution: [
93-
{ key: 'process_request_id', label: this.$t('Request ID') },
94-
{ key: 'node_id', label: this.$t('Node ID') },
187+
{ key: 'case_number', label: this.$t('Case #') },
188+
{ key: 'process_name', label: this.$t('Process') },
189+
{ key: 'node_name', label: this.$t('Node') },
95190
{ key: 'flow_genie_name', label: this.$t('FlowGenie Name') },
96191
{ key: 'user_name', label: this.$t('User') },
97192
{ key: 'status', label: this.$t('Status') },
98193
{ key: 'duration', label: this.$t('Execution Time') },
194+
{ key: 'llm_calls', label: this.$t('LLM Calls') },
99195
{ key: 'tools', label: this.$t('Tools') },
100196
{ key: 'tokens_used', label: this.$t('Tokens Used') },
101197
{ key: 'created_at', label: this.$t('Date'), format: dateFormatter },
@@ -141,6 +237,7 @@ export default {
141237
this.fetchData();
142238
},
143239
async fetchData(params = {}) {
240+
this.loading = true;
144241
try {
145242
const response = await ProcessMaker.apiClient.get(this.apiEndpoint, {
146243
params: {
@@ -160,6 +257,8 @@ export default {
160257
// eslint-disable-next-line no-console
161258
console.log(error);
162259
this.data = [];
260+
} finally {
261+
this.loading = false;
163262
}
164263
},
165264
handlePageChange(newPage) {
@@ -170,6 +269,22 @@ export default {
170269
this.page = 1;
171270
this.fetchData(params);
172271
},
272+
getStatusClasses(status) {
273+
const statusClasses = {
274+
completed: 'tw-bg-green-100 tw-text-green-800',
275+
error: 'tw-bg-red-100 tw-text-red-800',
276+
processing: 'tw-bg-yellow-100 tw-text-yellow-800',
277+
};
278+
return statusClasses[status] || 'tw-bg-gray-100 tw-text-gray-800';
279+
},
280+
formatStatus(status) {
281+
const statusLabels = {
282+
completed: this.$t('Completed'),
283+
error: this.$t('Error'),
284+
processing: this.$t('Processing'),
285+
};
286+
return statusLabels[status] || status;
287+
},
173288
},
174289
};
175290
</script>

resources/js/admin/logs/components/Logs/Sidebar/Sidebar.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
2-
<aside class="tw-w-72 tw-shrink-0">
3-
<div class="tw-rounded-xl tw-border tw-border-zinc-200 tw-p-3 tw-bg-white tw-h-screen">
2+
<aside class="tw-w-72 tw-shrink-0 tw-h-full">
3+
<div class="tw-rounded-xl tw-border tw-border-zinc-200 tw-p-3 tw-bg-white tw-h-full tw-overflow-y-auto">
44
<div class="tw-px-2 tw-py-1 tw-text-xs tw-font-semibold tw-uppercase tw-text-zinc-500">
55
Logs
66
</div>

0 commit comments

Comments
 (0)