2022-11-04 06:04:31 -07:00
|
|
|
import { createApiKey, deleteApiKey, getApiKey } from '@/api/api-keys';
|
2023-01-24 17:18:39 -08:00
|
|
|
import {
|
|
|
|
getLdapConfig,
|
|
|
|
getLdapSynchronizations,
|
|
|
|
runLdapSync,
|
|
|
|
testLdapConnection,
|
|
|
|
updateLdapConfig,
|
|
|
|
} from '@/api/ldap';
|
2022-11-04 06:04:31 -07:00
|
|
|
import { getPromptsData, getSettings, submitContactInfo, submitValueSurvey } from '@/api/settings';
|
|
|
|
import { testHealthEndpoint } from '@/api/templates';
|
2023-04-24 03:18:24 -07:00
|
|
|
import type { EnterpriseEditionFeature } from '@/constants';
|
|
|
|
import { CONTACT_PROMPT_MODAL_KEY, STORES, VALUE_SURVEY_MODAL_KEY } from '@/constants';
|
|
|
|
import type {
|
2023-03-17 13:07:08 -07:00
|
|
|
ILdapConfig,
|
2022-11-04 06:04:31 -07:00
|
|
|
IN8nPromptResponse,
|
|
|
|
IN8nPrompts,
|
|
|
|
IN8nValueSurveyData,
|
|
|
|
ISettingsState,
|
|
|
|
} from '@/Interface';
|
2023-04-24 03:18:24 -07:00
|
|
|
import { UserManagementAuthenticationMethod } from '@/Interface';
|
|
|
|
import type {
|
2023-04-21 04:30:57 -07:00
|
|
|
IDataObject,
|
2023-10-25 07:35:22 -07:00
|
|
|
LogLevel,
|
2023-04-21 04:30:57 -07:00
|
|
|
IN8nUISettings,
|
|
|
|
ITelemetrySettings,
|
|
|
|
WorkflowSettings,
|
|
|
|
} from 'n8n-workflow';
|
2023-11-28 03:15:08 -08:00
|
|
|
import { ExpressionEvaluatorProxy } from 'n8n-workflow';
|
2022-11-04 06:04:31 -07:00
|
|
|
import { defineStore } from 'pinia';
|
2023-05-05 01:41:54 -07:00
|
|
|
import { useRootStore } from './n8nRoot.store';
|
|
|
|
import { useUIStore } from './ui.store';
|
|
|
|
import { useUsersStore } from './users.store';
|
|
|
|
import { useVersionsStore } from './versions.store';
|
2023-11-28 03:15:08 -08:00
|
|
|
import { makeRestApiRequest } from '@/utils/apiUtils';
|
|
|
|
import { useTitleChange } from '@/composables/useTitleChange';
|
|
|
|
import { useToast } from '@/composables/useToast';
|
2023-11-03 07:22:37 -07:00
|
|
|
import { i18n } from '@/plugins/i18n';
|
2022-11-04 06:04:31 -07:00
|
|
|
|
|
|
|
export const useSettingsStore = defineStore(STORES.SETTINGS, {
|
|
|
|
state: (): ISettingsState => ({
|
2023-11-03 07:22:37 -07:00
|
|
|
initialized: false,
|
2022-11-04 06:04:31 -07:00
|
|
|
settings: {} as IN8nUISettings,
|
|
|
|
promptsData: {} as IN8nPrompts,
|
|
|
|
userManagement: {
|
2023-07-12 05:11:46 -07:00
|
|
|
quota: -1,
|
2022-11-04 06:04:31 -07:00
|
|
|
showSetupOnFirstLoad: false,
|
|
|
|
smtpSetup: false,
|
2023-03-17 13:07:08 -07:00
|
|
|
authenticationMethod: UserManagementAuthenticationMethod.Email,
|
2022-11-04 06:04:31 -07:00
|
|
|
},
|
|
|
|
templatesEndpointHealthy: false,
|
|
|
|
api: {
|
|
|
|
enabled: false,
|
|
|
|
latestVersion: 0,
|
|
|
|
path: '/',
|
2023-01-02 03:14:58 -08:00
|
|
|
swaggerUi: {
|
|
|
|
enabled: false,
|
|
|
|
},
|
2022-11-04 06:04:31 -07:00
|
|
|
},
|
2023-01-24 17:18:39 -08:00
|
|
|
ldap: {
|
|
|
|
loginLabel: '',
|
|
|
|
loginEnabled: false,
|
|
|
|
},
|
2023-03-02 00:00:51 -08:00
|
|
|
saml: {
|
|
|
|
loginLabel: '',
|
|
|
|
loginEnabled: false,
|
|
|
|
},
|
2023-08-23 19:59:16 -07:00
|
|
|
mfa: {
|
|
|
|
enabled: false,
|
|
|
|
},
|
2022-11-04 06:04:31 -07:00
|
|
|
onboardingCallPromptEnabled: false,
|
|
|
|
saveDataErrorExecution: 'all',
|
|
|
|
saveDataSuccessExecution: 'all',
|
|
|
|
saveManualExecutions: false,
|
|
|
|
}),
|
|
|
|
getters: {
|
|
|
|
isEnterpriseFeatureEnabled() {
|
2023-11-03 07:22:37 -07:00
|
|
|
return (feature: EnterpriseEditionFeature): boolean => this.settings.enterprise?.[feature];
|
2022-11-04 06:04:31 -07:00
|
|
|
},
|
|
|
|
versionCli(): string {
|
|
|
|
return this.settings.versionCli;
|
|
|
|
},
|
|
|
|
isPublicApiEnabled(): boolean {
|
|
|
|
return this.api.enabled;
|
|
|
|
},
|
2023-01-02 03:14:58 -08:00
|
|
|
isSwaggerUIEnabled(): boolean {
|
|
|
|
return this.api.swaggerUi.enabled;
|
|
|
|
},
|
2022-11-04 06:04:31 -07:00
|
|
|
publicApiLatestVersion(): number {
|
|
|
|
return this.api.latestVersion;
|
|
|
|
},
|
|
|
|
publicApiPath(): string {
|
|
|
|
return this.api.path;
|
|
|
|
},
|
2023-01-24 17:18:39 -08:00
|
|
|
isLdapLoginEnabled(): boolean {
|
|
|
|
return this.ldap.loginEnabled;
|
|
|
|
},
|
|
|
|
ldapLoginLabel(): string {
|
|
|
|
return this.ldap.loginLabel;
|
|
|
|
},
|
2023-03-02 00:00:51 -08:00
|
|
|
isSamlLoginEnabled(): boolean {
|
|
|
|
return this.saml.loginEnabled;
|
|
|
|
},
|
|
|
|
samlLoginLabel(): string {
|
|
|
|
return this.saml.loginLabel;
|
|
|
|
},
|
2022-11-04 06:04:31 -07:00
|
|
|
showSetupPage(): boolean {
|
|
|
|
return this.userManagement.showSetupOnFirstLoad === true;
|
|
|
|
},
|
2022-12-21 07:42:07 -08:00
|
|
|
deploymentType(): string {
|
|
|
|
return this.settings.deployment?.type || 'default';
|
|
|
|
},
|
2022-11-04 06:04:31 -07:00
|
|
|
isDesktopDeployment(): boolean {
|
|
|
|
if (!this.settings.deployment) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return this.settings.deployment?.type.startsWith('desktop_');
|
|
|
|
},
|
|
|
|
isCloudDeployment(): boolean {
|
2023-11-13 05:10:42 -08:00
|
|
|
return this.settings.deployment?.type === 'cloud';
|
2022-11-04 06:04:31 -07:00
|
|
|
},
|
|
|
|
isSmtpSetup(): boolean {
|
|
|
|
return this.userManagement.smtpSetup;
|
|
|
|
},
|
|
|
|
isPersonalizationSurveyEnabled(): boolean {
|
|
|
|
return (
|
|
|
|
this.settings.telemetry &&
|
|
|
|
this.settings.telemetry.enabled &&
|
|
|
|
this.settings.personalizationSurveyEnabled
|
|
|
|
);
|
|
|
|
},
|
|
|
|
telemetry(): ITelemetrySettings {
|
|
|
|
return this.settings.telemetry;
|
|
|
|
},
|
2023-10-25 07:35:22 -07:00
|
|
|
logLevel(): LogLevel {
|
2022-11-04 06:04:31 -07:00
|
|
|
return this.settings.logLevel;
|
|
|
|
},
|
|
|
|
isTelemetryEnabled(): boolean {
|
|
|
|
return this.settings.telemetry && this.settings.telemetry.enabled;
|
|
|
|
},
|
2023-08-23 19:59:16 -07:00
|
|
|
isMfaFeatureEnabled(): boolean {
|
|
|
|
return this.settings?.mfa?.enabled;
|
|
|
|
},
|
2022-11-04 06:04:31 -07:00
|
|
|
areTagsEnabled(): boolean {
|
|
|
|
return this.settings.workflowTagsDisabled !== undefined
|
|
|
|
? !this.settings.workflowTagsDisabled
|
|
|
|
: true;
|
|
|
|
},
|
|
|
|
isHiringBannerEnabled(): boolean {
|
|
|
|
return this.settings.hiringBannerEnabled;
|
|
|
|
},
|
|
|
|
isTemplatesEnabled(): boolean {
|
|
|
|
return Boolean(this.settings.templates && this.settings.templates.enabled);
|
|
|
|
},
|
|
|
|
isTemplatesEndpointReachable(): boolean {
|
|
|
|
return this.templatesEndpointHealthy;
|
|
|
|
},
|
|
|
|
templatesHost(): string {
|
|
|
|
return this.settings.templates.host;
|
|
|
|
},
|
2023-02-10 06:02:47 -08:00
|
|
|
pushBackend(): IN8nUISettings['pushBackend'] {
|
|
|
|
return this.settings.pushBackend;
|
|
|
|
},
|
2022-11-04 06:04:31 -07:00
|
|
|
isCommunityNodesFeatureEnabled(): boolean {
|
|
|
|
return this.settings.communityNodesEnabled;
|
|
|
|
},
|
|
|
|
isNpmAvailable(): boolean {
|
|
|
|
return this.settings.isNpmAvailable;
|
|
|
|
},
|
|
|
|
allowedModules(): { builtIn?: string[]; external?: string[] } {
|
|
|
|
return this.settings.allowedModules;
|
|
|
|
},
|
|
|
|
isQueueModeEnabled(): boolean {
|
|
|
|
return this.settings.executionMode === 'queue';
|
|
|
|
},
|
2023-11-10 14:48:31 -08:00
|
|
|
isWorkerViewAvailable(): boolean {
|
|
|
|
return !!this.settings.enterprise?.workerView;
|
|
|
|
},
|
2023-04-21 04:30:57 -07:00
|
|
|
workflowCallerPolicyDefaultOption(): WorkflowSettings.CallerPolicy {
|
2022-11-04 06:04:31 -07:00
|
|
|
return this.settings.workflowCallerPolicyDefaultOption;
|
|
|
|
},
|
2023-03-17 13:07:08 -07:00
|
|
|
isDefaultAuthenticationSaml(): boolean {
|
|
|
|
return this.userManagement.authenticationMethod === UserManagementAuthenticationMethod.Saml;
|
|
|
|
},
|
2023-07-14 06:36:17 -07:00
|
|
|
permanentlyDismissedBanners(): string[] {
|
|
|
|
return this.settings.banners?.dismissed ?? [];
|
|
|
|
},
|
2023-07-12 05:11:46 -07:00
|
|
|
isBelowUserQuota(): boolean {
|
|
|
|
const userStore = useUsersStore();
|
|
|
|
return (
|
|
|
|
this.userManagement.quota === -1 || this.userManagement.quota > userStore.allUsers.length
|
|
|
|
);
|
|
|
|
},
|
2023-10-10 03:15:18 -07:00
|
|
|
isDevRelease(): boolean {
|
|
|
|
return this.settings.releaseChannel === 'dev';
|
|
|
|
},
|
2022-11-04 06:04:31 -07:00
|
|
|
},
|
|
|
|
actions: {
|
2023-11-03 07:22:37 -07:00
|
|
|
async initialize() {
|
|
|
|
if (this.initialized) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const { showToast } = useToast();
|
|
|
|
try {
|
|
|
|
await this.getSettings();
|
|
|
|
|
|
|
|
ExpressionEvaluatorProxy.setEvaluator(this.settings.expressions.evaluator);
|
|
|
|
|
|
|
|
// Re-compute title since settings are now available
|
|
|
|
useTitleChange().titleReset();
|
|
|
|
|
|
|
|
this.initialized = true;
|
|
|
|
} catch (e) {
|
|
|
|
showToast({
|
|
|
|
title: i18n.baseText('startupError'),
|
|
|
|
message: i18n.baseText('startupError.message'),
|
|
|
|
type: 'error',
|
|
|
|
duration: 0,
|
|
|
|
dangerouslyUseHTMLString: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
},
|
2022-11-04 06:04:31 -07:00
|
|
|
setSettings(settings: IN8nUISettings): void {
|
|
|
|
this.settings = settings;
|
2023-03-17 13:07:08 -07:00
|
|
|
this.userManagement = settings.userManagement;
|
2023-03-24 07:57:22 -07:00
|
|
|
if (this.userManagement) {
|
|
|
|
this.userManagement.showSetupOnFirstLoad = !!settings.userManagement.showSetupOnFirstLoad;
|
|
|
|
}
|
2023-01-02 03:14:58 -08:00
|
|
|
this.api = settings.publicApi;
|
2022-11-04 06:04:31 -07:00
|
|
|
this.onboardingCallPromptEnabled = settings.onboardingCallPromptEnabled;
|
2023-03-24 07:57:22 -07:00
|
|
|
if (settings.sso?.ldap) {
|
|
|
|
this.ldap.loginEnabled = settings.sso.ldap.loginEnabled;
|
|
|
|
this.ldap.loginLabel = settings.sso.ldap.loginLabel;
|
|
|
|
}
|
|
|
|
if (settings.sso?.saml) {
|
|
|
|
this.saml.loginEnabled = settings.sso.saml.loginEnabled;
|
|
|
|
this.saml.loginLabel = settings.sso.saml.loginLabel;
|
|
|
|
}
|
2023-08-17 05:00:17 -07:00
|
|
|
if (settings.enterprise?.showNonProdBanner) {
|
2023-09-21 00:47:21 -07:00
|
|
|
useUIStore().pushBannerToStack('NON_PRODUCTION_LICENSE');
|
|
|
|
}
|
|
|
|
if (settings.versionCli) {
|
|
|
|
useRootStore().setVersionCli(settings.versionCli);
|
|
|
|
}
|
|
|
|
|
|
|
|
const isV1BannerDismissedPermanently = (settings.banners?.dismissed || []).includes('V1');
|
|
|
|
if (!isV1BannerDismissedPermanently && useRootStore().versionCli.startsWith('1.')) {
|
|
|
|
useUIStore().pushBannerToStack('V1');
|
2023-08-17 05:00:17 -07:00
|
|
|
}
|
2022-11-04 06:04:31 -07:00
|
|
|
},
|
|
|
|
async getSettings(): Promise<void> {
|
|
|
|
const rootStore = useRootStore();
|
|
|
|
const settings = await getSettings(rootStore.getRestApiContext);
|
|
|
|
|
|
|
|
this.setSettings(settings);
|
|
|
|
this.settings.communityNodesEnabled = settings.communityNodesEnabled;
|
|
|
|
this.setAllowedModules(settings.allowedModules as { builtIn?: string; external?: string });
|
|
|
|
this.setSaveDataErrorExecution(settings.saveDataErrorExecution);
|
|
|
|
this.setSaveDataSuccessExecution(settings.saveDataSuccessExecution);
|
|
|
|
this.setSaveManualExecutions(settings.saveManualExecutions);
|
|
|
|
|
|
|
|
rootStore.setUrlBaseWebhook(settings.urlBaseWebhook);
|
|
|
|
rootStore.setUrlBaseEditor(settings.urlBaseEditor);
|
2023-12-13 07:00:51 -08:00
|
|
|
rootStore.setEndpointForm(settings.endpointForm);
|
|
|
|
rootStore.setEndpointFormTest(settings.endpointFormTest);
|
|
|
|
rootStore.setEndpointFormWaiting(settings.endpointFormWaiting);
|
2022-11-04 06:04:31 -07:00
|
|
|
rootStore.setEndpointWebhook(settings.endpointWebhook);
|
|
|
|
rootStore.setEndpointWebhookTest(settings.endpointWebhookTest);
|
|
|
|
rootStore.setTimezone(settings.timezone);
|
|
|
|
rootStore.setExecutionTimeout(settings.executionTimeout);
|
|
|
|
rootStore.setMaxExecutionTimeout(settings.maxExecutionTimeout);
|
|
|
|
rootStore.setVersionCli(settings.versionCli);
|
|
|
|
rootStore.setInstanceId(settings.instanceId);
|
|
|
|
rootStore.setOauthCallbackUrls(settings.oauthCallbackUrls);
|
|
|
|
rootStore.setN8nMetadata(settings.n8nMetadata || {});
|
|
|
|
rootStore.setDefaultLocale(settings.defaultLocale);
|
|
|
|
rootStore.setIsNpmAvailable(settings.isNpmAvailable);
|
2023-07-14 06:36:17 -07:00
|
|
|
|
2022-11-09 01:01:50 -08:00
|
|
|
useVersionsStore().setVersionNotificationSettings(settings.versionNotifications);
|
2022-11-04 06:04:31 -07:00
|
|
|
},
|
|
|
|
stopShowingSetupPage(): void {
|
2023-06-15 05:30:05 -07:00
|
|
|
this.userManagement.showSetupOnFirstLoad = false;
|
2022-11-04 06:04:31 -07:00
|
|
|
},
|
2023-04-21 01:32:23 -07:00
|
|
|
disableTemplates(): void {
|
2023-06-15 05:30:05 -07:00
|
|
|
this.settings = {
|
|
|
|
...this.settings,
|
|
|
|
templates: {
|
|
|
|
...this.settings.templates,
|
|
|
|
enabled: false,
|
|
|
|
},
|
|
|
|
};
|
2023-04-21 01:32:23 -07:00
|
|
|
},
|
2022-11-04 06:04:31 -07:00
|
|
|
setPromptsData(promptsData: IN8nPrompts): void {
|
2023-06-15 05:30:05 -07:00
|
|
|
this.promptsData = promptsData;
|
2022-11-04 06:04:31 -07:00
|
|
|
},
|
2023-04-25 09:18:46 -07:00
|
|
|
setAllowedModules(allowedModules: { builtIn?: string[]; external?: string[] }): void {
|
|
|
|
this.settings.allowedModules = allowedModules;
|
2022-11-04 06:04:31 -07:00
|
|
|
},
|
|
|
|
async fetchPromptsData(): Promise<void> {
|
|
|
|
if (!this.isTelemetryEnabled) {
|
2023-04-24 04:17:08 -07:00
|
|
|
return;
|
2022-11-04 06:04:31 -07:00
|
|
|
}
|
|
|
|
|
2023-04-24 04:17:08 -07:00
|
|
|
const uiStore = useUIStore();
|
|
|
|
const usersStore = useUsersStore();
|
|
|
|
const promptsData: IN8nPrompts = await getPromptsData(
|
|
|
|
this.settings.instanceId,
|
|
|
|
usersStore.currentUserId || '',
|
|
|
|
);
|
2022-11-04 06:04:31 -07:00
|
|
|
|
2023-04-24 04:17:08 -07:00
|
|
|
if (promptsData && promptsData.showContactPrompt) {
|
|
|
|
uiStore.openModal(CONTACT_PROMPT_MODAL_KEY);
|
|
|
|
} else if (promptsData && promptsData.showValueSurvey) {
|
|
|
|
uiStore.openModal(VALUE_SURVEY_MODAL_KEY);
|
2022-11-04 06:04:31 -07:00
|
|
|
}
|
2023-04-24 04:17:08 -07:00
|
|
|
|
|
|
|
this.setPromptsData(promptsData);
|
2022-11-04 06:04:31 -07:00
|
|
|
},
|
|
|
|
async submitContactInfo(email: string): Promise<IN8nPromptResponse | undefined> {
|
|
|
|
try {
|
|
|
|
const usersStore = useUsersStore();
|
|
|
|
return await submitContactInfo(
|
|
|
|
this.settings.instanceId,
|
|
|
|
usersStore.currentUserId || '',
|
|
|
|
email,
|
|
|
|
);
|
|
|
|
} catch (error) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
async submitValueSurvey(params: IN8nValueSurveyData): Promise<IN8nPromptResponse | undefined> {
|
|
|
|
try {
|
|
|
|
const usersStore = useUsersStore();
|
|
|
|
return await submitValueSurvey(
|
|
|
|
this.settings.instanceId,
|
|
|
|
usersStore.currentUserId || '',
|
|
|
|
params,
|
|
|
|
);
|
|
|
|
} catch (error) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
async testTemplatesEndpoint(): Promise<void> {
|
|
|
|
const timeout = new Promise((_, reject) => setTimeout(() => reject(), 2000));
|
|
|
|
await Promise.race([testHealthEndpoint(this.templatesHost), timeout]);
|
|
|
|
this.templatesEndpointHealthy = true;
|
|
|
|
},
|
|
|
|
async getApiKey(): Promise<string | null> {
|
|
|
|
const rootStore = useRootStore();
|
|
|
|
const { apiKey } = await getApiKey(rootStore.getRestApiContext);
|
|
|
|
return apiKey;
|
|
|
|
},
|
|
|
|
async createApiKey(): Promise<string | null> {
|
|
|
|
const rootStore = useRootStore();
|
|
|
|
const { apiKey } = await createApiKey(rootStore.getRestApiContext);
|
|
|
|
return apiKey;
|
|
|
|
},
|
|
|
|
async deleteApiKey(): Promise<void> {
|
|
|
|
const rootStore = useRootStore();
|
|
|
|
await deleteApiKey(rootStore.getRestApiContext);
|
|
|
|
},
|
2023-01-24 17:18:39 -08:00
|
|
|
async getLdapConfig() {
|
|
|
|
const rootStore = useRootStore();
|
2023-05-10 08:10:03 -07:00
|
|
|
return getLdapConfig(rootStore.getRestApiContext);
|
2023-01-24 17:18:39 -08:00
|
|
|
},
|
|
|
|
async getLdapSynchronizations(pagination: { page: number }) {
|
|
|
|
const rootStore = useRootStore();
|
2023-05-10 08:10:03 -07:00
|
|
|
return getLdapSynchronizations(rootStore.getRestApiContext, pagination);
|
2023-01-24 17:18:39 -08:00
|
|
|
},
|
|
|
|
async testLdapConnection() {
|
|
|
|
const rootStore = useRootStore();
|
2023-05-10 08:10:03 -07:00
|
|
|
return testLdapConnection(rootStore.getRestApiContext);
|
2023-01-24 17:18:39 -08:00
|
|
|
},
|
|
|
|
async updateLdapConfig(ldapConfig: ILdapConfig) {
|
|
|
|
const rootStore = useRootStore();
|
2023-05-10 08:10:03 -07:00
|
|
|
return updateLdapConfig(rootStore.getRestApiContext, ldapConfig);
|
2023-01-24 17:18:39 -08:00
|
|
|
},
|
|
|
|
async runLdapSync(data: IDataObject) {
|
|
|
|
const rootStore = useRootStore();
|
2023-05-10 08:10:03 -07:00
|
|
|
return runLdapSync(rootStore.getRestApiContext, data);
|
2023-01-24 17:18:39 -08:00
|
|
|
},
|
2022-11-04 06:04:31 -07:00
|
|
|
setSaveDataErrorExecution(newValue: string) {
|
2023-06-15 05:30:05 -07:00
|
|
|
this.saveDataErrorExecution = newValue;
|
2022-11-04 06:04:31 -07:00
|
|
|
},
|
|
|
|
setSaveDataSuccessExecution(newValue: string) {
|
2023-06-15 05:30:05 -07:00
|
|
|
this.saveDataSuccessExecution = newValue;
|
2022-11-04 06:04:31 -07:00
|
|
|
},
|
|
|
|
setSaveManualExecutions(saveManualExecutions: boolean) {
|
2023-06-15 05:30:05 -07:00
|
|
|
this.saveManualExecutions = saveManualExecutions;
|
2022-11-04 06:04:31 -07:00
|
|
|
},
|
2023-04-24 01:50:49 -07:00
|
|
|
async getTimezones(): Promise<IDataObject> {
|
|
|
|
const rootStore = useRootStore();
|
|
|
|
return makeRestApiRequest(rootStore.getRestApiContext, 'GET', '/options/timezones');
|
|
|
|
},
|
2022-11-04 06:04:31 -07:00
|
|
|
},
|
|
|
|
});
|