Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 142 additions & 31 deletions ui/src/components/ListPreview.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,46 @@
<template>
<el-table :data="value" stripe>
<el-table-column v-for="(column, index) in generateTableColumns" :key="index" :prop="column" :label="column">
<template #default="scope">
<span v-if="isComplex(scope.row[column])">
<el-tooltip :content="JSON.stringify(scope.row[column], null, 2)">
<span class="preview-row">{{ truncate(JSON.stringify(scope.row[column])) }}</span>
</el-tooltip>
</span>
<span v-else>
{{ scope.row[column] }}
</span>
</template>
</el-table-column>
</el-table>
<div class="list-preview-container">
<el-table :data="previewData" stripe class="ion-table-preview">
<el-table-column type="index" :index="indexMethod" label="#" width="60" align="center" />
<el-table-column v-for="(column, index) in generateTableColumns" :key="index" :prop="column" :label="column">
<template #default="scope">
<div :class="['cell-wrapper', {'expanded': expandedCells.has(getCellKey(scope.$index, column))}]">
<span v-if="isComplex(scope.row[column])">
<span class="preview-cell">{{ getTruncatedContent(scope.row[column], scope.$index, column) }}</span>
<el-button
v-if="needsExpansion(scope.row[column])"
link
type="primary"
size="small"
class="expand-button"
@click="toggleExpand(scope.$index, column)"
>
{{ expandedCells.has(getCellKey(scope.$index, column)) ? $t('preview.collapse') : $t('preview.expand') }}
</el-button>
</span>
<span v-else class="preview-cell">
{{ scope.row[column] }}
</span>
</div>
</template>
</el-table-column>
</el-table>

<Pagination
v-if="totalPages > 1"
:total="props.value.length"
:size="pageSize"
:page="currentPage"
@page-changed="onPageChanged"
/>
</div>
</template>

<script setup lang="ts">
import {ref, computed} from "vue";
import Pagination from "./layout/Pagination.vue";

const MAX_CELL_CHARS = 2000;

const props = defineProps({
value: {
Expand All @@ -25,29 +49,125 @@
}
});

const maxColumnLength = ref(100);
const expandedCells = ref(new Set<string>());
const currentPage = ref(1);
const pageSize = ref(50);

const previewData = computed(() => {
const startIndex = (currentPage.value - 1) * pageSize.value;
const endIndex = startIndex + pageSize.value;
return props.value.slice(startIndex, endIndex);
});

const totalPages = computed(() => {
return Math.ceil(props.value.length / pageSize.value);
});

const indexMethod = (index: number) => {
return (currentPage.value - 1) * pageSize.value + index + 1;
};

const onPageChanged = (payload: { page?: number; size?: number }): void => {
if (payload.page !== undefined) {
currentPage.value = payload.page;
}
if (payload.size !== undefined) {
pageSize.value = payload.size;
}
expandedCells.value.clear();
};

const generateTableColumns = computed(() => {
const allKeys = new Set<string>();
props.value.forEach(item => {
Object.keys(item).forEach(key => allKeys.add(key));
if (item && typeof item === "object") {
Object.keys(item).forEach(key => allKeys.add(key));
}
});
return Array.from(allKeys);
});


const isComplex = (data: any): boolean => {
return data instanceof Array || data instanceof Object;
return data !== null && typeof data === "object";
};

const getCellKey = (rowIndex: number, column: string): string => {
return `${rowIndex}-${column}`;
};

const needsExpansion = (data: any): boolean => {
const stringified = JSON.stringify(data, null, 2);
return stringified.length > MAX_CELL_CHARS;
};

const getTruncatedContent = (data: any, rowIndex: number, column: string): string => {
const cellKey = getCellKey(rowIndex, column);
const stringified = JSON.stringify(data, null, 2);

if (expandedCells.value.has(cellKey)) {
return stringified;
}

if (stringified.length > MAX_CELL_CHARS) {
return stringified.slice(0, MAX_CELL_CHARS) + "... [truncated]";
}

return stringified;
};

const truncate = (text: any): string | any => {
if (typeof text !== "string") return text;
return text.length > maxColumnLength.value
? text.slice(0, maxColumnLength.value) + "..."
: text;
const toggleExpand = (rowIndex: number, column: string): void => {
const cellKey = getCellKey(rowIndex, column);
if (expandedCells.value.has(cellKey)) {
expandedCells.value.delete(cellKey);
} else {
expandedCells.value.add(cellKey);
}
};
</script>

<style scoped lang="scss">
.list-preview-container {
width: 100%;
overflow: auto;
}

.ion-table-preview {
table-layout: fixed;
width: 100%;

:deep(.el-table__body-wrapper) {
overflow-x: auto;
}
}

.cell-wrapper {
max-height: 120px;
overflow: hidden;
position: relative;
display: block;
word-break: break-word;

&.expanded {
max-height: none;
overflow: visible;
}
}

.preview-cell {
display: block;
white-space: pre-wrap;
word-wrap: break-word;
font-family: monospace;
font-size: 12px;
line-height: 1.4;
}

.expand-button {
margin-top: 4px;
font-size: 12px;
}

:deep(.ks-editor) {
.editor-container {
box-shadow: none;
Expand All @@ -59,13 +179,4 @@
}
}
}

.preview-row {
height: 24px;
overflow: hidden;
white-space: pre;
text-overflow: ellipsis;
display: inline-block;
max-width: 100%;
}
</style>
6 changes: 3 additions & 3 deletions ui/src/components/executions/FilePreview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -161,15 +161,15 @@
];

const configPreviewInitialRows = (): number => {
return miscStore.configs?.preview.initial || 50;
return miscStore.configs?.preview.initial || 500;
};

const configPreviewMaxRows = (): number => {
return miscStore.configs?.preview.max || 5000;
return miscStore.configs?.preview.max || 5000;
};

const maxPreviewOptions = computed(() => {
return [10, 25, 50, 100, 500, 1000, 5000, 10000, 25000, 50000].filter(
return [50, 100, 250, 500, 1000, 5000, 10000, 25000, 50000].filter(
value => value <= configPreviewMaxRows()
);
});
Expand Down
10 changes: 9 additions & 1 deletion ui/src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1740,7 +1740,15 @@
"label": "Preview",
"force-editor": "Enforce editor view",
"auto-view": "Auto view",
"view": "View"
"view": "View",
"rows_truncated": "Showing {shown} of {total} rows. Download the file to view all data.",
"pagination_info": "Showing rows {start}-{end} of {total}.",
"showing_rows": "Showing rows {start}-{end} of {total}",
"expand": "Expand",
"collapse": "Collapse",
"previous": "Previous",
"next": "Next",
"page_of": "Page {current} of {total}"
},
"filter": {
"update": "Update",
Expand Down
Loading