mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-19 11:01:15 +00:00
feat(editor): Evaluation feature Phase one readiness (no-changelog) (#13383)
Co-authored-by: Oleg Ivaniv <me@olegivaniv.com>
This commit is contained in:
committed by
GitHub
parent
7bd83d7d33
commit
b2293b7ad5
@@ -1,31 +1,43 @@
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from '@/composables/useI18n';
|
||||
import { ElCollapseTransition } from 'element-plus';
|
||||
import { ref, nextTick } from 'vue';
|
||||
import { computed, nextTick, ref, useCssModule } from 'vue';
|
||||
|
||||
interface EvaluationStep {
|
||||
title: string;
|
||||
title?: string;
|
||||
warning?: boolean;
|
||||
small?: boolean;
|
||||
expanded?: boolean;
|
||||
description?: string;
|
||||
issues?: Array<{ field: string; message: string }>;
|
||||
showIssues?: boolean;
|
||||
tooltip?: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<EvaluationStep>(), {
|
||||
description: '',
|
||||
warning: false,
|
||||
small: false,
|
||||
expanded: true,
|
||||
expanded: false,
|
||||
issues: () => [],
|
||||
showIssues: true,
|
||||
title: '',
|
||||
});
|
||||
|
||||
const locale = useI18n();
|
||||
const isExpanded = ref(props.expanded);
|
||||
const contentRef = ref<HTMLElement | null>(null);
|
||||
const containerRef = ref<HTMLElement | null>(null);
|
||||
const showTooltip = ref(false);
|
||||
const $style = useCssModule();
|
||||
|
||||
const containerClass = computed(() => {
|
||||
return {
|
||||
[$style.wrap]: true,
|
||||
[$style.expanded]: isExpanded.value,
|
||||
[$style.hasIssues]: props.issues.length > 0,
|
||||
};
|
||||
});
|
||||
|
||||
const toggleExpand = async () => {
|
||||
isExpanded.value = !isExpanded.value;
|
||||
@@ -36,66 +48,98 @@ const toggleExpand = async () => {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleMouseEnter = () => {
|
||||
if (!props.tooltip) return;
|
||||
showTooltip.value = true;
|
||||
};
|
||||
|
||||
const handleMouseLeave = () => {
|
||||
showTooltip.value = false;
|
||||
};
|
||||
|
||||
const renderIssues = computed(() => props.showIssues && props.issues.length);
|
||||
const issuesList = computed(() => props.issues.map((issue) => issue.message).join(', '));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
ref="containerRef"
|
||||
:class="[$style.evaluationStep, small && $style.small]"
|
||||
data-test-id="evaluation-step"
|
||||
>
|
||||
<div :class="$style.content">
|
||||
<div :class="$style.header">
|
||||
<div :class="[$style.icon, warning && $style.warning]">
|
||||
<slot name="icon" />
|
||||
<div :class="containerClass">
|
||||
<slot name="containerPrefix" />
|
||||
<div
|
||||
ref="containerRef"
|
||||
:class="[$style.evaluationStep, small && $style.small]"
|
||||
data-test-id="evaluation-step"
|
||||
@mouseenter="handleMouseEnter"
|
||||
@mouseleave="handleMouseLeave"
|
||||
>
|
||||
<div :class="$style.content">
|
||||
<div :class="$style.header" @click="toggleExpand">
|
||||
<h3 :class="$style.title">
|
||||
<span :class="$style.label">
|
||||
<slot v-if="$slots.title" name="title" />
|
||||
<span v-else>{{ title }}</span>
|
||||
<N8nInfoTip
|
||||
v-if="tooltip"
|
||||
:class="$style.infoTip"
|
||||
:bold="true"
|
||||
type="tooltip"
|
||||
theme="info"
|
||||
tooltip-placement="top"
|
||||
>
|
||||
{{ tooltip }}
|
||||
</N8nInfoTip>
|
||||
</span>
|
||||
</h3>
|
||||
<span v-if="renderIssues" :class="$style.warningIcon">
|
||||
<N8nInfoTip :bold="true" type="tooltip" theme="warning" tooltip-placement="right">
|
||||
{{ issuesList }}
|
||||
</N8nInfoTip>
|
||||
</span>
|
||||
<button
|
||||
v-if="$slots.cardContent"
|
||||
:class="$style.collapseButton"
|
||||
:aria-expanded="isExpanded"
|
||||
data-test-id="evaluation-step-collapse-button"
|
||||
>
|
||||
{{
|
||||
isExpanded
|
||||
? locale.baseText('testDefinition.edit.step.collapse')
|
||||
: locale.baseText('testDefinition.edit.step.configure')
|
||||
}}
|
||||
<font-awesome-icon :icon="isExpanded ? 'angle-down' : 'angle-right'" size="lg" />
|
||||
</button>
|
||||
</div>
|
||||
<h3 :class="$style.title">{{ title }}</h3>
|
||||
<span v-if="issues.length > 0 && showIssues" :class="$style.warningIcon">
|
||||
<N8nInfoTip :bold="true" type="tooltip" theme="warning" tooltip-placement="right">
|
||||
{{ issues.map((issue) => issue.message).join(', ') }}
|
||||
</N8nInfoTip>
|
||||
</span>
|
||||
<button
|
||||
v-if="$slots.cardContent"
|
||||
:class="$style.collapseButton"
|
||||
:aria-expanded="isExpanded"
|
||||
:aria-controls="'content-' + title.replace(/\s+/g, '-')"
|
||||
data-test-id="evaluation-step-collapse-button"
|
||||
@click="toggleExpand"
|
||||
>
|
||||
{{
|
||||
isExpanded
|
||||
? locale.baseText('testDefinition.edit.step.collapse')
|
||||
: locale.baseText('testDefinition.edit.step.expand')
|
||||
}}
|
||||
<font-awesome-icon :icon="isExpanded ? 'angle-down' : 'angle-right'" size="lg" />
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="description" :class="$style.description">{{ description }}</div>
|
||||
<ElCollapseTransition v-if="$slots.cardContent">
|
||||
<div v-show="isExpanded" :class="$style.cardContentWrapper">
|
||||
<div ref="contentRef" :class="$style.cardContent" data-test-id="evaluation-step-content">
|
||||
<slot name="cardContent" />
|
||||
<ElCollapseTransition v-if="$slots.cardContent">
|
||||
<div v-show="isExpanded" :class="$style.cardContentWrapper">
|
||||
<div
|
||||
ref="contentRef"
|
||||
:class="$style.cardContent"
|
||||
data-test-id="evaluation-step-content"
|
||||
>
|
||||
<div v-if="description" :class="$style.description">{{ description }}</div>
|
||||
<slot name="cardContent" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ElCollapseTransition>
|
||||
</ElCollapseTransition>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style module lang="scss">
|
||||
.wrap {
|
||||
position: relative;
|
||||
}
|
||||
.evaluationStep {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--spacing-m);
|
||||
background: var(--color-background-light);
|
||||
padding: var(--spacing-s);
|
||||
border-radius: var(--border-radius-xlarge);
|
||||
box-shadow: var(--box-shadow-base);
|
||||
background: var(--color-background-xlight);
|
||||
border-radius: var(--border-radius-large);
|
||||
border: var(--border-base);
|
||||
width: 100%;
|
||||
color: var(--color-text-dark);
|
||||
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
&.small {
|
||||
width: 80%;
|
||||
margin-left: auto;
|
||||
@@ -117,13 +161,14 @@ const toggleExpand = async () => {
|
||||
|
||||
.content {
|
||||
display: grid;
|
||||
gap: var(--spacing-2xs);
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
gap: var(--spacing-2xs);
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
padding: var(--spacing-s);
|
||||
}
|
||||
|
||||
.title {
|
||||
@@ -131,17 +176,28 @@ const toggleExpand = async () => {
|
||||
font-size: var(--font-size-s);
|
||||
line-height: 1.125rem;
|
||||
}
|
||||
|
||||
.label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-4xs);
|
||||
}
|
||||
.infoTip {
|
||||
opacity: 0;
|
||||
}
|
||||
.evaluationStep:hover .infoTip {
|
||||
opacity: 1;
|
||||
}
|
||||
.warningIcon {
|
||||
color: var(--color-warning);
|
||||
}
|
||||
|
||||
.cardContent {
|
||||
font-size: var(--font-size-s);
|
||||
margin-top: var(--spacing-xs);
|
||||
padding: 0 var(--spacing-s);
|
||||
margin: var(--spacing-s) 0;
|
||||
}
|
||||
.collapseButton {
|
||||
cursor: pointer;
|
||||
pointer-events: none;
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
@@ -151,9 +207,16 @@ const toggleExpand = async () => {
|
||||
text-wrap: none;
|
||||
overflow: hidden;
|
||||
min-width: fit-content;
|
||||
|
||||
.hasIssues & {
|
||||
color: var(--color-danger);
|
||||
}
|
||||
}
|
||||
.cardContentWrapper {
|
||||
height: max-content;
|
||||
.expanded & {
|
||||
border-top: var(--border-base);
|
||||
}
|
||||
}
|
||||
|
||||
.description {
|
||||
@@ -161,4 +224,15 @@ const toggleExpand = async () => {
|
||||
color: var(--color-text-light);
|
||||
line-height: 1rem;
|
||||
}
|
||||
|
||||
.customTooltip {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
background: var(--color-background-dark);
|
||||
color: var(--color-text-light);
|
||||
padding: var(--spacing-3xs) var(--spacing-2xs);
|
||||
border-radius: var(--border-radius-base);
|
||||
font-size: var(--font-size-2xs);
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user