From ea89c36447df49db12e2d27eaa4e55690b1d756b 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: Thu, 12 Sep 2024 20:07:19 +0200 Subject: [PATCH] fix(editor): Render the current first in CollaborationPane (no-changelog) (#10799) --- .../MainHeader/CollaborationPane.vue | 14 ++-- .../__tests__/CollaborationPane.test.ts | 77 +++++-------------- 2 files changed, 25 insertions(+), 66 deletions(-) diff --git a/packages/editor-ui/src/components/MainHeader/CollaborationPane.vue b/packages/editor-ui/src/components/MainHeader/CollaborationPane.vue index 43423c914ce99..313aa93c72c2f 100644 --- a/packages/editor-ui/src/components/MainHeader/CollaborationPane.vue +++ b/packages/editor-ui/src/components/MainHeader/CollaborationPane.vue @@ -4,7 +4,6 @@ import { useDocumentVisibility } from '@vueuse/core'; import { useUsersStore } from '@/stores/users.store'; import { useCollaborationStore } from '@/stores/collaboration.store'; -import { isUserGlobalOwner } from '@/utils/userUtils'; const collaborationStore = useCollaborationStore(); const usersStore = useUsersStore(); @@ -21,13 +20,12 @@ watch(visibility, (visibilityState) => { const showUserStack = computed(() => collaborationStore.collaborators.length > 1); const collaboratorsSorted = computed(() => { - const currentWorkflowUsers = collaborationStore.collaborators.map(({ user }) => user); - const owner = currentWorkflowUsers.find(isUserGlobalOwner); - return { - defaultGroup: owner - ? [owner, ...currentWorkflowUsers.filter((user) => user.id !== owner.id)] - : currentWorkflowUsers, - }; + const users = collaborationStore.collaborators.map(({ user }) => user); + // Move the current user to the first position, if not already there. + const index = users.findIndex((user) => user.id === usersStore.currentUser?.id); + if (index < 1) return { defaultGroup: users }; + const [currentUser] = users.splice(index, 1); + return { defaultGroup: [currentUser, ...users] }; }); const currentUserEmail = computed(() => usersStore.currentUser?.email); diff --git a/packages/editor-ui/src/components/__tests__/CollaborationPane.test.ts b/packages/editor-ui/src/components/__tests__/CollaborationPane.test.ts index cd7af346f021a..6405d108212cd 100644 --- a/packages/editor-ui/src/components/__tests__/CollaborationPane.test.ts +++ b/packages/editor-ui/src/components/__tests__/CollaborationPane.test.ts @@ -1,69 +1,29 @@ -import { merge } from 'lodash-es'; -import { SETTINGS_STORE_DEFAULT_STATE, waitAllPromises } from '@/__tests__/utils'; -import { ROLE, STORES } from '@/constants'; import { createTestingPinia } from '@pinia/testing'; -import CollaborationPane from '@/components//MainHeader/CollaborationPane.vue'; +import { mock } from 'vitest-mock-extended'; + +import { STORES } from '@/constants'; +import CollaborationPane from '@/components/MainHeader/CollaborationPane.vue'; +import type { IUser } from '@/Interface'; + import type { RenderOptions } from '@/__tests__/render'; import { createComponentRenderer } from '@/__tests__/render'; +import { waitAllPromises } from '@/__tests__/utils'; -const OWNER_USER = { - createdAt: '2023-11-22T10:17:12.246Z', - id: 'aaaaaa', - email: 'owner@user.com', - firstName: 'Owner', - lastName: 'User', - role: ROLE.Owner, - disabled: false, - isPending: false, - fullName: 'Owner User', -}; - -const MEMBER_USER = { - createdAt: '2023-11-22T10:17:12.246Z', - id: 'aaabbb', - email: 'member@user.com', - firstName: 'Member', - lastName: 'User', - role: ROLE.Member, - disabled: false, - isPending: false, - fullName: 'Member User', -}; - -const MEMBER_USER_2 = { - createdAt: '2023-11-22T10:17:12.246Z', - id: 'aaaccc', - email: 'member2@user.com', - firstName: 'Another Member', - lastName: 'User', - role: ROLE.Member, - disabled: false, - isPending: false, - fullName: 'Another Member User', -}; +const OWNER_USER = mock({ id: 'owner-id' }); +const MEMBER_USER = mock({ id: 'member-id' }); +const MEMBER_USER_2 = mock({ id: 'member-id-2' }); const initialState = { - [STORES.SETTINGS]: { - settings: merge({}, SETTINGS_STORE_DEFAULT_STATE.settings), - }, - [STORES.WORKFLOWS]: { - workflow: { - id: 'w1', - }, - }, [STORES.USERS]: { - currentUserId: 'aaaaaa', - users: { - aaaaaa: OWNER_USER, - aaabbb: MEMBER_USER, - aaaccc: MEMBER_USER_2, + currentUserId: OWNER_USER.id, + usersById: { + [OWNER_USER.id]: OWNER_USER, + [MEMBER_USER.id]: MEMBER_USER, + [MEMBER_USER_2.id]: MEMBER_USER_2, }, }, [STORES.COLLABORATION]: { - collaborators: [ - { lastSeen: '2023-11-22T10:17:12.246Z', user: MEMBER_USER }, - { lastSeen: '2023-11-22T10:17:12.246Z', user: OWNER_USER }, - ], + collaborators: [{ user: MEMBER_USER }, { user: OWNER_USER }], }, }; @@ -89,9 +49,10 @@ describe('CollaborationPane', () => { expect(queryByTestId(`user-stack-avatar-${MEMBER_USER_2.id}`)).toBeNull(); }); - it('should always render owner first in the list', async () => { + it('should always render the current user first in the list', async () => { const { getByTestId } = renderComponent(); await waitAllPromises(); + const firstAvatar = getByTestId('user-stack-avatars').querySelector('.n8n-avatar'); // Owner is second in the store but should be rendered first expect(firstAvatar).toHaveAttribute('data-test-id', `user-stack-avatar-${OWNER_USER.id}`); @@ -103,7 +64,7 @@ describe('CollaborationPane', () => { initialState: { ...initialState, [STORES.COLLABORATION]: { - collaborators: [{ lastSeen: '2023-11-22T10:17:12.246Z', user: OWNER_USER }], + collaborators: [{ user: OWNER_USER }], }, }, }),