feat: application booting.

This commit is contained in:
a.bouhuolia
2021-09-08 16:27:16 +02:00
parent 7b3d310eab
commit 361aab89e6
93 changed files with 961 additions and 723 deletions

View File

@@ -1,9 +1,5 @@
import t from 'store/types';
export const setLogin = ({ user, token, tenant }) => ({
type: t.LOGIN_SUCCESS,
payload: { user, token, tenant, },
});
export const setLogin = () => ({ type: t.LOGIN_SUCCESS });
export const setLogout = () => ({ type: t.LOGOUT });
export const setStoreReset = () => ({ type: t.RESET });

View File

@@ -2,36 +2,28 @@ import { createReducer } from '@reduxjs/toolkit';
import { persistReducer } from 'redux-persist';
import purgeStoredState from 'redux-persist/es/purgeStoredState';
import storage from 'redux-persist/lib/storage';
import { getCookie, setCookie } from 'utils';
import t from 'store/types';
import { removeCookie } from '../../utils';
// Read stored data in cookies and merge it with the initial state.
const initialState = {
token: '',
organization: '',
organizationId: null,
user: '',
tenant: {},
locale: '',
token: getCookie('token'),
organizationId: getCookie('organization_id'),
tenantId: getCookie('tenant_id'),
userId: getCookie('authenticated_user_id'),
locale: getCookie('locale'),
errors: [],
};
const STORAGE_KEY = 'bigcapital:authentication';
const CONFIG = {
key: STORAGE_KEY,
blacklist: ['errors'],
whitelist: [],
storage,
};
const reducerInstance = createReducer(initialState, {
[t.LOGIN_SUCCESS]: (state, action) => {
const { token, user, tenant } = action.payload;
state.token = token;
state.user = user;
state.organization = tenant.organization_id;
state.organizationId = tenant.id;
state.tenant = tenant;
},
[t.LOGIN_FAILURE]: (state, action) => {
state.errors = action.errors;
},
@@ -40,15 +32,12 @@ const reducerInstance = createReducer(initialState, {
state.errors = [];
},
[t.RESET]: () => {
[t.RESET]: (state) => {
purgeStoredState(CONFIG);
}
},
});
export default persistReducer(
CONFIG,
reducerInstance,
);
export default persistReducer(CONFIG, reducerInstance);
export const isAuthenticated = (state) => !!state.authentication.token;
export const hasErrorType = (state, errorType) => {
@@ -59,4 +48,4 @@ export const isTenantSeeded = (state) => !!state.tenant.seeded_at;
export const isTenantBuilt = (state) => !!state.tenant.initialized_at;
export const isTenantHasSubscription = () => false;
export const isTenantSubscriptionExpired = () => false;
export const isTenantSubscriptionExpired = () => false;

View File

@@ -1,8 +1,8 @@
import { defaultTo } from 'lodash';
import { createSelector } from '@reduxjs/toolkit';
const getCurrentOrganizationId = (state) => state.authentication.organization;
const getCurrentTenantId = (state) => state.authentication.organizationId;
const getCurrentOrganizationId = (state) => state.authentication.organizationId;
const getCurrentTenantId = (state) => state.authentication.tenantId;
const getOrganizationsMap = (state) => state.organizations.data;
// Retrieve organization tenant id.

View File

@@ -10,13 +10,14 @@ import loggerMiddleware from 'middleware/logger';
import rootReducer from 'store/reducers';
import ResetMiddleware from './ResetMiddleware';
const createStoreFactory = (initialState = {}) => {
/**
|--------------------------------------------------
| Middleware Configuration
|--------------------------------------------------
*/
const middleware = [thunkMiddleware, loggerMiddleware ];
const middleware = [thunkMiddleware, loggerMiddleware];
/**
|--------------------------------------------------
@@ -41,8 +42,6 @@ const createStoreFactory = (initialState = {}) => {
rootReducer,
initialState,
composeEnhancers(applyMiddleware(...middleware), ...enhancers),
);
store.asyncReducers = {};
return store;

View File

@@ -69,4 +69,19 @@ export function toggleExpendSidebar(toggle) {
type: t.SIDEBAR_EXPEND_TOGGLE,
payload: { toggle }
};
}
export function appIsLoading(toggle) {
return {
type: t.APP_IS_LOADING,
payload: { isLoading: toggle },
};
}
export function appIntlIsLoading(toggle) {
return {
type: t.APP_INTL_IS_LOADING,
payload: { isLoading: toggle },
};
}

View File

@@ -16,6 +16,8 @@ const initialState = {
topbarEditViewId: null,
requestsLoading: 0,
backLink: false,
appIsLoading: true,
appIntlIsLoading: true,
};
const STORAGE_KEY = 'bigcapital:dashboard';
@@ -100,6 +102,16 @@ const reducerInstance = createReducer(initialState, {
state.backLink = backLink;
},
[t.APP_IS_LOADING]: (state, action) => {
const { isLoading } = action.payload;
state.appIsLoading = isLoading;
},
[t.APP_INTL_IS_LOADING]: (state, action) => {
const { isLoading } = action.payload;
state.appIntlIsLoading = isLoading;
},
[t.RESET]: () => {
purgeStoredState(CONFIG);
},

View File

@@ -14,4 +14,6 @@ export default {
SET_TOPBAR_EDIT_VIEW: 'SET_TOPBAR_EDIT_VIEW',
SIDEBAR_EXPEND_TOGGLE: 'SIDEBAR_EXPEND_TOGGLE',
SET_DASHBOARD_BACK_LINK: 'SET_DASHBOARD_BACK_LINK',
APP_IS_LOADING: 'APP_IS_LOADING',
APP_INTL_IS_LOADING: 'APP_INTL_IS_LOADING'
};

View File

@@ -29,12 +29,12 @@ export const fetchOrganizations = () => (dispatch) =>
export const setOrganizationSetupCompleted =
(congrats) => (dispatch, getState) => {
const organizationId = getState().authentication.organizationId;
const tenantId = getState().authentication.tenantId;
dispatch({
type: t.SET_ORGANIZATION_CONGRATS,
payload: {
organizationId,
tenantId,
congrats,
},
});

View File

@@ -27,10 +27,10 @@ const reducer = createReducer(initialState, {
},
[t.SET_ORGANIZATION_CONGRATS]: (state, action) => {
const { organizationId, congrats } = action.payload;
const { tenantId, congrats } = action.payload;
state.data[organizationId] = {
...(state.data[organizationId] || {}),
state.data[tenantId] = {
...(state.data[tenantId] || {}),
is_congrats: !!congrats,
};
}

View File

@@ -1,50 +1,39 @@
import { createSelector } from '@reduxjs/toolkit';
const organizationSelector = (state, props) => state.organizations.data[props.organizationId];
const organizationSelector = (state, props) => {
const tenantId = state.organizations.byOrganizationId[props.organizationId];
return state.organizations.data[tenantId];
};
export const getOrganizationByIdFactory = () => createSelector(
organizationSelector,
(organization) => organization
);
export const getOrganizationByIdFactory = () =>
createSelector(organizationSelector, (organization) => organization);
export const isOrganizationSeededFactory = () => createSelector(
organizationSelector,
(organization) => {
export const isOrganizationSeededFactory = () =>
createSelector(organizationSelector, (organization) => {
return !!organization?.seeded_at;
},
);
});
export const isOrganizationBuiltFactory = () => createSelector(
organizationSelector,
(organization) => {
export const isOrganizationBuiltFactory = () =>
createSelector(organizationSelector, (organization) => {
return !!organization?.initialized_at;
},
);
});
export const isOrganizationReadyFactory = () => createSelector(
organizationSelector,
(organization) => {
export const isOrganizationReadyFactory = () =>
createSelector(organizationSelector, (organization) => {
return organization?.is_ready;
},
);
});
export const isOrganizationSubscribedFactory = () => createSelector(
organizationSelector,
(organization) => {
export const isOrganizationSubscribedFactory = () =>
createSelector(organizationSelector, (organization) => {
return organization?.subscriptions?.length > 0;
}
);
});
export const isOrganizationCongratsFactory = () => createSelector(
organizationSelector,
(organization) => {
export const isOrganizationCongratsFactory = () =>
createSelector(organizationSelector, (organization) => {
return !!organization?.is_congrats;
}
);
});
export const isOrganizationBuildRunningFactory = () => createSelector(
organizationSelector,
(organization) => {
export const isOrganizationBuildRunningFactory = () =>
createSelector(organizationSelector, (organization) => {
return !!organization?.is_build_running;
}
)
});

View File

@@ -1,5 +1,6 @@
export default {
ORGANIZATION_SET: 'ORGANIZATION_SET',
ORGANIZATIONS_LIST_SET: 'ORGANIZATIONS_LIST_SET',
SET_ORGANIZATION_CONGRATS: 'SET_ORGANIZATION_CONGRATS'
};

View File

@@ -17,7 +17,7 @@ const getSubscriptionPeriods = () => [
const getSubscriptionPlans = () => [
{
name: intl.get('plan.essential.title'),
slug: 'free',
slug: 'essentials',
description: [
intl.get('plan.feature.sale_purchase_invoice'),
intl.get('plan.feature.receivable_payable_accounts'),