UNPKG

n8n-editor-ui

Version:

Workflow Editor UI for n8n

285 lines (284 loc) 11.4 kB
import { o as __toESM } from "./chunk-6z4oVpB-.js"; import { Cn as toDisplayString, D as createElementBlock, E as createCommentVNode, G as nextTick, Gt as unref, It as ref, M as createVNode, P as defineComponent, T as createBlock, W as mergeProps, _ as Fragment, _t as watch, at as renderSlot, bt as withCtx, c as useCssModule, et as openBlock, it as renderList, vn as normalizeClass, w as createBaseVNode } from "./vue.runtime.esm-bundler-tP5dCd7J.js"; import { ht as N8nTooltip_default, wn as N8nIcon_default } from "./src-DgvumQTi.js"; import { t as __plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-BwBpWJRZ.js"; import { n as ElTableColumn, t as ElTable } from "./table-DzZuElSR.js"; import { ho as require_isEqual } from "./constants-BbpucWL4.js"; var LONG_TABLE_CELL_MIN_WIDTH = 250; var specialKeys = [ "promptTokens", "completionTokens", "totalTokens", "executionTime" ]; function getDefaultOrderedColumns(run, filteredTestCases) { const metricColumns = Object.keys(run?.metrics ?? {}).filter((key) => !specialKeys.includes(key)); const specialColumns = specialKeys.filter((key) => run?.metrics ? key in run.metrics : false); const inputColumns = getTestCasesColumns(filteredTestCases ?? [], "inputs"); const outputColumns = getTestCasesColumns(filteredTestCases ?? [], "outputs"); return [ ...mapToColumns(inputColumns, "inputs"), ...mapToColumns(outputColumns, "outputs"), ...mapToColumns(metricColumns, "metrics", true), ...mapToColumns(specialColumns, "metrics", true) ]; } function applyCachedVisibility(columns, visibility) { if (!visibility) return columns; return columns.map((column) => column.disabled ? column : { ...column, visible: visibility.hasOwnProperty(column.key) ? visibility[column.key] : column.visible }); } function applyCachedSortOrder(defaultOrder, cachedOrder) { if (!cachedOrder?.length) return defaultOrder; const result = cachedOrder.map((columnKey) => { const matchingColumn = defaultOrder.find((col) => columnKey === col.key); if (!matchingColumn) return { key: columnKey, disabled: true }; return matchingColumn; }); const missingColumns = defaultOrder.filter((defaultCol) => !cachedOrder.includes(defaultCol.key)); result.push(...missingColumns); return result; } function getTestCasesColumns(cases, columnType) { const inputColumnNames = cases.reduce((set, testCase) => { Object.keys(testCase[columnType] ?? {}).forEach((key) => set.add(key)); return set; }, /* @__PURE__ */ new Set([])); return Array.from(inputColumnNames.keys()); } function mapToColumns(columnNames, columnType, numeric) { return columnNames.map((column) => ({ key: `${columnType}.${column}`, label: column, visible: true, disabled: false, columnType, numeric })); } function formatValue(key, value, { numeric } = { numeric: false }) { let stringValue; if (numeric && typeof value === "number" && !specialKeys.includes(key)) stringValue = value.toFixed(2) ?? "-"; else if (typeof value === "object" && value !== null) stringValue = JSON.stringify(value, null, 2); else stringValue = `${value}`; return stringValue; } function getTestTableHeaders(columnNames, testCases) { return columnNames.filter((column) => !column.disabled && column.visible).map((column) => { const hasLongContent = Boolean(testCases.find((row) => { const value = row[column.columnType]?.[column.label]; return formatValue(column.label, value, { numeric: column.numeric })?.length > 10; })); return { prop: column.key, label: column.disabled ? column.key : column.label, sortable: true, filter: true, showHeaderTooltip: true, minWidth: hasLongContent ? LONG_TABLE_CELL_MIN_WIDTH : 125, formatter: (row) => { const value = row[column.columnType]?.[column.label]; return formatValue(column.label, value, { numeric: column.numeric }); } }; }); } var import_isEqual = /* @__PURE__ */ __toESM(require_isEqual()); var TestTableBase_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({ __name: "TestTableBase", props: { data: {}, columns: {}, showControls: { type: Boolean }, defaultSort: { default: () => ({ prop: "date", order: "descending" }) }, selectable: { type: Boolean, default: false }, selectableFilter: { type: Function, default: () => true }, expandedRows: { default: () => /* @__PURE__ */ new Set() } }, emits: ["rowClick", "selectionChange"], setup(__props, { emit: __emit }) { const props = __props; const $style = useCssModule(); const tableRef = ref(); const selectedRows = ref([]); const localData = ref([]); const emit = __emit; watch(() => props.data, async (newData) => { if (!(0, import_isEqual.default)(localData.value, newData)) { const currentSelectionIds = selectedRows.value.map((row) => row.id); localData.value = newData; await nextTick(); tableRef.value?.sort(props.defaultSort.prop, props.defaultSort.order); currentSelectionIds.forEach((id) => { const row = localData.value.find((r) => r.id === id); if (row) tableRef.value?.toggleRowSelection(row, true); }); } }, { immediate: true, deep: true }); const handleSelectionChange = (rows) => { selectedRows.value = rows; emit("selectionChange", rows); }; const handleColumnResize = (newWidth, _oldWidth, column) => { if (column.minWidth && newWidth < column.minWidth) column.width = column.minWidth; }; const getCellClassName = ({ row }) => { return `${props.expandedRows?.has(row.id) ? $style.expandedCell : $style.baseCell}`; }; const getRowClassName = ({ row }) => { return `${"status" in row && row?.status === "error" ? $style.customDisabledRow : $style.customRow} ${props.expandedRows?.has(row.id) ? $style.expandedRow : ""}`; }; return (_ctx, _cache) => { return openBlock(), createBlock(unref(ElTable), { ref_key: "tableRef", ref: tableRef, class: normalizeClass(unref($style).table), "default-sort": _ctx.defaultSort, data: localData.value, border: true, "cell-class-name": getCellClassName, "row-class-name": getRowClassName, "scrollbar-always-on": "", onSelectionChange: handleSelectionChange, onHeaderDragend: handleColumnResize, onRowClick: _cache[0] || (_cache[0] = (row) => _ctx.$emit("rowClick", row)) }, { default: withCtx(() => [_ctx.selectable ? (openBlock(), createBlock(unref(ElTableColumn), { key: 0, type: "selection", selectable: _ctx.selectableFilter, "data-test-id": "table-column-select", width: "46", fixed: "", align: "center" }, null, 8, ["selectable"])) : createCommentVNode("", true), (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.columns, (column) => { return openBlock(), createBlock(unref(ElTableColumn), mergeProps({ key: column.prop, ref_for: true }, column, { resizable: true, "data-test-id": "table-column", "min-width": column.minWidth ?? unref(125) }), { header: withCtx((headerProps) => [createVNode(unref(N8nTooltip_default), { content: headerProps.column.label, placement: "top", disabled: !column.showHeaderTooltip }, { default: withCtx(() => [createBaseVNode("div", { class: normalizeClass(unref($style).customHeaderCell) }, [createBaseVNode("div", { class: normalizeClass(unref($style).customHeaderCellLabel) }, toDisplayString(headerProps.column.label), 3), headerProps.column.sortable && headerProps.column.order ? (openBlock(), createElementBlock("div", { key: 0, class: normalizeClass(unref($style).customHeaderCellSort) }, [createVNode(unref(N8nIcon_default), { icon: headerProps.column.order === "descending" ? "arrow-up" : "arrow-down", size: "small" }, null, 8, ["icon"])], 2)) : createCommentVNode("", true)], 2)]), _: 2 }, 1032, ["content", "disabled"])]), default: withCtx(({ row }) => [ column.prop === "id" ? renderSlot(_ctx.$slots, "id", mergeProps({ key: 0, ref_for: true }, { row })) : createCommentVNode("", true), column.prop === "index" ? renderSlot(_ctx.$slots, "index", mergeProps({ key: 1, ref_for: true }, { row })) : createCommentVNode("", true), column.prop === "status" ? renderSlot(_ctx.$slots, "status", mergeProps({ key: 2, ref_for: true }, { row })) : createCommentVNode("", true) ]), _: 2 }, 1040, ["min-width"]); }), 128))]), _: 3 }, 8, [ "class", "default-sort", "data" ]); }; } }); var TestTableBase_vue_vue_type_style_index_0_lang_module_default = { baseCell: "_baseCell_1cahf_123", expandedCell: "_expandedCell_1cahf_134", customRow: "_customRow_1cahf_144", customDisabledRow: "_customDisabledRow_1cahf_149", customHeaderCell: "_customHeaderCell_1cahf_154", customHeaderCellLabel: "_customHeaderCellLabel_1cahf_159", customHeaderCellSort: "_customHeaderCellSort_1cahf_168", table: "_table_1cahf_173" }; var TestTableBase_default = /* @__PURE__ */ __plugin_vue_export_helper_default(TestTableBase_vue_vue_type_script_setup_true_lang_default, [["__cssModules", { "$style": TestTableBase_vue_vue_type_style_index_0_lang_module_default }]]); var testCaseErrorDictionary = { MOCKED_NODE_NOT_FOUND: "evaluation.runDetail.error.mockedNodeMissing", FAILED_TO_EXECUTE_WORKFLOW: "evaluation.runDetail.error.executionFailed", INVALID_METRICS: "evaluation.runDetail.error.invalidMetrics", UNKNOWN_ERROR: "evaluation.runDetail.error.unknownError", NO_METRICS_COLLECTED: "evaluation.runDetail.error.noMetricsCollected" }; var testRunErrorDictionary = { TEST_CASES_NOT_FOUND: "evaluation.listRuns.error.testCasesNotFound", INTERRUPTED: "evaluation.listRuns.error.executionInterrupted", UNKNOWN_ERROR: "evaluation.listRuns.error.unknownError", EVALUATION_TRIGGER_NOT_FOUND: "evaluation.listRuns.error.evaluationTriggerNotFound", EVALUATION_TRIGGER_NOT_CONFIGURED: "evaluation.listRuns.error.evaluationTriggerNotConfigured", EVALUATION_TRIGGER_DISABLED: "evaluation.listRuns.error.evaluationTriggerDisabled", SET_OUTPUTS_NODE_NOT_CONFIGURED: "evaluation.listRuns.error.setOutputsNodeNotConfigured", SET_METRICS_NODE_NOT_FOUND: "evaluation.listRuns.error.setMetricsNodeNotFound", SET_METRICS_NODE_NOT_CONFIGURED: "evaluation.listRuns.error.setMetricsNodeNotConfigured", CANT_FETCH_TEST_CASES: "evaluation.listRuns.error.cantFetchTestCases", PARTIAL_CASES_FAILED: "evaluation.runDetail.error.partialCasesFailed" }; const getErrorBaseKey = (errorCode) => { return testCaseErrorDictionary[errorCode] ?? testRunErrorDictionary[errorCode] ?? ""; }; const statusDictionary = { new: { icon: "status-new", color: "foreground-xdark" }, running: { icon: "spinner", color: "secondary" }, completed: { icon: "status-completed", color: "success" }, error: { icon: "triangle-alert", color: "danger" }, cancelled: { icon: "status-canceled", color: "foreground-xdark" }, warning: { icon: "status-warning", color: "warning" }, success: { icon: "status-completed", color: "success" } }; export { applyCachedVisibility as a, getTestTableHeaders as c, applyCachedSortOrder as i, statusDictionary as n, getDefaultOrderedColumns as o, TestTableBase_default as r, getTestCasesColumns as s, getErrorBaseKey as t };