first commit
This commit is contained in:
10
ui/src/state/helpers.js
Normal file
10
ui/src/state/helpers.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { mapState, mapGetters, mapActions } from 'vuex'
|
||||
|
||||
export const authComputed = {
|
||||
...mapState('auth', {
|
||||
currentUser: (state) => state.currentUser,
|
||||
}),
|
||||
...mapGetters('auth', ['loggedIn']),
|
||||
}
|
||||
|
||||
export const authMethods = mapActions('auth', ['logIn', 'logOut'])
|
||||
95
ui/src/state/modules/auth.js
Normal file
95
ui/src/state/modules/auth.js
Normal file
@@ -0,0 +1,95 @@
|
||||
import axios from 'axios'
|
||||
|
||||
export const state = {
|
||||
currentUser: getSavedState('auth.currentUser'),
|
||||
initialized: getSavedState('system.initialized'),
|
||||
}
|
||||
|
||||
export const mutations = {
|
||||
SET_CURRENT_USER(state, newValue) {
|
||||
state.currentUser = newValue
|
||||
saveState('auth.currentUser', newValue)
|
||||
setDefaultAuthHeaders(state)
|
||||
},
|
||||
SET_INITIALIZATION_STATUS(state, newValue) {
|
||||
state.initialized = newValue
|
||||
saveState('system.initialized', newValue)
|
||||
},
|
||||
}
|
||||
|
||||
export const getters = {
|
||||
// Whether the user is currently logged in.
|
||||
loggedIn(state) {
|
||||
return !!state.currentUser
|
||||
},
|
||||
isInitialized(state) {
|
||||
return state.initialized == null || state.initialized.initialized
|
||||
},
|
||||
}
|
||||
|
||||
export const actions = {
|
||||
// This is automatically run in `src/state/store.js` when the app
|
||||
// starts, along with any other actions named `init` in other modules.
|
||||
init({ state, dispatch }) {
|
||||
dispatch('systemInitialized')
|
||||
setDefaultAuthHeaders(state)
|
||||
dispatch('validate')
|
||||
},
|
||||
|
||||
logIn({ commit, dispatch, getters }, { username, password } = {}) {
|
||||
if (getters.loggedIn) return dispatch('validate')
|
||||
|
||||
return axios.post('/api/login', { email: username, password }).then((response) => {
|
||||
const user = response.data
|
||||
commit('SET_CURRENT_USER', user)
|
||||
dispatch('vehicles/fetchMasters', null, { root: true })
|
||||
return user
|
||||
})
|
||||
},
|
||||
|
||||
// Logs out the current user.
|
||||
logOut({ commit }) {
|
||||
commit('SET_CURRENT_USER', null)
|
||||
},
|
||||
|
||||
// Validates the current user's token and refreshes it
|
||||
// with new data from the API.
|
||||
validate({ commit, state }) {
|
||||
if (!state.currentUser) return Promise.resolve(null)
|
||||
|
||||
return axios
|
||||
.post('/api/refresh', { refreshToken: state.currentUser.refreshToken })
|
||||
.then((response) => {
|
||||
const user = response.data
|
||||
commit('SET_CURRENT_USER', user)
|
||||
return user
|
||||
})
|
||||
.catch((ex) => {
|
||||
commit('SET_CURRENT_USER', null)
|
||||
})
|
||||
},
|
||||
|
||||
systemInitialized({ commit, state }) {
|
||||
return axios.get('/api/system/status').then((response) => {
|
||||
const data = response.data
|
||||
commit('SET_INITIALIZATION_STATUS', data)
|
||||
return data
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
// ===
|
||||
// Private helpers
|
||||
// ===
|
||||
|
||||
function getSavedState(key) {
|
||||
return JSON.parse(window.localStorage.getItem(key))
|
||||
}
|
||||
|
||||
function saveState(key, state) {
|
||||
window.localStorage.setItem(key, JSON.stringify(state))
|
||||
}
|
||||
|
||||
function setDefaultAuthHeaders(state) {
|
||||
axios.defaults.headers.common.Authorization = state.currentUser ? state.currentUser.token : ''
|
||||
}
|
||||
121
ui/src/state/modules/auth.unit.js
Normal file
121
ui/src/state/modules/auth.unit.js
Normal file
@@ -0,0 +1,121 @@
|
||||
import axios from 'axios'
|
||||
import * as authModule from './auth'
|
||||
|
||||
describe('@state/modules/auth', () => {
|
||||
it('exports a valid Vuex module', () => {
|
||||
expect(authModule).toBeAVuexModule()
|
||||
})
|
||||
|
||||
describe('in a store', () => {
|
||||
let store
|
||||
beforeEach(() => {
|
||||
store = createModuleStore(authModule)
|
||||
window.localStorage.clear()
|
||||
})
|
||||
|
||||
it('mutations.SET_CURRENT_USER correctly sets axios default authorization header', () => {
|
||||
axios.defaults.headers.common.Authorization = ''
|
||||
|
||||
store.commit('SET_CURRENT_USER', { token: 'some-token' })
|
||||
expect(axios.defaults.headers.common.Authorization).toEqual('some-token')
|
||||
|
||||
store.commit('SET_CURRENT_USER', null)
|
||||
expect(axios.defaults.headers.common.Authorization).toEqual('')
|
||||
})
|
||||
|
||||
it('mutations.SET_CURRENT_USER correctly saves currentUser in localStorage', () => {
|
||||
let savedCurrentUser = JSON.parse(
|
||||
window.localStorage.getItem('auth.currentUser')
|
||||
)
|
||||
expect(savedCurrentUser).toEqual(null)
|
||||
|
||||
const expectedCurrentUser = { token: 'some-token' }
|
||||
store.commit('SET_CURRENT_USER', expectedCurrentUser)
|
||||
|
||||
savedCurrentUser = JSON.parse(
|
||||
window.localStorage.getItem('auth.currentUser')
|
||||
)
|
||||
expect(savedCurrentUser).toEqual(expectedCurrentUser)
|
||||
})
|
||||
|
||||
it('getters.loggedIn returns true when currentUser is an object', () => {
|
||||
store.commit('SET_CURRENT_USER', {})
|
||||
expect(store.getters.loggedIn).toEqual(true)
|
||||
})
|
||||
|
||||
it('getters.loggedIn returns false when currentUser is null', () => {
|
||||
store.commit('SET_CURRENT_USER', null)
|
||||
expect(store.getters.loggedIn).toEqual(false)
|
||||
})
|
||||
|
||||
it('actions.logIn resolves to a refreshed currentUser when already logged in', () => {
|
||||
expect.assertions(2)
|
||||
|
||||
store.commit('SET_CURRENT_USER', { token: validUserExample.token })
|
||||
return store.dispatch('logIn').then((user) => {
|
||||
expect(user).toEqual(validUserExample)
|
||||
expect(store.state.currentUser).toEqual(validUserExample)
|
||||
})
|
||||
})
|
||||
|
||||
it('actions.logIn commits the currentUser and resolves to the user when NOT already logged in and provided a correct username and password', () => {
|
||||
expect.assertions(2)
|
||||
|
||||
return store
|
||||
.dispatch('logIn', { username: 'admin', password: 'password' })
|
||||
.then((user) => {
|
||||
expect(user).toEqual(validUserExample)
|
||||
expect(store.state.currentUser).toEqual(validUserExample)
|
||||
})
|
||||
})
|
||||
|
||||
it('actions.logIn rejects with 401 when NOT already logged in and provided an incorrect username and password', () => {
|
||||
expect.assertions(1)
|
||||
|
||||
return store
|
||||
.dispatch('logIn', {
|
||||
username: 'bad username',
|
||||
password: 'bad password',
|
||||
})
|
||||
.catch((error) => {
|
||||
expect(error.message).toEqual('Request failed with status code 401')
|
||||
})
|
||||
})
|
||||
|
||||
it('actions.validate resolves to null when currentUser is null', () => {
|
||||
expect.assertions(1)
|
||||
|
||||
store.commit('SET_CURRENT_USER', null)
|
||||
return store.dispatch('validate').then((user) => {
|
||||
expect(user).toEqual(null)
|
||||
})
|
||||
})
|
||||
|
||||
it('actions.validate resolves to null when currentUser contains an invalid token', () => {
|
||||
expect.assertions(2)
|
||||
|
||||
store.commit('SET_CURRENT_USER', { token: 'invalid-token' })
|
||||
return store.dispatch('validate').then((user) => {
|
||||
expect(user).toEqual(null)
|
||||
expect(store.state.currentUser).toEqual(null)
|
||||
})
|
||||
})
|
||||
|
||||
it('actions.validate resolves to a user when currentUser contains a valid token', () => {
|
||||
expect.assertions(2)
|
||||
|
||||
store.commit('SET_CURRENT_USER', { token: validUserExample.token })
|
||||
return store.dispatch('validate').then((user) => {
|
||||
expect(user).toEqual(validUserExample)
|
||||
expect(store.state.currentUser).toEqual(validUserExample)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const validUserExample = {
|
||||
id: 1,
|
||||
username: 'admin',
|
||||
name: 'Vue Master',
|
||||
token: 'valid-token-for-admin',
|
||||
}
|
||||
81
ui/src/state/modules/index.js
Normal file
81
ui/src/state/modules/index.js
Normal file
@@ -0,0 +1,81 @@
|
||||
// Register each file as a corresponding Vuex module. Module nesting
|
||||
// will mirror [sub-]directory hierarchy and modules are namespaced
|
||||
// as the camelCase equivalent of their file name.
|
||||
|
||||
import camelCase from 'lodash/camelCase'
|
||||
|
||||
const modulesCache = {}
|
||||
const storeData = { modules: {} }
|
||||
|
||||
;(function updateModules() {
|
||||
// Allow us to dynamically require all Vuex module files.
|
||||
// https://webpack.js.org/guides/dependency-management/#require-context
|
||||
const requireModule = require.context(
|
||||
// Search for files in the current directory.
|
||||
'.',
|
||||
// Search for files in subdirectories.
|
||||
true,
|
||||
// Include any .js files that are not this file or a unit test.
|
||||
/^((?!index|\.unit\.).)*\.js$/
|
||||
)
|
||||
|
||||
// For every Vuex module...
|
||||
requireModule.keys().forEach((fileName) => {
|
||||
const moduleDefinition =
|
||||
requireModule(fileName).default || requireModule(fileName)
|
||||
|
||||
// Skip the module during hot reload if it refers to the
|
||||
// same module definition as the one we have cached.
|
||||
if (modulesCache[fileName] === moduleDefinition) return
|
||||
|
||||
// Update the module cache, for efficient hot reloading.
|
||||
modulesCache[fileName] = moduleDefinition
|
||||
|
||||
// Get the module path as an array.
|
||||
const modulePath = fileName
|
||||
// Remove the "./" from the beginning.
|
||||
.replace(/^\.\//, '')
|
||||
// Remove the file extension from the end.
|
||||
.replace(/\.\w+$/, '')
|
||||
// Split nested modules into an array path.
|
||||
.split(/\//)
|
||||
// camelCase all module namespaces and names.
|
||||
.map(camelCase)
|
||||
|
||||
// Get the modules object for the current path.
|
||||
const { modules } = getNamespace(storeData, modulePath)
|
||||
|
||||
// Add the module to our modules object.
|
||||
modules[modulePath.pop()] = {
|
||||
// Modules are namespaced by default.
|
||||
namespaced: true,
|
||||
...moduleDefinition,
|
||||
}
|
||||
})
|
||||
|
||||
// If the environment supports hot reloading...
|
||||
if (module.hot) {
|
||||
// Whenever any Vuex module is updated...
|
||||
module.hot.accept(requireModule.id, () => {
|
||||
// Update `storeData.modules` with the latest definitions.
|
||||
updateModules()
|
||||
// Trigger a hot update in the store.
|
||||
require('../store').default.hotUpdate({ modules: storeData.modules })
|
||||
})
|
||||
}
|
||||
})()
|
||||
|
||||
// Recursively get the namespace of a Vuex module, even if nested.
|
||||
function getNamespace(subtree, path) {
|
||||
if (path.length === 1) return subtree
|
||||
|
||||
const namespace = path.shift()
|
||||
subtree.modules[namespace] = {
|
||||
modules: {},
|
||||
namespaced: true,
|
||||
...subtree.modules[namespace],
|
||||
}
|
||||
return getNamespace(subtree.modules[namespace], path)
|
||||
}
|
||||
|
||||
export default storeData.modules
|
||||
88
ui/src/state/modules/users.js
Normal file
88
ui/src/state/modules/users.js
Normal file
@@ -0,0 +1,88 @@
|
||||
import axios from 'axios'
|
||||
|
||||
export const state = {
|
||||
cached: [],
|
||||
me: null,
|
||||
}
|
||||
|
||||
export const getters = {}
|
||||
|
||||
export const mutations = {
|
||||
CACHE_USER(state, newUser) {
|
||||
state.cached.push(newUser)
|
||||
},
|
||||
CACHE_MY_USER(state, newUser) {
|
||||
state.me = newUser
|
||||
},
|
||||
}
|
||||
|
||||
export const actions = {
|
||||
init({ dispatch, rootState }) {
|
||||
const { currentUser } = rootState.auth
|
||||
if (currentUser != null) {
|
||||
dispatch('me')
|
||||
}
|
||||
},
|
||||
forceMe({ commit, state }) {
|
||||
return axios
|
||||
.get('/api/me')
|
||||
.then((response) => {
|
||||
commit('CACHE_MY_USER', response.data)
|
||||
return response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error.response && error.response.status === 401) {
|
||||
commit('CACHE_MY_USER', null)
|
||||
} else {
|
||||
console.warn(error)
|
||||
}
|
||||
return null
|
||||
})
|
||||
},
|
||||
users() {
|
||||
return axios
|
||||
.get('/api/users')
|
||||
.then((response) => {
|
||||
return response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error.response && error.response.status === 401) {
|
||||
} else {
|
||||
console.warn(error)
|
||||
}
|
||||
return null
|
||||
})
|
||||
},
|
||||
me({ commit, state }) {
|
||||
if (state.me) {
|
||||
return Promise.resolve(state.me)
|
||||
}
|
||||
return axios
|
||||
.get('/api/me')
|
||||
.then((response) => {
|
||||
commit('CACHE_MY_USER', response.data)
|
||||
return response.data
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error.response && error.response.status === 401) {
|
||||
commit('CACHE_MY_USER', null)
|
||||
} else {
|
||||
console.warn(error)
|
||||
}
|
||||
return null
|
||||
})
|
||||
},
|
||||
fetchUser({ commit, state, rootState }, { username }) {
|
||||
// 1. Check if we already have the user as a current user.
|
||||
const { currentUser } = rootState.auth
|
||||
if (currentUser && currentUser.username === username) {
|
||||
return Promise.resolve(currentUser)
|
||||
}
|
||||
|
||||
// 2. Check if we've already fetched and cached the user.
|
||||
const matchedUser = state.cached.find((user) => user.username === username)
|
||||
if (matchedUser) {
|
||||
return Promise.resolve(matchedUser)
|
||||
}
|
||||
},
|
||||
}
|
||||
64
ui/src/state/modules/users.unit.js
Normal file
64
ui/src/state/modules/users.unit.js
Normal file
@@ -0,0 +1,64 @@
|
||||
import * as usersModule from './users'
|
||||
|
||||
describe('@state/modules/users', () => {
|
||||
it('exports a valid Vuex module', () => {
|
||||
expect(usersModule).toBeAVuexModule()
|
||||
})
|
||||
|
||||
describe('in a store when logged in', () => {
|
||||
let store
|
||||
beforeEach(() => {
|
||||
store = createModuleStore(usersModule, {
|
||||
currentUser: validUserExample,
|
||||
})
|
||||
})
|
||||
|
||||
it('actions.fetchUser returns the current user without fetching it again', () => {
|
||||
expect.assertions(2)
|
||||
|
||||
const axios = require('axios')
|
||||
const originalAxiosGet = axios.get
|
||||
axios.get = jest.fn()
|
||||
|
||||
return store.dispatch('fetchUser', { username: 'admin' }).then((user) => {
|
||||
expect(user).toEqual(validUserExample)
|
||||
expect(axios.get).not.toHaveBeenCalled()
|
||||
axios.get = originalAxiosGet
|
||||
})
|
||||
})
|
||||
|
||||
it('actions.fetchUser rejects with 400 when provided a bad username', () => {
|
||||
expect.assertions(1)
|
||||
|
||||
return store
|
||||
.dispatch('fetchUser', { username: 'bad-username' })
|
||||
.catch((error) => {
|
||||
expect(error.response.status).toEqual(400)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('in a store when logged out', () => {
|
||||
let store
|
||||
beforeEach(() => {
|
||||
store = createModuleStore(usersModule)
|
||||
})
|
||||
|
||||
it('actions.fetchUser rejects with 401', () => {
|
||||
expect.assertions(1)
|
||||
|
||||
return store
|
||||
.dispatch('fetchUser', { username: 'admin' })
|
||||
.catch((error) => {
|
||||
expect(error.response.status).toEqual(401)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const validUserExample = {
|
||||
id: 1,
|
||||
username: 'admin',
|
||||
name: 'Vue Master',
|
||||
token: 'valid-token-for-admin',
|
||||
}
|
||||
49
ui/src/state/modules/utils.js
Normal file
49
ui/src/state/modules/utils.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import axios from 'axios'
|
||||
|
||||
export const state = {
|
||||
isMobile: false,
|
||||
settings: null,
|
||||
}
|
||||
export const mutations = {
|
||||
CACHE_ISMOBILE(state, isMobile) {
|
||||
state.isMobile = isMobile
|
||||
},
|
||||
CACHE_SETTINGS(state, settings) {
|
||||
state.settings = settings
|
||||
},
|
||||
}
|
||||
export const getters = {}
|
||||
export const actions = {
|
||||
init({ dispatch, rootState }) {
|
||||
dispatch('checkSize')
|
||||
const { currentUser } = rootState.auth
|
||||
if (currentUser) {
|
||||
dispatch('getSettings')
|
||||
}
|
||||
},
|
||||
checkSize({ commit }) {
|
||||
commit('CACHE_ISMOBILE', window.innerWidth < 600)
|
||||
return window.innerWidth < 600
|
||||
},
|
||||
getSettings({ commit }) {
|
||||
return axios.get(`/api/settings`).then((response) => {
|
||||
const data = response.data
|
||||
commit('CACHE_SETTINGS', data)
|
||||
return data
|
||||
})
|
||||
},
|
||||
saveSettings({ commit, dispatch }, { settings }) {
|
||||
return axios.post(`/api/settings`, { ...settings }).then((response) => {
|
||||
const data = response.data
|
||||
dispatch('getSettings')
|
||||
return data
|
||||
})
|
||||
},
|
||||
saveUserSettings({ commit, dispatch }, { settings }) {
|
||||
return axios.post(`/api/me/settings`, { ...settings }).then((response) => {
|
||||
const data = response.data
|
||||
dispatch('users/forceMe', {}, { root: true }).then((data) => {})
|
||||
return data
|
||||
})
|
||||
},
|
||||
}
|
||||
150
ui/src/state/modules/vehicles.js
Normal file
150
ui/src/state/modules/vehicles.js
Normal file
@@ -0,0 +1,150 @@
|
||||
import axios from 'axios'
|
||||
import { filter } from 'lodash'
|
||||
|
||||
import parseISO from 'date-fns/parseISO'
|
||||
export const state = {
|
||||
vehicles: [],
|
||||
roleMasters: [],
|
||||
fuelUnitMasters: [],
|
||||
distanceUnitMasters: [],
|
||||
currencyMasters: [],
|
||||
fuelTypeMasters: [],
|
||||
quickEntries: [],
|
||||
vehicleStats: new Map(),
|
||||
}
|
||||
|
||||
export const getters = {
|
||||
unprocessedQuickEntries: (state) => {
|
||||
return filter(state.quickEntries, (o) => o.processDate == null)
|
||||
},
|
||||
processedQuickEntries: (state) => {
|
||||
return filter(state.quickEntries, (o) => o.processDate != null)
|
||||
},
|
||||
}
|
||||
|
||||
export const mutations = {
|
||||
CACHE_VEHICLE(state, newVehicles) {
|
||||
state.vehicles = newVehicles
|
||||
},
|
||||
CACHE_VEHICLE_STATS(state, stats) {
|
||||
state.vehicleStats.set(stats.vehicleId, stats)
|
||||
},
|
||||
CACHE_FUEL_UNIT_MASTERS(state, masters) {
|
||||
state.fuelUnitMasters = masters
|
||||
},
|
||||
CACHE_DISTANCE_UNIT_MASTERS(state, masters) {
|
||||
state.distanceUnitMasters = masters
|
||||
},
|
||||
CACHE_FUEL_TYPE_MASTERS(state, masters) {
|
||||
state.fuelTypeMasters = masters
|
||||
},
|
||||
CACHE_CURRENCY_MASTERS(state, masters) {
|
||||
state.currencyMasters = masters
|
||||
},
|
||||
CACHE_QUICK_ENTRIES(state, entries) {
|
||||
state.quickEntries = entries
|
||||
},
|
||||
CACHE_ROLE_MASTERS(state, roles) {
|
||||
state.roleMasters = roles
|
||||
},
|
||||
}
|
||||
|
||||
export const actions = {
|
||||
init({ dispatch, rootState }) {
|
||||
const { currentUser } = rootState.auth
|
||||
if (currentUser) {
|
||||
dispatch('fetchVehicles')
|
||||
dispatch('fetchMasters')
|
||||
dispatch('fetchQuickEntries', { force: true })
|
||||
}
|
||||
},
|
||||
fetchMasters({ commit, state, rootState }) {
|
||||
return axios.get('/api/masters').then((response) => {
|
||||
const fuelUnitMasters = response.data.fuelUnits
|
||||
const fuelTypeMasters = response.data.fuelTypes
|
||||
commit('CACHE_FUEL_UNIT_MASTERS', fuelUnitMasters)
|
||||
commit('CACHE_FUEL_TYPE_MASTERS', fuelTypeMasters)
|
||||
commit('CACHE_CURRENCY_MASTERS', response.data.currencies)
|
||||
commit('CACHE_DISTANCE_UNIT_MASTERS', response.data.distanceUnits)
|
||||
commit('CACHE_ROLE_MASTERS', response.data.roles)
|
||||
return response.data
|
||||
})
|
||||
},
|
||||
fetchVehicles({ commit, state, rootState }) {
|
||||
return axios.get('/api/me/vehicles').then((response) => {
|
||||
const data = response.data
|
||||
commit('CACHE_VEHICLE', data)
|
||||
return data
|
||||
})
|
||||
},
|
||||
fetchQuickEntries({ commit, state, rootState }, { force }) {
|
||||
if (state.quickEntries && !force) {
|
||||
return Promise.resolve(state.quickEntries)
|
||||
}
|
||||
return axios.get('/api/me/quickEntries').then((response) => {
|
||||
const data = response.data
|
||||
commit('CACHE_QUICK_ENTRIES', data)
|
||||
return data
|
||||
})
|
||||
},
|
||||
fetchVehicleById({ commit, state, rootState }, { vehicleId }) {
|
||||
const matchedVehicle = state.vehicles.find((vehicle) => vehicle.id === vehicleId)
|
||||
if (matchedVehicle) {
|
||||
return Promise.resolve(matchedVehicle)
|
||||
}
|
||||
return axios.get('/api/vehicles/' + vehicleId).then((response) => {
|
||||
const data = response.data
|
||||
// commit('CACHE_VEHICLE', data)
|
||||
return data
|
||||
})
|
||||
},
|
||||
fetchFillupById({ commit, state, rootState }, { vehicleId, fillupId }) {
|
||||
return axios.get(`/api/vehicles/${vehicleId}/fillups/${fillupId}`).then((response) => {
|
||||
const data = response.data
|
||||
data.date = parseISO(data.date)
|
||||
return data
|
||||
})
|
||||
},
|
||||
fetchExpenseById({ commit, state, rootState }, { vehicleId, expenseId }) {
|
||||
return axios.get(`/api/vehicles/${vehicleId}/expenses/${expenseId}`).then((response) => {
|
||||
const data = response.data
|
||||
data.date = parseISO(data.date)
|
||||
return data
|
||||
})
|
||||
},
|
||||
fetchAttachmentsByVehicleId({ commit, state, rootState }, { vehicleId }) {
|
||||
return axios.get(`/api/vehicles/${vehicleId}/attachments`).then((response) => {
|
||||
const data = response.data
|
||||
|
||||
return data
|
||||
})
|
||||
},
|
||||
fetchUsersByVehicleId({ commit, state, rootState }, { vehicleId, force }) {
|
||||
return axios.get(`/api/vehicles/${vehicleId}/users`).then((response) => {
|
||||
const data = response.data
|
||||
// data.vehicleId = vehicleId
|
||||
// commit('CACHE_VEHICLE_STATS', data)
|
||||
|
||||
return data
|
||||
})
|
||||
},
|
||||
fetchStatsByVehicleId({ commit, state, rootState }, { vehicleId, force }) {
|
||||
if (state.vehicleStats.has(vehicleId) && !force) {
|
||||
return Promise.resolve(state.vehicleStats.get(vehicleId))
|
||||
}
|
||||
return axios.get(`/api/vehicles/${vehicleId}/stats`).then((response) => {
|
||||
const data = response.data
|
||||
data.vehicleId = vehicleId
|
||||
commit('CACHE_VEHICLE_STATS', data)
|
||||
|
||||
return data
|
||||
})
|
||||
},
|
||||
setQuickEntryAsProcessed({ commit, state, rootState, dispatch }, { id }) {
|
||||
return axios.post(`/api/quickEntries/${id}/process`, {}).then((response) => {
|
||||
const data = response.data
|
||||
dispatch('fetchQuickEntries', { force: true })
|
||||
return data
|
||||
})
|
||||
},
|
||||
}
|
||||
21
ui/src/state/store.js
Normal file
21
ui/src/state/store.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import dispatchActionForAllModules from '@utils/dispatch-action-for-all-modules'
|
||||
|
||||
import modules from './modules'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
const store = new Vuex.Store({
|
||||
modules,
|
||||
// Enable strict mode in development to get a warning
|
||||
// when mutating state outside of a mutation.
|
||||
// https://vuex.vuejs.org/guide/strict.html
|
||||
strict: process.env.NODE_ENV !== 'production',
|
||||
})
|
||||
|
||||
export default store
|
||||
|
||||
// Automatically run the `init` action for every module,
|
||||
// if one exists.
|
||||
dispatchActionForAllModules('init')
|
||||
Reference in New Issue
Block a user