mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 13:50:31 +00:00
WIP
This commit is contained in:
10
client/src/store/accounting/accounting.actions.js
Normal file
10
client/src/store/accounting/accounting.actions.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import ApiService from 'services/ApiService';
|
||||
import t from 'store/types';
|
||||
|
||||
export const makeJournalEntries = ({ form }) => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.post('accounting/make-journal-entries', form).then((response) => {
|
||||
resolve(response);
|
||||
}).catch((error) => { reject(error); });
|
||||
});
|
||||
}
|
||||
5
client/src/store/accounting/accountsing.types.js
Normal file
5
client/src/store/accounting/accountsing.types.js
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
export default {
|
||||
MAKE_JOURNAL_ENTRIES: 'MAKE_JOURNAL_ENTRIES',
|
||||
}
|
||||
108
client/src/store/accounts/accounts.actions.js
Normal file
108
client/src/store/accounts/accounts.actions.js
Normal file
@@ -0,0 +1,108 @@
|
||||
import ApiService from 'services/ApiService';
|
||||
import t from 'store/types';
|
||||
|
||||
export const fetchAccountTypes = () => {
|
||||
return (dispatch, getState) => new Promise((resolve, reject) => {
|
||||
ApiService.get('account_types').then((response) => {
|
||||
dispatch({
|
||||
type: t.ACCOUNT_TYPES_LIST_SET,
|
||||
account_types: response.data.account_types,
|
||||
});
|
||||
resolve(response);
|
||||
}).catch((error) => { reject(error); });
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchAccountsList = ({ query } = {}) => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.get('accounts', { params: query }).then((response) => {
|
||||
dispatch({
|
||||
type: t.ACCOUNTS_PAGE_SET,
|
||||
accounts: response.data.accounts,
|
||||
customViewId: response.data.customViewId,
|
||||
});
|
||||
dispatch({
|
||||
type: t.ACCOUNTS_ITEMS_SET,
|
||||
accounts: response.data.accounts,
|
||||
});
|
||||
resolve(response);
|
||||
}).catch((error) => { reject(error); });
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchAccountsDataTable = ({ query }) => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.get('accounts', ).then((response) => {
|
||||
dispatch({
|
||||
type: t.ACCOUNTS_DATA_TABLE,
|
||||
data: response.data,
|
||||
})
|
||||
}).catch((error) => { reject(error); })
|
||||
})
|
||||
};
|
||||
|
||||
export const submitAccount = ({ form }) => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.post('accounts', form).then((response) => {
|
||||
dispatch({ type: t.CLEAR_ACCOUNT_FORM_ERRORS });
|
||||
resolve(response);
|
||||
}).catch((error) => {
|
||||
const { response } = error;
|
||||
const { data } = response;
|
||||
const { errors } = data;
|
||||
|
||||
dispatch({ type: t.CLEAR_ACCOUNT_FORM_ERRORS });
|
||||
if (errors){
|
||||
dispatch({ type: t.ACCOUNT_FORM_ERRORS, errors });
|
||||
}
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const editAccount = ({ id, form }) => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.post(`accounts/${id}`, form).then((response) => {
|
||||
dispatch({type: t.CLEAR_ACCOUNT_FORM_ERRORS});
|
||||
resolve(response);
|
||||
}).catch((error) => {
|
||||
const { response } = error;
|
||||
const { data } = response;
|
||||
const { errors } = data;
|
||||
|
||||
dispatch({type: t.CLEAR_ACCOUNT_FORM_ERRORS});
|
||||
if (errors){
|
||||
dispatch({ type: t.ACCOUNT_FORM_ERRORS, errors });
|
||||
}
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const activeAccount = ({ id }) => {
|
||||
return (dispatch) => ApiService.post(`accounts/${id}/active`);
|
||||
};
|
||||
|
||||
export const inactiveAccount = ({ id }) => {
|
||||
return (dispatch) => ApiService.post(`accounts/${id}/inactive`);
|
||||
};
|
||||
|
||||
export const deleteAccount = ({ id }) => {
|
||||
return (dispatch) => ApiService.delete(`accounts/${id}`);
|
||||
};
|
||||
|
||||
export const deleteBulkAccounts = ({ ids }) => {
|
||||
|
||||
};
|
||||
|
||||
export const fetchAccount = ({ id }) => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.get(`accounts/${id}`).then((response) => {
|
||||
dispatch({
|
||||
type: t.ACCOUNT_SET,
|
||||
account: response.data.account,
|
||||
});
|
||||
resolve(response);
|
||||
}).catch((error) => { reject(error); });
|
||||
});
|
||||
}
|
||||
62
client/src/store/accounts/accounts.reducer.js
Normal file
62
client/src/store/accounts/accounts.reducer.js
Normal file
@@ -0,0 +1,62 @@
|
||||
import t from 'store/types';
|
||||
import { createReducer } from '@reduxjs/toolkit';
|
||||
|
||||
const initialState = {
|
||||
items: {},
|
||||
views: {},
|
||||
accountsTypes: [],
|
||||
accountsById: {},
|
||||
accountFormErrors: [],
|
||||
datatableQuery: {},
|
||||
currentViewId: -1,
|
||||
bulkActions: {},
|
||||
};
|
||||
|
||||
export default createReducer(initialState, {
|
||||
[t.ACCOUNTS_ITEMS_SET]: (state, action) => {
|
||||
const _items = {};
|
||||
|
||||
action.accounts.forEach((account) => {
|
||||
_items[account.id] = account;
|
||||
});
|
||||
state.items = {
|
||||
...state.items,
|
||||
..._items,
|
||||
};
|
||||
},
|
||||
|
||||
[t.ACCOUNTS_PAGE_SET]: (state, action) => {
|
||||
const viewId = action.customViewId || -1;
|
||||
const view = state.views[viewId] || {};
|
||||
|
||||
state.views[viewId] = {
|
||||
...view,
|
||||
ids: action.accounts.map(i => i.id),
|
||||
};
|
||||
state.accounts = action.accounts;
|
||||
},
|
||||
|
||||
[t.ACCOUNT_TYPES_LIST_SET]: (state, action) => {
|
||||
state.accountsTypes = action.account_types;
|
||||
},
|
||||
|
||||
[t.ACCOUNT_SET]: (state, action) => {
|
||||
state.accountsById[action.account.id] = action.account;
|
||||
},
|
||||
|
||||
[t.ACCOUNT_BULK_ACTION_ADD]: (state, action) => {
|
||||
state.bulkActions[action.account_id] = true;
|
||||
},
|
||||
|
||||
[t.ACCOUNT_BULK_ACTION_REMOVE]: (state, action) => {
|
||||
delete state.bulkActions[action.account_id];
|
||||
},
|
||||
|
||||
[t.ACCOUNTS_SET_CURRENT_VIEW]: (state, action) => {
|
||||
state.currentViewId = action.currentViewId;
|
||||
}
|
||||
});
|
||||
|
||||
export const getAccountById = (state, id) => {
|
||||
return state.accounts.accountsById[id];
|
||||
};
|
||||
9
client/src/store/accounts/accounts.selectors.js
Normal file
9
client/src/store/accounts/accounts.selectors.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import {pickItemsFromIds} from 'store/selectors';
|
||||
|
||||
export const getAccountsItems = (state, viewId) => {
|
||||
const accountsView = state.accounts.views[(viewId || -1)];
|
||||
const accountsItems = state.accounts.items;
|
||||
|
||||
return (typeof accountsView === 'object')
|
||||
? (pickItemsFromIds(accountsItems, accountsView.ids) || []) : [];
|
||||
}
|
||||
15
client/src/store/accounts/accounts.types.js
Normal file
15
client/src/store/accounts/accounts.types.js
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
|
||||
export default {
|
||||
ACCOUNT_TYPES_LIST_SET: 'ACCOUNT_TYPES_LIST_SET',
|
||||
ACCOUNTS_PAGE_SET: 'ACCOUNTS_PAGE_SET',
|
||||
ACCOUNTS_ITEMS_SET: 'ACCOUNTS_ITEMS_SET',
|
||||
ACCOUNT_SET: 'ACCOUNT_SET',
|
||||
ACCOUNT_FORM_ERRORS: 'ACCOUNT_FORM_ERRORS',
|
||||
CLEAR_ACCOUNT_FORM_ERRORS: 'CLEAR_ACCOUNT_FORM_ERRORS',
|
||||
|
||||
ACCOUNT_BULK_ACTION_ADD: 'ACCOUNT_BULK_ACTION_ADD',
|
||||
ACCOUNT_BULK_ACTION_REMOVE: 'ACCOUNT_BULK_ACTION_REMOVE',
|
||||
|
||||
ACCOUNTS_SET_CURRENT_VIEW: 'ACCOUNTS_SET_CURRENT_VIEW',
|
||||
};
|
||||
@@ -1,18 +0,0 @@
|
||||
import ApiService from 'services/ApiService';
|
||||
import t from 'store/types';
|
||||
|
||||
export default function login({ form }) {
|
||||
return (dispatch) => {
|
||||
ApiService.post('/auth/login', form).then(response => {
|
||||
const { data } = response;
|
||||
|
||||
if (data.token && data.user) {
|
||||
dispatch({
|
||||
type: t.LOGIN_SUCCESS,
|
||||
user: data.user,
|
||||
token: data.token,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
35
client/src/store/authentication/authentication.actions.js
Normal file
35
client/src/store/authentication/authentication.actions.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import ApiService from 'services/ApiService';
|
||||
import t from 'store/types';
|
||||
|
||||
export default function login({ form }) {
|
||||
return (dispatch) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
ApiService.post('auth/login', form).then(response => {
|
||||
const { data } = response;
|
||||
|
||||
dispatch({type: t.LOGIN_CLEAR_ERRORS});
|
||||
if (data.token && data.user) {
|
||||
dispatch({
|
||||
type: t.LOGIN_SUCCESS,
|
||||
user: data.user,
|
||||
token: data.token,
|
||||
});
|
||||
}
|
||||
resolve(response);
|
||||
}).catch((error) => {
|
||||
const { response } = error;
|
||||
const { data } = response;
|
||||
const { errors } = data;
|
||||
|
||||
dispatch({type: t.LOGIN_CLEAR_ERRORS});
|
||||
|
||||
if (errors){
|
||||
dispatch({
|
||||
type: t.LOGIN_FAILURE, errors,
|
||||
});
|
||||
}
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
34
client/src/store/authentication/authentication.reducer.js
Normal file
34
client/src/store/authentication/authentication.reducer.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import {createReducer} from '@reduxjs/toolkit';
|
||||
import t from 'store/types';
|
||||
|
||||
const initialState = {
|
||||
token: '',
|
||||
user: '',
|
||||
locale: '',
|
||||
errors: [],
|
||||
};
|
||||
|
||||
export default createReducer(initialState, {
|
||||
[t.LOGIN_SUCCESS]: (state, action) => {
|
||||
state.token = action.token;
|
||||
state.user = action.user;
|
||||
},
|
||||
|
||||
[t.LOGIN_FAILURE]: (state, action) => {
|
||||
state.errors = action.errors;
|
||||
},
|
||||
|
||||
[t.LOGOUT]: (state) => {
|
||||
state.token = '';
|
||||
state.user = {};
|
||||
},
|
||||
|
||||
[t.LOGIN_CLEAR_ERRORS]: (state) => {
|
||||
state.errors = [];
|
||||
},
|
||||
});
|
||||
|
||||
export const isAuthenticated = (state) => !!state.authentication.token;
|
||||
export const hasErrorType = (state, errorType) => {
|
||||
return state.authentication.errors.find(e => e.type === errorType);
|
||||
};
|
||||
@@ -1,9 +1,8 @@
|
||||
|
||||
const ACTION = {
|
||||
export default {
|
||||
LOGIN_REQUEST: 'LOGIN_REQUEST',
|
||||
LOGIN_SUCCESS: 'LOGIN_SUCCESS',
|
||||
LOGIN_FAILURE: 'LOGIN_FAILURE',
|
||||
LOGOUT: 'LOGOUT',
|
||||
};
|
||||
|
||||
export default ACTION;
|
||||
LOGIN_CLEAR_ERRORS: 'LOGIN_CLEAR_ERRORS',
|
||||
};
|
||||
@@ -3,8 +3,11 @@ import thunkMiddleware from 'redux-thunk';
|
||||
import monitorReducerEnhancer from 'store/enhancers/monitorReducer';
|
||||
import loggerMiddleware from 'middleware/logger'
|
||||
import rootReducer from 'store/reducers';
|
||||
import { loadState, saveState } from 'store/localStorage';
|
||||
|
||||
const createStore = (initialState = {}) => {
|
||||
const createStore = (initialState = {
|
||||
...loadState(),
|
||||
}) => {
|
||||
/**
|
||||
|--------------------------------------------------
|
||||
| Middleware Configuration
|
||||
@@ -43,6 +46,13 @@ const createStore = (initialState = {}) => {
|
||||
);
|
||||
store.asyncReducers = {};
|
||||
|
||||
store.subscribe(() => {
|
||||
saveState({
|
||||
authentication: {
|
||||
token: store.getState().authentication.token,
|
||||
},
|
||||
});
|
||||
});
|
||||
return store;
|
||||
};
|
||||
export default createStore();
|
||||
|
||||
26
client/src/store/currencies/currencies.actions.js
Normal file
26
client/src/store/currencies/currencies.actions.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import ApiService from "services/ApiService";
|
||||
import t from 'store/types';
|
||||
|
||||
export const fetchCurrencies = () => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.get(`currencies/registered`).then((response) => {
|
||||
dispatch({
|
||||
type: t.CURRENCIES_REGISTERED_SET,
|
||||
currencies: response.data.currencies,
|
||||
});
|
||||
resolve(response);
|
||||
}).catch(error => { reject(error); });
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchAllCurrencies = () => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.get(`currencies/all`).then((response) => {
|
||||
dispatch({
|
||||
type: t.CURRENCIES_ALL_SET,
|
||||
currencies: response.data.currencies,
|
||||
});
|
||||
resolve(response);
|
||||
}).catch(error => { reject(error); });
|
||||
});
|
||||
};
|
||||
18
client/src/store/currencies/currencies.reducer.js
Normal file
18
client/src/store/currencies/currencies.reducer.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import {createReducer} from '@reduxjs/toolkit'
|
||||
import t from 'store/types';
|
||||
|
||||
const initialState = {
|
||||
all: [],
|
||||
registered: [],
|
||||
};
|
||||
|
||||
export default createReducer(initialState, {
|
||||
[t.CURRENCIES_REGISTERED_SET]: (state, action) => {
|
||||
state.registered = action.currencies;
|
||||
},
|
||||
|
||||
[t.CURRENCIES_ALL_SET]: (state, action) => {
|
||||
state.all = action.currencies;
|
||||
},
|
||||
});
|
||||
|
||||
5
client/src/store/currencies/currencies.types.js
Normal file
5
client/src/store/currencies/currencies.types.js
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
export default {
|
||||
CURRENCIES_REGISTERED_SET: 'CURRENCIES_REGISTERED_SET',
|
||||
CURRENCIES_ALL_SET: 'CURRENCIES_ALL_SET',
|
||||
};
|
||||
15
client/src/store/customFields/customFields.actions.js
Normal file
15
client/src/store/customFields/customFields.actions.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import ApiService from 'services/ApiService';
|
||||
import t from 'store/types';
|
||||
|
||||
export const fetchResourceFields = ({ resourceSlug }) => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.get(`fields/resource/${resourceSlug}`).then((response) => {
|
||||
dispatch({
|
||||
type: t.CUSTOM_FIELDS_RESOURCE_SET,
|
||||
resourceSlug: resourceSlug,
|
||||
fields: response.data.fields,
|
||||
});
|
||||
resolve(response);
|
||||
}).catch(error => { reject(error); });
|
||||
});
|
||||
}
|
||||
24
client/src/store/customFields/customFields.reducer.js
Normal file
24
client/src/store/customFields/customFields.reducer.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import {createReducer} from '@reduxjs/toolkit';
|
||||
import t from 'store/types';
|
||||
|
||||
const initialState = {
|
||||
custom_fields: {
|
||||
accounts: [{
|
||||
label_name: 'Label',
|
||||
predefined: true,
|
||||
data_type: 'text',
|
||||
help_text: '123sdasd',
|
||||
active: true,
|
||||
}]
|
||||
},
|
||||
};
|
||||
|
||||
export default createReducer(initialState, {
|
||||
[t.CUSTOM_FIELDS_RESOURCE_SET]: (state, action) => {
|
||||
state.fields.custom_fields[action.resource_slug] = action.custom_field;
|
||||
}
|
||||
});
|
||||
|
||||
export const getCustomFieldsByResource = (state, resourceSlug) => {
|
||||
return state.fields.custom_fields[resourceSlug];
|
||||
}
|
||||
4
client/src/store/customFields/customFields.types.js
Normal file
4
client/src/store/customFields/customFields.types.js
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
export default {
|
||||
CUSTOM_FIELDS_RESOURCE_SET: 'CUSTOM_FIELDS_RESOURCE_SET',
|
||||
};
|
||||
45
client/src/store/customViews/customViews.actions.js
Normal file
45
client/src/store/customViews/customViews.actions.js
Normal file
@@ -0,0 +1,45 @@
|
||||
import ApiService from "services/ApiService";
|
||||
import t from 'store/types';
|
||||
|
||||
export const submitView = ({ form }) => {
|
||||
return (dispatch) => ApiService.post('views', form);
|
||||
};
|
||||
|
||||
export const editView = ({ id, form }) => {
|
||||
return (dispatch) => ApiService.post(`views/${id}`);
|
||||
};
|
||||
|
||||
export const deleteView = ({ id }) => {
|
||||
return (dispatch) => ApiService.delete(`views/${id}`);
|
||||
};
|
||||
|
||||
export const fetchView = ({ id }) => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.get(`views/${id}`).then((response) => {
|
||||
dispatch({
|
||||
type: t.VIEW_META_SET,
|
||||
view: response.data.view,
|
||||
});
|
||||
resolve(response);
|
||||
}).catch(error => { reject(error); });
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchResourceViews = ({ resourceSlug }) => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.get('views', { query: { resource_name: resourceSlug } })
|
||||
.then((response) => {
|
||||
dispatch({
|
||||
type: t.RESOURCE_VIEWS_SET,
|
||||
resource: resourceSlug,
|
||||
views: response.data.views,
|
||||
});
|
||||
dispatch({
|
||||
type: t.VIEW_ITEMS_SET,
|
||||
views: response.data.views,
|
||||
});
|
||||
resolve(response);
|
||||
})
|
||||
.catch((error) => { reject(error); });
|
||||
});
|
||||
};
|
||||
30
client/src/store/customViews/customViews.reducer.js
Normal file
30
client/src/store/customViews/customViews.reducer.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import { createReducer } from "@reduxjs/toolkit";
|
||||
import t from 'store/types';
|
||||
|
||||
const initialState = {
|
||||
views: {},
|
||||
resourceViews: {
|
||||
'accounts': [],
|
||||
'expenses': [],
|
||||
},
|
||||
viewsMeta: {},
|
||||
};
|
||||
|
||||
export default createReducer(initialState, {
|
||||
[t.VIEW_META_SET]: (state, action) => {
|
||||
state.viewsMeta[action.view.id] = action.view;
|
||||
},
|
||||
|
||||
[t.RESOURCE_VIEWS_SET]: (state, action) => {
|
||||
state.resourceViews[action.resource] = action.views.map(v => v.id);
|
||||
},
|
||||
|
||||
[t.VIEW_ITEMS_SET]: (state, action) => {
|
||||
const _views = {};
|
||||
|
||||
action.views.forEach((view) => {
|
||||
_views[view.id] = view;
|
||||
});
|
||||
state.views = { ...state.views, ..._views };
|
||||
},
|
||||
})
|
||||
15
client/src/store/customViews/customViews.selectors.js
Normal file
15
client/src/store/customViews/customViews.selectors.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import {pickItemsFromIds} from 'store/selectors';
|
||||
|
||||
|
||||
export const getResourceViews = (state, resourceName) => {
|
||||
const resourceViewsIds = state.views.resourceViews[resourceName] || [];
|
||||
return pickItemsFromIds(state.views.views, resourceViewsIds);
|
||||
};
|
||||
|
||||
export const getViewMeta = (state, viewId) => {
|
||||
return state.views.viewsMeta[viewId] || {};
|
||||
};
|
||||
|
||||
export const getViewItem = (state, viewId) => {
|
||||
return state.views.views[viewId] || {};
|
||||
};
|
||||
6
client/src/store/customViews/customViews.types.js
Normal file
6
client/src/store/customViews/customViews.types.js
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
export default {
|
||||
VIEW_META_SET: 'VIEW_META_SET',
|
||||
VIEW_ITEMS_SET: 'VIEW_ITEMS_SET',
|
||||
RESOURCE_VIEWS_SET: 'RESOURCE_VIEWS_SET',
|
||||
};
|
||||
17
client/src/store/dashboard/dashboard.actions.js
Normal file
17
client/src/store/dashboard/dashboard.actions.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import t from 'store/types';
|
||||
|
||||
export function openDialog(name, payload) {
|
||||
return {
|
||||
type: t.OPEN_DIALOG,
|
||||
name: name,
|
||||
payload: payload,
|
||||
};
|
||||
};
|
||||
|
||||
export function closeDialog(name, payload) {
|
||||
return {
|
||||
type: t.CLOSE_DIALOG,
|
||||
name: name,
|
||||
payload: payload,
|
||||
}
|
||||
}
|
||||
55
client/src/store/dashboard/dashboard.reducer.js
Normal file
55
client/src/store/dashboard/dashboard.reducer.js
Normal file
@@ -0,0 +1,55 @@
|
||||
import t from 'store/types';
|
||||
import { createReducer } from '@reduxjs/toolkit';
|
||||
|
||||
const initialState = {
|
||||
pageTitle: '',
|
||||
pageSubtitle: 'Hello World',
|
||||
preferencesPageTitle: '',
|
||||
dialogs: {},
|
||||
topbarEditViewId: 1,
|
||||
};
|
||||
|
||||
export default createReducer(initialState, {
|
||||
[t.CHANGE_DASHBOARD_PAGE_TITLE]: (state, action) => {
|
||||
state.pageTitle = action.pageTitle;
|
||||
},
|
||||
|
||||
[t.ALTER_DASHBOARD_PAGE_SUBTITLE]: (state, action) => {
|
||||
state.pageSubtitle = action.pageSubtitle;
|
||||
},
|
||||
|
||||
[t.CHANGE_PREFERENCES_PAGE_TITLE]: (state, action) => {
|
||||
state.preferencesPageTitle = action.pageTitle;
|
||||
},
|
||||
|
||||
[t.OPEN_DIALOG]: (state, action) => {
|
||||
state.dialogs[action.name] = {
|
||||
isOpen: true,
|
||||
payload: action.payload || {},
|
||||
};
|
||||
},
|
||||
|
||||
[t.CLOSE_DIALOG]: (state, action) => {
|
||||
state.dialogs[action.name] = {
|
||||
...state.dialogs[action.name],
|
||||
isOpen: false,
|
||||
};
|
||||
},
|
||||
|
||||
[t.CLOSE_ALL_DIALOGS]: (state, action) => {
|
||||
|
||||
},
|
||||
|
||||
[t.SET_TOPBAR_EDIT_VIEW]: (state, action) => {
|
||||
state.topbarEditViewId = action.id;
|
||||
}
|
||||
});
|
||||
|
||||
export const getDialogPayload = (state, dialogName) => {
|
||||
return typeof state.dashboard.dialogs[dialogName] !== 'undefined'
|
||||
? state.dashboard.dialogs[dialogName].payload : {};
|
||||
};
|
||||
|
||||
export const getDialogActiveStatus = (state, dialogName) => {
|
||||
return true;
|
||||
};
|
||||
12
client/src/store/dashboard/dashboard.types.js
Normal file
12
client/src/store/dashboard/dashboard.types.js
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
|
||||
|
||||
export default {
|
||||
OPEN_DIALOG: 'OPEN_DIALOG',
|
||||
CLOSE_DIALOG: 'CLOSE_DIALOG',
|
||||
CLOSE_ALL_DIALOGS: 'CLOSE_ALL_DIALOGS',
|
||||
CHANGE_DASHBOARD_PAGE_TITLE: 'CHANGE_DASHBOARD_PAGE_TITLE',
|
||||
CHANGE_PREFERENCES_PAGE_TITLE: 'CHANGE_PREFERENCES_PAGE_TITLE',
|
||||
ALTER_DASHBOARD_PAGE_SUBTITLE: 'ALTER_DASHBOARD_PAGE_SUBTITLE',
|
||||
SET_TOPBAR_EDIT_VIEW: 'SET_TOPBAR_EDIT_VIEW',
|
||||
};
|
||||
41
client/src/store/expenses/expenses.actions.js
Normal file
41
client/src/store/expenses/expenses.actions.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import ApiService from "services/ApiService";
|
||||
import t from 'store/types';
|
||||
|
||||
export const fetchExpensesList = ({ query }) => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.get('expenses').then((response) => {
|
||||
dispatch({
|
||||
type: t.EXPENSES_LIST_SET,
|
||||
expenses: response.data.expenses,
|
||||
});
|
||||
}).catch(error => { reject(error); });
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchExpense = ({ id }) => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.get(`expenses/${id}`).then((response) => {
|
||||
dispatch({
|
||||
type: t.EXPENSE_SET,
|
||||
expense: response.data.expense,
|
||||
});
|
||||
}).catch(error => { reject(error); });
|
||||
});
|
||||
};
|
||||
|
||||
export const submitExpense = ({ form }) => {
|
||||
return (dispatch) => ApiService.post('expenses', { ...form });
|
||||
};
|
||||
|
||||
export const editExpense = ({ form, id }) => {
|
||||
return (dispatch) => ApiService.post(`expensed/${id}`, form);
|
||||
};
|
||||
|
||||
export const deleteExpense = ({ id }) => {
|
||||
return (dispatch) => ApiService.delete(`expenses/${id}`);
|
||||
};
|
||||
|
||||
export const publishExpense = ({ id }) => {
|
||||
return (dispatch) => ApiService.post(`expenses/${id}/publish`);
|
||||
};
|
||||
|
||||
21
client/src/store/expenses/expenses.reducer.js
Normal file
21
client/src/store/expenses/expenses.reducer.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import { createReducer } from '@reduxjs/toolkit';
|
||||
import t from 'store/types';
|
||||
|
||||
const initialState = {
|
||||
list: [],
|
||||
detailsById: {},
|
||||
};
|
||||
|
||||
export default createReducer(initialState, {
|
||||
[t.EXPENSES_LIST_SET]: (state, action) => {
|
||||
state.list = action.expenses;
|
||||
},
|
||||
|
||||
[t.EXPENSE_SET]: (state, action) => {
|
||||
state.detailsById[action.expense.id] = action.expense;
|
||||
},
|
||||
});
|
||||
|
||||
export const getExpenseById = (state, id) => {
|
||||
return state.expenses.detailsById[id];
|
||||
};
|
||||
5
client/src/store/expenses/expenses.types.js
Normal file
5
client/src/store/expenses/expenses.types.js
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
export default {
|
||||
EXPENSES_LIST_SET: 'EXPENSES_LIST_SET',
|
||||
EXPENSE_SET: 'EXPENSE_SET',
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
import ApiService from "services/ApiService";
|
||||
import t from 'store/types';
|
||||
|
||||
export const fetchGeneralLedger = ({ query }) => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.get('/financial_statements/general_ledger').then((response) => {
|
||||
dispatch({
|
||||
type: t.GENERAL_LEDGER_STATEMENT_SET,
|
||||
data: response.data,
|
||||
});
|
||||
resolve(response);
|
||||
}).catch((error) => { reject(error); });
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchBalanceSheet = ({ query }) => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.get('/financial_statements/balance_sheet', { params: query }).then((response) => {
|
||||
dispatch({
|
||||
type: t.BALANCE_SHEET_STATEMENT_SET,
|
||||
data: response.data,
|
||||
});
|
||||
resolve(response);
|
||||
}).catch((error) => { reject(error); });
|
||||
});
|
||||
};
|
||||
@@ -1,12 +1,14 @@
|
||||
import t from 'store/types';
|
||||
import { createReducer } from '@reduxjs/toolkit';
|
||||
import t from 'store/types';
|
||||
|
||||
const initialState = {
|
||||
pageTitle: '',
|
||||
balanceSheet: [],
|
||||
generalLedger: [],
|
||||
trialBalance: [],
|
||||
};
|
||||
|
||||
export default createReducer(initialState, {
|
||||
[t.CHANGE_DASHBOARD_PAGE_TITLE]: (state, action) => {
|
||||
state.pageTitle = action.pageTitle;
|
||||
[t.BALANCE_SHEET_STATEMENT_SET]: (state, action) => {
|
||||
state.balanceSheet.push(action.data);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
export default {
|
||||
GENERAL_LEDGER_STATEMENT_SET: 'GENERAL_LEDGER_STATEMENT_SET',
|
||||
BALANCE_SHEET_STATEMENT_SET: 'BALANCE_SHEET_STATEMENT_SET',
|
||||
}
|
||||
37
client/src/store/items/items.actions.js
Normal file
37
client/src/store/items/items.actions.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import ApiService from "services/ApiService"
|
||||
import t from 'store/types';
|
||||
|
||||
export const submitItem = ({ form }) => {
|
||||
return (dispatch) => ApiService.post(`items`, form);
|
||||
};
|
||||
|
||||
export const editItem = ({ id, form }) => {
|
||||
return (dispatch) => ApiService.post(`items/${id}`, form);
|
||||
};
|
||||
|
||||
export const fetchItems = ({ query }) => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.get(`items`, query).then(response => {
|
||||
dispatch({
|
||||
type: t.ITEMS_LIST_SET,
|
||||
items: response.data.items,
|
||||
});
|
||||
resolve(response);
|
||||
}).catch(error => { reject(error); });
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchItem = ({ id }) => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.get(`items/${id}`).then((response) => {
|
||||
dispatch({
|
||||
type: t.ITEM_SET,
|
||||
item: response.data.item,
|
||||
});
|
||||
}).catch(error => { reject(error); });
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteItem = ({ id }) => {
|
||||
return (dispatch) => ApiService.delete(`items/${id}`);
|
||||
};
|
||||
6
client/src/store/items/items.reducer.js
Normal file
6
client/src/store/items/items.reducer.js
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
const initialState = {
|
||||
list: [],
|
||||
itemById: {},
|
||||
};
|
||||
|
||||
23
client/src/store/localStorage.js
Normal file
23
client/src/store/localStorage.js
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
const LOCAL_STORAGE_NAMESPACE = 'application_state';
|
||||
|
||||
export const loadState = () => {
|
||||
try {
|
||||
const serializedState = localStorage.getItem(LOCAL_STORAGE_NAMESPACE);
|
||||
if (serializedState === null) {
|
||||
return undefined;
|
||||
}
|
||||
return JSON.parse(serializedState);
|
||||
} catch(error) {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
export const saveState = (state) => {
|
||||
try {
|
||||
const serializedState = JSON.stringify(state);
|
||||
localStorage.setItem(LOCAL_STORAGE_NAMESPACE, serializedState);
|
||||
} catch (error) {
|
||||
throw new Error('Something want wrong');
|
||||
}
|
||||
}
|
||||
26
client/src/store/preferences/preferences.actions.js
Normal file
26
client/src/store/preferences/preferences.actions.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import ApiService from "services/ApiService";
|
||||
import t from 'store/types';
|
||||
|
||||
export const savePreferences = ({ options }) => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.post('options', { options }).then((response) => {
|
||||
dispatch({
|
||||
type: t.OPTIONS_SET,
|
||||
options: response.data.options,
|
||||
});
|
||||
resolve(response);
|
||||
}).catch(error => { reject(error); });
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchPreferences = () => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.get('options').then((response) => {
|
||||
dispatch({
|
||||
type: t.OPTIONS.SET,
|
||||
options: response.data.options,
|
||||
});
|
||||
resolve(response);
|
||||
}).catch(error => { reject(error); });
|
||||
})
|
||||
}
|
||||
6
client/src/store/preferences/preferences.types.js
Normal file
6
client/src/store/preferences/preferences.types.js
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
export default {
|
||||
RESOURCE_COLUMNS_SET: 'RESOURCE_COLUMNS_SET',
|
||||
RESOURCE_FIELDS_SET: 'RESOURCE_FIELDS_SET',
|
||||
};
|
||||
25
client/src/store/reducers.js
Normal file
25
client/src/store/reducers.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import { combineReducers } from 'redux';
|
||||
|
||||
import authentication from './authentication/authentication.reducer';
|
||||
import dashboard from './dashboard/dashboard.reducer';
|
||||
import users from './users/users.reducer';
|
||||
import accounts from './accounts/accounts.reducer';
|
||||
import fields from './customFields/customFields.reducer';
|
||||
import views from './customViews/customViews.reducer';
|
||||
import expenses from './expenses/expenses.reducer';
|
||||
import currencies from './currencies/currencies.reducer';
|
||||
import resources from './resources/resources.reducer';
|
||||
import financialStatements from './financialStatement/financialStatements.reducer';
|
||||
|
||||
export default combineReducers({
|
||||
authentication,
|
||||
dashboard,
|
||||
users,
|
||||
accounts,
|
||||
fields,
|
||||
views,
|
||||
expenses,
|
||||
currencies,
|
||||
resources,
|
||||
financialStatements,
|
||||
});
|
||||
@@ -1,20 +0,0 @@
|
||||
import t from 'store/types';
|
||||
|
||||
export default function authentication(state = {}, action) {
|
||||
switch(action.type) {
|
||||
case t.LOGIN_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
token: action.token,
|
||||
}
|
||||
case t.LOGOUT:
|
||||
return {
|
||||
...state,
|
||||
token: '',
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export const isAuthenticated = (state) => !!state.token;
|
||||
@@ -1,12 +0,0 @@
|
||||
import { combineReducers } from 'redux';
|
||||
import authentication from './authentication';
|
||||
import dashboard from './dashboard';
|
||||
// import accounts from './accounts';
|
||||
// import users from './users';
|
||||
|
||||
export default combineReducers({
|
||||
authentication,
|
||||
dashboard,
|
||||
// users,
|
||||
// accounts,
|
||||
});
|
||||
0
client/src/store/resources/resource.types.js
Normal file
0
client/src/store/resources/resource.types.js
Normal file
29
client/src/store/resources/resources.actions.js
Normal file
29
client/src/store/resources/resources.actions.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import ApiService from "services/ApiService";
|
||||
import t from 'store/types';
|
||||
|
||||
export const fetchResourceColumns = ({ resourceSlug }) => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.get(`resources/${resourceSlug}/columns`).then((response) => {
|
||||
console.log(t.RESOURCE_COLUMNS_SET);
|
||||
dispatch({
|
||||
type: t.RESOURCE_COLUMNS_SET,
|
||||
columns: response.data.resource_columns,
|
||||
resource_slug: resourceSlug,
|
||||
});
|
||||
resolve(response);
|
||||
}).catch((error) => { reject(error); });
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchResourceFields = ({ resourceSlug }) => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.get(`resources/${resourceSlug}/fields`).then((response) => {
|
||||
dispatch({
|
||||
type: t.RESOURCE_FIELDS_SET,
|
||||
fields: response.data.resource_fields,
|
||||
resource_slug: resourceSlug,
|
||||
});
|
||||
resolve(response);
|
||||
}).catch((error) => { reject(error); });
|
||||
});
|
||||
};
|
||||
39
client/src/store/resources/resources.reducer.js
Normal file
39
client/src/store/resources/resources.reducer.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import { createReducer } from "@reduxjs/toolkit";
|
||||
import t from 'store/types';
|
||||
|
||||
const initialState = {
|
||||
resourceFields: {
|
||||
// resource name => { field_id }
|
||||
},
|
||||
resourceColumns: {},
|
||||
};
|
||||
|
||||
export default createReducer(initialState, {
|
||||
[t.RESOURCE_COLUMNS_SET]: (state, action) => {
|
||||
state.resourceColumns[action.resource_slug] = action.columns;
|
||||
},
|
||||
|
||||
[t.RESOURCE_FIELDS_SET]: (state, action) => {
|
||||
state.resourceFields[action.resource_slug] = action.fields;
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* Retrieve resource fields of the given resource slug.
|
||||
* @param {Object} state
|
||||
* @param {String} resourceSlug
|
||||
*/
|
||||
export const getResourceFields = (state, resourceSlug) => {
|
||||
const resourceFields = state.resources.resourceFields[resourceSlug];
|
||||
return resourceFields ? Object.values(resourceFields) : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve resource columns of the given resource slug.
|
||||
* @param {State} state
|
||||
* @param {String} resourceSlug -
|
||||
*/
|
||||
export const getResourceColumns = (state, resourceSlug) => {
|
||||
const resourceColumns = state.resources.resourceColumns[resourceSlug];
|
||||
return resourceColumns ? Object.values(resourceColumns) : [];
|
||||
}
|
||||
31
client/src/store/selectors.js
Normal file
31
client/src/store/selectors.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import {pick} from 'lodash';
|
||||
|
||||
export const pickItemsFromIds = (items, ids) => {
|
||||
return Object.values(pick(items, ids));
|
||||
}
|
||||
|
||||
export const getCurrentPageResults = (items, page, name) => {
|
||||
const currentPage = page.pages[page.currentPages[name]]
|
||||
return typeof currentPage == 'undefined' ? [] : Object.values(pick(items || [], currentPage.ids))
|
||||
}
|
||||
|
||||
export const getCurrentTotalResultsCount = (pagination, name) => {
|
||||
const currentPageUrl = pagination.currentPages[name]
|
||||
const currentPage = pagination.pages[currentPageUrl]
|
||||
return typeof currentPageUrl == 'undefined' ? 0 : pagination.params[currentPage.params]
|
||||
}
|
||||
|
||||
export const getAllResults = (items, pagination, name) => {
|
||||
const currentPage = pagination.pages[pagination.currentPages[name]]
|
||||
if (typeof currentPage == 'undefined') {
|
||||
return []
|
||||
}
|
||||
let allPagesKeys = Object.keys(pagination.pages)
|
||||
let allPagesIds = []
|
||||
for (let key of allPagesKeys) {
|
||||
if (pagination.pages[key].params == currentPage.params) {
|
||||
allPagesIds = allPagesIds.concat(pagination.pages[key].ids)
|
||||
}
|
||||
}
|
||||
return Object.values(pick(items || [], allPagesIds))
|
||||
}
|
||||
27
client/src/store/types.js
Normal file
27
client/src/store/types.js
Normal file
@@ -0,0 +1,27 @@
|
||||
import authentication from './authentication/authentication.types';
|
||||
import accounts from './accounts/accounts.types';
|
||||
import currencies from './currencies/currencies.types';
|
||||
import customFields from './customFields/customFields.types';
|
||||
import customViews from './customViews/customViews.types';
|
||||
import dashboard from './dashboard/dashboard.types';
|
||||
import expenses from './expenses/expenses.types';
|
||||
import items from './items/items.types';
|
||||
import preferences from './preferences/preferences.types';
|
||||
import resources from './resources/resource.types';
|
||||
import users from './users/users.types';
|
||||
import financialStatements from './financialStatement/financialStatements.types';
|
||||
|
||||
export default {
|
||||
...authentication,
|
||||
...accounts,
|
||||
...currencies,
|
||||
...customFields,
|
||||
...customViews,
|
||||
...dashboard,
|
||||
...expenses,
|
||||
...items,
|
||||
...preferences,
|
||||
...resources,
|
||||
...users,
|
||||
...financialStatements,
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
|
||||
const ACTION = {
|
||||
CHANGE_DASHBOARD_PAGE_TITLE: 'CHANGE_DASHBOARD_PAGE_TITLE',
|
||||
};
|
||||
|
||||
export default ACTION;
|
||||
@@ -1,7 +0,0 @@
|
||||
import authentication from './authentication';
|
||||
import dashboard from './dashboard';
|
||||
|
||||
export default {
|
||||
...authentication,
|
||||
...dashboard,
|
||||
};
|
||||
46
client/src/store/users/users.actions.js
Normal file
46
client/src/store/users/users.actions.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import ApiService from "services/ApiService";
|
||||
import t from 'store/types';
|
||||
|
||||
export const fetchUsers = () => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.get(`users`).then((response) => {
|
||||
dispatch({
|
||||
type: t.USERS_LIST_SET,
|
||||
users: response.data.users,
|
||||
});
|
||||
resolve(response);
|
||||
}).catch((error) => { reject(error); });
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchUser = ({ id }) => {
|
||||
return (dispatch) => new Promise((resolve, reject) => {
|
||||
ApiService.get(`users/${id}`).then((response) => {
|
||||
dispatch({
|
||||
type: t.USER_DETAILS_SET,
|
||||
user: response.data.user,
|
||||
});
|
||||
resolve(response);
|
||||
}).catch(error => { reject(error); });
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteUser = ({ id }) => {
|
||||
return (dispatch) => ApiService.delete(`users/${id}`);
|
||||
};
|
||||
|
||||
export const submitUser = ({ form }) => {
|
||||
return (dispatch) => ApiService.post(`users`, form);
|
||||
};
|
||||
|
||||
export const editUser = ({ form, id }) => {
|
||||
return (dispatch) => ApiService.post(`users/${id}`, form);
|
||||
};
|
||||
|
||||
export const inactiveUser = ({ id }) => {
|
||||
return (dispatch) => ApiService.post(`users/${id}/inactive`);
|
||||
};
|
||||
|
||||
export const activeUser = ({ id }) => {
|
||||
return (dispatch) => ApiService.post(`users/${id}/active`);
|
||||
}
|
||||
26
client/src/store/users/users.reducer.js
Normal file
26
client/src/store/users/users.reducer.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import { createReducer } from "@reduxjs/toolkit";
|
||||
import t from 'store/types';
|
||||
|
||||
const initialState = {
|
||||
list: {},
|
||||
userById: {},
|
||||
};
|
||||
|
||||
export default createReducer(initialState, {
|
||||
[t.USERS_LIST_SET]: (state, action) => {
|
||||
state.list = action.users;
|
||||
},
|
||||
|
||||
[t.USER_DETAILS_SET]: (state, action) => {
|
||||
state.userById[action.user.id] = action.user;
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* Retrieve the user details of the given user id,
|
||||
* @param {Object} state
|
||||
* @param {Numeric} id
|
||||
*/
|
||||
export const getUserDetails = (state, id) => {
|
||||
return state.users.userById[id];
|
||||
};
|
||||
5
client/src/store/users/users.types.js
Normal file
5
client/src/store/users/users.types.js
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
export default {
|
||||
USERS_LIST_SET: 'USERS_LIST_SET',
|
||||
USER_DETAILS_SET: 'USER_DETAILS_SET',
|
||||
};
|
||||
Reference in New Issue
Block a user