diff --git a/packages/frontend/editor-ui/src/components/MainSidebar.vue b/packages/frontend/editor-ui/src/components/MainSidebar.vue
index 7bf0fe220c0..5d85a80e514 100644
--- a/packages/frontend/editor-ui/src/components/MainSidebar.vue
+++ b/packages/frontend/editor-ui/src/components/MainSidebar.vue
@@ -111,7 +111,9 @@ const mainMenuItems = computed(() => [
customIconSize: 'medium',
position: 'bottom',
route: { to: { name: VIEWS.INSIGHTS } },
- available: hasPermission(['rbac'], { rbac: { scope: 'insights:list' } }),
+ available:
+ settingsStore.settings.insights.enabled &&
+ hasPermission(['rbac'], { rbac: { scope: 'insights:list' } }),
},
{
id: 'help',
diff --git a/packages/frontend/editor-ui/src/components/WorkflowSettings.vue b/packages/frontend/editor-ui/src/components/WorkflowSettings.vue
index c08b51bf421..f4995de52c4 100644
--- a/packages/frontend/editor-ui/src/components/WorkflowSettings.vue
+++ b/packages/frontend/editor-ui/src/components/WorkflowSettings.vue
@@ -380,7 +380,11 @@ const toggleTimeout = () => {
const updateTimeSavedPerExecution = (value: string) => {
const numValue = parseInt(value, 10);
- workflowSettings.value.timeSavedPerExecution = isNaN(numValue) ? undefined : numValue;
+ workflowSettings.value.timeSavedPerExecution = isNaN(numValue)
+ ? undefined
+ : numValue < 0
+ ? 0
+ : numValue;
};
onMounted(async () => {
@@ -826,6 +830,7 @@ onMounted(async () => {
:disabled="readOnlyEnv || !workflowPermissions.update"
data-test-id="workflow-settings-time-saved-per-execution"
type="number"
+ min="0"
@update:model-value="updateTimeSavedPerExecution"
/>
{{ i18n.baseText('workflowSettings.timeSavedPerExecution.hint') }}
diff --git a/packages/frontend/editor-ui/src/features/insights/chartjs.utils.ts b/packages/frontend/editor-ui/src/features/insights/chartjs.utils.ts
index cb733576d9e..feed42f377b 100644
--- a/packages/frontend/editor-ui/src/features/insights/chartjs.utils.ts
+++ b/packages/frontend/editor-ui/src/features/insights/chartjs.utils.ts
@@ -52,7 +52,7 @@ export const generateLineChartOptions = (
callbacks: {
label(context: ScriptableContext<'line'>) {
const label = context.dataset.label ?? '';
- return `${label} ${smartDecimal(context.parsed.y)}`;
+ return `${label} ${smartDecimal(context.parsed.y).toLocaleString('en-US')}`;
},
labelColor(context: ScriptableContext<'line'>) {
return {
diff --git a/packages/frontend/editor-ui/src/features/insights/components/InsightsSummary.test.ts b/packages/frontend/editor-ui/src/features/insights/components/InsightsSummary.test.ts
index 36b870739b2..437063bf6f2 100644
--- a/packages/frontend/editor-ui/src/features/insights/components/InsightsSummary.test.ts
+++ b/packages/frontend/editor-ui/src/features/insights/components/InsightsSummary.test.ts
@@ -36,38 +36,50 @@ describe('InsightsSummary', () => {
[[]],
[
[
- { id: 'total', value: 525, deviation: 85, unit: '' },
- { id: 'failed', value: 14, deviation: 3, unit: '' },
- { id: 'failureRate', value: 1.9, deviation: -0.8, unit: '%' },
- { id: 'timeSaved', value: 55.55555555555556, deviation: -5.164722222222222, unit: 'h' },
- { id: 'averageRunTime', value: 2.5, deviation: -0.5, unit: 's' },
+ { id: 'total', value: 525, deviation: 85, unit: '', deviationUnit: '%' },
+ { id: 'failed', value: 14, deviation: 3, unit: '', deviationUnit: '%' },
+ { id: 'failureRate', value: 1.9, deviation: -0.8, unit: '%', deviationUnit: 'pp' },
+ {
+ id: 'timeSaved',
+ value: 55.55555555555556,
+ deviation: -5.164722222222222,
+ unit: 'h',
+ deviationUnit: 'h',
+ },
+ { id: 'averageRunTime', value: 2.5, deviation: -0.5, unit: 's', deviationUnit: 's' },
],
],
[
[
- { id: 'total', value: 525, deviation: 85, unit: '' },
- { id: 'failed', value: 14, deviation: 3, unit: '' },
- { id: 'failureRate', value: 1.9, deviation: -0.8, unit: '%' },
- { id: 'timeSaved', value: 0, deviation: 0, unit: 'h' },
- { id: 'averageRunTime', value: 2.5, deviation: -0.5, unit: 's' },
+ { id: 'total', value: 525, deviation: 85, unit: '', deviationUnit: '%' },
+ { id: 'failed', value: 14, deviation: 3, unit: '', deviationUnit: '%' },
+ { id: 'failureRate', value: 1.9, deviation: -0.8, unit: '%', deviationUnit: 'pp' },
+ { id: 'timeSaved', value: 0, deviation: 0, unit: 'h', deviationUnit: 'h' },
+ { id: 'averageRunTime', value: 2.5, deviation: -0.5, unit: 's', deviationUnit: 's' },
],
],
[
[
- { id: 'total', value: 525, deviation: -2, unit: '' },
- { id: 'failed', value: 14, deviation: -3, unit: '' },
- { id: 'failureRate', value: 1.9, deviation: 0.8, unit: '%' },
- { id: 'timeSaved', value: 55.55555555555556, deviation: 0, unit: 'h' },
- { id: 'averageRunTime', value: 2.5, deviation: 0.5, unit: 's' },
+ { id: 'total', value: 525, deviation: -2, unit: '', deviationUnit: '%' },
+ { id: 'failed', value: 14, deviation: -3, unit: '', deviationUnit: '%' },
+ { id: 'failureRate', value: 1.9, deviation: 0.8, unit: '%', deviationUnit: 'pp' },
+ { id: 'timeSaved', value: 55.55555555555556, deviation: 0, unit: 'h', deviationUnit: 'h' },
+ { id: 'averageRunTime', value: 2.5, deviation: 0.5, unit: 's', deviationUnit: 's' },
],
],
[
[
- { id: 'total', value: 525, deviation: null, unit: '' },
- { id: 'failed', value: 14, deviation: null, unit: '' },
- { id: 'failureRate', value: 1.9, deviation: null, unit: '%' },
- { id: 'timeSaved', value: 55.55555555555556, deviation: null, unit: 'h' },
- { id: 'averageRunTime', value: 2.5, deviation: null, unit: 's' },
+ { id: 'total', value: 525, deviation: null, unit: '', deviationUnit: '%' },
+ { id: 'failed', value: 14, deviation: null, unit: '', deviationUnit: '%' },
+ { id: 'failureRate', value: 1.9, deviation: null, unit: '%', deviationUnit: 'pp' },
+ {
+ id: 'timeSaved',
+ value: 55.55555555555556,
+ deviation: null,
+ unit: 'h',
+ deviationUnit: 'h',
+ },
+ { id: 'averageRunTime', value: 2.5, deviation: null, unit: 's', deviationUnit: 's' },
],
],
])('should render the summary correctly', (summary) => {
diff --git a/packages/frontend/editor-ui/src/features/insights/components/InsightsSummary.vue b/packages/frontend/editor-ui/src/features/insights/components/InsightsSummary.vue
index 3c2c3bd2530..4f6037cece5 100644
--- a/packages/frontend/editor-ui/src/features/insights/components/InsightsSummary.vue
+++ b/packages/frontend/editor-ui/src/features/insights/components/InsightsSummary.vue
@@ -8,7 +8,7 @@ import {
import type { InsightsSummaryDisplay } from '@/features/insights/insights.types';
import type { InsightsSummary } from '@n8n/api-types';
import { smartDecimal } from '@n8n/utils/number/smartDecimal';
-import { computed, useCssModule } from 'vue';
+import { computed, ref, useCssModule } from 'vue';
import { useRoute } from 'vue-router';
const props = defineProps<{
@@ -20,6 +20,8 @@ const i18n = useI18n();
const route = useRoute();
const $style = useCssModule();
+const lastNDays = ref(7);
+
const summaryTitles = computed>(() => ({
total: i18n.baseText('insights.banner.title.total'),
failed: i18n.baseText('insights.banner.title.failed'),
@@ -35,7 +37,6 @@ const summaryWithRouteLocations = computed(() =>
})),
);
-const getSign = (n: number) => (n > 0 ? '+' : undefined);
const getImpactStyle = (id: keyof InsightsSummary, value: number) => {
const impact = INSIGHTS_UNIT_IMPACT_MAPPING[id];
if (value === 0 || impact === INSIGHT_IMPACT_TYPES.NEUTRAL) {
@@ -53,18 +54,25 @@ const getImpactStyle = (id: keyof InsightsSummary, value: number) => {
-
{{
- i18n.baseText('insights.banner.title', { interpolate: { count: 7 } })
- }}
-
- {{ summaryTitles[id] }}
+
+
+
+ {{ i18n.baseText('insights.banner.title.timeSaved.tooltip') }}
+
+ {{ summaryTitles[id] }}
+
+
+ {{
+ i18n.baseText('insights.lastNDays', { interpolate: { count: lastNDays } })
+ }}
--
@@ -84,14 +92,19 @@ const getImpactStyle = (id: keyof InsightsSummary, value: number) => {
{{ smartDecimal(value) }} {{ unit }}{{ smartDecimal(value).toLocaleString('en-US') }} {{ unit }}
- {{ getSign(deviation) }}{{ smartDecimal(deviation) }}
+
+
+ {{ i18n.baseText('insights.banner.failureRate.deviation.tooltip') }}
+
+ {{ smartDecimal(Math.abs(deviation)).toLocaleString('en-US') }}{{ deviationUnit }}
+
@@ -108,7 +121,7 @@ const getImpactStyle = (id: keyof InsightsSummary, value: number) => {
ul {
display: flex;
- height: 91px;
+ height: 101px;
align-items: stretch;
justify-content: space-evenly;
border: var(--border-width-base) var(--border-style-base) var(--color-foreground-base);
@@ -131,9 +144,10 @@ const getImpactStyle = (id: keyof InsightsSummary, value: number) => {
a {
display: grid;
align-items: center;
+ align-content: center;
width: 100%;
height: 100%;
- padding: var(--spacing-m) var(--spacing-l);
+ padding: var(--spacing-3xs) var(--spacing-l) 0;
border-bottom: 3px solid transparent;
&:hover {
@@ -148,17 +162,25 @@ const getImpactStyle = (id: keyof InsightsSummary, value: number) => {
}
strong {
+ justify-self: flex-start;
color: var(--color-text-dark);
font-size: var(--font-size-s);
font-weight: 400;
white-space: nowrap;
- margin-bottom: var(--spacing-2xs);
+ margin-bottom: var(--spacing-3xs);
+ }
+
+ .days {
+ padding: 0;
+ margin: 0 0 var(--spacing-xs);
+ color: var(--color-text-light);
+ font-size: var(--font-size-2xs);
+ font-weight: var(--font-weight-normal);
}
span {
display: flex;
align-items: baseline;
- gap: var(--spacing-xs);
&.empty {
em {
@@ -185,7 +207,7 @@ const getImpactStyle = (id: keyof InsightsSummary, value: number) => {
align-items: baseline;
justify-content: flex-start;
color: var(--color-text-dark);
- font-size: var(--font-size-2xl);
+ font-size: 24px;
line-height: 100%;
font-weight: 600;
font-style: normal;
@@ -202,9 +224,10 @@ const getImpactStyle = (id: keyof InsightsSummary, value: number) => {
position: relative;
display: flex;
align-items: center;
- padding: 0 0 0 18px;
- font-size: 14px;
- font-weight: 400;
+ padding: 0 0 0 14px;
+ margin: 0 0 0 var(--spacing-xs);
+ font-size: var(--font-size-2xs);
+ font-weight: var(--font-weight-bold);
white-space: nowrap;
}
}
@@ -223,13 +246,13 @@ const getImpactStyle = (id: keyof InsightsSummary, value: number) => {
color: var(--color-text-light);
.icon {
- font-size: 23px;
+ font-size: 17px;
}
}
.icon {
position: absolute;
- font-size: 32px;
+ font-size: 17px;
left: 0;
top: 50%;
transform: translateY(-50%);
diff --git a/packages/frontend/editor-ui/src/features/insights/components/__snapshots__/InsightsSummary.test.ts.snap b/packages/frontend/editor-ui/src/features/insights/components/__snapshots__/InsightsSummary.test.ts.snap
index 1aec2429922..7a73890386e 100644
--- a/packages/frontend/editor-ui/src/features/insights/components/__snapshots__/InsightsSummary.test.ts.snap
+++ b/packages/frontend/editor-ui/src/features/insights/components/__snapshots__/InsightsSummary.test.ts.snap
@@ -2,62 +2,99 @@
exports[`InsightsSummary > should render the summary correctly 1`] = `
"
-
Production executions for the last 7 days
"
`;
exports[`InsightsSummary > should render the summary correctly 2`] = `
"
-
Production executions for the last 7 days
"
`;
exports[`InsightsSummary > should render the summary correctly 3`] = `
"
-
Production executions for the last 7 days
"
`;
exports[`InsightsSummary > should render the summary correctly 4`] = `
"
-
Production executions for the last 7 days
"
`;
exports[`InsightsSummary > should render the summary correctly 5`] = `
"
-
Production executions for the last 7 days
"
`;
diff --git a/packages/frontend/editor-ui/src/features/insights/components/charts/InsightsChartAverageRuntime.vue b/packages/frontend/editor-ui/src/features/insights/components/charts/InsightsChartAverageRuntime.vue
index ca23c97a548..41eb3585376 100644
--- a/packages/frontend/editor-ui/src/features/insights/components/charts/InsightsChartAverageRuntime.vue
+++ b/packages/frontend/editor-ui/src/features/insights/components/charts/InsightsChartAverageRuntime.vue
@@ -1,17 +1,17 @@