From d277e0ba0e5d87500457538b4b0f1363e267f071 Mon Sep 17 00:00:00 2001 From: Charlie Kolb Date: Mon, 24 Feb 2025 11:08:00 +0100 Subject: [PATCH 01/68] fix: Prevent flicker during paginated workflow navigation (#13348) --- .../src/components/layouts/ResourcesListLayout.vue | 5 ++++- packages/editor-ui/src/views/WorkflowsView.vue | 8 +++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/editor-ui/src/components/layouts/ResourcesListLayout.vue b/packages/editor-ui/src/components/layouts/ResourcesListLayout.vue index db811c61e9..edf00b32ec 100644 --- a/packages/editor-ui/src/components/layouts/ResourcesListLayout.vue +++ b/packages/editor-ui/src/components/layouts/ResourcesListLayout.vue @@ -551,7 +551,7 @@ const loadPaginationFromQueryString = async () => { -
+
{ } } } +.resource-list-loading-instant { + animation: 0.01s linear 0s forwards changeVisibility; +} @keyframes changeVisibility { from { diff --git a/packages/editor-ui/src/views/WorkflowsView.vue b/packages/editor-ui/src/views/WorkflowsView.vue index e67099f78a..a71732ef90 100644 --- a/packages/editor-ui/src/views/WorkflowsView.vue +++ b/packages/editor-ui/src/views/WorkflowsView.vue @@ -40,6 +40,7 @@ import ProjectHeader from '@/components/Projects/ProjectHeader.vue'; import { getEasyAiWorkflowJson } from '@/utils/easyAiWorkflowUtils'; import { useDebounce } from '@/composables/useDebounce'; import { createEventBus } from 'n8n-design-system/utils'; +import { debounce } from 'lodash-es'; interface Filters extends BaseFilters { status: string | boolean; @@ -237,7 +238,11 @@ const setPageSize = async (size: number) => { }; const fetchWorkflows = async () => { - loading.value = true; + // We debounce here so that fast enough fetches don't trigger + // the placeholder graphics for a few milliseconds, which would cause a flicker + const delayedLoading = debounce(() => { + loading.value = true; + }, 300); const routeProjectId = route.params?.projectId as string | undefined; const homeProjectFilter = filters.value.homeProject || undefined; @@ -252,6 +257,7 @@ const fetchWorkflows = async () => { tags: filters.value.tags.map((tagId) => tagsStore.tagsById[tagId]?.name), }, ); + delayedLoading.cancel(); workflows.value = fetchedWorkflows; loading.value = false; return fetchedWorkflows; From f2b15ea086fcc541a5a584998985d712335210ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Mon, 24 Feb 2025 13:11:25 +0100 Subject: [PATCH 02/68] fix(editor): Polyfill `Array.prototype.toSorted` (no-chanhelog) (#13463) --- packages/editor-ui/package.json | 1 + packages/editor-ui/src/App.vue | 8 ++---- packages/editor-ui/src/polyfills.ts | 7 +++++ pnpm-lock.yaml | 44 +++++++++++++++++++++++------ 4 files changed, 46 insertions(+), 14 deletions(-) create mode 100644 packages/editor-ui/src/polyfills.ts diff --git a/packages/editor-ui/package.json b/packages/editor-ui/package.json index 89eda3e680..e1da571499 100644 --- a/packages/editor-ui/package.json +++ b/packages/editor-ui/package.json @@ -46,6 +46,7 @@ "@vue-flow/node-resizer": "^1.4.0", "@vueuse/components": "^10.11.0", "@vueuse/core": "catalog:frontend", + "array.prototype.tosorted": "1.1.4", "axios": "catalog:", "bowser": "2.11.0", "change-case": "^5.4.4", diff --git a/packages/editor-ui/src/App.vue b/packages/editor-ui/src/App.vue index 30ce2a686d..7178d73bbc 100644 --- a/packages/editor-ui/src/App.vue +++ b/packages/editor-ui/src/App.vue @@ -1,7 +1,8 @@ + + + + diff --git a/packages/editor-ui/src/components/Folders/constants.ts b/packages/editor-ui/src/components/Folders/constants.ts new file mode 100644 index 0000000000..9485fce77d --- /dev/null +++ b/packages/editor-ui/src/components/Folders/constants.ts @@ -0,0 +1,10 @@ +export const FOLDER_LIST_ITEM_ACTIONS = { + OPEN: 'open', + CREATE: 'create', + CREATE_WORKFLOW: 'create_workflow', + RENAME: 'rename', + MOVE: 'move', + CHOWN: 'change_owner', + TAGS: 'manage_tags', + DELETE: 'delete', +}; diff --git a/packages/editor-ui/src/components/Projects/ProjectCardBadge.vue b/packages/editor-ui/src/components/Projects/ProjectCardBadge.vue index fcfd437052..57844522b2 100644 --- a/packages/editor-ui/src/components/Projects/ProjectCardBadge.vue +++ b/packages/editor-ui/src/components/Projects/ProjectCardBadge.vue @@ -3,12 +3,12 @@ import { computed } from 'vue'; import { useI18n } from '@/composables/useI18n'; import type { ResourceType } from '@/utils/projects.utils'; import { splitName } from '@/utils/projects.utils'; -import type { ICredentialsResponse, IWorkflowDb } from '@/Interface'; -import type { Project } from '@/types/projects.types'; +import type { Project, ProjectIcon as BadgeIcon } from '@/types/projects.types'; import { ProjectTypes } from '@/types/projects.types'; +import type { CredentialsResource, WorkflowResource } from '../layouts/ResourcesListLayout.vue'; type Props = { - resource: IWorkflowDb | ICredentialsResponse; + resource: WorkflowResource | CredentialsResource; resourceType: ResourceType; resourceTypeLabel: string; personalProject: Project | null; @@ -68,16 +68,16 @@ const badgeText = computed(() => { return name ?? email ?? ''; } }); -const badgeIcon = computed(() => { +const badgeIcon = computed(() => { switch (projectState.value) { case ProjectState.Owned: case ProjectState.SharedOwned: - return 'user'; + return { type: 'icon', value: 'user' }; case ProjectState.Team: case ProjectState.SharedTeam: - return 'layer-group'; + return props.resource.homeProject?.icon ?? { type: 'icon', value: 'layer-group' }; default: - return ''; + return { type: 'icon', value: 'layer-group' }; } }); const badgeTooltip = computed(() => { @@ -129,12 +129,12 @@ const badgeTooltip = computed(() => {
- + {{ badgeText }} { } } +.projectBadge { + & > span { + display: flex; + gap: var(--spacing-3xs); + } +} + .countBadge { margin-left: -5px; z-index: 0; diff --git a/packages/editor-ui/src/components/Projects/ProjectIcon.vue b/packages/editor-ui/src/components/Projects/ProjectIcon.vue index ae3c47b4e3..7b32c8c556 100644 --- a/packages/editor-ui/src/components/Projects/ProjectIcon.vue +++ b/packages/editor-ui/src/components/Projects/ProjectIcon.vue @@ -3,15 +3,17 @@ import type { ProjectIcon } from '@/types/projects.types'; type Props = { icon: ProjectIcon; - size?: 'small' | 'medium' | 'large'; + size?: 'mini' | 'small' | 'medium' | 'large'; round?: boolean; borderLess?: boolean; + color?: 'text-light' | 'text-base' | 'text-dark'; }; const props = withDefaults(defineProps(), { size: 'medium', round: false, borderLess: false, + color: 'text-base', });