mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-25 04:34:06 -08:00
feat(editor): Finalize workers view (#8052)
https://linear.app/n8n/issue/PAY-1065
This commit is contained in:
parent
d917dfe9f8
commit
edfa78414d
|
@ -1,4 +1,4 @@
|
|||
import { INSTANCE_MEMBERS } from '../constants';
|
||||
import { INSTANCE_MEMBERS, INSTANCE_OWNER } from '../constants';
|
||||
import { WorkerViewPage } from '../pages';
|
||||
|
||||
const workerViewPage = new WorkerViewPage();
|
||||
|
@ -29,7 +29,7 @@ describe('Worker View (licensed)', () => {
|
|||
});
|
||||
|
||||
it('should show up in the menu sidebar', () => {
|
||||
cy.signin(INSTANCE_MEMBERS[0]);
|
||||
cy.signin(INSTANCE_OWNER);
|
||||
cy.enableQueueMode();
|
||||
cy.visit(workerViewPage.url);
|
||||
workerViewPage.getters.menuItem().should('exist');
|
||||
|
|
|
@ -16,6 +16,7 @@ export type Resource =
|
|||
| 'tag'
|
||||
| 'user'
|
||||
| 'variable'
|
||||
| 'workersView'
|
||||
| 'workflow';
|
||||
|
||||
export type ResourceScope<
|
||||
|
@ -50,6 +51,7 @@ export type SourceControlScope = ResourceScope<'sourceControl', 'pull' | 'push'
|
|||
export type TagScope = ResourceScope<'tag'>;
|
||||
export type UserScope = ResourceScope<'user', DefaultOperations | 'resetPassword' | 'changeRole'>;
|
||||
export type VariableScope = ResourceScope<'variable'>;
|
||||
export type WorkersViewScope = ResourceScope<'workersView', 'manage'>;
|
||||
export type WorkflowScope = ResourceScope<'workflow', DefaultOperations | 'share' | 'execute'>;
|
||||
|
||||
export type Scope =
|
||||
|
@ -69,6 +71,7 @@ export type Scope =
|
|||
| TagScope
|
||||
| UserScope
|
||||
| VariableScope
|
||||
| WorkersViewScope
|
||||
| WorkflowScope;
|
||||
|
||||
export type ScopeLevel = 'global' | 'project' | 'resource';
|
||||
|
|
|
@ -66,6 +66,7 @@ export const ownerPermissions: Scope[] = [
|
|||
'workflow:list',
|
||||
'workflow:share',
|
||||
'workflow:execute',
|
||||
'workersView:manage',
|
||||
];
|
||||
export const adminPermissions: Scope[] = ownerPermissions.concat();
|
||||
export const memberPermissions: Scope[] = [
|
||||
|
|
|
@ -31,6 +31,7 @@ import type { BaseTextKey } from '@/plugins/i18n';
|
|||
import { useUIStore } from '@/stores/ui.store';
|
||||
import { useSettingsStore } from '@/stores/settings.store';
|
||||
import { useRootStore } from '@/stores/n8nRoot.store';
|
||||
import { hasPermission } from '@/rbac/permissions';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SettingsSidebar',
|
||||
|
@ -123,7 +124,8 @@ export default defineComponent({
|
|||
label: this.$locale.baseText('mainSidebar.workersView'),
|
||||
position: 'top',
|
||||
available:
|
||||
this.settingsStore.isQueueModeEnabled && this.settingsStore.isWorkerViewAvailable,
|
||||
this.settingsStore.isQueueModeEnabled &&
|
||||
hasPermission(['rbac'], { rbac: { scope: 'workersView:manage' } }),
|
||||
activateOnRouteNames: [VIEWS.WORKER_VIEW],
|
||||
},
|
||||
];
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
<div :class="$style.workerListHeader">
|
||||
<n8n-heading tag="h1" size="2xlarge">{{ pageTitle }}</n8n-heading>
|
||||
</div>
|
||||
<div v-if="isMounting">
|
||||
<n8n-loading :class="$style.tableLoader" variant="custom" />
|
||||
<div v-if="!initialStatusReceived">
|
||||
<n8n-spinner />
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="workerIds.length === 0">{{ $locale.baseText('workerList.empty') }}</div>
|
||||
|
@ -55,14 +55,8 @@ export default defineComponent({
|
|||
...pushConnection.setup?.(props, ctx),
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isMounting: true,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
setPageTitle(`n8n - ${this.pageTitle}`);
|
||||
this.isMounting = false;
|
||||
|
||||
this.$telemetry.track('User viewed worker view', {
|
||||
instance_id: this.rootStore.instanceId,
|
||||
|
@ -91,6 +85,9 @@ export default defineComponent({
|
|||
}
|
||||
return returnData;
|
||||
},
|
||||
initialStatusReceived(): boolean {
|
||||
return this.orchestrationManagerStore.initialStatusReceived;
|
||||
},
|
||||
workerIds(): string[] {
|
||||
return Object.keys(this.orchestrationManagerStore.workers);
|
||||
},
|
||||
|
|
|
@ -628,7 +628,7 @@
|
|||
"workerList.actionBox.description": "View the current state of workers connected to your instance.",
|
||||
"workerList.actionBox.description.link": "More info",
|
||||
"workerList.actionBox.buttonText": "See plans",
|
||||
"workerList.docs.url": "https://docs.n8n.io",
|
||||
"workerList.docs.url": "https://docs.n8n.io/hosting/scaling/queue-mode/#view-running-workers",
|
||||
"executionSidebar.executionName": "Execution {id}",
|
||||
"executionSidebar.searchPlaceholder": "Search executions...",
|
||||
"executionView.onPaste.title": "Cannot paste here",
|
||||
|
|
|
@ -7,6 +7,7 @@ export const WORKER_HISTORY_LENGTH = 100;
|
|||
const STALE_SECONDS = 120 * 1000;
|
||||
|
||||
export interface IOrchestrationStoreState {
|
||||
initialStatusReceived: boolean;
|
||||
workers: { [id: string]: IPushDataWorkerStatusPayload };
|
||||
workersHistory: {
|
||||
[id: string]: IWorkerHistoryItem[];
|
||||
|
@ -22,6 +23,7 @@ export interface IWorkerHistoryItem {
|
|||
|
||||
export const useOrchestrationStore = defineStore('orchestrationManager', {
|
||||
state: (): IOrchestrationStoreState => ({
|
||||
initialStatusReceived: false,
|
||||
workers: {},
|
||||
workersHistory: {},
|
||||
workersLastUpdated: {},
|
||||
|
@ -38,6 +40,8 @@ export const useOrchestrationStore = defineStore('orchestrationManager', {
|
|||
this.workersHistory[data.workerId].shift();
|
||||
}
|
||||
this.workersLastUpdated[data.workerId] = Date.now();
|
||||
|
||||
this.initialStatusReceived = true;
|
||||
},
|
||||
removeStaleWorkers() {
|
||||
for (const id in this.workersLastUpdated) {
|
||||
|
|
Loading…
Reference in a new issue