mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
fix(editor): Fix Admin panel icon in the sidebar for cloud deployments (no-changelog) (#7738)
Co-authored-by: ricardo <ricardoespinoza105@gmail.com> Co-authored-by: Mutasem Aldmour <mutasem@n8n.io>
This commit is contained in:
parent
b66b8c18e9
commit
2d039010db
|
@ -64,4 +64,20 @@ describe('BannerStack', { disableAutoLogin: true }, () => {
|
||||||
|
|
||||||
mainSidebar.actions.signout();
|
mainSidebar.actions.signout();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Should show admin button', () => {
|
||||||
|
cy.intercept('GET', '/rest/settings', (req) => {
|
||||||
|
req.on('response', (res) => {
|
||||||
|
res.send({
|
||||||
|
data: { ...res.body.data, deployment: { type: 'cloud' }, n8nMetadata: { userId: 1 } },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}).as('loadSettings');
|
||||||
|
|
||||||
|
cy.signin({ email: INSTANCE_OWNER.email, password: INSTANCE_OWNER.password });
|
||||||
|
|
||||||
|
cy.visit(workflowPage.url);
|
||||||
|
|
||||||
|
mainSidebar.getters.adminPanel().should('be.visible');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,6 +12,7 @@ export class MainSidebar extends BasePage {
|
||||||
workflows: () => this.getters.menuItem('Workflows'),
|
workflows: () => this.getters.menuItem('Workflows'),
|
||||||
credentials: () => this.getters.menuItem('Credentials'),
|
credentials: () => this.getters.menuItem('Credentials'),
|
||||||
executions: () => this.getters.menuItem('Executions'),
|
executions: () => this.getters.menuItem('Executions'),
|
||||||
|
adminPanel: () => this.getters.menuItem('Admin Panel'),
|
||||||
userMenu: () => cy.get('div[class="action-dropdown-container"]'),
|
userMenu: () => cy.get('div[class="action-dropdown-container"]'),
|
||||||
logo: () => cy.getByTestId('n8n-logo'),
|
logo: () => cy.getByTestId('n8n-logo'),
|
||||||
};
|
};
|
||||||
|
|
|
@ -60,8 +60,6 @@ import {
|
||||||
} from '@/stores';
|
} from '@/stores';
|
||||||
import { useHistoryHelper } from '@/composables/useHistoryHelper';
|
import { useHistoryHelper } from '@/composables/useHistoryHelper';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import type { ExternalHooks } from '@/types';
|
|
||||||
import type { PartialDeep } from 'type-fest';
|
|
||||||
import { runExternalHook } from '@/utils';
|
import { runExternalHook } from '@/utils';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
@ -136,19 +134,10 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async initializeHooks(): Promise<void> {
|
async initializeHooks(): Promise<void> {
|
||||||
const hooksImports = [];
|
|
||||||
|
|
||||||
if (this.settingsStore.isCloudDeployment) {
|
if (this.settingsStore.isCloudDeployment) {
|
||||||
hooksImports.push(
|
const { n8nCloudHooks } = await import('@/hooks/cloud');
|
||||||
import('./hooks/cloud').then(
|
extendExternalHooks(n8nCloudHooks);
|
||||||
({ n8nCloudHooks }: { n8nCloudHooks: PartialDeep<ExternalHooks> }) => {
|
|
||||||
extendExternalHooks(n8nCloudHooks);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.allSettled(hooksImports);
|
|
||||||
},
|
},
|
||||||
async onAfterAuthenticate() {
|
async onAfterAuthenticate() {
|
||||||
if (this.onAfterAuthenticateInitialized) {
|
if (this.onAfterAuthenticateInitialized) {
|
||||||
|
@ -160,7 +149,6 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.initializeCloudData(),
|
|
||||||
this.initializeSourceControl(),
|
this.initializeSourceControl(),
|
||||||
this.initializeTemplates(),
|
this.initializeTemplates(),
|
||||||
this.initializeNodeTranslationHeaders(),
|
this.initializeNodeTranslationHeaders(),
|
||||||
|
@ -172,7 +160,9 @@ export default defineComponent({
|
||||||
async mounted() {
|
async mounted() {
|
||||||
this.logHiringBanner();
|
this.logHiringBanner();
|
||||||
|
|
||||||
|
await this.settingsStore.initialize();
|
||||||
await this.initializeHooks();
|
await this.initializeHooks();
|
||||||
|
await this.initializeCloudData();
|
||||||
|
|
||||||
void this.checkForNewVersions();
|
void this.checkForNewVersions();
|
||||||
void this.onAfterAuthenticate();
|
void this.onAfterAuthenticate();
|
||||||
|
|
|
@ -270,6 +270,14 @@ export default defineComponent({
|
||||||
this.settingsStore.isQueueModeEnabled && this.settingsStore.isWorkerViewAvailable,
|
this.settingsStore.isQueueModeEnabled && this.settingsStore.isWorkerViewAvailable,
|
||||||
activateOnRouteNames: [VIEWS.WORKER_VIEW],
|
activateOnRouteNames: [VIEWS.WORKER_VIEW],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'cloud-admin',
|
||||||
|
type: 'link',
|
||||||
|
position: 'bottom',
|
||||||
|
label: 'Admin Panel',
|
||||||
|
icon: 'home',
|
||||||
|
available: this.settingsStore.isCloudDeployment && this.usersStore.isInstanceOwner,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'settings',
|
id: 'settings',
|
||||||
icon: 'cog',
|
icon: 'cog',
|
||||||
|
@ -461,6 +469,10 @@ export default defineComponent({
|
||||||
this.uiStore.openModal(ABOUT_MODAL_KEY);
|
this.uiStore.openModal(ABOUT_MODAL_KEY);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'cloud-admin': {
|
||||||
|
this.cloudPlanStore.redirectToDashboard();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'quickstart':
|
case 'quickstart':
|
||||||
case 'docs':
|
case 'docs':
|
||||||
case 'forum':
|
case 'forum':
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { hooksAddAdminIcon, hooksAddFakeDoorFeatures } from '@/hooks/utils';
|
import { hooksAddFakeDoorFeatures } from '@/hooks/utils';
|
||||||
import {
|
import {
|
||||||
getAuthenticationModalEventData,
|
getAuthenticationModalEventData,
|
||||||
getExpressionEditorEventsData,
|
getExpressionEditorEventsData,
|
||||||
|
@ -29,9 +29,6 @@ import type { ExternalHooks } from '@/types';
|
||||||
export const n8nCloudHooks: PartialDeep<ExternalHooks> = {
|
export const n8nCloudHooks: PartialDeep<ExternalHooks> = {
|
||||||
app: {
|
app: {
|
||||||
mount: [
|
mount: [
|
||||||
() => {
|
|
||||||
hooksAddAdminIcon();
|
|
||||||
},
|
|
||||||
() => {
|
() => {
|
||||||
hooksAddFakeDoorFeatures();
|
hooksAddFakeDoorFeatures();
|
||||||
},
|
},
|
||||||
|
@ -43,9 +40,6 @@ export const n8nCloudHooks: PartialDeep<ExternalHooks> = {
|
||||||
const segmentStore = useSegment();
|
const segmentStore = useSegment();
|
||||||
segmentStore.identify();
|
segmentStore.identify();
|
||||||
},
|
},
|
||||||
() => {
|
|
||||||
hooksAddAdminIcon();
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
createNodeActiveChanged: [
|
createNodeActiveChanged: [
|
||||||
(_, meta) => {
|
(_, meta) => {
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
import { useUIStore } from '@/stores/ui.store';
|
|
||||||
import type { IMenuItem } from 'n8n-design-system/types';
|
|
||||||
import { useUsersStore } from '@/stores/users.store';
|
|
||||||
import { addAutoLoginToAdminPanelButton } from '@/hooks/utils/hooksAddAutoLoginToAdminPanelButton';
|
|
||||||
|
|
||||||
let adminIconAdded = false;
|
|
||||||
|
|
||||||
export const hooksAddAdminIcon = () => {
|
|
||||||
if (adminIconAdded) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uiStore = useUIStore();
|
|
||||||
const usersStore = useUsersStore();
|
|
||||||
|
|
||||||
if (usersStore?.globalRoleName !== 'owner') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const menuItems: IMenuItem[] = [
|
|
||||||
{
|
|
||||||
id: 'admin',
|
|
||||||
type: 'link',
|
|
||||||
position: 'bottom',
|
|
||||||
label: 'Admin Panel',
|
|
||||||
icon: 'home',
|
|
||||||
properties: {
|
|
||||||
href: 'https://app.n8n.cloud',
|
|
||||||
newWindow: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
addAutoLoginToAdminPanelButton();
|
|
||||||
|
|
||||||
uiStore.sidebarMenuItems = [...uiStore.sidebarMenuItems, ...menuItems] as IMenuItem[];
|
|
||||||
adminIconAdded = true;
|
|
||||||
};
|
|
|
@ -1,15 +0,0 @@
|
||||||
export function addAutoLoginToAdminPanelButton() {
|
|
||||||
const adminPanelHost = new URL(window.location.href).host.split('.').slice(1).join('.');
|
|
||||||
|
|
||||||
document.body?.addEventListener('click', async (e) => {
|
|
||||||
if (!e.target || !(e.target instanceof Element)) return;
|
|
||||||
if (e.target.getAttribute('id') !== 'admin' && !e.target.closest('#admin')) return;
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
const restPath = window.REST_ENDPOINT ?? 'rest';
|
|
||||||
const response = await fetch(`/${restPath}/cloud/proxy/login/code`);
|
|
||||||
const { code } = await response.json();
|
|
||||||
window.location.href = `https://${adminPanelHost}/login?code=${code}`;
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,4 +1,2 @@
|
||||||
export * from './hooksAddAdminIcon';
|
|
||||||
export * from './hooksAddAutoLoginToAdminPanelButton';
|
|
||||||
export * from './hooksAddFakeDoorFeatures';
|
export * from './hooksAddFakeDoorFeatures';
|
||||||
export * from './hooksNodesPanel';
|
export * from './hooksNodesPanel';
|
||||||
|
|
|
@ -897,7 +897,6 @@ router.beforeEach(async (to, from, next) => {
|
||||||
|
|
||||||
const settingsStore = useSettingsStore();
|
const settingsStore = useSettingsStore();
|
||||||
const usersStore = useUsersStore();
|
const usersStore = useUsersStore();
|
||||||
await settingsStore.initialize();
|
|
||||||
await usersStore.initialize();
|
await usersStore.initialize();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -151,6 +151,12 @@ export const useCloudPlanStore = defineStore(STORES.CLOUD_PLAN, () => {
|
||||||
} catch {}
|
} catch {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const redirectToDashboard = async () => {
|
||||||
|
const adminPanelHost = new URL(window.location.href).host.split('.').slice(1).join('.');
|
||||||
|
const { code } = await getAutoLoginCode();
|
||||||
|
window.location.href = `https://${adminPanelHost}/login?code=${code}`;
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
state,
|
state,
|
||||||
getOwnerCurrentPlan,
|
getOwnerCurrentPlan,
|
||||||
|
@ -166,5 +172,6 @@ export const useCloudPlanStore = defineStore(STORES.CLOUD_PLAN, () => {
|
||||||
checkForCloudPlanData,
|
checkForCloudPlanData,
|
||||||
fetchUserCloudAccount,
|
fetchUserCloudAccount,
|
||||||
getAutoLoginCode,
|
getAutoLoginCode,
|
||||||
|
redirectToDashboard,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue