web/satellite: fetch frontend config from the satellite

This change updates the satellite frontend to retrieve its
configuration from the satellite.

References #5494

Change-Id: I1eb961f8a32f7d88173006117d41eddb57624692
This commit is contained in:
Jeremy Wharton 2023-03-24 00:55:48 -05:00
parent fd28a665c7
commit be567021d9
45 changed files with 303 additions and 196 deletions

View File

@ -31,6 +31,14 @@ export default class App extends Vue {
* Sets up variables from meta tags from config such satellite name, etc.
*/
public mounted(): void {
try {
this.$store.dispatch(APP_STATE_ACTIONS.FETCH_CONFIG);
} catch (error) {
// TODO: Use a harsher error-handling approach when the config is necessary
// for the frontend to function.
this.$notify.error(error.message, null);
}
const satelliteName = MetaUtils.getMetaContent('satellite-name');
const partneredSatellitesData = MetaUtils.getMetaContent('partnered-satellites');
let partneredSatellitesJSON = [];

View File

@ -0,0 +1,26 @@
// Copyright (C) 2023 Storj Labs, Inc.
// See LICENSE for copying information.
import { HttpClient } from '@/utils/httpClient';
import { FrontendConfig, FrontendConfigApi } from '@/types/config';
/**
* FrontendConfigHttpApi is an HTTP implementation of the frontend config API.
*/
export class FrontendConfigHttpApi implements FrontendConfigApi {
private readonly http: HttpClient = new HttpClient();
private readonly ROOT_PATH: string = '/config';
/**
* Returns the frontend config.
*
* @throws Error
*/
public async get(): Promise<FrontendConfig> {
const response = await this.http.get(this.ROOT_PATH);
if (!response.ok) {
throw new Error('Cannot get frontend config');
}
return await response.json() as FrontendConfig;
}
}

View File

@ -44,7 +44,7 @@ const store = useStore();
* Indicates if date picker is shown.
*/
const isDatePickerVisible = computed((): boolean => {
return store.state.appStateModule.appState.activeDropdown === APP_STATE_DROPDOWNS.AG_DATE_PICKER;
return store.state.appStateModule.viewsState.activeDropdown === APP_STATE_DROPDOWNS.AG_DATE_PICKER;
});
/**

View File

@ -51,7 +51,7 @@ export default class BucketsSelection extends Vue {
* Indicates if dropdown is shown.
*/
public get isDropdownShown(): boolean {
return this.$store.state.appStateModule.appState.activeDropdown === APP_STATE_DROPDOWNS.BUCKET_NAMES;
return this.$store.state.appStateModule.viewsState.activeDropdown === APP_STATE_DROPDOWNS.BUCKET_NAMES;
}
/**

View File

@ -80,7 +80,7 @@ export default class DurationSelection extends Vue {
* Indicates if date picker is shown.
*/
public get isDurationPickerVisible(): boolean {
return this.$store.state.appStateModule.appState.activeDropdown === APP_STATE_DROPDOWNS.AG_DATE_PICKER;
return this.$store.state.appStateModule.viewsState.activeDropdown === APP_STATE_DROPDOWNS.AG_DATE_PICKER;
}
/**

View File

@ -159,14 +159,14 @@ export default class BillingArea extends Vue {
* Indicates if free credits dropdown shown.
*/
public get isCreditsDropdownShown(): boolean {
return this.$store.state.appStateModule.appState.activeDropdown === APP_STATE_DROPDOWNS.FREE_CREDITS;
return this.$store.state.appStateModule.viewsState.activeDropdown === APP_STATE_DROPDOWNS.FREE_CREDITS;
}
/**
* Indicates if available balance dropdown shown.
*/
public get isBalanceDropdownShown(): boolean {
return this.$store.state.appStateModule.appState.activeDropdown === APP_STATE_DROPDOWNS.AVAILABLE_BALANCE;
return this.$store.state.appStateModule.viewsState.activeDropdown === APP_STATE_DROPDOWNS.AVAILABLE_BALANCE;
}
/**

View File

@ -61,7 +61,7 @@ const currentOption = ref<string>(periodOptions[0]);
* Indicates if periods dropdown is shown.
*/
const isDropdownShown = computed((): boolean => {
return store.state.appStateModule.appState.activeDropdown === APP_STATE_DROPDOWNS.PERIODS;
return store.state.appStateModule.viewsState.activeDropdown === APP_STATE_DROPDOWNS.PERIODS;
});
/**

View File

@ -103,7 +103,7 @@ export default class TokenDepositSelection3 extends Vue {
* isSelectionShown flag that indicate is token amount selection shown.
*/
public get isSelectionShown(): boolean {
return this.$store.state.appStateModule.appState.activeDropdown === APP_STATE_DROPDOWNS.PAYMENT_SELECTION;
return this.$store.state.appStateModule.viewsState.activeDropdown === APP_STATE_DROPDOWNS.PAYMENT_SELECTION;
}
/**

View File

@ -72,7 +72,7 @@ export default class AllModals extends Vue {
*/
public get activeModal(): unknown | null {
// modal could be of VueConstructor type or Object (for composition api components).
return this.$store.state.appStateModule.appState.activeModal;
return this.$store.state.appStateModule.viewsState.activeModal;
}
}
</script>

View File

@ -2,7 +2,7 @@
// See LICENSE for copying information.
<template>
<VModal class="modal" :on-close="onClose">
<VModal v-if="plan" class="modal" :on-close="onClose">
<template #content>
<div v-if="!isSuccess" class="content">
<div class="content__top">
@ -78,7 +78,7 @@
</template>
<script setup lang="ts">
import { computed, ref } from 'vue';
import { computed, ref, watch } from 'vue';
import { RouteConfig } from '@/router';
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
@ -111,15 +111,22 @@ const stripeCardInput = ref<(StripeCardInput & StripeForm) | null>(null);
/**
* Returns the pricing plan selected from the onboarding tour.
*/
const plan = computed((): PricingPlanInfo => {
return store.state.appStateModule.appState.selectedPricingPlan;
const plan = computed((): PricingPlanInfo | null => {
return store.state.appStateModule.viewsState.selectedPricingPlan;
});
watch(plan, () => {
if (!plan.value) {
store.commit(APP_STATE_MUTATIONS.REMOVE_ACTIVE_MODAL);
notify.error('No pricing plan has been selected.', null);
}
});
/**
* Returns whether this modal corresponds to a free pricing plan.
*/
const isFree = computed((): boolean => {
return plan.value.type === PricingPlanType.FREE;
return plan.value?.type === PricingPlanType.FREE;
});
/**
@ -136,7 +143,7 @@ function onClose(): void {
* Applies the selected pricing plan to the user.
*/
function onActivateClick(): void {
if (isLoading.value) return;
if (isLoading.value || !plan.value) return;
isLoading.value = true;
if (isFree.value) {
@ -151,6 +158,8 @@ function onActivateClick(): void {
* Adds card after Stripe confirmation.
*/
async function onCardAdded(token: string): Promise<void> {
if (!plan.value) return;
let action = PAYMENTS_ACTIONS.ADD_CREDIT_CARD;
if (plan.value.type === PricingPlanType.PARTNER) {
action = PAYMENTS_ACTIONS.PURCHASE_PACKAGE;

View File

@ -53,7 +53,7 @@ const notify = useNotify();
* Returns step from store.
*/
const storedStep = computed((): ManageProjectPassphraseStep | undefined => {
return store.state.appStateModule.appState.managePassphraseStep;
return store.state.appStateModule.viewsState.managePassphraseStep;
});
const activeStep = ref<ManageProjectPassphraseStep>(storedStep.value || ManageProjectPassphraseStep.ManageOptions);

View File

@ -108,7 +108,7 @@ const style = computed((): Record<string, string> => {
* Indicates if account dropdown is visible.
*/
const isDropdown = computed((): boolean => {
return store.state.appStateModule.appState.activeDropdown === APP_STATE_DROPDOWNS.ACCOUNT;
return store.state.appStateModule.viewsState.activeDropdown === APP_STATE_DROPDOWNS.ACCOUNT;
});
/**

View File

@ -252,14 +252,14 @@ export default class NavigationArea extends Vue {
* Indicates if resources dropdown shown.
*/
public get isResourcesDropdownShown(): boolean {
return this.$store.state.appStateModule.appState.activeDropdown === APP_STATE_DROPDOWNS.RESOURCES;
return this.$store.state.appStateModule.viewsState.activeDropdown === APP_STATE_DROPDOWNS.RESOURCES;
}
/**
* Indicates if quick start dropdown shown.
*/
public get isQuickStartDropdownShown(): boolean {
return this.$store.state.appStateModule.appState.activeDropdown === APP_STATE_DROPDOWNS.QUICK_START;
return this.$store.state.appStateModule.viewsState.activeDropdown === APP_STATE_DROPDOWNS.QUICK_START;
}
/**

View File

@ -228,7 +228,7 @@ export default class ProjectSelection extends Vue {
* Indicates if dropdown is shown.
*/
public get isDropdownShown(): boolean {
return this.$store.state.appStateModule.appState.activeDropdown === APP_STATE_DROPDOWNS.SELECT_PROJECT;
return this.$store.state.appStateModule.viewsState.activeDropdown === APP_STATE_DROPDOWNS.SELECT_PROJECT;
}
/**

View File

@ -198,7 +198,7 @@ export default class UploadFile extends Vue {
* Indicates if upload cancel popup is visible.
*/
public get isCancelUploadPopupVisible(): boolean {
return this.$store.state.appStateModule.appState.activeModal === MODALS.uploadCancelPopup;
return this.$store.state.appStateModule.viewsState.activeModal === MODALS.uploadCancelPopup;
}
/**

View File

@ -112,7 +112,7 @@ export default class AGName extends Vue {
* Returns back route from store.
*/
private get backRoute(): string {
return this.$store.state.appStateModule.appState.onbAGStepBackRoute;
return this.$store.state.appStateModule.viewsState.onbAGStepBackRoute;
}
}
</script>

View File

@ -189,7 +189,7 @@ export default class AGPermissions extends Vue {
* Returns clean API key from store.
*/
private get cleanAPIKey(): string {
return this.$store.state.appStateModule.appState.onbCleanApiKey;
return this.$store.state.appStateModule.viewsState.onbCleanApiKey;
}
/**

View File

@ -84,14 +84,14 @@ export default class APIKey extends Vue {
* Returns API key from store.
*/
public get storedAPIKey(): string {
return this.$store.state.appStateModule.appState.onbApiKey;
return this.$store.state.appStateModule.viewsState.onbApiKey;
}
/**
* Returns back route from store.
*/
private get backRoute(): string {
return this.$store.state.appStateModule.appState.onbAPIKeyStepBackRoute;
return this.$store.state.appStateModule.viewsState.onbAPIKeyStepBackRoute;
}
}
</script>

View File

@ -105,7 +105,7 @@ export default class PermissionsSelect extends Vue {
* Indicates if dropdown is visible.
*/
public get isDropdownVisible(): boolean {
return this.$store.state.appStateModule.appState.activeDropdown === APP_STATE_DROPDOWNS.PERMISSIONS;
return this.$store.state.appStateModule.viewsState.activeDropdown === APP_STATE_DROPDOWNS.PERMISSIONS;
}
/**

View File

@ -86,7 +86,7 @@ export default class OSContainer extends Vue {
* Returns selected os from store.
*/
public get storedOsSelected(): OnboardingOS | null {
return this.$store.state.appStateModule.appState.onbSelectedOs;
return this.$store.state.appStateModule.viewsState.onbSelectedOs;
}
/**

View File

@ -346,7 +346,7 @@ export default class ProjectDashboard extends Vue {
* Indicates if charts date picker is shown.
*/
public get isChartsDatePicker(): boolean {
return this.$store.state.appStateModule.appState.activeDropdown === APP_STATE_DROPDOWNS.CHART_DATE_PICKER;
return this.$store.state.appStateModule.viewsState.activeDropdown === APP_STATE_DROPDOWNS.CHART_DATE_PICKER;
}
/**
@ -416,7 +416,7 @@ export default class ProjectDashboard extends Vue {
* Indicates if user has just logged in.
*/
public get hasJustLoggedIn(): boolean {
return this.$store.state.appStateModule.appState.hasJustLoggedIn;
return this.$store.state.appStateModule.viewsState.hasJustLoggedIn;
}
/**

View File

@ -13,19 +13,19 @@ import { ProjectMembersApiGql } from '@/api/projectMembers';
import { ProjectsApiGql } from '@/api/projects';
import { notProjectRelatedRoutes, RouteConfig, router } from '@/router';
import { AccessGrantsState, makeAccessGrantsModule } from '@/store/modules/accessGrants';
import { appStateModule } from '@/store/modules/appState';
import { makeAppStateModule, AppState } from '@/store/modules/appState';
import { BucketsState, makeBucketsModule } from '@/store/modules/buckets';
import { makeNotificationsModule, NotificationsState } from '@/store/modules/notifications';
import { makeObjectsModule, OBJECTS_ACTIONS, ObjectsState } from '@/store/modules/objects';
import { makePaymentsModule, PaymentsState } from '@/store/modules/payments';
import { makeProjectMembersModule, ProjectMembersState } from '@/store/modules/projectMembers';
import { makeProjectsModule, PROJECTS_MUTATIONS, ProjectsState } from '@/store/modules/projects';
import { makeUsersModule } from '@/store/modules/users';
import { User } from '@/types/users';
import { makeUsersModule, UsersState } from '@/store/modules/users';
import { FilesState, makeFilesModule } from '@/store/modules/files';
import { NavigationLink } from '@/types/navigation';
import { MODALS } from '@/utils/constants/appStatePopUps';
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
import { FrontendConfigHttpApi } from '@/api/config';
Vue.use(Vuex);
@ -36,6 +36,7 @@ const bucketsApi = new BucketsApiGql();
const projectMembersApi = new ProjectMembersApiGql();
const projectsApi = new ProjectsApiGql();
const paymentsApi = new PaymentsHttpApi();
const configApi = new FrontendConfigHttpApi();
// We need to use a WebWorker factory because jest testing does not support
// WebWorkers yet. This is a way to avoid a direct dependency to `new Worker`.
@ -48,10 +49,10 @@ const webWorkerFactory = {
export interface ModulesState {
notificationsModule: NotificationsState;
accessGrantsModule: AccessGrantsState;
appStateModule: typeof appStateModule.state;
appStateModule: AppState;
projectMembersModule: ProjectMembersState;
paymentsModule: PaymentsState;
usersModule: User;
usersModule: UsersState;
projectsModule: ProjectsState;
objectsModule: ObjectsState;
bucketUsageModule: BucketsState;
@ -63,7 +64,7 @@ export const store = new Vuex.Store<ModulesState>({
modules: {
notificationsModule: makeNotificationsModule(),
accessGrantsModule: makeAccessGrantsModule(accessGrantsApi, webWorkerFactory),
appStateModule,
appStateModule: makeAppStateModule(configApi),
projectMembersModule: makeProjectMembersModule(projectMembersApi),
paymentsModule: makePaymentsModule(paymentsApi),
usersModule: makeUsersModule(authApi),
@ -114,7 +115,7 @@ router.beforeEach(async (to, from, next) => {
store.commit(APP_STATE_MUTATIONS.TOGGLE_HAS_JUST_LOGGED_IN);
}
if (!to.path.includes(RouteConfig.UploadFile.path) && (store.state.appStateModule.appState.activeModal !== MODALS.uploadCancelPopup)) {
if (!to.path.includes(RouteConfig.UploadFile.path) && (store.state.appStateModule.viewsState.activeModal !== MODALS.uploadCancelPopup)) {
const areUploadsInProgress: boolean = await store.dispatch(OBJECTS_ACTIONS.CHECK_ONGOING_UPLOADS, to.path);
if (areUploadsInProgress) return;
}

View File

@ -3,15 +3,17 @@
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import { OnboardingOS, PartneredSatellite, PricingPlanInfo } from '@/types/common';
import { AppState } from '@/utils/constants/appStateEnum';
import { FetchState } from '@/utils/constants/fetchStateEnum';
import { ManageProjectPassphraseStep } from '@/types/managePassphrase';
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
import { MetaUtils } from '@/utils/meta';
import { FrontendConfig, FrontendConfigApi } from '@/types/config';
import { StoreModule } from '@/types/store';
// Object that contains all states of views
class ViewsState {
constructor(
public fetchState = AppState.LOADING,
public fetchState = FetchState.LOADING,
public isSuccessfulPasswordResetShown = false,
public isBillingNotificationShown = true,
public hasJustLoggedIn = false,
@ -30,9 +32,9 @@ class ViewsState {
) {}
}
class State {
export class AppState {
constructor(
public appState: ViewsState = new ViewsState(),
public viewsState: ViewsState = new ViewsState(),
public satelliteName = '',
public partneredSatellites = new Array<PartneredSatellite>(),
public isBetaSatellite = false,
@ -40,136 +42,147 @@ class State {
public couponCodeSignupUIEnabled = false,
public isAllProjectsDashboard = MetaUtils.getMetaContent('all-projects-dashboard') === 'true',
public isNewAccessGrantFlow = false,
public config: FrontendConfig = new FrontendConfig(),
) {}
}
interface AppContext {
state: State
state: AppState
commit: (string, ...unknown) => void
}
export const appStateModule = {
state: new State(),
mutations: {
[APP_STATE_MUTATIONS.TOGGLE_SUCCESSFUL_PASSWORD_RESET](state: State): void {
state.appState.isSuccessfulPasswordResetShown = !state.appState.isSuccessfulPasswordResetShown;
export function makeAppStateModule(configApi: FrontendConfigApi): StoreModule<AppState, AppContext> {
return {
state: new AppState(),
mutations: {
[APP_STATE_MUTATIONS.TOGGLE_SUCCESSFUL_PASSWORD_RESET](state: AppState): void {
state.viewsState.isSuccessfulPasswordResetShown = !state.viewsState.isSuccessfulPasswordResetShown;
},
[APP_STATE_MUTATIONS.TOGGLE_HAS_JUST_LOGGED_IN](state: AppState): void {
state.viewsState.hasJustLoggedIn = !state.viewsState.hasJustLoggedIn;
},
[APP_STATE_MUTATIONS.CLOSE_BILLING_NOTIFICATION](state: AppState): void {
state.viewsState.isBillingNotificationShown = false;
},
[APP_STATE_MUTATIONS.CLEAR](state: AppState): void {
state.viewsState.activeModal = null;
state.viewsState.isSuccessfulPasswordResetShown = false;
state.viewsState.hasJustLoggedIn = false;
state.viewsState.onbAGStepBackRoute = '';
state.viewsState.onbAPIKeyStepBackRoute = '';
state.viewsState.onbCleanApiKey = '';
state.viewsState.onbApiKey = '';
state.viewsState.setDefaultPaymentMethodID = '';
state.viewsState.deletePaymentMethodID = '';
state.viewsState.onbSelectedOs = null;
state.viewsState.managePassphraseStep = undefined;
state.viewsState.selectedPricingPlan = null;
},
[APP_STATE_MUTATIONS.CHANGE_FETCH_STATE](state: AppState, newFetchState: FetchState): void {
state.viewsState.fetchState = newFetchState;
},
[APP_STATE_MUTATIONS.SET_SATELLITE_NAME](state: AppState, satelliteName: string): void {
state.satelliteName = satelliteName;
},
[APP_STATE_MUTATIONS.SET_PARTNERED_SATELLITES](state: AppState, partneredSatellites: PartneredSatellite[]): void {
state.partneredSatellites = partneredSatellites;
},
[APP_STATE_MUTATIONS.SET_SATELLITE_STATUS](state: AppState, isBetaSatellite: boolean): void {
state.isBetaSatellite = isBetaSatellite;
},
[APP_STATE_MUTATIONS.SET_ACCESS_GRANT_FLOW_STATUS](state: AppState, isNewAccessGrantFlow: boolean): void {
state.isNewAccessGrantFlow = isNewAccessGrantFlow;
},
[APP_STATE_MUTATIONS.SET_ONB_AG_NAME_STEP_BACK_ROUTE](state: AppState, backRoute: string): void {
state.viewsState.onbAGStepBackRoute = backRoute;
},
[APP_STATE_MUTATIONS.SET_ONB_API_KEY_STEP_BACK_ROUTE](state: AppState, backRoute: string): void {
state.viewsState.onbAPIKeyStepBackRoute = backRoute;
},
[APP_STATE_MUTATIONS.SET_ONB_API_KEY](state: AppState, apiKey: string): void {
state.viewsState.onbApiKey = apiKey;
},
[APP_STATE_MUTATIONS.SET_ONB_CLEAN_API_KEY](state: AppState, apiKey: string): void {
state.viewsState.onbCleanApiKey = apiKey;
},
[APP_STATE_MUTATIONS.SET_COUPON_CODE_BILLING_UI_STATUS](state: AppState, couponCodeBillingUIEnabled: boolean): void {
state.couponCodeBillingUIEnabled = couponCodeBillingUIEnabled;
},
[APP_STATE_MUTATIONS.SET_COUPON_CODE_SIGNUP_UI_STATUS](state: AppState, couponCodeSignupUIEnabled: boolean): void {
state.couponCodeSignupUIEnabled = couponCodeSignupUIEnabled;
},
[APP_STATE_MUTATIONS.SET_ONB_OS](state: AppState, os: OnboardingOS): void {
state.viewsState.onbSelectedOs = os;
},
[APP_STATE_MUTATIONS.SET_PRICING_PLAN](state: AppState, plan: PricingPlanInfo): void {
state.viewsState.selectedPricingPlan = plan;
},
[APP_STATE_MUTATIONS.SET_MANAGE_PASSPHRASE_STEP](state: AppState, step: ManageProjectPassphraseStep | undefined): void {
state.viewsState.managePassphraseStep = step;
},
[APP_STATE_MUTATIONS.SET_CONFIG](state: AppState, config: FrontendConfig): void {
state.config = config;
},
[APP_STATE_MUTATIONS.TOGGLE_ACTIVE_DROPDOWN](state: AppState, dropdown: string): void {
state.viewsState.activeDropdown = dropdown;
},
[APP_STATE_MUTATIONS.UPDATE_ACTIVE_MODAL](state: AppState, modal: unknown): void {
// modal could be of VueConstructor type or Object (for composition api components).
if (state.viewsState.activeModal === modal) {
state.viewsState.activeModal = null;
return;
}
state.viewsState.activeModal = modal;
},
[APP_STATE_MUTATIONS.REMOVE_ACTIVE_MODAL](state: AppState): void {
state.viewsState.activeModal = null;
},
},
[APP_STATE_MUTATIONS.TOGGLE_HAS_JUST_LOGGED_IN](state: State): void {
state.appState.hasJustLoggedIn = !state.appState.hasJustLoggedIn;
},
[APP_STATE_MUTATIONS.CLOSE_BILLING_NOTIFICATION](state: State): void {
state.appState.isBillingNotificationShown = false;
},
[APP_STATE_MUTATIONS.CLEAR](state: State): void {
state.appState.activeModal = null;
state.appState.isSuccessfulPasswordResetShown = false;
state.appState.hasJustLoggedIn = false;
state.appState.onbAGStepBackRoute = '';
state.appState.onbAPIKeyStepBackRoute = '';
state.appState.onbCleanApiKey = '';
state.appState.onbApiKey = '';
state.appState.setDefaultPaymentMethodID = '';
state.appState.deletePaymentMethodID = '';
state.appState.onbSelectedOs = null;
state.appState.managePassphraseStep = undefined;
state.appState.selectedPricingPlan = null;
},
[APP_STATE_MUTATIONS.CHANGE_STATE](state: State, newFetchState: AppState): void {
state.appState.fetchState = newFetchState;
},
[APP_STATE_MUTATIONS.SET_SATELLITE_NAME](state: State, satelliteName: string): void {
state.satelliteName = satelliteName;
},
[APP_STATE_MUTATIONS.SET_PARTNERED_SATELLITES](state: State, partneredSatellites: PartneredSatellite[]): void {
state.partneredSatellites = partneredSatellites;
},
[APP_STATE_MUTATIONS.SET_SATELLITE_STATUS](state: State, isBetaSatellite: boolean): void {
state.isBetaSatellite = isBetaSatellite;
},
[APP_STATE_MUTATIONS.SET_ACCESS_GRANT_FLOW_STATUS](state: State, isNewAccessGrantFlow: boolean): void {
state.isNewAccessGrantFlow = isNewAccessGrantFlow;
},
[APP_STATE_MUTATIONS.SET_ONB_AG_NAME_STEP_BACK_ROUTE](state: State, backRoute: string): void {
state.appState.onbAGStepBackRoute = backRoute;
},
[APP_STATE_MUTATIONS.SET_ONB_API_KEY_STEP_BACK_ROUTE](state: State, backRoute: string): void {
state.appState.onbAPIKeyStepBackRoute = backRoute;
},
[APP_STATE_MUTATIONS.SET_ONB_API_KEY](state: State, apiKey: string): void {
state.appState.onbApiKey = apiKey;
},
[APP_STATE_MUTATIONS.SET_ONB_CLEAN_API_KEY](state: State, apiKey: string): void {
state.appState.onbCleanApiKey = apiKey;
},
[APP_STATE_MUTATIONS.SET_COUPON_CODE_BILLING_UI_STATUS](state: State, couponCodeBillingUIEnabled: boolean): void {
state.couponCodeBillingUIEnabled = couponCodeBillingUIEnabled;
},
[APP_STATE_MUTATIONS.SET_COUPON_CODE_SIGNUP_UI_STATUS](state: State, couponCodeSignupUIEnabled: boolean): void {
state.couponCodeSignupUIEnabled = couponCodeSignupUIEnabled;
},
[APP_STATE_MUTATIONS.SET_ONB_OS](state: State, os: OnboardingOS): void {
state.appState.onbSelectedOs = os;
},
[APP_STATE_MUTATIONS.SET_PRICING_PLAN](state: State, plan: PricingPlanInfo): void {
state.appState.selectedPricingPlan = plan;
},
[APP_STATE_MUTATIONS.SET_MANAGE_PASSPHRASE_STEP](state: State, step: ManageProjectPassphraseStep | undefined): void {
state.appState.managePassphraseStep = step;
},
[APP_STATE_MUTATIONS.TOGGLE_ACTIVE_DROPDOWN](state: State, dropdown: string): void {
state.appState.activeDropdown = dropdown;
},
[APP_STATE_MUTATIONS.UPDATE_ACTIVE_MODAL](state: State, modal: unknown): void {
// modal could be of VueConstructor type or Object (for composition api components).
if (state.appState.activeModal === modal) {
state.appState.activeModal = null;
return;
}
state.appState.activeModal = modal;
},
[APP_STATE_MUTATIONS.REMOVE_ACTIVE_MODAL](state: State): void {
state.appState.activeModal = null;
},
},
actions: {
[APP_STATE_ACTIONS.TOGGLE_ACTIVE_DROPDOWN]: function ({ commit, state }: AppContext, dropdown: string): void {
if (state.appState.activeDropdown === dropdown) {
commit(APP_STATE_MUTATIONS.TOGGLE_ACTIVE_DROPDOWN, 'none');
return;
}
commit(APP_STATE_MUTATIONS.TOGGLE_ACTIVE_DROPDOWN, dropdown);
},
[APP_STATE_ACTIONS.TOGGLE_SUCCESSFUL_PASSWORD_RESET]: function ({ commit, state }: AppContext): void {
if (!state.appState.isSuccessfulPasswordResetShown) {
commit(APP_STATE_MUTATIONS.TOGGLE_ACTIVE_DROPDOWN, 'none');
}
actions: {
[APP_STATE_ACTIONS.TOGGLE_ACTIVE_DROPDOWN]: function ({ commit, state }: AppContext, dropdown: string): void {
if (state.viewsState.activeDropdown === dropdown) {
commit(APP_STATE_MUTATIONS.TOGGLE_ACTIVE_DROPDOWN, 'none');
return;
}
commit(APP_STATE_MUTATIONS.TOGGLE_ACTIVE_DROPDOWN, dropdown);
},
[APP_STATE_ACTIONS.TOGGLE_SUCCESSFUL_PASSWORD_RESET]: function ({ commit, state }: AppContext): void {
if (!state.viewsState.isSuccessfulPasswordResetShown) {
commit(APP_STATE_MUTATIONS.TOGGLE_ACTIVE_DROPDOWN, 'none');
}
commit(APP_STATE_MUTATIONS.TOGGLE_SUCCESSFUL_PASSWORD_RESET);
commit(APP_STATE_MUTATIONS.TOGGLE_SUCCESSFUL_PASSWORD_RESET);
},
[APP_STATE_ACTIONS.CLOSE_POPUPS]: function ({ commit }: AppContext): void {
commit(APP_STATE_MUTATIONS.TOGGLE_ACTIVE_DROPDOWN, '');
},
[APP_STATE_ACTIONS.CLEAR]: function ({ commit }: AppContext): void {
commit(APP_STATE_MUTATIONS.CLEAR);
commit(APP_STATE_MUTATIONS.TOGGLE_ACTIVE_DROPDOWN, '');
},
[APP_STATE_ACTIONS.CHANGE_FETCH_STATE]: function ({ commit }: AppContext, newFetchState: FetchState): void {
commit(APP_STATE_MUTATIONS.CHANGE_FETCH_STATE, newFetchState);
},
[APP_STATE_ACTIONS.SET_SATELLITE_NAME]: function ({ commit }: AppContext, satelliteName: string): void {
commit(APP_STATE_MUTATIONS.SET_SATELLITE_NAME, satelliteName);
},
[APP_STATE_ACTIONS.SET_PARTNERED_SATELLITES]: function ({ commit }: AppContext, partneredSatellites: PartneredSatellite[]): void {
commit(APP_STATE_MUTATIONS.SET_PARTNERED_SATELLITES, partneredSatellites);
},
[APP_STATE_ACTIONS.SET_SATELLITE_STATUS]: function ({ commit }: AppContext, isBetaSatellite: boolean): void {
commit(APP_STATE_MUTATIONS.SET_SATELLITE_STATUS, isBetaSatellite);
},
[APP_STATE_ACTIONS.SET_COUPON_CODE_BILLING_UI_STATUS]: function ({ commit }: AppContext, couponCodeBillingUIEnabled: boolean): void {
commit(APP_STATE_MUTATIONS.SET_COUPON_CODE_BILLING_UI_STATUS, couponCodeBillingUIEnabled);
},
[APP_STATE_ACTIONS.SET_COUPON_CODE_SIGNUP_UI_STATUS]: function ({ commit }: AppContext, couponCodeSignupUIEnabled: boolean): void {
commit(APP_STATE_MUTATIONS.SET_COUPON_CODE_SIGNUP_UI_STATUS, couponCodeSignupUIEnabled);
},
[APP_STATE_ACTIONS.FETCH_CONFIG]: async function ({ commit }: AppContext): Promise<FrontendConfig> {
const result = await configApi.get();
commit(APP_STATE_MUTATIONS.SET_CONFIG, result);
return result;
},
},
[APP_STATE_ACTIONS.CLOSE_POPUPS]: function ({ commit }: AppContext): void {
commit(APP_STATE_MUTATIONS.TOGGLE_ACTIVE_DROPDOWN, '');
},
[APP_STATE_ACTIONS.CLEAR]: function ({ commit }: AppContext): void {
commit(APP_STATE_MUTATIONS.CLEAR);
commit(APP_STATE_MUTATIONS.TOGGLE_ACTIVE_DROPDOWN, '');
},
[APP_STATE_ACTIONS.CHANGE_STATE]: function ({ commit }: AppContext, newFetchState: AppState): void {
commit(APP_STATE_MUTATIONS.CHANGE_STATE, newFetchState);
},
[APP_STATE_ACTIONS.SET_SATELLITE_NAME]: function ({ commit }: AppContext, satelliteName: string): void {
commit(APP_STATE_MUTATIONS.SET_SATELLITE_NAME, satelliteName);
},
[APP_STATE_ACTIONS.SET_PARTNERED_SATELLITES]: function ({ commit }: AppContext, partneredSatellites: PartneredSatellite[]): void {
commit(APP_STATE_MUTATIONS.SET_PARTNERED_SATELLITES, partneredSatellites);
},
[APP_STATE_ACTIONS.SET_SATELLITE_STATUS]: function ({ commit }: AppContext, isBetaSatellite: boolean): void {
commit(APP_STATE_MUTATIONS.SET_SATELLITE_STATUS, isBetaSatellite);
},
[APP_STATE_ACTIONS.SET_COUPON_CODE_BILLING_UI_STATUS]: function ({ commit }: AppContext, couponCodeBillingUIEnabled: boolean): void {
commit(APP_STATE_MUTATIONS.SET_COUPON_CODE_BILLING_UI_STATUS, couponCodeBillingUIEnabled);
},
[APP_STATE_ACTIONS.SET_COUPON_CODE_SIGNUP_UI_STATUS]: function ({ commit }: AppContext, couponCodeSignupUIEnabled: boolean): void {
commit(APP_STATE_MUTATIONS.SET_COUPON_CODE_SIGNUP_UI_STATUS, couponCodeSignupUIEnabled);
},
},
};
};
}

View File

@ -14,7 +14,7 @@ export const APP_STATE_MUTATIONS = {
TOGGLE_HAS_JUST_LOGGED_IN: 'TOGGLE_HAS_JUST_LOGGED_IN',
CLEAR: 'CLEAR_APPSTATE',
CLOSE_BILLING_NOTIFICATION: 'closeBillingNotification',
CHANGE_STATE: 'CHANGE_STATE',
CHANGE_FETCH_STATE: 'CHANGE_FETCH_STATE',
SET_SATELLITE_NAME: 'SET_SATELLITE_NAME',
SET_PARTNERED_SATELLITES: 'SET_PARTNERED_SATELLITES',
SET_SATELLITE_STATUS: 'SET_SATELLITE_STATUS',
@ -31,4 +31,5 @@ export const APP_STATE_MUTATIONS = {
UPDATE_ACTIVE_MODAL: 'UPDATE_ACTIVE_MODAL',
REMOVE_ACTIVE_MODAL: 'REMOVE_ACTIVE_MODAL',
SET_PRICING_PLAN: 'SET_PRICING_PLAN',
SET_CONFIG: 'SET_CONFIG',
};

View File

@ -0,0 +1,17 @@
// Copyright (C) 2023 Storj Labs, Inc.
// See LICENSE for copying information.
import { FrontendConfig } from '@/types/config.gen';
export * from '@/types/config.gen';
/**
* Exposes functionality related to retrieving the frontend config.
*/
export interface FrontendConfigApi {
/**
* Returns the frontend config.
*
* @throws Error
*/
get(): Promise<FrontendConfig>;
}

View File

@ -3,7 +3,7 @@
package main
//go:generate go run $GOFILE -o=config.gen.ts
//go:generate go run $GOFILE -o=../types/config.gen.ts
import (
"flag"
@ -38,7 +38,7 @@ func main() {
result.WriteString(types.GenerateTypescriptDefinitions())
content := strings.ReplaceAll(result.String(), "\t", " ")
err := os.WriteFile("config.gen.ts", []byte(content), 0644)
err := os.WriteFile(*outPath, []byte(content), 0644)
if err != nil {
panic(err)
}

View File

@ -5,7 +5,7 @@ export const APP_STATE_ACTIONS = {
TOGGLE_SUCCESSFUL_PASSWORD_RESET: 'TOGGLE_SUCCESSFUL_PASSWORD_RESET',
CLOSE_POPUPS: 'closePopups',
CLEAR: 'clearAppstate',
CHANGE_STATE: 'changeFetchState',
CHANGE_FETCH_STATE: 'changeFetchState',
SET_SATELLITE_NAME: 'SET_SATELLITE_NAME',
SET_PARTNERED_SATELLITES: 'SET_PARTNERED_SATELLITES',
SET_SATELLITE_STATUS: 'SET_SATELLITE_STATUS',
@ -13,6 +13,7 @@ export const APP_STATE_ACTIONS = {
SET_COUPON_CODE_SIGNUP_UI_STATUS: 'SET_COUPON_CODE_SIGNUP_UI_STATUS',
SET_ENCRYPTION_PASSPHRASE_FLOW_STATUS: 'SET_ENCRYPTION_PASSPHRASE_FLOW_STATUS',
TOGGLE_ACTIVE_DROPDOWN: 'TOGGLE_ACTIVE_DROPDOWN',
FETCH_CONFIG: 'FETCH_CONFIG',
};
export const NOTIFICATION_ACTIONS = {

View File

@ -1,7 +1,7 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
export enum AppState {
export enum FetchState {
LOADING = 1,
LOADED,
ERROR,

View File

@ -98,7 +98,7 @@ import { USER_ACTIONS } from '@/store/modules/users';
import { Project } from '@/types/projects';
import { ErrorUnauthorized } from '@/api/errors/ErrorUnauthorized';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import { AppState } from '@/utils/constants/appStateEnum';
import { FetchState } from '@/utils/constants/fetchStateEnum';
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
import { OAuthClient, OAuthClientsAPI } from '@/api/oauthClients';
import { AnalyticsHttpApi } from '@/api/analytics';
@ -160,7 +160,7 @@ export default class Authorize extends Vue {
await this.$store.dispatch(USER_ACTIONS.GET);
} catch (error) {
if (!(error instanceof ErrorUnauthorized)) {
await this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.ERROR);
await this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_FETCH_STATE, FetchState.ERROR);
await this.$notify.error(error.message, null);
}

View File

@ -114,7 +114,7 @@ import { USER_ACTIONS } from '@/store/modules/users';
import { CouponType } from '@/types/coupons';
import { Project } from '@/types/projects';
import { APP_STATE_ACTIONS, NOTIFICATION_ACTIONS, PM_ACTIONS } from '@/utils/constants/actionNames';
import { AppState } from '@/utils/constants/appStateEnum';
import { FetchState } from '@/utils/constants/fetchStateEnum';
import { LocalData } from '@/utils/localData';
import { User } from '@/types/users';
import { AuthHttpApi } from '@/api/auth';
@ -318,7 +318,7 @@ const isBetaSatellite = computed((): boolean => {
* Indicates if loading screen is active.
*/
const isLoading = computed((): boolean => {
return store.state.appStateModule.appState.fetchState === AppState.LOADING;
return store.state.appStateModule.viewsState.fetchState === FetchState.LOADING;
});
/**
@ -333,7 +333,7 @@ const showMFARecoveryCodeBar = computed((): boolean => {
* Indicates whether the billing relocation notification should be shown.
*/
const isBillingNotificationShown = computed((): boolean => {
return store.state.appStateModule.appState.isBillingNotificationShown;
return store.state.appStateModule.viewsState.isBillingNotificationShown;
});
/**
@ -607,7 +607,7 @@ onMounted(async () => {
});
if (!(error instanceof ErrorUnauthorized)) {
await store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.ERROR);
await store.dispatch(APP_STATE_ACTIONS.CHANGE_FETCH_STATE, FetchState.ERROR);
await notify.error(error.message, AnalyticsErrorEventSource.OVERALL_APP_WRAPPER_ERROR);
}
@ -657,7 +657,7 @@ onMounted(async () => {
await analytics.pageVisit(onboardingPath);
await router.push(onboardingPath);
await store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.LOADED);
await store.dispatch(APP_STATE_ACTIONS.CHANGE_FETCH_STATE, FetchState.LOADED);
} catch (error) {
notify.error(error.message, AnalyticsErrorEventSource.OVERALL_APP_WRAPPER_ERROR);
return;
@ -668,7 +668,7 @@ onMounted(async () => {
selectProject(projects);
await store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.LOADED);
await store.dispatch(APP_STATE_ACTIONS.CHANGE_FETCH_STATE, FetchState.LOADED);
});
onBeforeUnmount(() => {

View File

@ -167,7 +167,7 @@ import { AuthHttpApi } from '@/api/auth';
import { ErrorMFARequired } from '@/api/errors/ErrorMFARequired';
import { RouteConfig } from '@/router';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import { AppState } from '@/utils/constants/appStateEnum';
import { FetchState } from '@/utils/constants/fetchStateEnum';
import { Validator } from '@/utils/validation';
import { ErrorUnauthorized } from '@/api/errors/ErrorUnauthorized';
import { ErrorBadRequest } from '@/api/errors/ErrorBadRequest';
@ -443,7 +443,7 @@ async function login(): Promise<void> {
}
await store.dispatch(USER_ACTIONS.LOGIN);
await store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.LOADING);
await store.dispatch(APP_STATE_ACTIONS.CHANGE_FETCH_STATE, FetchState.LOADING);
isLoading.value = false;
analytics.pageVisit(returnURL.value);

View File

@ -160,7 +160,7 @@ export default class ResetPassword extends Vue {
* Returns whether the successful password reset area is shown.
*/
public get isSuccessfulPasswordResetShown() : boolean {
return this.$store.state.appStateModule.appState.isSuccessfulPasswordResetShown;
return this.$store.state.appStateModule.viewsState.isSuccessfulPasswordResetShown;
}
/**

View File

@ -127,7 +127,7 @@ import { OBJECTS_ACTIONS } from '@/store/modules/objects';
import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
import { ErrorUnauthorized } from '@/api/errors/ErrorUnauthorized';
import { MetaUtils } from '@/utils/meta';
import { AppState } from '@/utils/constants/appStateEnum';
import { FetchState } from '@/utils/constants/fetchStateEnum';
import { LocalData } from '@/utils/localData';
import { CouponType } from '@/types/coupons';
import { AuthHttpApi } from '@/api/auth';
@ -259,7 +259,7 @@ const isBillingPage = computed(() => {
*/
const isBillingNotificationShown = computed((): boolean => {
return !isBillingPage.value
&& store.state.appStateModule.appState.isBillingNotificationShown;
&& store.state.appStateModule.viewsState.isBillingNotificationShown;
});
/**
@ -273,7 +273,7 @@ const isBetaSatellite = computed((): boolean => {
* Indicates if loading screen is active.
*/
const isLoading = computed((): boolean => {
return store.state.appStateModule.appState.fetchState === AppState.LOADING;
return store.state.appStateModule.viewsState.fetchState === FetchState.LOADING;
});
/**
@ -546,7 +546,7 @@ onMounted(async () => {
});
if (!(error instanceof ErrorUnauthorized)) {
await store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.ERROR);
await store.dispatch(APP_STATE_ACTIONS.CHANGE_FETCH_STATE, FetchState.ERROR);
await notify.error(error.message, AnalyticsErrorEventSource.ALL_PROJECT_DASHBOARD);
}
@ -587,7 +587,7 @@ onMounted(async () => {
return;
}
await store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.LOADED);
await store.dispatch(APP_STATE_ACTIONS.CHANGE_FETCH_STATE, FetchState.LOADED);
});
onBeforeUnmount(() => {

View File

@ -96,7 +96,7 @@ const isHoveredOver = ref(false);
* Indicates if account dropdown is open.
*/
const isDropdownOpen = computed((): boolean => {
return store.state.appStateModule.appState.activeDropdown === APP_STATE_DROPDOWNS.ALL_DASH_ACCOUNT;
return store.state.appStateModule.viewsState.activeDropdown === APP_STATE_DROPDOWNS.ALL_DASH_ACCOUNT;
});
/**

View File

@ -86,7 +86,7 @@ const props = withDefaults(defineProps<{
* isDropdownOpen if dropdown is open.
*/
const isDropdownOpen = computed((): boolean => {
return store.state.appStateModule.appState.activeDropdown === props.project.id;
return store.state.appStateModule.viewsState.activeDropdown === props.project.id;
});
/**

View File

@ -4,15 +4,18 @@
import { createLocalVue, mount } from '@vue/test-utils';
import Vuex from 'vuex';
import { FrontendConfigApiMock } from '../../../mock/api/config';
import { NotificatorPlugin } from '@/utils/plugins/notificator';
import { makeNotificationsModule } from '@/store/modules/notifications';
import { appStateModule } from '@/store/modules/appState';
import { makeAppStateModule } from '@/store/modules/appState';
import AddCardForm from '@/components/account/billing/paymentMethods/AddCardForm.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
const appStateModule = makeAppStateModule(new FrontendConfigApiMock());
const notificationsModule = makeNotificationsModule();
const store = new Vuex.Store({ modules: { appStateModule, notificationsModule } });

View File

@ -5,9 +5,9 @@ import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import { PaymentsMock } from '../../../../mock/api/payments';
import { FrontendConfigApiMock } from '../../../../mock/api/config';
import { appStateModule } from '@/store/modules/appState';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import { makeAppStateModule } from '@/store/modules/appState';
import { makePaymentsModule } from '@/store/modules/payments';
import { Coupon, CouponDuration } from '@/types/payments';
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
@ -17,6 +17,7 @@ import CouponArea from '@/components/account/billing/coupons/CouponArea.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
const appStateModule = makeAppStateModule(new FrontendConfigApiMock());
const paymentsApi = new PaymentsMock();
const paymentsModule = makePaymentsModule(paymentsApi);
paymentsApi.setMockCoupon(new Coupon(

View File

@ -8,8 +8,9 @@ import { createLocalVue, shallowMount } from '@vue/test-utils';
import { ProjectsApiMock } from '../../../../mock/api/projects';
import { PaymentsMock } from '../../../../mock/api/payments';
import { FrontendConfigApiMock } from '../../../../mock/api/config';
import { appStateModule } from '@/store/modules/appState';
import { makeAppStateModule } from '@/store/modules/appState';
import { makeProjectsModule, PROJECTS_MUTATIONS } from '@/store/modules/projects';
import { Project } from '@/types/projects';
import { makePaymentsModule } from '@/store/modules/payments';
@ -17,6 +18,7 @@ import { makePaymentsModule } from '@/store/modules/payments';
import PeriodSelection from '@/components/account/billing/depositAndBillingHistory/PeriodSelection.vue';
const localVue = createLocalVue();
const appStateModule = makeAppStateModule(new FrontendConfigApiMock());
const projectsApi = new ProjectsApiMock();
const projectsModule = makeProjectsModule(projectsApi);
const paymentsApi = new PaymentsMock();

View File

@ -7,8 +7,9 @@ import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
import { PaymentsMock } from '../../../../mock/api/payments';
import { ProjectsApiMock } from '../../../../mock/api/projects';
import { UsersApiMock } from '../../../../mock/api/users';
import { FrontendConfigApiMock } from '../../../../mock/api/config';
import { appStateModule } from '@/store/modules/appState';
import { makeAppStateModule } from '@/store/modules/appState';
import { makeNotificationsModule } from '@/store/modules/notifications';
import { makePaymentsModule, PAYMENTS_MUTATIONS } from '@/store/modules/payments';
import { makeProjectsModule } from '@/store/modules/projects';
@ -23,6 +24,7 @@ const localVue = createLocalVue();
localVue.use(Vuex);
const appStateModule = makeAppStateModule(new FrontendConfigApiMock());
const paymentsApi = new PaymentsMock();
const paymentsModule = makePaymentsModule(paymentsApi);
const usersApi = new UsersApiMock();

View File

@ -5,8 +5,9 @@ import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import { ProjectMembersApiMock } from '../../mock/api/projectMembers';
import { FrontendConfigApiMock } from '../../mock/api/config';
import { appStateModule } from '@/store/modules/appState';
import { makeAppStateModule } from '@/store/modules/appState';
import { makeNotificationsModule } from '@/store/modules/notifications';
import { makeProjectMembersModule } from '@/store/modules/projectMembers';
import { ProjectMember, ProjectMemberHeaderState, ProjectMembersPage } from '@/types/projectMembers';
@ -26,6 +27,7 @@ const projectMembers: ProjectMember[] = [
const api = new ProjectMembersApiMock();
api.setMockPage(new ProjectMembersPage(projectMembers));
const appStateModule = makeAppStateModule(new FrontendConfigApiMock());
const notificationsModule = makeNotificationsModule();
const projectMembersModule = makeProjectMembersModule(api);

View File

@ -10,10 +10,11 @@ import { PaymentsMock } from '../../mock/api/payments';
import { ProjectMembersApiMock } from '../../mock/api/projectMembers';
import { ProjectsApiMock } from '../../mock/api/projects';
import { UsersApiMock } from '../../mock/api/users';
import { FrontendConfigApiMock } from '../../mock/api/config';
import { RouteConfig, router } from '@/router';
import { makeAccessGrantsModule } from '@/store/modules/accessGrants';
import { appStateModule } from '@/store/modules/appState';
import { makeAppStateModule } from '@/store/modules/appState';
import { makeBucketsModule } from '@/store/modules/buckets';
import { makeNotificationsModule } from '@/store/modules/notifications';
import { makePaymentsModule } from '@/store/modules/payments';
@ -22,7 +23,7 @@ import { makeProjectsModule } from '@/store/modules/projects';
import { makeUsersModule } from '@/store/modules/users';
import { User } from '@/types/users';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import { AppState } from '@/utils/constants/appStateEnum';
import { FetchState } from '@/utils/constants/fetchStateEnum';
import { NotificatorPlugin } from '@/utils/plugins/notificator';
import DashboardArea from '@/views/DashboardArea.vue';
import { AnalyticsHttpApi } from '@/api/analytics';
@ -36,6 +37,7 @@ const projectsApi = new ProjectsApiMock();
usersApi.setMockUser(new User('1', '2', '3', '4', '5', '6', 1));
projectsApi.setMockProjects([]);
const appStateModule = makeAppStateModule(new FrontendConfigApiMock());
const usersModule = makeUsersModule(usersApi);
const projectsModule = makeProjectsModule(projectsApi);
const accessGrantsModule = makeAccessGrantsModule(new AccessGrantsMock());
@ -78,7 +80,7 @@ describe('Dashboard', () => {
});
it('renders correctly when data is loaded', () => {
store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.LOADED);
store.dispatch(APP_STATE_ACTIONS.CHANGE_FETCH_STATE, FetchState.LOADED);
const wrapper = shallowMount(DashboardArea, {
store,

View File

@ -0,0 +1,13 @@
// Copyright (C) 2023 Storj Labs, Inc.
// See LICENSE for copying information.
import { FrontendConfig, FrontendConfigApi } from '@/types/config';
/**
* FrontendConfigHttpApi is a mock implementation of the frontend config API.
*/
export class FrontendConfigApiMock implements FrontendConfigApi {
public async get(): Promise<FrontendConfig> {
return new FrontendConfig();
}
}

View File

@ -4,14 +4,18 @@
import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import { FrontendConfigApiMock } from '../../mock/api/config';
import { router } from '@/router';
import { appStateModule } from '@/store/modules/appState';
import { makeAppStateModule } from '@/store/modules/appState';
import OverviewStep from '@/components/onboardingTour/steps/OverviewStep.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
const appStateModule = makeAppStateModule(new FrontendConfigApiMock());
const store = new Vuex.Store({ modules: { appStateModule } });
// TODO: figure out how to fix the test

View File

@ -6,8 +6,9 @@ import { createLocalVue, shallowMount } from '@vue/test-utils';
import { ProjectMembersApiMock } from '../mock/api/projectMembers';
import { ProjectsApiMock } from '../mock/api/projects';
import { FrontendConfigApiMock } from '../mock/api/config';
import { appStateModule } from '@/store/modules/appState';
import { makeAppStateModule } from '@/store/modules/appState';
import { makeProjectMembersModule, PROJECT_MEMBER_MUTATIONS } from '@/store/modules/projectMembers';
import { makeProjectsModule } from '@/store/modules/projects';
import { ProjectMember, ProjectMembersPage } from '@/types/projectMembers';
@ -18,6 +19,7 @@ import ProjectMembersArea from '@/components/team/ProjectMembersArea.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
const appStateModule = makeAppStateModule(new FrontendConfigApiMock());
const pmApi = new ProjectMembersApiMock();
const projectMembersModule = makeProjectMembersModule(pmApi);
const projectsApi = new ProjectsApiMock();