refactor(editor): Decouple REST calls from views (no-changelog) (#5202)

* decouple rest calls

* remove console.log
This commit is contained in:
Michael Auerswald
2023-01-20 12:08:40 +01:00
committed by GitHub
parent 7aa65315cc
commit b69f480d4c
6 changed files with 139 additions and 76 deletions

View File

@@ -0,0 +1,54 @@
import { IRestApiContext } from '@/Interface';
import { makeRestApiRequest } from '@/utils';
import { IDataObject, MessageEventBusDestinationOptions } from 'n8n-workflow';
export async function saveDestinationToDb(
context: IRestApiContext,
destination: MessageEventBusDestinationOptions,
subscribedEvents: string[] = [],
) {
if (destination.id) {
const data: IDataObject = {
...destination,
subscribedEvents,
};
return makeRestApiRequest(context, 'POST', '/eventbus/destination', data);
}
}
export async function deleteDestinationFromDb(context: IRestApiContext, destinationId: string) {
return makeRestApiRequest(context, 'DELETE', `/eventbus/destination?id=${destinationId}`);
}
export async function sendTestMessageToDestination(
context: IRestApiContext,
destination: MessageEventBusDestinationOptions,
) {
if (destination.id) {
const data: IDataObject = {
...destination,
};
return makeRestApiRequest(context, 'GET', '/eventbus/testmessage', data);
}
}
export async function getEventNamesFromBackend(context: IRestApiContext): Promise<string[]> {
return makeRestApiRequest(context, 'GET', '/eventbus/eventnames');
}
export async function getDestinationsFromBackend(
context: IRestApiContext,
): Promise<MessageEventBusDestinationOptions[]> {
return makeRestApiRequest(context, 'GET', '/eventbus/destination');
}
export async function getExecutionEvents(context: IRestApiContext, executionId: string) {
return makeRestApiRequest(context, 'GET', `/eventbus/execution/${executionId}`);
}
export async function recoverExecutionDataFromEvents(
context: IRestApiContext,
executionId: string,
) {
return makeRestApiRequest(context, 'GET', `/eventbus/execution-recover/${executionId}`);
}

View File

@@ -51,7 +51,6 @@ import mixins from 'vue-typed-mixins';
import { EnterpriseEditionFeature } from '@/constants';
import { showMessage } from '@/mixins/showMessage';
import { useLogStreamingStore } from '../../stores/logStreamingStore';
import { restApi } from '@/mixins/restApi';
import Vue from 'vue';
import { mapStores } from 'pinia';
import {
@@ -59,7 +58,6 @@ import {
defaultMessageEventBusDestinationOptions,
MessageEventBusDestinationOptions,
} from 'n8n-workflow';
import { saveDestinationToDb } from './Helpers.ee';
import { BaseTextKey } from '../../plugins/i18n';
export const DESTINATION_LIST_ITEM_ACTIONS = {
@@ -67,7 +65,7 @@ export const DESTINATION_LIST_ITEM_ACTIONS = {
DELETE: 'delete',
};
export default mixins(showMessage, restApi).extend({
export default mixins(showMessage).extend({
data() {
return {
EnterpriseEditionFeature,
@@ -142,7 +140,7 @@ export default mixins(showMessage, restApi).extend({
this.saveDestination();
},
async saveDestination() {
await saveDestinationToDb(this.restApi(), this.nodeParameters);
await this.logStreamingStore.saveDestination(this.nodeParameters);
},
async onAction(action: string) {
if (action === DESTINATION_LIST_ITEM_ACTIONS.OPEN) {

View File

@@ -178,7 +178,6 @@ import mixins from 'vue-typed-mixins';
import { useLogStreamingStore } from '../../stores/logStreamingStore';
import { useNDVStore } from '../../stores/ndv';
import { useWorkflowsStore } from '../../stores/workflows';
import { restApi } from '../../mixins/restApi';
import ParameterInputList from '@/components/ParameterInputList.vue';
import NodeCredentials from '@/components/NodeCredentials.vue';
import { IMenuItem, INodeUi, ITab, IUpdateInformation } from '../../Interface';
@@ -200,7 +199,7 @@ import Modal from '@/components/Modal.vue';
import { showMessage } from '@/mixins/showMessage';
import { useUIStore } from '../../stores/ui';
import { useUsersStore } from '../../stores/users';
import { destinationToFakeINodeUi, saveDestinationToDb, sendTestMessage } from './Helpers.ee';
import { destinationToFakeINodeUi } from './Helpers.ee';
import {
webhookModalDescription,
sentryModalDescription,
@@ -212,7 +211,7 @@ import SaveButton from '../SaveButton.vue';
import EventSelection from '@/components/SettingsLogStreaming/EventSelection.ee.vue';
import { Checkbox } from 'element-ui';
export default mixins(showMessage, restApi).extend({
export default mixins(showMessage).extend({
name: 'event-destination-settings-modal',
props: {
modalName: String,
@@ -427,12 +426,14 @@ export default mixins(showMessage, restApi).extend({
this.nodeParameters = deepCopy(nodeParameters);
this.workflowsStore.updateNodeProperties({
name: this.node.name,
properties: { parameters: this.nodeParameters as unknown as IDataObject },
properties: { parameters: this.nodeParameters as unknown as IDataObject, position: [0, 0] },
});
this.logStreamingStore.updateDestination(this.nodeParameters);
if (this.hasOnceBeenSaved) {
this.logStreamingStore.updateDestination(this.nodeParameters);
}
},
async sendTestEvent() {
this.testMessageResult = await sendTestMessage(this.restApi(), this.nodeParameters);
this.testMessageResult = await this.logStreamingStore.sendTestMessage(this.nodeParameters);
this.testMessageSent = true;
},
async removeThis() {
@@ -467,12 +468,14 @@ export default mixins(showMessage, restApi).extend({
if (this.unchanged || !this.destination.id) {
return;
}
await saveDestinationToDb(this.restApi(), this.nodeParameters);
this.hasOnceBeenSaved = true;
this.testMessageSent = false;
this.unchanged = true;
this.$props.eventBus.$emit('destinationWasSaved', this.destination.id);
this.uiStore.stateIsDirty = false;
const saveResult = await this.logStreamingStore.saveDestination(this.nodeParameters);
if (saveResult === true) {
this.hasOnceBeenSaved = true;
this.testMessageSent = false;
this.unchanged = true;
this.$props.eventBus.$emit('destinationWasSaved', this.destination.id);
this.uiStore.stateIsDirty = false;
}
},
},
});

View File

@@ -1,6 +1,5 @@
import { INodeCredentials, INodeParameters, MessageEventBusDestinationOptions } from 'n8n-workflow';
import { INodeUi, IRestApi } from '../../Interface';
import { useLogStreamingStore } from '../../stores/logStreamingStore';
import { INodeUi } from '../../Interface';
export function destinationToFakeINodeUi(
destination: MessageEventBusDestinationOptions,
@@ -20,39 +19,3 @@ export function destinationToFakeINodeUi(
},
} as INodeUi;
}
export async function saveDestinationToDb(
restApi: IRestApi,
destination: MessageEventBusDestinationOptions,
) {
const logStreamingStore = useLogStreamingStore();
if (destination.id) {
const data: MessageEventBusDestinationOptions = {
...destination,
subscribedEvents: logStreamingStore.getSelectedEvents(destination.id),
};
try {
await restApi.makeRestApiRequest('POST', '/eventbus/destination', data);
} catch (error) {
console.log(error);
}
logStreamingStore.updateDestination(destination);
}
}
export async function sendTestMessage(
restApi: IRestApi,
destination: MessageEventBusDestinationOptions,
) {
if (destination.id) {
try {
const sendResult = await restApi.makeRestApiRequest('GET', '/eventbus/testmessage', {
id: destination.id,
});
return sendResult;
} catch (error) {
console.log(error);
}
return false;
}
}

View File

@@ -1,5 +1,13 @@
import { deepCopy, MessageEventBusDestinationOptions } from 'n8n-workflow';
import { defineStore } from 'pinia';
import {
deleteDestinationFromDb,
getDestinationsFromBackend,
getEventNamesFromBackend,
saveDestinationToDb,
sendTestMessageToDestination,
} from '../api/eventbus.ee';
import { useRootStore } from './n8nRootStore';
export interface EventSelectionItem {
selected: boolean;
@@ -8,18 +16,19 @@ export interface EventSelectionItem {
label: string;
}
export interface EventSelectionGroup extends EventSelectionItem {
interface EventSelectionGroup extends EventSelectionItem {
children: EventSelectionItem[];
}
export interface TreeAndSelectionStoreItem {
interface DestinationStoreItem {
destination: MessageEventBusDestinationOptions;
selectedEvents: Set<string>;
eventGroups: EventSelectionGroup[];
isNew: boolean;
}
export interface DestinationSettingsStore {
[key: string]: TreeAndSelectionStoreItem;
[key: string]: DestinationStoreItem;
}
export const useLogStreamingStore = defineStore('logStreaming', {
@@ -51,13 +60,15 @@ export const useLogStreamingStore = defineStore('logStreaming', {
return destinations;
},
updateDestination(destination: MessageEventBusDestinationOptions) {
this.$patch((state) => {
if (destination.id && destination.id in this.items) {
state.items[destination.id].destination = destination;
}
// to trigger refresh
state.items = deepCopy(state.items);
});
if (destination.id && destination.id in this.items) {
this.$patch((state) => {
if (destination.id && destination.id in this.items) {
state.items[destination.id].destination = destination;
}
// to trigger refresh
state.items = deepCopy(state.items);
});
}
},
removeDestination(destinationId: string) {
if (!destinationId) return;
@@ -159,7 +170,8 @@ export const useLogStreamingStore = defineStore('logStreaming', {
destination,
selectedEvents: new Set<string>(),
eventGroups: [],
} as TreeAndSelectionStoreItem;
isNew: false,
} as DestinationStoreItem;
}
this.items[destination.id]?.selectedEvents?.clear();
if (destination.subscribedEvents) {
@@ -173,6 +185,44 @@ export const useLogStreamingStore = defineStore('logStreaming', {
);
}
},
async saveDestination(destination: MessageEventBusDestinationOptions): Promise<boolean> {
if (destination.id) {
const rootStore = useRootStore();
const selectedEvents = this.getSelectedEvents(destination.id);
try {
await saveDestinationToDb(rootStore.getRestApiContext, destination, selectedEvents);
this.updateDestination(destination);
return true;
} catch (e) {
return false;
}
}
return false;
},
async sendTestMessage(destination: MessageEventBusDestinationOptions) {
if (destination.id) {
const rootStore = useRootStore();
const testResult = await sendTestMessageToDestination(
rootStore.getRestApiContext,
destination,
);
return testResult;
}
return false;
},
async fetchEventNames(): Promise<string[]> {
const rootStore = useRootStore();
return getEventNamesFromBackend(rootStore.getRestApiContext);
},
async fetchDestinations(): Promise<MessageEventBusDestinationOptions[]> {
const rootStore = useRootStore();
return getDestinationsFromBackend(rootStore.getRestApiContext);
},
async deleteDestination(destinationId: string) {
const rootStore = useRootStore();
await deleteDestinationFromDb(rootStore.getRestApiContext, destinationId);
this.removeDestination(destinationId);
},
},
});

View File

@@ -90,7 +90,6 @@ import { useSettingsStore } from '../stores/settings';
import { useUIStore } from '../stores/ui';
import { LOG_STREAM_MODAL_KEY, EnterpriseEditionFeature } from '../constants';
import Vue from 'vue';
import { restApi } from '../mixins/restApi';
import {
deepCopy,
defaultMessageEventBusDestinationOptions,
@@ -99,7 +98,7 @@ import {
import PageViewLayout from '@/components/layouts/PageViewLayout.vue';
import EventDestinationCard from '@/components/SettingsLogStreaming/EventDestinationCard.ee.vue';
export default mixins(restApi).extend({
export default mixins().extend({
name: 'SettingsLogStreamingView',
props: {},
components: {
@@ -125,7 +124,7 @@ export default mixins(restApi).extend({
this.uiStore.nodeViewInitialized = false;
// fetch Destination data from the backend
await this.getDestinationDataFromREST();
await this.getDestinationDataFromBackend();
// since we are not really integrated into the hooks, we listen to the store and refresh the destinations
this.logStreamingStore.$onAction(({ name, after }) => {
@@ -174,18 +173,18 @@ export default mixins(restApi).extend({
},
},
methods: {
async getDestinationDataFromREST(): Promise<any> {
async getDestinationDataFromBackend(): Promise<void> {
this.logStreamingStore.clearEventNames();
this.logStreamingStore.clearDestinationItemTrees();
this.allDestinations = [];
const eventNamesData = await this.restApi().makeRestApiRequest('get', '/eventbus/eventnames');
const eventNamesData = await this.logStreamingStore.fetchEventNames();
if (eventNamesData) {
for (const eventName of eventNamesData) {
this.logStreamingStore.addEventName(eventName);
}
}
const destinationData: MessageEventBusDestinationOptions[] =
await this.restApi().makeRestApiRequest('get', '/eventbus/destination');
await this.logStreamingStore.fetchDestinations();
if (destinationData) {
for (const destination of destinationData) {
this.logStreamingStore.addDestination(destination);
@@ -218,11 +217,7 @@ export default mixins(restApi).extend({
},
async onRemove(destinationId?: string) {
if (!destinationId) return;
await this.restApi().makeRestApiRequest(
'DELETE',
`/eventbus/destination?id=${destinationId}`,
);
this.logStreamingStore.removeDestination(destinationId);
await this.logStreamingStore.deleteDestination(destinationId);
const foundNode = this.workflowsStore.getNodeByName(destinationId);
if (foundNode) {
this.workflowsStore.removeNode(foundNode);