diff options
Diffstat (limited to 'src/store')
-rw-r--r-- | src/store/calendars.js | 17 | ||||
-rw-r--r-- | src/store/devices.js | 36 | ||||
-rw-r--r-- | src/store/drivers.js | 17 | ||||
-rw-r--r-- | src/store/errors.js | 21 | ||||
-rw-r--r-- | src/store/events.js | 23 | ||||
-rw-r--r-- | src/store/geofences.js | 20 | ||||
-rw-r--r-- | src/store/groups.js | 17 | ||||
-rw-r--r-- | src/store/index.js | 42 | ||||
-rw-r--r-- | src/store/maintenances.js | 17 | ||||
-rw-r--r-- | src/store/reports.js | 29 | ||||
-rw-r--r-- | src/store/session.js | 53 | ||||
-rw-r--r-- | src/store/throttleMiddleware.js | 36 |
12 files changed, 328 insertions, 0 deletions
diff --git a/src/store/calendars.js b/src/store/calendars.js new file mode 100644 index 00000000..2d92c004 --- /dev/null +++ b/src/store/calendars.js @@ -0,0 +1,17 @@ +import { createSlice } from '@reduxjs/toolkit'; + +const { reducer, actions } = createSlice({ + name: 'calendars', + initialState: { + items: {}, + }, + reducers: { + refresh(state, action) { + state.items = {}; + action.payload.forEach((item) => state.items[item.id] = item); + }, + }, +}); + +export { actions as calendarsActions }; +export { reducer as calendarsReducer }; diff --git a/src/store/devices.js b/src/store/devices.js new file mode 100644 index 00000000..f2f6263b --- /dev/null +++ b/src/store/devices.js @@ -0,0 +1,36 @@ +import { createSlice } from '@reduxjs/toolkit'; + +const { reducer, actions } = createSlice({ + name: 'devices', + initialState: { + items: {}, + selectedId: null, + selectedIds: [], + }, + reducers: { + refresh(state, action) { + state.items = {}; + action.payload.forEach((item) => state.items[item.id] = item); + }, + update(state, action) { + action.payload.forEach((item) => state.items[item.id] = item); + }, + select(state, action) { + state.selectedId = action.payload; + }, + selectId(state, action) { + state.selectedId = action.payload; + state.selectedIds = state.selectedId ? [state.selectedId] : []; + }, + selectIds(state, action) { + state.selectedIds = action.payload; + [state.selectedId] = state.selectedIds; + }, + remove(state, action) { + delete state.items[action.payload]; + }, + }, +}); + +export { actions as devicesActions }; +export { reducer as devicesReducer }; diff --git a/src/store/drivers.js b/src/store/drivers.js new file mode 100644 index 00000000..d62bd476 --- /dev/null +++ b/src/store/drivers.js @@ -0,0 +1,17 @@ +import { createSlice } from '@reduxjs/toolkit'; + +const { reducer, actions } = createSlice({ + name: 'drivers', + initialState: { + items: {}, + }, + reducers: { + refresh(state, action) { + state.items = {}; + action.payload.forEach((item) => state.items[item.uniqueId] = item); + }, + }, +}); + +export { actions as driversActions }; +export { reducer as driversReducer }; diff --git a/src/store/errors.js b/src/store/errors.js new file mode 100644 index 00000000..a484239a --- /dev/null +++ b/src/store/errors.js @@ -0,0 +1,21 @@ +import { createSlice } from '@reduxjs/toolkit'; + +const { reducer, actions } = createSlice({ + name: 'errors', + initialState: { + errors: [], + }, + reducers: { + push(state, action) { + state.errors.push(action.payload); + }, + pop(state) { + if (state.errors.length) { + state.errors.shift(); + } + }, + }, +}); + +export { actions as errorsActions }; +export { reducer as errorsReducer }; diff --git a/src/store/events.js b/src/store/events.js new file mode 100644 index 00000000..35e7081e --- /dev/null +++ b/src/store/events.js @@ -0,0 +1,23 @@ +import { createSlice } from '@reduxjs/toolkit'; + +const { reducer, actions } = createSlice({ + name: 'events', + initialState: { + items: [], + }, + reducers: { + add(state, action) { + state.items.unshift(...action.payload); + state.items.splice(50); + }, + delete(state, action) { + state.items = state.items.filter((item) => item.id !== action.payload.id); + }, + deleteAll(state) { + state.items = []; + }, + }, +}); + +export { actions as eventsActions }; +export { reducer as eventsReducer }; diff --git a/src/store/geofences.js b/src/store/geofences.js new file mode 100644 index 00000000..f2b7666a --- /dev/null +++ b/src/store/geofences.js @@ -0,0 +1,20 @@ +import { createSlice } from '@reduxjs/toolkit'; + +const { reducer, actions } = createSlice({ + name: 'geofences', + initialState: { + items: {}, + }, + reducers: { + refresh(state, action) { + state.items = {}; + action.payload.forEach((item) => state.items[item.id] = item); + }, + update(state, action) { + action.payload.forEach((item) => state.items[item.id] = item); + }, + }, +}); + +export { actions as geofencesActions }; +export { reducer as geofencesReducer }; diff --git a/src/store/groups.js b/src/store/groups.js new file mode 100644 index 00000000..607b8609 --- /dev/null +++ b/src/store/groups.js @@ -0,0 +1,17 @@ +import { createSlice } from '@reduxjs/toolkit'; + +const { reducer, actions } = createSlice({ + name: 'groups', + initialState: { + items: {}, + }, + reducers: { + refresh(state, action) { + state.items = {}; + action.payload.forEach((item) => state.items[item.id] = item); + }, + }, +}); + +export { actions as groupsActions }; +export { reducer as groupsReducer }; diff --git a/src/store/index.js b/src/store/index.js new file mode 100644 index 00000000..ea685ff3 --- /dev/null +++ b/src/store/index.js @@ -0,0 +1,42 @@ +import { combineReducers, configureStore } from '@reduxjs/toolkit'; + +import { errorsReducer as errors } from './errors'; +import { sessionReducer as session } from './session'; +import { devicesReducer as devices } from './devices'; +import { eventsReducer as events } from './events'; +import { geofencesReducer as geofences } from './geofences'; +import { groupsReducer as groups } from './groups'; +import { driversReducer as drivers } from './drivers'; +import { maintenancesReducer as maintenances } from './maintenances'; +import { calendarsReducer as calendars } from './calendars'; +import { reportsReducer as reports } from './reports'; +import throttleMiddleware from './throttleMiddleware'; + +const reducer = combineReducers({ + errors, + session, + devices, + events, + geofences, + groups, + drivers, + maintenances, + calendars, + reports, +}); + +export { errorsActions } from './errors'; +export { sessionActions } from './session'; +export { devicesActions } from './devices'; +export { eventsActions } from './events'; +export { geofencesActions } from './geofences'; +export { groupsActions } from './groups'; +export { driversActions } from './drivers'; +export { maintenancesActions } from './maintenances'; +export { calendarsActions } from './calendars'; +export { reportsActions } from './reports'; + +export default configureStore({ + reducer, + middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(throttleMiddleware), +}); diff --git a/src/store/maintenances.js b/src/store/maintenances.js new file mode 100644 index 00000000..0f5e41d1 --- /dev/null +++ b/src/store/maintenances.js @@ -0,0 +1,17 @@ +import { createSlice } from '@reduxjs/toolkit'; + +const { reducer, actions } = createSlice({ + name: 'maintenances', + initialState: { + items: {}, + }, + reducers: { + refresh(state, action) { + state.items = {}; + action.payload.forEach((item) => state.items[item.id] = item); + }, + }, +}); + +export { actions as maintenancesActions }; +export { reducer as maintenancesReducer }; diff --git a/src/store/reports.js b/src/store/reports.js new file mode 100644 index 00000000..d0c1f6dd --- /dev/null +++ b/src/store/reports.js @@ -0,0 +1,29 @@ +import { createSlice } from '@reduxjs/toolkit'; +import dayjs from 'dayjs'; + +const { reducer, actions } = createSlice({ + name: 'reports', + initialState: { + groupIds: [], + period: 'today', + from: dayjs().subtract(1, 'hour').locale('en').format('YYYY-MM-DDTHH:mm'), + to: dayjs().locale('en').format('YYYY-MM-DDTHH:mm'), + }, + reducers: { + updateGroupIds(state, action) { + state.groupIds = action.payload; + }, + updatePeriod(state, action) { + state.period = action.payload; + }, + updateFrom(state, action) { + state.from = action.payload; + }, + updateTo(state, action) { + state.to = action.payload; + }, + }, +}); + +export { actions as reportsActions }; +export { reducer as reportsReducer }; diff --git a/src/store/session.js b/src/store/session.js new file mode 100644 index 00000000..bfe94a41 --- /dev/null +++ b/src/store/session.js @@ -0,0 +1,53 @@ +import { createSlice } from '@reduxjs/toolkit'; + +const { reducer, actions } = createSlice({ + name: 'session', + initialState: { + server: null, + user: null, + socket: null, + includeLogs: false, + logs: [], + positions: {}, + history: {}, + }, + reducers: { + updateServer(state, action) { + state.server = action.payload; + }, + updateUser(state, action) { + state.user = action.payload; + }, + updateSocket(state, action) { + state.socket = action.payload; + }, + enableLogs(state, action) { + state.includeLogs = action.payload; + if (!action.payload) { + state.logs = []; + } + }, + updateLogs(state, action) { + state.logs.push(...action.payload); + }, + updatePositions(state, action) { + const liveRoutes = state.user.attributes.mapLiveRoutes || state.server.attributes.mapLiveRoutes || 'none'; + const liveRoutesLimit = state.user.attributes['web.liveRouteLength'] || state.server.attributes['web.liveRouteLength'] || 10; + action.payload.forEach((position) => { + state.positions[position.deviceId] = position; + if (liveRoutes !== 'none') { + const route = state.history[position.deviceId] || []; + const last = route.at(-1); + if (!last || (last[0] !== position.longitude && last[1] !== position.latitude)) { + state.history[position.deviceId] = [...route.slice(1 - liveRoutesLimit), [position.longitude, position.latitude]]; + } + } else { + state.history = {}; + } + }); + }, + }, +}); + +export { actions as sessionActions }; +export { reducer as sessionReducer }; diff --git a/src/store/throttleMiddleware.js b/src/store/throttleMiddleware.js new file mode 100644 index 00000000..d5a98add --- /dev/null +++ b/src/store/throttleMiddleware.js @@ -0,0 +1,36 @@ +import { batch } from 'react-redux'; + +const threshold = 3; +const interval = 1500; + +export default () => (next) => { + const buffer = []; + let throttle = false; + let counter = 0; + + setInterval(() => { + if (throttle) { + if (buffer.length < threshold) { + throttle = false; + } + batch(() => buffer.splice(0, buffer.length).forEach((action) => next(action))); + } else { + if (counter > threshold) { + throttle = true; + } + counter = 0; + } + }, interval); + + return (action) => { + if (action.type === 'devices/update' || action.type === 'positions/update') { + if (throttle) { + buffer.push(action); + return null; + } + counter += 1; + return next(action); + } + return next(action); + }; +}; |