93
93
:key="index + '-' + column.name"
94
94
class="field_list"
95
95
>
96
- <high-light
97
- :content="
98
- column.name == 'source'
99
- ? column.prop(row)
100
- : column.prop(row, column.name).length > 100
101
- ? column.prop(row, column.name).substr(0, 100) + '...'
102
- : column.name != '@timestamp'
103
- ? row[column.name]
104
- : column.prop(row, column.name)
105
- "
106
- :query-string="
107
- searchObj.meta.sqlMode
108
- ? searchObj.data.query.split('where')[1]
109
- : searchObj.data.query
110
- "
111
- :title="
112
- column.prop(row, column.name).length > 100 &&
113
- column.name != 'source'
114
- ? column.prop(row, column.name)
115
- : ''
116
- "
117
- ></high-light>
96
+ <div class="flex row items-center no-wrap">
97
+ <q-btn
98
+ v-if="column.name === '@timestamp'"
99
+ :icon="
100
+ expandedLogs[row._timestamp]
101
+ ? 'expand_more'
102
+ : 'chevron_right'
103
+ "
104
+ dense
105
+ size="xs"
106
+ flat
107
+ class="q-mr-xs"
108
+ @click.stop="expandLog(row)"
109
+ ></q-btn>
110
+ <high-light
111
+ :content="
112
+ column.name == 'source'
113
+ ? column.prop(row)
114
+ : searchObj.data.resultGrid.columns.length > 2 &&
115
+ column.prop(row, column.name).length > 100
116
+ ? column.prop(row, column.name).substr(0, 100) + '...'
117
+ : column.name != '@timestamp'
118
+ ? row[column.name]
119
+ : column.prop(row, column.name)
120
+ "
121
+ :query-string="
122
+ searchObj.meta.sqlMode
123
+ ? searchObj.data.query.split('where')[1]
124
+ : searchObj.data.query
125
+ "
126
+ :title="
127
+ column.prop(row, column.name).length > 100 &&
128
+ column.name != 'source'
129
+ ? column.prop(row, column.name)
130
+ : ''
131
+ "
132
+ ></high-light>
133
+ </div>
118
134
<div
119
135
v-if="column.closable && row[column.name]"
120
136
class="field_overlay"
137
153
"
138
154
/>
139
155
</div>
140
- </q-td> </q-tr
141
- ></template>
156
+ </q-td>
157
+ </q-tr>
158
+ <q-tr v-if="expandedLogs[row._timestamp]">
159
+ <td :colspan="searchObj.data.resultGrid.columns.length">
160
+ <pre class="log_json_content">{{ row }}</pre>
161
+ </td>
162
+ </q-tr>
163
+ </template>
142
164
</q-virtual-scroll>
143
165
<q-dialog
144
166
v-model="searchObj.meta.showDetailTab"
172
194
173
195
<script lang="ts">
174
196
import { defineComponent, ref } from "vue";
175
- import { useQuasar, date } from "quasar";
197
+ import { useQuasar } from "quasar";
176
198
import { useStore } from "vuex";
177
199
import { useI18n } from "vue-i18n";
178
200
@@ -264,6 +286,7 @@ export default defineComponent({
264
286
const searchTableRef: any = ref(null);
265
287
266
288
const plotChart: any = ref(null);
289
+ const expandedLogs: any = ref({});
267
290
268
291
const reDrawChart = () => {
269
292
if (
@@ -315,6 +338,12 @@ export default defineComponent({
315
338
emit("remove:searchTerm", term);
316
339
};
317
340
341
+ const expandLog = async (row: any) => {
342
+ if (expandedLogs.value[row._timestamp])
343
+ delete expandedLogs.value[row._timestamp];
344
+ else expandedLogs.value[row._timestamp] = true;
345
+ };
346
+
318
347
return {
319
348
t,
320
349
store,
@@ -330,7 +359,9 @@ export default defineComponent({
330
359
navigateRowDetail,
331
360
totalHeight,
332
361
reDrawChart,
362
+ expandLog,
333
363
getImageURL,
364
+ expandedLogs,
334
365
};
335
366
},
336
367
});
@@ -463,6 +494,10 @@ export default defineComponent({
463
494
font-weight: bold;
464
495
}
465
496
}
497
+
498
+ .log_json_content {
499
+ white-space: pre-wrap;
500
+ }
466
501
}
467
502
.thead-sticky tr > *,
468
503
.tfoot-sticky tr > * {
@@ -486,6 +521,8 @@ export default defineComponent({
486
521
position: relative;
487
522
overflow: visible;
488
523
cursor: default;
524
+ font-size: 12px;
525
+ font-family: monospace;
489
526
490
527
.field_overlay {
491
528
position: absolute;
0 commit comments