mirror of
https://github.com/n8n-io/n8n.git
synced 2026-06-01 17:27:14 +02:00
feat(editor): Add templates quality experiment inline section on empty project layout (no-changelog) (#22078)
This commit is contained in:
parent
77b7c2dd1a
commit
2ba34dbb74
|
|
@ -13,7 +13,6 @@ import { useTagsStore } from '@/features/shared/tags/tags.store';
|
|||
import { useUsersStore } from '@/features/settings/users/users.store';
|
||||
import { useWorkflowsStore } from '@/app/stores/workflows.store';
|
||||
import type { Project } from '@/features/collaboration/projects/projects.types';
|
||||
import { TemplateClickSource } from '@/experiments/utils';
|
||||
import WorkflowsView from '@/app/views/WorkflowsView.vue';
|
||||
import { STORES } from '@n8n/stores';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
|
|
@ -172,36 +171,6 @@ describe('WorkflowsView', () => {
|
|||
|
||||
expect(router.currentRoute.value.name).toBe(VIEWS.NEW_WORKFLOW);
|
||||
});
|
||||
|
||||
it('should show template card', async () => {
|
||||
const projectsStore = mockedStore(useProjectsStore);
|
||||
projectsStore.currentProject = { scopes: ['workflow:create'] } as Project;
|
||||
|
||||
settingsStore.settings.templates = { enabled: true, host: 'http://example.com' };
|
||||
const { getByTestId } = renderComponent({ pinia });
|
||||
await waitAllPromises();
|
||||
|
||||
expect(getByTestId('new-workflow-from-template-card')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should track template card click', async () => {
|
||||
const projectsStore = mockedStore(useProjectsStore);
|
||||
projectsStore.currentProject = { scopes: ['workflow:create'] } as Project;
|
||||
|
||||
settingsStore.settings.templates = { enabled: true, host: 'http://example.com' };
|
||||
const { getByTestId } = renderComponent({ pinia });
|
||||
await waitAllPromises();
|
||||
|
||||
const card = getByTestId('new-workflow-from-template-card');
|
||||
await userEvent.click(card);
|
||||
|
||||
expect(mockTrack).toHaveBeenCalledWith(
|
||||
'User clicked on templates',
|
||||
expect.objectContaining({
|
||||
source: TemplateClickSource.emptyInstanceCard,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetch workflow options', () => {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import { useCalloutHelpers } from '@/app/composables/useCalloutHelpers';
|
|||
import {
|
||||
DEFAULT_WORKFLOW_PAGE_SIZE,
|
||||
EnterpriseEditionFeature,
|
||||
EXPERIMENT_TEMPLATES_DATA_QUALITY_KEY,
|
||||
MODAL_CONFIRM,
|
||||
VIEWS,
|
||||
} from '@/app/constants';
|
||||
|
|
@ -33,6 +32,7 @@ import { usePersonalizedTemplatesStore } from '@/experiments/personalizedTemplat
|
|||
import { useReadyToRunWorkflowsStore } from '@/experiments/readyToRunWorkflows/stores/readyToRunWorkflows.store';
|
||||
import TemplateRecommendationV2 from '@/experiments/templateRecoV2/components/TemplateRecommendationV2.vue';
|
||||
import TemplateRecommendationV3 from '@/experiments/personalizedTemplatesV3/components/TemplateRecommendationV3.vue';
|
||||
import TemplatesDataQualityInlineSection from '@/experiments/templatesDataQuality/components/TemplatesDataQualityInlineSection.vue';
|
||||
import { usePersonalizedTemplatesV2Store } from '@/experiments/templateRecoV2/stores/templateRecoV2.store';
|
||||
import { usePersonalizedTemplatesV3Store } from '@/experiments/personalizedTemplatesV3/stores/personalizedTemplatesV3.store';
|
||||
import EmptyStateLayout from '@/app/components/layouts/EmptyStateLayout.vue';
|
||||
|
|
@ -55,7 +55,6 @@ import { useProjectsStore } from '@/features/collaboration/projects/projects.sto
|
|||
import { useSettingsStore } from '@/app/stores/settings.store';
|
||||
import { useSourceControlStore } from '@/features/integrations/sourceControl.ee/sourceControl.store';
|
||||
import { useTagsStore } from '@/features/shared/tags/tags.store';
|
||||
import { useTemplatesStore } from '@/features/workflows/templates/templates.store';
|
||||
import { useUIStore } from '@/app/stores/ui.store';
|
||||
import { useUsageStore } from '@/features/settings/usage/usage.store';
|
||||
import { useUsersStore } from '@/features/settings/users/users.store';
|
||||
|
|
@ -66,11 +65,6 @@ import {
|
|||
ProjectTypes,
|
||||
} from '@/features/collaboration/projects/projects.types';
|
||||
import { getEasyAiWorkflowJson } from '@/features/workflows/templates/utils/workflowSamples';
|
||||
import {
|
||||
isExtraTemplateLinksExperimentEnabled,
|
||||
TemplateClickSource,
|
||||
trackTemplatesClick,
|
||||
} from '@/experiments/utils';
|
||||
import type { PathItem } from '@n8n/design-system/components/N8nBreadcrumbs/Breadcrumbs.vue';
|
||||
import { useI18n } from '@n8n/i18n';
|
||||
import { getResourcePermissions } from '@n8n/permissions';
|
||||
|
|
@ -140,7 +134,6 @@ const tagsStore = useTagsStore();
|
|||
const foldersStore = useFoldersStore();
|
||||
const usageStore = useUsageStore();
|
||||
const insightsStore = useInsightsStore();
|
||||
const templatesStore = useTemplatesStore();
|
||||
const aiStarterTemplatesStore = useAITemplatesStarterCollectionStore();
|
||||
const personalizedTemplatesStore = usePersonalizedTemplatesStore();
|
||||
const readyToRunWorkflowsStore = useReadyToRunWorkflowsStore();
|
||||
|
|
@ -390,16 +383,20 @@ const showEasyAIWorkflowCallout = computed(() => {
|
|||
return !easyAIWorkflowOnboardingDone;
|
||||
});
|
||||
|
||||
const templatesCardEnabled = computed(() => {
|
||||
return isExtraTemplateLinksExperimentEnabled() && settingsStore.isTemplatesEnabled;
|
||||
});
|
||||
|
||||
const projectPermissions = computed(() => {
|
||||
return getResourcePermissions(
|
||||
projectsStore.currentProject?.scopes ?? personalProject.value?.scopes,
|
||||
);
|
||||
});
|
||||
|
||||
const showTemplatesDataQualityInline = computed(() => {
|
||||
return (
|
||||
templatesDataQualityStore.isFeatureEnabled() &&
|
||||
!readOnlyEnv.value &&
|
||||
projectPermissions.value.workflow.create
|
||||
);
|
||||
});
|
||||
|
||||
const showReadyToRunWorkflowsCallout = computed(() => {
|
||||
const isEnabled = readyToRunWorkflowsStore.isFeatureEnabled;
|
||||
const isDismissed = readyToRunWorkflowsStore.isCalloutDismissed;
|
||||
|
|
@ -921,22 +918,6 @@ const addWorkflow = () => {
|
|||
trackEmptyCardClick('blank');
|
||||
};
|
||||
|
||||
const openTemplatesRepository = async () => {
|
||||
trackTemplatesClick(TemplateClickSource.emptyInstanceCard);
|
||||
|
||||
if (templatesStore.hasCustomTemplatesHost) {
|
||||
await router.push({ name: VIEWS.TEMPLATES });
|
||||
return;
|
||||
}
|
||||
|
||||
if (templatesDataQualityStore.isFeatureEnabled()) {
|
||||
uiStore.openModal(EXPERIMENT_TEMPLATES_DATA_QUALITY_KEY);
|
||||
return;
|
||||
}
|
||||
|
||||
window.open(templatesStore.websiteTemplateRepositoryURL, '_blank');
|
||||
};
|
||||
|
||||
const trackEmptyCardClick = (option: 'blank' | 'templates' | 'courses') => {
|
||||
telemetry.track('User clicked empty page option', {
|
||||
option,
|
||||
|
|
@ -2247,25 +2228,9 @@ const onNameSubmit = async (name: string) => {
|
|||
</N8nText>
|
||||
</div>
|
||||
</N8nCard>
|
||||
<N8nCard
|
||||
v-if="templatesCardEnabled"
|
||||
:class="$style.emptyStateCard"
|
||||
hoverable
|
||||
data-test-id="new-workflow-from-template-card"
|
||||
@click="openTemplatesRepository"
|
||||
>
|
||||
<div :class="$style.emptyStateCardContent">
|
||||
<N8nIcon
|
||||
:class="$style.emptyStateCardIcon"
|
||||
:stroke-width="1.5"
|
||||
icon="package-open"
|
||||
color="foreground-dark"
|
||||
/>
|
||||
<N8nText size="large" class="mt-xs pl-2xs pr-2xs">
|
||||
{{ i18n.baseText('workflows.empty.startWithTemplate') }}
|
||||
</N8nText>
|
||||
</div>
|
||||
</N8nCard>
|
||||
</div>
|
||||
<div v-if="showTemplatesDataQualityInline" :class="$style.templatesContainer">
|
||||
<TemplatesDataQualityInlineSection />
|
||||
</div>
|
||||
<TemplateRecommendationV3 v-if="showTemplateRecommendationV3" />
|
||||
<TemplateRecommendationV2 v-else-if="showTemplateRecommendationV2" />
|
||||
|
|
@ -2369,6 +2334,16 @@ const onNameSubmit = async (name: string) => {
|
|||
justify-content: center;
|
||||
}
|
||||
|
||||
.templatesContainer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
|
||||
> section {
|
||||
margin-top: var(--spacing--3xl);
|
||||
}
|
||||
}
|
||||
|
||||
.easy-ai-workflow-callout {
|
||||
// Make the callout padding in line with workflow cards
|
||||
margin-top: var(--spacing--xs);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user