Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(editor): Project related frontend fixes (no-changelog) #9482

Merged
29 changes: 28 additions & 1 deletion cypress/e2e/39-projects.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('Projects', () => {
cy.changeQuota('maxTeamProjects', -1);
});

it('should handle workflows and credentials', () => {
it('should handle workflows and credentials and menu items', () => {
cy.signin(INSTANCE_ADMIN);
cy.visit(workflowsPage.url);
workflowsPage.getters.workflowCards().should('not.have.length');
Expand Down Expand Up @@ -147,5 +147,32 @@ describe('Projects', () => {
cy.wait('@credentialsList').then((interception) => {
expect(interception.request.url).not.to.contain('filter');
});

let menuItems = cy.getByTestId('menu-item');

menuItems.filter('[class*=active_]').should('have.length', 1);
menuItems.filter(':contains("Home")[class*=active_]').should('exist');

projects.getMenuItems().first().click();

menuItems = cy.getByTestId('menu-item');

menuItems.filter('[class*=active_]').should('have.length', 1);
menuItems.filter(':contains("Development")[class*=active_]').should('exist');

workflowsPage.getters.workflowCards().first().click();

menuItems = cy.getByTestId('menu-item');

menuItems.filter('[class*=active_]').should('have.length', 1);
menuItems.filter(':contains("Development")[class*=active_]').should('exist');

cy.getByTestId('menu-item').filter(':contains("Variables")').click();
cy.getByTestId('unavailable-resources-list').should('be.visible');

menuItems = cy.getByTestId('menu-item');

menuItems.filter('[class*=active_]').should('have.length', 1);
menuItems.filter(':contains("Variables")[class*=active_]').should('exist');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
class="pt-2xs"
:projects="projectsStore.projects"
:placeholder="$locale.baseText('forms.resourceFiltersDropdown.owner.placeholder')"
:empty-options-text="$locale.baseText('projects.sharing.noMatchingProjects')"
@update:model-value="setKeyValue('homeProject', ($event as ProjectSharingData).id)"
/>
</enterprise-edition>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,12 @@ const onDelete = () => {
<n8n-text color="text-dark">{{
locale.baseText('projects.settings.delete.question.transfer.title')
}}</n8n-text>
<ProjectSharing v-model="selectedProject" class="pt-2xs" :projects="props.projects" />
<ProjectSharing
v-model="selectedProject"
class="pt-2xs"
:projects="props.projects"
:empty-options-text="locale.baseText('projects.sharing.noMatchingProjects')"
/>
</div>

<el-radio
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ const activeTab = computed(() => {
return routes.includes(route.name as VIEWS) ? 'home' : undefined;
});

const isActiveProject = (projectId: string) =>
route?.params?.projectId === projectId || projectsStore.currentProjectId === projectId
? projectId
: undefined;
const getProjectMenuItem = (project: ProjectListItem) => ({
id: project.id,
label: project.name,
Expand Down Expand Up @@ -146,7 +142,7 @@ onMounted(async () => {
:item="getProjectMenuItem(project)"
:compact="props.collapsed"
:handle-select="projectClicked"
:active-tab="isActiveProject(project.id)"
:active-tab="projectsStore.projectNavActiveId"
mode="tabs"
data-test-id="project-menu-item"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type Props = {
readonly?: boolean;
static?: boolean;
placeholder?: string;
emptyOptionsText?: string;
};

const props = defineProps<Props>();
Expand All @@ -34,6 +35,9 @@ const selectPlaceholder = computed(
? locale.baseText('projects.sharing.placeholder')
: locale.baseText('projects.sharing.placeholder.single')),
);
const noDataText = computed(
() => props.emptyOptionsText ?? locale.baseText('projects.sharing.noMatchingUsers'),
);
const filteredProjects = computed(() =>
props.projects
.filter(
Expand Down Expand Up @@ -101,7 +105,7 @@ watch(
:filter-method="setFilter"
:placeholder="selectPlaceholder"
:default-first-option="true"
:no-data-text="locale.baseText('projects.sharing.noMatchingProjects')"
:no-data-text="noDataText"
size="large"
:disabled="props.readonly"
@update:model-value="onProjectSelected"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const processedName = computed(() => splitName(props.project.name ?? ''));
<div :class="$style.projectInfo" data-test-id="project-sharing-info">
<div>
<N8nAvatar :first-name="processedName.firstName" :last-name="processedName.lastName" />
<div class="flex flex-col">
<div :class="$style.text">
<p v-if="processedName.firstName || processedName.lastName">
{{ processedName.firstName }} {{ processedName.lastName }}
</p>
Expand Down Expand Up @@ -54,4 +54,9 @@ const processedName = computed(() => splitName(props.project.name ?? ''));
line-height: var(--font-line-height-loose);
}
}

.text {
display: flex;
flex-direction: column;
}
</style>
15 changes: 13 additions & 2 deletions packages/editor-ui/src/features/projects/projects.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@ export const useProjectsStore = defineStore('projects', () => {
team: 0,
public: 0,
});
const projectNavActiveIdState = ref<string | string[] | null>(null);

const currentProjectId = computed(
() =>
(route.params?.projectId as string | undefined) ||
(route.query?.projectId as string | undefined) ||
(route.params?.projectId as string | undefined) ??
(route.query?.projectId as string | undefined) ??
currentProject.value?.id,
);
const isProjectHome = computed(() => route.path.includes('home'));
Expand All @@ -56,6 +57,13 @@ export const useProjectsStore = defineStore('projects', () => {
hasPermission(['rbac'], { rbac: { scope: 'project:create' } }),
);

const projectNavActiveId = computed<string | string[] | null>({
get: () => route?.params?.projectId ?? projectNavActiveIdState.value,
set: (value: string | string[] | null) => {
projectNavActiveIdState.value = value;
},
});

const setCurrentProject = (project: Project | null) => {
currentProject.value = project;
};
Expand Down Expand Up @@ -113,6 +121,8 @@ export const useProjectsStore = defineStore('projects', () => {
watch(
route,
async (newRoute) => {
projectNavActiveId.value = null;

if (newRoute?.path?.includes('home')) {
setCurrentProject(null);
}
Expand Down Expand Up @@ -140,6 +150,7 @@ export const useProjectsStore = defineStore('projects', () => {
canCreateProjects,
hasPermissionToCreateProjects,
teamProjectsAvailable,
projectNavActiveId,
setCurrentProject,
getAllProjects,
getMyProjects,
Expand Down
3 changes: 2 additions & 1 deletion packages/editor-ui/src/plugins/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@
"credentials.noResults.withSearch.switchToShared.preamble": "some credentials may be",
"credentials.noResults.withSearch.switchToShared.link": "hidden",
"credentials.create.personal.toast.title": "Credential successfully created",
"credentials.create.personal.toast.text": "This credential is currently private to you. View sharing options.",
"credentials.create.personal.toast.text": "This credential is currently private to you.",
"credentials.create.project.toast.title": "Credential successfully created in {projectName}",
"credentials.create.project.toast.text": "All members from {projectName} will have access to this credential.",
"credentials.shareModal.info.members": "This credential is owned by the {projectName} project which currently has {members} with access to this credential.",
Expand Down Expand Up @@ -2433,6 +2433,7 @@
"projects.settings.role.upgrade.title": "Upgrade to unlock additional roles",
"projects.settings.role.upgrade.message": "You're currently limited to {limit} on the {planName} plan and can only assign the admin role to users within this project. To create more projects and unlock additional roles, upgrade your plan.",
"projects.sharing.noMatchingProjects": "There are no available projects",
"projects.sharing.noMatchingUsers": "No matching users",
"projects.sharing.placeholder": "Add projects...",
"projects.sharing.placeholder.single": "Select project",
"projects.error.title": "Project error",
Expand Down
4 changes: 4 additions & 0 deletions packages/editor-ui/src/views/NodeView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3726,6 +3726,10 @@ export default defineComponent({
await this.openWorkflow(workflow);
await this.checkAndInitDebugMode();

if (this.projectsStore.currentProjectId) {
this.projectsStore.projectNavActiveId = this.projectsStore.currentProjectId;
}

if (workflow.meta?.onboardingId) {
this.$telemetry.track(
`User opened workflow from onboarding template with ID ${workflow.meta.onboardingId}`,
Expand Down
Loading