Files
Automata/packages/editor-ui/src/modules/settings.ts
Milorad FIlipović 3ebfa45570 refactor: Add Onboarding call prompts (#3682)
*  Implemented initial onboarding call prompt logic

*  Added onboarding call prompt feature environment variable

*  Implemented onboarding session signup modal

* 📈 Added initial telemetry for the onboarding call prompt

* ✔️ Fixing linter error in server.ts

* 💄 Updating onboaring call prompt and modal wording and styling

*  Implemented initial version of fake doors feature

*  Added parameters to onboarding call prompt request

*  Finished implementing fake doors in settings

* 🔨 Updating onboarding call prompt fetching logic (fetching before timeout starts)

* 👌 Updating onboarding call prompt and fake door components based on the front-end review feedback

*  Updated fake doors so they support UI location specification. Added credentials UI fake doors.

*  Added checkbox to the signup form, improved N8NCheckbox formatting to better handle overflow

* 💄 Moving seignup checkbox label text to i18n file, updating checkbox component css to force text wrap

*  Update API calls to work with the new workflow request and response formats

* 👌 Updating fake door front-end based on the review feedback

* 👌 Updating onboarding call prompt and fake doors UI based in the product feedback

*   Updated onboarding call prompts front-end to work with new endpoints and added new telemetry events

* 🐛 Fixing onboarding call prompts not appearing in first user sessions

* ️ add createdAt to PublicUser

* 👌 Updating onboarding call prompts front-end to work with the latest back-end and addressing latest product review

*  Improving error handling when submitting user emails on signup

* 💄 Updating info text on Logging feature page

* 💄 Updating first onboarding call prompt timeout to 5 minutes

* 💄 Fixing `N8nCheckbox` component font overflow

Co-authored-by: Ben Hesseldieck <b.hesseldieck@gmail.com>
2022-07-27 16:28:13 +02:00

204 lines
7.7 KiB
TypeScript

import { ActionContext, Module } from 'vuex';
import {
ILogLevel,
IN8nPrompts,
IN8nUISettings,
IN8nValueSurveyData,
IRootState,
ISettingsState,
} from '../Interface';
import { getPromptsData, submitValueSurvey, submitContactInfo, getSettings } from '../api/settings';
import Vue from 'vue';
import { CONTACT_PROMPT_MODAL_KEY, VALUE_SURVEY_MODAL_KEY } from '@/constants';
import { ITelemetrySettings } from 'n8n-workflow';
import { testHealthEndpoint } from '@/api/templates';
import {createApiKey, deleteApiKey, getApiKey} from "@/api/api-keys";
const module: Module<ISettingsState, IRootState> = {
namespaced: true,
state: {
settings: {} as IN8nUISettings,
promptsData: {} as IN8nPrompts,
userManagement: {
enabled: false,
showSetupOnFirstLoad: false,
smtpSetup: false,
},
templatesEndpointHealthy: false,
api: {
enabled: false,
latestVersion: 0,
path: '/',
},
onboardingCallPromptEnabled: false,
},
getters: {
versionCli(state: ISettingsState) {
return state.settings.versionCli;
},
isUserManagementEnabled(state: ISettingsState): boolean {
return state.userManagement.enabled;
},
isPublicApiEnabled(state: ISettingsState): boolean {
return state.api.enabled;
},
publicApiLatestVersion(state: ISettingsState): number {
return state.api.latestVersion;
},
publicApiPath(state: ISettingsState): string {
return state.api.path;
},
showSetupPage(state: ISettingsState) {
return state.userManagement.showSetupOnFirstLoad;
},
getPromptsData(state: ISettingsState) {
return state.promptsData;
},
isSmtpSetup(state: ISettingsState) {
return state.userManagement.smtpSetup;
},
isPersonalizationSurveyEnabled(state: ISettingsState) {
return state.settings.telemetry.enabled && state.settings.personalizationSurveyEnabled;
},
telemetry: (state): ITelemetrySettings => {
return state.settings.telemetry;
},
logLevel: (state): ILogLevel => {
return state.settings.logLevel;
},
isTelemetryEnabled: (state) => {
return state.settings.telemetry && state.settings.telemetry.enabled;
},
areTagsEnabled: (state) => {
return state.settings.workflowTagsDisabled !== undefined ? !state.settings.workflowTagsDisabled : true;
},
isHiringBannerEnabled: (state): boolean => {
return state.settings.hiringBannerEnabled;
},
isTemplatesEnabled: (state): boolean => {
return Boolean(state.settings.templates && state.settings.templates.enabled);
},
isTemplatesEndpointReachable: (state): boolean => {
return state.templatesEndpointHealthy;
},
templatesHost: (state): string => {
return state.settings.templates.host;
},
isOnboardingCallPromptFeatureEnabled: (state): boolean => {
return state.onboardingCallPromptEnabled;
},
isCommunityNodesFeatureEnabled: (state): boolean => {
return state.settings.communityNodesEnabled;
},
isQueueModeEnabled: (state): boolean => {
return state.settings.executionMode === 'queue';
},
},
mutations: {
setSettings(state: ISettingsState, settings: IN8nUISettings) {
state.settings = settings;
state.userManagement.enabled = settings.userManagement.enabled;
state.userManagement.showSetupOnFirstLoad = !!settings.userManagement.showSetupOnFirstLoad;
state.userManagement.smtpSetup = settings.userManagement.smtpSetup;
state.api.enabled = settings.publicApi.enabled;
state.api.latestVersion = settings.publicApi.latestVersion;
state.api.path = settings.publicApi.path;
state.onboardingCallPromptEnabled = settings.onboardingCallPromptEnabled;
},
stopShowingSetupPage(state: ISettingsState) {
Vue.set(state.userManagement, 'showSetupOnFirstLoad', false);
},
setPromptsData(state: ISettingsState, promptsData: IN8nPrompts) {
Vue.set(state, 'promptsData', promptsData);
},
setTemplatesEndpointHealthy(state: ISettingsState) {
state.templatesEndpointHealthy = true;
},
setCommunityNodesFeatureEnabled(state: ISettingsState, isEnabled: boolean) {
state.settings.communityNodesEnabled = isEnabled;
},
},
actions: {
async getSettings(context: ActionContext<ISettingsState, IRootState>) {
const settings = await getSettings(context.rootGetters.getRestApiContext);
context.commit('setSettings', settings);
// todo refactor to this store
context.commit('setUrlBaseWebhook', settings.urlBaseWebhook, {root: true});
context.commit('setEndpointWebhook', settings.endpointWebhook, {root: true});
context.commit('setEndpointWebhookTest', settings.endpointWebhookTest, {root: true});
context.commit('setSaveDataErrorExecution', settings.saveDataErrorExecution, {root: true});
context.commit('setSaveDataSuccessExecution', settings.saveDataSuccessExecution, {root: true});
context.commit('setSaveManualExecutions', settings.saveManualExecutions, {root: true});
context.commit('setTimezone', settings.timezone, {root: true});
context.commit('setExecutionTimeout', settings.executionTimeout, {root: true});
context.commit('setMaxExecutionTimeout', settings.maxExecutionTimeout, {root: true});
context.commit('setVersionCli', settings.versionCli, {root: true});
context.commit('setInstanceId', settings.instanceId, {root: true});
context.commit('setOauthCallbackUrls', settings.oauthCallbackUrls, {root: true});
context.commit('setN8nMetadata', settings.n8nMetadata || {}, {root: true});
context.commit('setDefaultLocale', settings.defaultLocale, {root: true});
context.commit('versions/setVersionNotificationSettings', settings.versionNotifications, {root: true});
context.commit('setCommunityNodesFeatureEnabled', settings.communityNodesEnabled === true);
},
async fetchPromptsData(context: ActionContext<ISettingsState, IRootState>) {
if (!context.getters.isTelemetryEnabled) {
return;
}
try {
const instanceId = context.state.settings.instanceId;
const userId = context.rootGetters['users/currentUserId'];
const promptsData: IN8nPrompts = await getPromptsData(instanceId, userId);
if (promptsData && promptsData.showContactPrompt) {
context.commit('ui/openModal', CONTACT_PROMPT_MODAL_KEY, {root: true});
} else if (promptsData && promptsData.showValueSurvey) {
context.commit('ui/openModal', VALUE_SURVEY_MODAL_KEY, {root: true});
}
context.commit('setPromptsData', promptsData);
} catch (e) {
return e;
}
},
async submitContactInfo(context: ActionContext<ISettingsState, IRootState>, email: string) {
try {
const instanceId = context.state.settings.instanceId;
const userId = context.rootGetters['users/currentUserId'];
return await submitContactInfo(instanceId, userId, email);
} catch (e) {
return e;
}
},
async submitValueSurvey(context: ActionContext<ISettingsState, IRootState>, params: IN8nValueSurveyData) {
try {
const instanceId = context.state.settings.instanceId;
const userId = context.rootGetters['users/currentUserId'];
return await submitValueSurvey(instanceId, userId, params);
} catch (e) {
return e;
}
},
async testTemplatesEndpoint(context: ActionContext<ISettingsState, IRootState>) {
const timeout = new Promise((_, reject) => setTimeout(() => reject(), 2000));
await Promise.race([testHealthEndpoint(context.getters.templatesHost), timeout]);
context.commit('setTemplatesEndpointHealthy', true);
},
async getApiKey(context: ActionContext<ISettingsState, IRootState>) {
const { apiKey } = await getApiKey(context.rootGetters['getRestApiContext']);
return apiKey;
},
async createApiKey(context: ActionContext<ISettingsState, IRootState>) {
const { apiKey } = await createApiKey(context.rootGetters['getRestApiContext']);
return apiKey;
},
async deleteApiKey(context: ActionContext<ISettingsState, IRootState>) {
await deleteApiKey(context.rootGetters['getRestApiContext']);
},
},
};
export default module;