mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-17 05:29:44 +02:00
fix(editor): Rename the Only you label to Available to you in the credential sharing modal (no-changelog) (#40411)
This commit is contained in:
parent
eaf8c25d1c
commit
eac5d1d7b3
|
|
@ -1199,8 +1199,10 @@
|
|||
"credentialEdit.credentialSharing.unshare.confirm.cancelButtonText": "Cancel",
|
||||
"credentialEdit.credentialSharing.usedIn": "Used in \"{workflowName}\"",
|
||||
"credentialEdit.credentialSharing.usedIn.count": "Used in {count} workflows",
|
||||
"credentialEdit.credentialSharing.onlyYou": "Only you",
|
||||
"credentialEdit.credentialSharing.onlyOwner": "Only {name}",
|
||||
"credentialEdit.credentialSharing.availableToYou": "Available to you",
|
||||
"credentialEdit.credentialSharing.availableToYou.tooltip": "Only you can use this credential in {project}. Share it to let others in that project use it.",
|
||||
"credentialEdit.credentialSharing.availableToOwner": "Available to {name}",
|
||||
"credentialEdit.credentialSharing.availableToOwner.tooltip": "Only {name} can use this credential in {project}.",
|
||||
"credentialEdit.credentialSharing.share": "Share",
|
||||
"credentialEdit.credentialSharing.shareWith": "Share with {project}",
|
||||
"credentialSelectModal.addNewCredential": "Add new credential",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { createComponentRenderer } from '@/__tests__/render';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { waitFor } from '@testing-library/vue';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { setActivePinia } from 'pinia';
|
||||
import CredentialSharing from './CredentialSharing.ee.vue';
|
||||
|
|
@ -9,7 +10,7 @@ import { useSettingsStore } from '@n8n/stores/settings.store';
|
|||
import { useRolesStore } from '@n8n/stores/roles.store';
|
||||
import type { ICredentialsResponse } from '../../credentials.types';
|
||||
import { createEventBus } from '@n8n/utils/event-bus';
|
||||
import { getDropdownItems } from '@/__tests__/utils';
|
||||
import { getDropdownItems, getTooltip, hoverTooltipTrigger } from '@/__tests__/utils';
|
||||
import { useI18n } from '@n8n/i18n';
|
||||
import type * as I18nModule from '@n8n/i18n';
|
||||
import { ProjectTypes } from '@/features/collaboration/projects/projects.types';
|
||||
|
|
@ -53,8 +54,12 @@ const mockBaseText = vi.fn((key: string, options?: { interpolate?: Record<string
|
|||
"Can use this credential. Can't edit it.",
|
||||
'credentialEdit.credentialSharing.usedIn': 'Used in "{workflowName}"',
|
||||
'credentialEdit.credentialSharing.usedIn.count': 'Used in {count} workflows',
|
||||
'credentialEdit.credentialSharing.onlyYou': 'Only you',
|
||||
'credentialEdit.credentialSharing.onlyOwner': 'Only {name}',
|
||||
'credentialEdit.credentialSharing.availableToYou': 'Available to you',
|
||||
'credentialEdit.credentialSharing.availableToYou.tooltip':
|
||||
'Only you can use this credential in {project}.',
|
||||
'credentialEdit.credentialSharing.availableToOwner': 'Available to {name}',
|
||||
'credentialEdit.credentialSharing.availableToOwner.tooltip':
|
||||
'Only {name} can use this credential in {project}.',
|
||||
'credentialEdit.credentialSharing.share': 'Share',
|
||||
'credentialEdit.credentialSharing.shareWith': 'Share with {project}',
|
||||
'auth.roles.owner': 'Owner',
|
||||
|
|
@ -664,7 +669,7 @@ describe('CredentialSharing.ee', () => {
|
|||
projectsStore.personalProject = ownerPersonalProject;
|
||||
});
|
||||
|
||||
it('shows a project the credential is used in but not shared with, with "Only you" and a Share action', () => {
|
||||
it('shows a project the credential is used in but not shared with, with "Available to you" and a Share action', () => {
|
||||
getDependenciesMock.mockReturnValue({
|
||||
dependencies: [
|
||||
{
|
||||
|
|
@ -696,7 +701,7 @@ describe('CredentialSharing.ee', () => {
|
|||
const row = getByTestId('project-sharing-unshared-item');
|
||||
expect(row).toHaveTextContent('Marketing');
|
||||
expect(row).toHaveTextContent('Used in "Email summary"');
|
||||
expect(row).toHaveTextContent('Only you');
|
||||
expect(row).toHaveTextContent('Available to you');
|
||||
expect(getByTestId('credential-used-in-project-share')).toHaveTextContent(
|
||||
'Share with Marketing',
|
||||
);
|
||||
|
|
@ -774,6 +779,75 @@ describe('CredentialSharing.ee', () => {
|
|||
expect(getByTestId('credential-used-in-project-share')).toHaveTextContent(/^\s*Share\s*$/);
|
||||
});
|
||||
|
||||
it('explains in a tooltip that only the owner can use the credential in the project', async () => {
|
||||
getDependenciesMock.mockReturnValue({
|
||||
dependencies: [
|
||||
{
|
||||
id: 'wf-1',
|
||||
name: 'Email summary',
|
||||
type: 'workflowParent',
|
||||
projectId: 'marketing-project',
|
||||
},
|
||||
],
|
||||
inaccessibleCount: 0,
|
||||
});
|
||||
|
||||
const credential = createCredential({
|
||||
homeProject: ownerPersonalProject,
|
||||
sharedWithProjects: [],
|
||||
});
|
||||
const { getByText } = renderComponent({
|
||||
props: {
|
||||
credentialId: credential.id,
|
||||
credentialData: {},
|
||||
credentialPermissions: { share: true },
|
||||
credential,
|
||||
modalBus: createEventBus(),
|
||||
},
|
||||
});
|
||||
|
||||
await hoverTooltipTrigger(getByText('Available to you'));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(getTooltip()).toHaveTextContent('Only you can use this credential in Marketing.'),
|
||||
);
|
||||
});
|
||||
|
||||
it('still explains the access in a tooltip when the project has no name', async () => {
|
||||
projectsStore.myProjects = [{ ...marketingProject, name: null }];
|
||||
getDependenciesMock.mockReturnValue({
|
||||
dependencies: [
|
||||
{
|
||||
id: 'wf-1',
|
||||
name: 'Email summary',
|
||||
type: 'workflowParent',
|
||||
projectId: 'marketing-project',
|
||||
},
|
||||
],
|
||||
inaccessibleCount: 0,
|
||||
});
|
||||
|
||||
const credential = createCredential({
|
||||
homeProject: ownerPersonalProject,
|
||||
sharedWithProjects: [],
|
||||
});
|
||||
const { getByText } = renderComponent({
|
||||
props: {
|
||||
credentialId: credential.id,
|
||||
credentialData: {},
|
||||
credentialPermissions: { share: true },
|
||||
credential,
|
||||
modalBus: createEventBus(),
|
||||
},
|
||||
});
|
||||
|
||||
await hoverTooltipTrigger(getByText('Available to you'));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(getTooltip()).toHaveTextContent('Only you can use this credential in'),
|
||||
);
|
||||
});
|
||||
|
||||
it('summarizes as "Used in N workflows" when the credential is used in more than one workflow in the same project', () => {
|
||||
getDependenciesMock.mockReturnValue({
|
||||
dependencies: [
|
||||
|
|
@ -943,7 +1017,7 @@ describe('CredentialSharing.ee', () => {
|
|||
expect(queryByTestId('project-sharing-unshared-item')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows "Only {owner}" instead of "Only you" when the viewer has share permission but is not the credential\'s owner (e.g. an instance admin)', () => {
|
||||
it('shows "Available to {owner}" instead of "Available to you" when the viewer has share permission but is not the credential\'s owner (e.g. an instance admin)', () => {
|
||||
// Viewer's own personal project differs from the credential's home
|
||||
// project, even though they can still share it (broad admin scope).
|
||||
projectsStore.personalProject = {
|
||||
|
|
@ -984,9 +1058,9 @@ describe('CredentialSharing.ee', () => {
|
|||
});
|
||||
|
||||
const row = getByTestId('project-sharing-unshared-item');
|
||||
expect(row).toHaveTextContent('Only Mona');
|
||||
expect(row).not.toHaveTextContent('Only Mona Pfeffer');
|
||||
expect(queryByText('Only you')).not.toBeInTheDocument();
|
||||
expect(row).toHaveTextContent('Available to Mona');
|
||||
expect(row).not.toHaveTextContent('Available to Mona Pfeffer');
|
||||
expect(queryByText('Available to you')).not.toBeInTheDocument();
|
||||
expect(getByTestId('credential-used-in-project-share')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import { getResourcePermissions } from '@n8n/permissions';
|
|||
import { useEnvFeatureFlag } from '@/features/shared/envFeatureFlag/useEnvFeatureFlag';
|
||||
import { useDependencies } from '@/app/composables/useDependencies';
|
||||
|
||||
import { N8nButton, N8nEmptyState, N8nInfoTip, N8nText } from '@n8n/design-system';
|
||||
import { N8nButton, N8nEmptyState, N8nInfoTip, N8nText, N8nTooltip } from '@n8n/design-system';
|
||||
type Props = {
|
||||
credentialId: string;
|
||||
credentialData: ICredentialDataDecryptedObject;
|
||||
|
|
@ -203,8 +203,8 @@ const usedInProjects = computed(() => {
|
|||
|
||||
const usedInAccessText = computed(() =>
|
||||
isOwnedByViewer.value
|
||||
? i18n.baseText('credentialEdit.credentialSharing.onlyYou')
|
||||
: i18n.baseText('credentialEdit.credentialSharing.onlyOwner', {
|
||||
? i18n.baseText('credentialEdit.credentialSharing.availableToYou')
|
||||
: i18n.baseText('credentialEdit.credentialSharing.availableToOwner', {
|
||||
interpolate: { name: credentialOwnerFirstName.value },
|
||||
}),
|
||||
);
|
||||
|
|
@ -220,6 +220,18 @@ function usedInShareLabel(project: Pick<ProjectSharingData, 'name'>) {
|
|||
: i18n.baseText('credentialEdit.credentialSharing.share');
|
||||
}
|
||||
|
||||
function usedInAccessTooltip(project: Pick<ProjectSharingData, 'name'>) {
|
||||
const projectName = project.name ?? '';
|
||||
|
||||
return isOwnedByViewer.value
|
||||
? i18n.baseText('credentialEdit.credentialSharing.availableToYou.tooltip', {
|
||||
interpolate: { project: projectName },
|
||||
})
|
||||
: i18n.baseText('credentialEdit.credentialSharing.availableToOwner.tooltip', {
|
||||
interpolate: { name: credentialOwnerFirstName.value, project: projectName },
|
||||
});
|
||||
}
|
||||
|
||||
function shareUsedInProject(projectId: string) {
|
||||
const project = projectsStore.myProjects.find((p) => p.id === projectId);
|
||||
if (!project) return;
|
||||
|
|
@ -314,9 +326,11 @@ function goToUpgrade() {
|
|||
>
|
||||
<template #unshared-actions="{ project }">
|
||||
<div :class="$style.onlyYou">
|
||||
<N8nText :class="$style.accessText" color="text-light" :title="usedInAccessText">
|
||||
{{ usedInAccessText }}
|
||||
</N8nText>
|
||||
<N8nTooltip :content="usedInAccessTooltip(project)" placement="top">
|
||||
<N8nText :class="$style.accessText" color="text-light">
|
||||
{{ usedInAccessText }}
|
||||
</N8nText>
|
||||
</N8nTooltip>
|
||||
<N8nButton
|
||||
variant="outline"
|
||||
data-test-id="credential-used-in-project-share"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user