This commit is contained in:
Ahmed Bouhuolia
2020-03-16 00:06:15 +02:00
parent 56701951b7
commit 73711384f6
7925 changed files with 18478 additions and 959 deletions

View 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); });
});
}

View File

@@ -0,0 +1,5 @@
export default {
MAKE_JOURNAL_ENTRIES: 'MAKE_JOURNAL_ENTRIES',
}

View 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); });
});
}

View 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];
};

View 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) || []) : [];
}

View 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',
};

View File

@@ -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,
});
}
});
}
}

View 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);
});
});
}
}

View 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);
};

View File

@@ -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',
};

View File

@@ -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();

View 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); });
});
};

View 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;
},
});

View File

@@ -0,0 +1,5 @@
export default {
CURRENCIES_REGISTERED_SET: 'CURRENCIES_REGISTERED_SET',
CURRENCIES_ALL_SET: 'CURRENCIES_ALL_SET',
};

View 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); });
});
}

View 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];
}

View File

@@ -0,0 +1,4 @@
export default {
CUSTOM_FIELDS_RESOURCE_SET: 'CUSTOM_FIELDS_RESOURCE_SET',
};

View 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); });
});
};

View 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 };
},
})

View 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] || {};
};

View 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',
};

View 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,
}
}

View 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;
};

View 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',
};

View 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`);
};

View 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];
};

View File

@@ -0,0 +1,5 @@
export default {
EXPENSES_LIST_SET: 'EXPENSES_LIST_SET',
EXPENSE_SET: 'EXPENSE_SET',
};

View File

@@ -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); });
});
};

View File

@@ -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);
},
});

View File

@@ -0,0 +1,6 @@
export default {
GENERAL_LEDGER_STATEMENT_SET: 'GENERAL_LEDGER_STATEMENT_SET',
BALANCE_SHEET_STATEMENT_SET: 'BALANCE_SHEET_STATEMENT_SET',
}

View 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}`);
};

View File

@@ -0,0 +1,6 @@
const initialState = {
list: [],
itemById: {},
};

View 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');
}
}

View 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); });
})
}

View File

@@ -0,0 +1,6 @@
export default {
RESOURCE_COLUMNS_SET: 'RESOURCE_COLUMNS_SET',
RESOURCE_FIELDS_SET: 'RESOURCE_FIELDS_SET',
};

View 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,
});

View File

@@ -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;

View File

@@ -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,
});

View 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); });
});
};

View 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) : [];
}

View 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
View 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,
}

View File

@@ -1,6 +0,0 @@
const ACTION = {
CHANGE_DASHBOARD_PAGE_TITLE: 'CHANGE_DASHBOARD_PAGE_TITLE',
};
export default ACTION;

View File

@@ -1,7 +0,0 @@
import authentication from './authentication';
import dashboard from './dashboard';
export default {
...authentication,
...dashboard,
};

View 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`);
}

View 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];
};

View File

@@ -0,0 +1,5 @@
export default {
USERS_LIST_SET: 'USERS_LIST_SET',
USER_DETAILS_SET: 'USER_DETAILS_SET',
};