mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-13 16:14:07 -08:00
feat(editor): Update ownership pills (#11155)
Some checks are pending
Test Master / install-and-build (push) Waiting to run
Test Master / Unit tests (18.x) (push) Blocked by required conditions
Test Master / Unit tests (20.x) (push) Blocked by required conditions
Test Master / Unit tests (22.4) (push) Blocked by required conditions
Test Master / Lint (push) Blocked by required conditions
Test Master / Notify Slack on failure (push) Blocked by required conditions
Some checks are pending
Test Master / install-and-build (push) Waiting to run
Test Master / Unit tests (18.x) (push) Blocked by required conditions
Test Master / Unit tests (20.x) (push) Blocked by required conditions
Test Master / Unit tests (22.4) (push) Blocked by required conditions
Test Master / Lint (push) Blocked by required conditions
Test Master / Notify Slack on failure (push) Blocked by required conditions
This commit is contained in:
parent
351134f786
commit
8147038cf8
|
@ -259,7 +259,7 @@ describe('Sharing', { disableAutoLogin: true }, () => {
|
|||
credentialsPage.getters
|
||||
.credentialCards()
|
||||
.should('have.length', 2)
|
||||
.filter(':contains("Owned by me")')
|
||||
.filter(':contains("Personal")')
|
||||
.should('have.length', 1);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -15,12 +15,8 @@ import {
|
|||
NDV,
|
||||
MainSidebar,
|
||||
} from '../pages';
|
||||
import {
|
||||
getVisibleDropdown,
|
||||
getVisibleModalOverlay,
|
||||
getVisibleSelect,
|
||||
getVisiblePopper,
|
||||
} from '../utils';
|
||||
import { clearNotifications } from '../pages/notifications';
|
||||
import { getVisibleDropdown, getVisibleModalOverlay, getVisibleSelect } from '../utils';
|
||||
|
||||
const workflowsPage = new WorkflowsPage();
|
||||
const workflowPage = new WorkflowPage();
|
||||
|
@ -453,38 +449,48 @@ describe('Projects', { disableAutoLogin: true }, () => {
|
|||
workflowsPage.getters.workflowCards().should('not.have.length');
|
||||
workflowsPage.getters.newWorkflowButtonCard().click();
|
||||
projects.createWorkflow('Test_workflow_1.json', 'Workflow in Home project');
|
||||
clearNotifications();
|
||||
|
||||
projects.getHomeButton().click();
|
||||
projects.getProjectTabCredentials().should('be.visible').click();
|
||||
credentialsPage.getters.emptyListCreateCredentialButton().click();
|
||||
projects.createCredential('Credential in Home project');
|
||||
|
||||
clearNotifications();
|
||||
|
||||
// Create a project and add a credential and a workflow to it
|
||||
projects.createProject('Project 1');
|
||||
clearNotifications();
|
||||
projects.getProjectTabCredentials().click();
|
||||
credentialsPage.getters.emptyListCreateCredentialButton().click();
|
||||
projects.createCredential('Credential in Project 1');
|
||||
clearNotifications();
|
||||
|
||||
projects.getProjectTabWorkflows().click();
|
||||
workflowsPage.getters.newWorkflowButtonCard().click();
|
||||
projects.createWorkflow('Test_workflow_1.json', 'Workflow in Project 1');
|
||||
|
||||
clearNotifications();
|
||||
|
||||
// Create another project and add a credential and a workflow to it
|
||||
projects.createProject('Project 2');
|
||||
clearNotifications();
|
||||
projects.getProjectTabCredentials().click();
|
||||
credentialsPage.getters.emptyListCreateCredentialButton().click();
|
||||
projects.createCredential('Credential in Project 2');
|
||||
clearNotifications();
|
||||
|
||||
projects.getProjectTabWorkflows().click();
|
||||
workflowsPage.getters.newWorkflowButtonCard().click();
|
||||
projects.createWorkflow('Test_workflow_1.json', 'Workflow in Project 2');
|
||||
clearNotifications();
|
||||
|
||||
// Move the workflow owned by me from Home to Project 1
|
||||
// Move the workflow Personal from Home to Project 1
|
||||
projects.getHomeButton().click();
|
||||
workflowsPage.getters
|
||||
.workflowCards()
|
||||
.should('have.length', 3)
|
||||
.filter(':contains("Owned by me")')
|
||||
.filter(':contains("Personal")')
|
||||
.should('exist');
|
||||
workflowsPage.getters.workflowCardActions('Workflow in Home project').click();
|
||||
workflowsPage.getters.workflowMoveButton().click();
|
||||
|
@ -501,11 +507,12 @@ describe('Projects', { disableAutoLogin: true }, () => {
|
|||
.filter(':contains("Project 1")')
|
||||
.click();
|
||||
projects.getResourceMoveModal().find('button:contains("Move workflow")').click();
|
||||
clearNotifications();
|
||||
|
||||
workflowsPage.getters
|
||||
.workflowCards()
|
||||
.should('have.length', 3)
|
||||
.filter(':contains("Owned by me")')
|
||||
.filter(':contains("Personal")')
|
||||
.should('not.exist');
|
||||
|
||||
// Move the workflow from Project 1 to Project 2
|
||||
|
@ -532,6 +539,7 @@ describe('Projects', { disableAutoLogin: true }, () => {
|
|||
workflowsPage.getters.workflowCards().should('have.length', 2);
|
||||
workflowsPage.getters.workflowCardActions('Workflow in Home project').click();
|
||||
workflowsPage.getters.workflowMoveButton().click();
|
||||
clearNotifications();
|
||||
|
||||
projects
|
||||
.getResourceMoveModal()
|
||||
|
@ -571,10 +579,11 @@ describe('Projects', { disableAutoLogin: true }, () => {
|
|||
.click();
|
||||
|
||||
projects.getResourceMoveModal().find('button:contains("Move workflow")').click();
|
||||
clearNotifications();
|
||||
workflowsPage.getters
|
||||
.workflowCards()
|
||||
.should('have.length', 3)
|
||||
.filter(':contains("Owned by me")')
|
||||
.filter(':contains("Personal")')
|
||||
.should('have.length', 1);
|
||||
|
||||
// Move the credential from Project 1 to Project 2
|
||||
|
@ -584,9 +593,6 @@ describe('Projects', { disableAutoLogin: true }, () => {
|
|||
credentialsPage.getters.credentialCardActions('Credential in Project 1').click();
|
||||
credentialsPage.getters.credentialMoveButton().click();
|
||||
|
||||
// wait for all poppers to be gone
|
||||
getVisiblePopper().should('have.length', 0);
|
||||
|
||||
projects
|
||||
.getResourceMoveModal()
|
||||
.should('be.visible')
|
||||
|
@ -599,7 +605,7 @@ describe('Projects', { disableAutoLogin: true }, () => {
|
|||
.filter(':contains("Project 2")')
|
||||
.click();
|
||||
projects.getResourceMoveModal().find('button:contains("Move credential")').click();
|
||||
|
||||
clearNotifications();
|
||||
credentialsPage.getters.credentialCards().should('not.have.length');
|
||||
|
||||
// Move the credential from Project 2 to admin user
|
||||
|
@ -610,9 +616,6 @@ describe('Projects', { disableAutoLogin: true }, () => {
|
|||
credentialsPage.getters.credentialCardActions('Credential in Project 1').click();
|
||||
credentialsPage.getters.credentialMoveButton().click();
|
||||
|
||||
// wait for all poppers to be gone
|
||||
getVisiblePopper().should('have.length', 0);
|
||||
|
||||
projects
|
||||
.getResourceMoveModal()
|
||||
.should('be.visible')
|
||||
|
@ -635,9 +638,6 @@ describe('Projects', { disableAutoLogin: true }, () => {
|
|||
credentialsPage.getters.credentialCardActions('Credential in Project 1').click();
|
||||
credentialsPage.getters.credentialMoveButton().click();
|
||||
|
||||
// wait for all poppers to be gone
|
||||
getVisiblePopper().should('have.length', 0);
|
||||
|
||||
projects
|
||||
.getResourceMoveModal()
|
||||
.should('be.visible')
|
||||
|
@ -651,13 +651,12 @@ describe('Projects', { disableAutoLogin: true }, () => {
|
|||
.click();
|
||||
projects.getResourceMoveModal().find('button:contains("Move credential")').click();
|
||||
|
||||
// wait for all poppers to be gone
|
||||
getVisiblePopper().should('have.length', 0);
|
||||
clearNotifications();
|
||||
|
||||
credentialsPage.getters
|
||||
.credentialCards()
|
||||
.should('have.length', 3)
|
||||
.filter(':contains("Owned by me")')
|
||||
.filter(':contains("Personal")')
|
||||
.should('have.length', 2);
|
||||
|
||||
// Move the credential from admin user back to its original project (Project 1)
|
||||
|
@ -716,7 +715,7 @@ describe('Projects', { disableAutoLogin: true }, () => {
|
|||
workflowsPage.getters
|
||||
.workflowCards()
|
||||
.should('have.length', 1)
|
||||
.filter(':contains("Owned by me")')
|
||||
.filter(':contains("Personal")')
|
||||
.should('exist');
|
||||
workflowsPage.getters.workflowCardActions('My workflow').click();
|
||||
workflowsPage.getters.workflowMoveButton().click();
|
||||
|
@ -737,7 +736,7 @@ describe('Projects', { disableAutoLogin: true }, () => {
|
|||
workflowsPage.getters
|
||||
.workflowCards()
|
||||
.should('have.length', 1)
|
||||
.filter(':contains("Owned by me")')
|
||||
.filter(':contains("Personal")')
|
||||
.should('not.exist');
|
||||
|
||||
//Log out with instance owner and log in with the member user
|
||||
|
|
|
@ -5,7 +5,7 @@ import { truncate } from 'n8n-design-system';
|
|||
const renderComponent = createComponentRenderer(ProjectCardBadge);
|
||||
|
||||
describe('ProjectCardBadge', () => {
|
||||
it('should show "Owned by me" badge if there is no homeProject', () => {
|
||||
it('should show "Personal" badge if there is no homeProject', () => {
|
||||
const { getByText } = renderComponent({
|
||||
props: {
|
||||
resource: {},
|
||||
|
@ -13,15 +13,16 @@ describe('ProjectCardBadge', () => {
|
|||
},
|
||||
});
|
||||
|
||||
expect(getByText('Owned by me')).toBeVisible();
|
||||
expect(getByText('Personal')).toBeVisible();
|
||||
});
|
||||
|
||||
it('should show "Owned by me" badge if homeProject ID equals personalProject ID', () => {
|
||||
it('should show "Personal" badge if homeProject ID equals personalProject ID', () => {
|
||||
const { getByText } = renderComponent({
|
||||
props: {
|
||||
resource: {
|
||||
homeProject: {
|
||||
id: '1',
|
||||
name: 'John',
|
||||
},
|
||||
},
|
||||
resourceType: 'workflow',
|
||||
|
@ -31,7 +32,27 @@ describe('ProjectCardBadge', () => {
|
|||
},
|
||||
});
|
||||
|
||||
expect(getByText('Owned by me')).toBeVisible();
|
||||
expect(getByText('Personal')).toBeVisible();
|
||||
});
|
||||
|
||||
it('should show shared with count', () => {
|
||||
const { getByText } = renderComponent({
|
||||
props: {
|
||||
resource: {
|
||||
sharedWithProjects: [{}, {}, {}],
|
||||
homeProject: {
|
||||
id: '1',
|
||||
name: 'John',
|
||||
},
|
||||
},
|
||||
resourceType: 'workflow',
|
||||
personalProject: {
|
||||
id: '1',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(getByText('+ 3')).toBeVisible();
|
||||
});
|
||||
|
||||
test.each([
|
||||
|
|
|
@ -52,12 +52,17 @@ const projectState = computed(() => {
|
|||
}
|
||||
return ProjectState.Unknown;
|
||||
});
|
||||
|
||||
const numberOfMembersInHomeTeamProject = computed(
|
||||
() => props.resource.sharedWithProjects?.length ?? 0,
|
||||
);
|
||||
|
||||
const badgeText = computed(() => {
|
||||
if (
|
||||
projectState.value === ProjectState.Owned ||
|
||||
projectState.value === ProjectState.SharedOwned
|
||||
) {
|
||||
return i18n.baseText('generic.ownedByMe');
|
||||
return i18n.baseText('projects.menu.personal');
|
||||
} else {
|
||||
const { name, email } = splitName(props.resource.homeProject?.name ?? '');
|
||||
return name ?? email ?? '';
|
||||
|
@ -65,12 +70,12 @@ const badgeText = computed(() => {
|
|||
});
|
||||
const badgeIcon = computed(() => {
|
||||
switch (projectState.value) {
|
||||
case ProjectState.SharedPersonal:
|
||||
case ProjectState.Owned:
|
||||
case ProjectState.SharedOwned:
|
||||
return 'user-friends';
|
||||
return 'user';
|
||||
case ProjectState.Team:
|
||||
case ProjectState.SharedTeam:
|
||||
return 'archive';
|
||||
return 'layer-group';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
|
@ -81,6 +86,7 @@ const badgeTooltip = computed(() => {
|
|||
return i18n.baseText('projects.badge.tooltip.sharedOwned', {
|
||||
interpolate: {
|
||||
resourceTypeLabel: props.resourceTypeLabel,
|
||||
count: numberOfMembersInHomeTeamProject.value,
|
||||
},
|
||||
});
|
||||
case ProjectState.SharedPersonal:
|
||||
|
@ -88,6 +94,7 @@ const badgeTooltip = computed(() => {
|
|||
interpolate: {
|
||||
resourceTypeLabel: props.resourceTypeLabel,
|
||||
name: badgeText.value,
|
||||
count: numberOfMembersInHomeTeamProject.value,
|
||||
},
|
||||
});
|
||||
case ProjectState.Personal:
|
||||
|
@ -109,6 +116,7 @@ const badgeTooltip = computed(() => {
|
|||
interpolate: {
|
||||
resourceTypeLabel: props.resourceTypeLabel,
|
||||
name: badgeText.value,
|
||||
count: numberOfMembersInHomeTeamProject.value,
|
||||
},
|
||||
});
|
||||
default:
|
||||
|
@ -118,14 +126,53 @@ const badgeTooltip = computed(() => {
|
|||
</script>
|
||||
<template>
|
||||
<N8nTooltip :disabled="!badgeTooltip" placement="top">
|
||||
<N8nBadge v-if="badgeText" class="mr-xs" theme="tertiary" bold data-test-id="card-badge">
|
||||
<span v-n8n-truncate:20>{{ badgeText }}</span>
|
||||
<N8nIcon v-if="badgeIcon" :icon="badgeIcon" size="small" class="ml-5xs" />
|
||||
</N8nBadge>
|
||||
<div class="mr-xs">
|
||||
<N8nBadge
|
||||
v-if="badgeText"
|
||||
:class="$style.badge"
|
||||
theme="tertiary"
|
||||
bold
|
||||
data-test-id="card-badge"
|
||||
>
|
||||
<N8nIcon v-if="badgeIcon" :icon="badgeIcon" size="small" class="mr-3xs" />
|
||||
<span v-n8n-truncate:20>{{ badgeText }}</span>
|
||||
</N8nBadge>
|
||||
<N8nBadge
|
||||
v-if="numberOfMembersInHomeTeamProject"
|
||||
:class="[$style.badge, $style.countBadge]"
|
||||
theme="tertiary"
|
||||
bold
|
||||
>
|
||||
+ {{ numberOfMembersInHomeTeamProject }}
|
||||
</N8nBadge>
|
||||
</div>
|
||||
<template #content>
|
||||
{{ badgeTooltip }}
|
||||
</template>
|
||||
</N8nTooltip>
|
||||
</template>
|
||||
|
||||
<style lang="scss" module></style>
|
||||
<style lang="scss" module>
|
||||
.badge {
|
||||
padding: var(--spacing-4xs) var(--spacing-2xs);
|
||||
background-color: var(--color-background-xlight);
|
||||
border-color: var(--color-foreground-base);
|
||||
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
height: 23px;
|
||||
:global(.n8n-text) {
|
||||
color: var(--color-text-base);
|
||||
}
|
||||
}
|
||||
|
||||
.countBadge {
|
||||
margin-left: -5px;
|
||||
z-index: 0;
|
||||
position: relative;
|
||||
height: 23px;
|
||||
:global(.n8n-text) {
|
||||
color: var(--color-text-light);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
"generic.seePlans": "See plans",
|
||||
"generic.loading": "Loading",
|
||||
"generic.and": "and",
|
||||
"generic.ownedByMe": "Owned by me",
|
||||
"generic.ownedByMe": "(You)",
|
||||
"generic.moreInfo": "More info",
|
||||
"generic.next": "Next",
|
||||
"about.aboutN8n": "About n8n",
|
||||
|
@ -2543,11 +2543,11 @@
|
|||
"projects.move.resource.success.message": "{resourceName} {resourceTypeLabel} was moved to {targetProjectName}. {workflow} {link}",
|
||||
"projects.move.resource.success.message.workflow": "Please double check any credentials this workflow is using are also shared with {targetProjectName}.",
|
||||
"projects.move.resource.success.link": "View {targetProjectName}",
|
||||
"projects.badge.tooltip.sharedOwned": "This {resourceTypeLabel} is owned by you and shared with one or more projects or users",
|
||||
"projects.badge.tooltip.sharedPersonal": "This {resourceTypeLabel} is owned by {name} and shared with one or more projects or users",
|
||||
"projects.badge.tooltip.sharedOwned": "This {resourceTypeLabel} is owned by you and shared with {count} users",
|
||||
"projects.badge.tooltip.sharedPersonal": "This {resourceTypeLabel} is owned by {name} and shared with {count} users",
|
||||
"projects.badge.tooltip.personal": "This {resourceTypeLabel} is owned by {name}",
|
||||
"projects.badge.tooltip.team": "This {resourceTypeLabel} is owned and accessible by the {name} project.",
|
||||
"projects.badge.tooltip.sharedTeam": "This {resourceTypeLabel} is owned and accessible by the {name} project and shared with one or more projects or users",
|
||||
"projects.badge.tooltip.sharedTeam": "This {resourceTypeLabel} is owned by the {name} project and accessible by {count} users",
|
||||
"mfa.setup.invalidAuthenticatorCode": "{code} is not a valid number",
|
||||
"mfa.setup.invalidCode": "Two-factor code failed. Please try again.",
|
||||
"mfa.code.modal.title": "Two-factor authentication",
|
||||
|
|
Loading…
Reference in a new issue