Skip to content

Commit

Permalink
wip: refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
burivuhster committed Feb 5, 2025
1 parent 8f8ff2c commit 264da71
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const metrics = computed(() => {
}, [] as string[]);
});
const getErrorTooltipLinkRoute = computed(() => (row: TestRunRecord) => {
const getErrorTooltipLinkRoute = (row: TestRunRecord) => {
if (row.errorCode === 'EVALUATION_WORKFLOW_NOT_FOUND') {
return {
name: VIEWS.TEST_DEFINITION_EDIT,
Expand All @@ -51,7 +51,7 @@ const getErrorTooltipLinkRoute = computed(() => (row: TestRunRecord) => {
}
return undefined;
});
};
const columns = computed((): Array<TestTableColumn<TestRunRecord>> => {
return [
Expand All @@ -75,7 +75,7 @@ const columns = computed((): Array<TestTableColumn<TestRunRecord>> => {
{ text: locale.baseText('testDefinition.listRuns.status.error'), value: 'error' },
{ text: locale.baseText('testDefinition.listRuns.status.cancelled'), value: 'cancelled' },
],
errorRoute: getErrorTooltipLinkRoute.value,
errorRoute: getErrorTooltipLinkRoute,
filterMethod: (value: string, row: TestRunRecord) => row.status === value,
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
<script setup lang="ts" generic="T">
import { useI18n } from '@/composables/useI18n';
import type { TestTableColumn } from './TestTableBase.vue';
import { useRouter } from 'vue-router';
import N8nTooltip from 'n8n-design-system/components/N8nTooltip';
import type { BaseTextKey } from '@/plugins/i18n';
defineProps<{
column: TestTableColumn<T>;
Expand All @@ -14,61 +11,7 @@ defineEmits<{
click: [];
}>();
const locale = useI18n();
const router = useRouter();
interface WithStatus {
status: string;
}
interface WithError {
errorCode: string;
}
function hasStatus(row: unknown): row is WithStatus {
return typeof row === 'object' && row !== null && 'status' in row;
}
function hasError(row: unknown): row is WithError {
return typeof row === 'object' && row !== null && 'errorCode' in row;
}
// FIXME: move status logic to a parent component
const statusThemeMap: Record<string, string> = {
new: 'default',
running: 'warning',
evaluation_running: 'warning',
completed: 'success',
error: 'danger',
success: 'success',
warning: 'warning',
cancelled: 'default',
};
const statusLabelMap: Record<string, string> = {
new: locale.baseText('testDefinition.listRuns.status.new'),
running: locale.baseText('testDefinition.listRuns.status.running'),
evaluation_running: locale.baseText('testDefinition.listRuns.status.evaluating'),
completed: locale.baseText('testDefinition.listRuns.status.completed'),
error: locale.baseText('testDefinition.listRuns.status.error'),
success: locale.baseText('testDefinition.listRuns.status.success'),
warning: locale.baseText('testDefinition.listRuns.status.warning'),
cancelled: locale.baseText('testDefinition.listRuns.status.cancelled'),
};
const errorTooltipMap: Record<string, BaseTextKey> = {
// Test case errors
MOCKED_NODE_DOES_NOT_EXIST: 'testDefinition.runDetail.error.mockedNodeMissing',
FAILED_TO_EXECUTE_EVALUATION_WORKFLOW: 'testDefinition.runDetail.error.evaluationFailed',
FAILED_TO_EXECUTE_WORKFLOW: 'testDefinition.runDetail.error.executionFailed',
TRIGGER_NO_LONGER_EXISTS: 'testDefinition.runDetail.error.triggerNoLongerExists',
METRICS_MISSING: 'testDefinition.runDetail.error.metricsMissing',
UNKNOWN_METRICS: 'testDefinition.runDetail.error.unknownMetrics',
INVALID_METRICS: 'testDefinition.runDetail.error.invalidMetrics',
// Test run errors
PAST_EXECUTIONS_NOT_FOUND: 'testDefinition.listRuns.error.noPastExecutions',
EVALUATION_WORKFLOW_NOT_FOUND: 'testDefinition.listRuns.error.evaluationWorkflowNotFound',
};
function hasProperty(row: unknown, prop: string): row is Record<string, unknown> {
return typeof row === 'object' && row !== null && prop in row;
Expand All @@ -80,32 +23,6 @@ const getCellContent = (column: TestTableColumn<T>, row: T) => {
}
return hasProperty(row, column.prop) ? row[column.prop] : undefined;
};
function getErrorTooltip(column: TestTableColumn<T>, row: T): string | undefined {
if (hasError(row) && errorTooltipMap[row.errorCode]) {
const tooltipLinkUrl = getErrorTooltipUrl(column, row);
if (tooltipLinkUrl) {
return locale.baseText(errorTooltipMap[row.errorCode], {
interpolate: {
url: tooltipLinkUrl,
},
});
} else {
return locale.baseText(errorTooltipMap[row.errorCode]);
}
}
return undefined;
}
function getErrorTooltipUrl(column: TestTableColumn<T>, row: T): string | undefined {
if (hasError(row) && column.errorRoute?.(row)) {
return router.resolve(column.errorRoute(row)!).href;
}
return undefined;
}
</script>

<template>
Expand All @@ -118,20 +35,6 @@ function getErrorTooltipUrl(column: TestTableColumn<T>, row: T): string | undefi
</router-link>
</div>

<N8nTooltip
v-else-if="column.prop === 'status' && hasStatus(row)"
placement="right"
:show-after="300"
:disabled="getErrorTooltip(column, row) === undefined"
>
<template #content>
<div v-n8n-html="getErrorTooltip(column, row)" />
</template>
<N8nBadge :theme="statusThemeMap[row.status]" class="mr-4xs">
{{ statusLabelMap[row.status] }}
</N8nBadge>
</N8nTooltip>

<div v-else>
{{ getCellContent(column, row) }}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<script setup lang="ts" generic="T">
import N8nTooltip from 'n8n-design-system/components/N8nTooltip';
import type { BaseTextKey } from '@/plugins/i18n';
import type { TestTableColumn } from '@/components/TestDefinition/shared/TestTableBase.vue';
import { useI18n } from '@/composables/useI18n';
import { useRouter } from 'vue-router';
defineProps<{
column: TestTableColumn<T>;
row: T & { status: string };
}>();
const locale = useI18n();
const router = useRouter();
interface WithError {
errorCode: string;
}
function hasError(row: unknown): row is WithError {
return typeof row === 'object' && row !== null && 'errorCode' in row;
}
const errorTooltipMap: Record<string, BaseTextKey> = {
// Test case errors
MOCKED_NODE_DOES_NOT_EXIST: 'testDefinition.runDetail.error.mockedNodeMissing',
FAILED_TO_EXECUTE_EVALUATION_WORKFLOW: 'testDefinition.runDetail.error.evaluationFailed',
FAILED_TO_EXECUTE_WORKFLOW: 'testDefinition.runDetail.error.executionFailed',
TRIGGER_NO_LONGER_EXISTS: 'testDefinition.runDetail.error.triggerNoLongerExists',
METRICS_MISSING: 'testDefinition.runDetail.error.metricsMissing',
UNKNOWN_METRICS: 'testDefinition.runDetail.error.unknownMetrics',
INVALID_METRICS: 'testDefinition.runDetail.error.invalidMetrics',
// Test run errors
PAST_EXECUTIONS_NOT_FOUND: 'testDefinition.listRuns.error.noPastExecutions',
EVALUATION_WORKFLOW_NOT_FOUND: 'testDefinition.listRuns.error.evaluationWorkflowNotFound',
};
// FIXME: move status logic to a parent component
const statusThemeMap: Record<string, string> = {
new: 'default',
running: 'warning',
evaluation_running: 'warning',
completed: 'success',
error: 'danger',
success: 'success',
warning: 'warning',
cancelled: 'default',
};
const statusLabelMap: Record<string, string> = {
new: locale.baseText('testDefinition.listRuns.status.new'),
running: locale.baseText('testDefinition.listRuns.status.running'),
evaluation_running: locale.baseText('testDefinition.listRuns.status.evaluating'),
completed: locale.baseText('testDefinition.listRuns.status.completed'),
error: locale.baseText('testDefinition.listRuns.status.error'),
success: locale.baseText('testDefinition.listRuns.status.success'),
warning: locale.baseText('testDefinition.listRuns.status.warning'),
cancelled: locale.baseText('testDefinition.listRuns.status.cancelled'),
};
function getErrorTooltip(column: TestTableColumn<T>, row: T): string | undefined {
if (hasError(row) && errorTooltipMap[row.errorCode]) {
const tooltipLinkUrl = getErrorTooltipUrl(column, row);
if (tooltipLinkUrl) {
return locale.baseText(errorTooltipMap[row.errorCode], {
interpolate: {
url: tooltipLinkUrl,
},
});
} else {
return locale.baseText(errorTooltipMap[row.errorCode]);
}
}
return undefined;
}
function getErrorTooltipUrl(column: TestTableColumn<T>, row: T): string | undefined {
if (hasError(row) && column.errorRoute?.(row)) {
return router.resolve(column.errorRoute(row)!).href;
}
return undefined;
}
</script>

<template>
<N8nTooltip
placement="right"
:show-after="300"
:disabled="getErrorTooltip(column, row) === undefined"
>
<template #content>
<div v-n8n-html="getErrorTooltip(column, row)" />
</template>
<N8nBadge :theme="statusThemeMap[row.status]" class="mr-4xs">
{{ statusLabelMap[row.status] }}
</N8nBadge>
</N8nTooltip>
</template>

<style scoped lang="scss"></style>
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script setup lang="ts" generic="T extends object">
import type { RouteLocationRaw } from 'vue-router';
import TableCell from './TableCell.vue';
import TableStatusCell from './TableStatusCell.vue';
import { ElTable, ElTableColumn } from 'element-plus';
import { ref, watch, nextTick, onMounted, onUnmounted } from 'vue';
import type { TableInstance } from 'element-plus';
Expand Down Expand Up @@ -30,6 +31,8 @@ export type TestTableColumn<TRow> = {
type TableRow = T & { id: string };
type TableRowWithStatus = TableRow & { status: string };
const MIN_TABLE_HEIGHT = 350;
const MAX_TABLE_HEIGHT = 1400;
const props = withDefaults(
Expand Down Expand Up @@ -95,6 +98,10 @@ const computeTableHeight = () => {
tableHeight.value = `${height - 100}px`;
};
function hasStatus(row: unknown): row is TableRowWithStatus {
return typeof row === 'object' && row !== null && 'status' in row;
}
onMounted(() => {
computeTableHeight();
Expand Down Expand Up @@ -132,8 +139,14 @@ onUnmounted(() => {
data-test-id="table-column"
>
<template #default="{ row }">
<TableStatusCell
v-if="column.prop === 'status' && hasStatus(row)"
:column="column"
:row="row"
/>
<TableCell
:key="row.status"
v-else
:key="row.id + column.prop"
:column="column"
:row="row"
data-test-id="table-cell"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const filteredTestCases = computed(() => {
return testCases.value;
});
const getErrorTooltipLinkRoute = computed(() => (row: TestCaseExecutionRecord) => {
const getErrorTooltipLinkRoute = (row: TestCaseExecutionRecord) => {
if (row.errorCode === 'FAILED_TO_EXECUTE_EVALUATION_WORKFLOW') {
return {
name: VIEWS.EXECUTION_PREVIEW,
Expand Down Expand Up @@ -85,7 +85,7 @@ const getErrorTooltipLinkRoute = computed(() => (row: TestCaseExecutionRecord) =
}
return undefined;
});
};
const columns = computed(
(): Array<TestTableColumn<TestCaseExecutionRecord>> => [
Expand Down Expand Up @@ -119,7 +119,7 @@ const columns = computed(
{ text: locale.baseText('testDefinition.listRuns.status.success'), value: 'success' },
{ text: locale.baseText('testDefinition.listRuns.status.error'), value: 'error' },
],
errorRoute: getErrorTooltipLinkRoute.value,
errorRoute: getErrorTooltipLinkRoute,
filterMethod: (value: string, row: TestCaseExecutionRecord) => row.status === value,
},
...Object.keys(run.value?.metrics ?? {}).map((metric) => ({
Expand Down

0 comments on commit 264da71

Please sign in to comment.