- Complete GGZ Ecademy Nuxt.js user portal - Learning products browser and management - Member management interface - User authentication and roles - Multi-language support (NL/EN) - Vuex store for state management - Component-based architecture
This commit is contained in:
43
store/columnBrowser.js
Normal file
43
store/columnBrowser.js
Normal file
@@ -0,0 +1,43 @@
|
||||
export const state = () => ({
|
||||
page: 1,
|
||||
resultsPerPage: 3,
|
||||
});
|
||||
|
||||
|
||||
export const getters = {
|
||||
|
||||
dataset: (state, rootGetters, rootState) => rootState.learning.columnsSorted.filter(el => el.display && !el.fixed),
|
||||
|
||||
firstEntry: (state) => (state.page - 1) * state.resultsPerPage,
|
||||
lastEntry: (state, getters) => getters.firstEntry + state.resultsPerPage,
|
||||
|
||||
subset: (state, getters) => getters.dataset.slice(getters.firstEntry, getters.lastEntry),
|
||||
|
||||
isFirstPage: (state) => state.page === 1,
|
||||
isLastPage: (state, getters) => state.page === getters.totalPages,
|
||||
totalPages: (state, getters) => Math.ceil(getters.dataset.length / state.resultsPerPage) || 1,
|
||||
|
||||
}
|
||||
|
||||
export const actions = {
|
||||
|
||||
async changePage({ commit, state, getters }, direction) {
|
||||
|
||||
if (!['previous', 'next'].includes(direction)) return
|
||||
|
||||
const currentPage = state.page
|
||||
|
||||
let newPage;
|
||||
|
||||
if ((direction === 'next') && !getters.isLastPage) newPage = currentPage + 1
|
||||
if ((direction === 'previous') && !getters.isFirstPage) newPage = currentPage - 1
|
||||
|
||||
|
||||
await commit('SET_PAGE', newPage);
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
export const mutations = {
|
||||
SET_PAGE: (state, page) => state.page = +page,
|
||||
}
|
||||
176
store/index.js
Normal file
176
store/index.js
Normal file
@@ -0,0 +1,176 @@
|
||||
import Util from '@/util'
|
||||
|
||||
export const getters = {
|
||||
loggedInUser: (state) => state.auth.user,
|
||||
learningProducts: (state) => state.learning.products,
|
||||
learningProductsActive: (state, getters) => {
|
||||
getters.learningProducts.filter((p) => !p.deleted_at)
|
||||
},
|
||||
hasLearningProducts: (state, getters) => getters.learningProducts.length > 0,
|
||||
|
||||
searchOverlay: (state) => state.navigation.searchOverlay,
|
||||
snackbar: (state) => state.snackbar,
|
||||
rightDrawer: (state) => state.navigation.rightDrawer,
|
||||
|
||||
isSuperAdmin: (state) =>
|
||||
state.auth.user.roles.some((r) => r.name === 'super_admin'),
|
||||
isAdmin: (state) => state.auth.user.roles.some((r) => r.name === 'admin'),
|
||||
isSuperAdminOrAdmin: (state, getters) =>
|
||||
getters.isSuperAdmin || getters.isAdmin,
|
||||
isOperator: (state) =>
|
||||
state.auth.user.roles.some((r) => r.name === 'operator'),
|
||||
isUser: (state) => state.auth.user.roles.some((r) => r.name === 'user'),
|
||||
isMember: (state) => state.auth.user.isMemberEditor || false,
|
||||
hasCharges: (state, getters) =>
|
||||
getters.isSuperAdmin || getters.isAdmin || getters.isOperator,
|
||||
isOnlyMemberEditor: (state, getters) =>
|
||||
!getters.hasCharges && getters.isMember,
|
||||
|
||||
notifications: (state) => state.auth.user.notifications,
|
||||
unreadNotifications: (state) =>
|
||||
state.auth.user.notifications.filter((n) => !n.read_at),
|
||||
readNotifications: (state) =>
|
||||
state.auth.user.notifications.filter((n) => n.read_at),
|
||||
hasNotifications: (state) => state.auth.user.notifications.length > 0,
|
||||
hasUnreadNotifications: (state, getters) =>
|
||||
getters.unreadNotifications.length > 0,
|
||||
isReadNotification: (state, getters) => (notificationId) => {
|
||||
if (!notificationId) return false
|
||||
return getters.notifications.find((n) => n.id === notificationId)
|
||||
},
|
||||
|
||||
columnsSortedSubset: (state, rootGetters) => {
|
||||
const actionsColumn = [
|
||||
{
|
||||
text: '',
|
||||
value: 'actions',
|
||||
sortable: false,
|
||||
fixed: true,
|
||||
},
|
||||
]
|
||||
|
||||
const columns = [
|
||||
...state.learning.columnsSorted.filter((el) => el.fixed),
|
||||
...rootGetters['columnBrowser/subset'],
|
||||
...actionsColumn,
|
||||
]
|
||||
return columns
|
||||
},
|
||||
|
||||
filters: (state) => state.learning.filters,
|
||||
filtersSelected: (state) => state.learning.filtersSelected,
|
||||
filtersSearchable: (state) => {
|
||||
return state.learning.filters.filter(
|
||||
(f) => !state.learning.filtersDisabledForSearch.includes(f.title)
|
||||
)
|
||||
},
|
||||
|
||||
// Map with filterId as key and full Filter object as value
|
||||
filtersMap: (state, getters) => {
|
||||
const map = new Map()
|
||||
getters.filters.forEach((filter) => map.set(filter.id, filter))
|
||||
return map
|
||||
},
|
||||
|
||||
filtersItemsMap: (state, getters) => {
|
||||
const map = new Map()
|
||||
// Cycle all filters
|
||||
getters.filters.forEach((filter) => {
|
||||
// Cycle all filter items
|
||||
filter.items.forEach((item) => {
|
||||
map.set(item.id, item)
|
||||
})
|
||||
})
|
||||
return map
|
||||
},
|
||||
|
||||
getFilterByTitle: (state, getters) => (title) => {
|
||||
if (!getters.filters.length > 0) return []
|
||||
return getters.filters.find((filter) => filter.title === title)
|
||||
},
|
||||
|
||||
getFilterById: (state, getters) => (filterId) => {
|
||||
const emptyFilter = {
|
||||
id: '*',
|
||||
title: '*',
|
||||
items: [],
|
||||
}
|
||||
|
||||
if (!filterId) {
|
||||
return emptyFilter
|
||||
}
|
||||
if (!getters.filtersMap.has(filterId)) {
|
||||
return emptyFilter
|
||||
}
|
||||
|
||||
return getters.filtersMap.get(filterId)
|
||||
},
|
||||
|
||||
getFilterItemById: (state, getters) => (filterItemId) => {
|
||||
const emptyFilterItem = {
|
||||
id: '*',
|
||||
filter_id: '*',
|
||||
title: '*',
|
||||
}
|
||||
|
||||
if (!filterItemId) {
|
||||
return emptyFilterItem
|
||||
}
|
||||
if (!getters.filtersItemsMap.has(filterItemId)) {
|
||||
return emptyFilterItem
|
||||
}
|
||||
|
||||
return getters.filtersItemsMap.get(filterItemId)
|
||||
},
|
||||
|
||||
filterItemsResolved:
|
||||
(state, getters) =>
|
||||
({ filterTitle = '', filters = [] }) => {
|
||||
const filter = getters.getFilterByTitle(filterTitle)
|
||||
return filters.filter((f) => f.filter_item.filter_id === filter.id)
|
||||
},
|
||||
|
||||
synonyms: (state) => state.learning.synonyms || [],
|
||||
attachedSynonymsIds: (state, getters) => {
|
||||
return getters.remoteProduct.synonyms
|
||||
? getters.remoteProduct.synonyms.map(({ id }) => id)
|
||||
: []
|
||||
},
|
||||
synonymsHaveChanges: (state, getters) =>
|
||||
!Util.arraysMatch(
|
||||
getters.attachedSynonymsIds,
|
||||
state.learning.synonymsSelected
|
||||
),
|
||||
|
||||
remoteProduct: (state) => state.learning.remote,
|
||||
localProduct: (state) => state.learning.local,
|
||||
|
||||
productHasChanges: (state, getters) => {
|
||||
if (!Util.areEqualInputs(getters.remoteProduct, getters.localProduct))
|
||||
return true
|
||||
|
||||
if (getters.synonymsHaveChanges) return true
|
||||
if (state.learning.cover.url) return true
|
||||
if (state.learning.tile.url) return true
|
||||
|
||||
return false
|
||||
},
|
||||
|
||||
isFilterTypeEmpty: (state, getters) => {
|
||||
const idType = getters.getFilterByTitle('type').id
|
||||
|
||||
if (!getters.localProduct.filtersGrouped) return true
|
||||
if (!getters.localProduct.filtersGrouped[idType]) return true
|
||||
|
||||
if (getters.localProduct.filtersGrouped[idType].length > 0) return false
|
||||
return true
|
||||
},
|
||||
|
||||
isLearningProductValidated: (state, getters) => {
|
||||
return (
|
||||
!!getters.localProduct.title &&
|
||||
!!getters.localProduct.code &&
|
||||
!!getters.localProduct.seo_title
|
||||
)
|
||||
},
|
||||
}
|
||||
448
store/learning.js
Normal file
448
store/learning.js
Normal file
@@ -0,0 +1,448 @@
|
||||
import Vue from 'vue'
|
||||
|
||||
export const state = () => ({
|
||||
products: [],
|
||||
remote: {},
|
||||
local: { filtersGrouped: {} },
|
||||
images: [],
|
||||
cover: {
|
||||
name: '',
|
||||
url: '',
|
||||
file: null,
|
||||
},
|
||||
tile: {
|
||||
name: '',
|
||||
url: '',
|
||||
file: null,
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
text: 'learning.product',
|
||||
sortable: false,
|
||||
value: 'cover',
|
||||
fixed: true,
|
||||
},
|
||||
{
|
||||
text: '',
|
||||
sortable: false,
|
||||
value: 'title',
|
||||
fixed: true,
|
||||
divider: true,
|
||||
},
|
||||
{
|
||||
text: 'learning.code',
|
||||
sortable: true,
|
||||
value: 'code',
|
||||
display: true,
|
||||
},
|
||||
{
|
||||
text: 'learning.partner',
|
||||
sortable: true,
|
||||
value: 'partner',
|
||||
display: true,
|
||||
},
|
||||
{
|
||||
text: 'learning.owner',
|
||||
sortable: true,
|
||||
value: 'owner',
|
||||
display: true,
|
||||
},
|
||||
{
|
||||
text: 'learning.status.title',
|
||||
sortable: false,
|
||||
value: 'status',
|
||||
display: true,
|
||||
},
|
||||
{
|
||||
text: 'learning.product_overview.duration',
|
||||
sortable: true,
|
||||
value: 'lead_time',
|
||||
display: true,
|
||||
},
|
||||
{
|
||||
text: 'learning.filters.product_type',
|
||||
sortable: false,
|
||||
value: 'product_type',
|
||||
display: true,
|
||||
},
|
||||
{
|
||||
text: 'learning.filters.theme',
|
||||
sortable: true,
|
||||
value: 'theme',
|
||||
display: true,
|
||||
},
|
||||
{
|
||||
text: 'learning.filters.course',
|
||||
sortable: false,
|
||||
value: 'course',
|
||||
display: true,
|
||||
},
|
||||
],
|
||||
filters: [],
|
||||
columnsSorted: [],
|
||||
columnsSortedSubset: [],
|
||||
filtersSelected: [],
|
||||
filtersDisabledForSearch: ['format_version'],
|
||||
versionsFiltersSelected: {},
|
||||
accreditationsFiltersSelected: {},
|
||||
checklists: [],
|
||||
checklistsSelected: [],
|
||||
synonyms: [],
|
||||
synonymsSelected: [],
|
||||
coursesTableOptions: {},
|
||||
})
|
||||
|
||||
export const actions = {
|
||||
async pullProducts({ commit, state }) {
|
||||
try {
|
||||
const response = await this.$axios.get('/learning-products')
|
||||
const learningProducts = response.data
|
||||
await commit('STORE_PRODUCTS', learningProducts)
|
||||
} catch (error) {
|
||||
console.log('pullProducts -> error', error)
|
||||
}
|
||||
},
|
||||
|
||||
async setColumns({ commit, state }, arrayColumns = state.columns) {
|
||||
await commit('SORT_COLUMNS', arrayColumns)
|
||||
},
|
||||
async setFilters({ commit, state }, arrayFilters = state.filters) {
|
||||
await commit('SORT_FILTERS', arrayFilters)
|
||||
},
|
||||
async resetProduct({ commit }) {
|
||||
await commit('RESET_PRODUCT')
|
||||
await commit('RESET_COVER')
|
||||
await commit('RESET_TILE')
|
||||
await commit('RESET_SELECTED_SYNONYMS')
|
||||
},
|
||||
|
||||
async storeProduct({ commit, state, rootGetters }, published = false) {
|
||||
// Set product to save as published
|
||||
if (published)
|
||||
await commit('UPDATE_FIELD', { field: 'published', value: 1 })
|
||||
if (state.local.in_the_picture)
|
||||
await commit('UPDATE_FIELD', { field: 'in_the_picture', value: 1 })
|
||||
if (state.local.for_members)
|
||||
await commit('UPDATE_FIELD', { field: 'for_members', value: 1 })
|
||||
|
||||
// Check if remotely the product was already set as published
|
||||
const wasPublished = state.remote.published
|
||||
|
||||
// If it has a parent_id, it's a draft of a product published
|
||||
const hasParentId = state.remote.parent_id
|
||||
|
||||
// Preparing data
|
||||
//-----------------------------------------
|
||||
const formData = new FormData()
|
||||
|
||||
for (let key in state.local) {
|
||||
if (state.local[key] && state.local[key] != 'null') {
|
||||
// If value is array/object, stringify that
|
||||
formData.append(
|
||||
key,
|
||||
typeof state.local[key] === 'object'
|
||||
? JSON.stringify(state.local[key])
|
||||
: state.local[key]
|
||||
)
|
||||
} else {
|
||||
formData.append(key, '')
|
||||
}
|
||||
}
|
||||
|
||||
if (state.tile.file) formData.append('tile', state.tile.file)
|
||||
else formData.delete('tile')
|
||||
|
||||
if (state.cover.file) formData.append('cover', state.cover.file)
|
||||
else formData.delete('cover')
|
||||
|
||||
if (state.local.parent_id == null) formData.delete('parent_id')
|
||||
|
||||
// If wasn't published and we want to save as draft
|
||||
if (wasPublished && !published && !hasParentId) {
|
||||
formData.append('parent_id', state.remote.id)
|
||||
formData.delete('published')
|
||||
formData.delete('id')
|
||||
}
|
||||
|
||||
if (rootGetters.synonymsHaveChanges) {
|
||||
formData.append(
|
||||
'synonymsSelected',
|
||||
JSON.stringify(state.synonymsSelected)
|
||||
)
|
||||
}
|
||||
|
||||
if (!formData.get('published')) {
|
||||
formData.delete('published')
|
||||
}
|
||||
|
||||
let slug = ''
|
||||
|
||||
// console.log([...formData])
|
||||
await this.$axios
|
||||
.post('/learning-products', formData)
|
||||
.then((response) => {
|
||||
// 'Cause if it's published we close the page
|
||||
Promise.resolve(response)
|
||||
if (!published) commit('SET_PRODUCT', response.data)
|
||||
slug = response.data.slug
|
||||
})
|
||||
.catch((error) => Promise.reject(error))
|
||||
|
||||
return slug
|
||||
},
|
||||
|
||||
async deleteProduct({ dispatch, state }, productId) {
|
||||
if (!productId) return
|
||||
|
||||
try {
|
||||
// $nuxt.$loading.start();
|
||||
await this.$axios.delete(`/learning-products/${productId}`)
|
||||
await dispatch('pullProducts')
|
||||
|
||||
$nuxt.$loading.finish()
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: `Product deleted`,
|
||||
color: 'success',
|
||||
icon: 'mdi-delete',
|
||||
})
|
||||
} catch (error) {
|
||||
console.log('deleteProduct -> error', error)
|
||||
$nuxt.$loading.finish()
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: error,
|
||||
color: 'error',
|
||||
icon: 'mdi-close',
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
async removeSynonym({ commit, state }, synonymId) {
|
||||
if (!synonymId) return
|
||||
|
||||
const backup = [...state.synonymsSelected]
|
||||
|
||||
const synonymsFiltered = backup.filter((s) => s !== synonymId)
|
||||
|
||||
commit('SELECT_SYNONYM', synonymsFiltered)
|
||||
},
|
||||
}
|
||||
|
||||
export const mutations = {
|
||||
STORE_PRODUCTS: (state, products) => {
|
||||
state.products = []
|
||||
state.products = [...products]
|
||||
},
|
||||
SORT_COLUMNS: (state, columns) => {
|
||||
state.columnsSorted = columns
|
||||
},
|
||||
SET_COLUMNS_SUBSET: (state, columns) => {
|
||||
state.columnsSortedSubset = null
|
||||
state.columnsSortedSubset = columns
|
||||
},
|
||||
SORT_FILTERS: (state, filters) => {
|
||||
// Workaround because Vuex doesn't recognize changes otherwise
|
||||
state.filters = []
|
||||
state.filters = [...filters]
|
||||
},
|
||||
SET_PRODUCT: (state, product) => {
|
||||
state.remote = {}
|
||||
state.local = {}
|
||||
state.remote = Object.assign({}, product)
|
||||
state.local = Object.assign({}, product)
|
||||
|
||||
// console.log(JSON.stringify(state.remote))
|
||||
// console.log(JSON.stringify(state.local))
|
||||
},
|
||||
RESET_PRODUCT: (state) => {
|
||||
state.remote = {}
|
||||
state.local = {}
|
||||
state.versionsFiltersSelected = {}
|
||||
},
|
||||
RESET_VERSIONS_FILTERS: (state) => {
|
||||
state.versionsFiltersSelected = {}
|
||||
},
|
||||
RESET_ACCREDITATIONS_FILTERS: (state) => {
|
||||
state.accreditationsFiltersSelected = {}
|
||||
},
|
||||
UPDATE_FIELD: (state, payload) => {
|
||||
state.local[payload.field] = payload.value
|
||||
},
|
||||
UPDATE_FILTERS: async (state, payload) => {
|
||||
if (payload.target === 'versions') {
|
||||
return Vue.set(
|
||||
state.versionsFiltersSelected,
|
||||
payload.filterId,
|
||||
Array.isArray(payload.value) ? payload.value : [payload.value]
|
||||
)
|
||||
|
||||
// Workaround because Vuex doesn't recognize changes otherwise
|
||||
// let tmp = Object.assign({}, state.versionsFiltersSelected)
|
||||
// state.versionsFiltersSelected = {}
|
||||
// state.versionsFiltersSelected = Object.assign({}, tmp)
|
||||
|
||||
// return state.versionsFiltersSelected[payload.filterId] = Array.isArray(payload.value)
|
||||
// ? payload.value
|
||||
// : [payload.value]
|
||||
}
|
||||
|
||||
if (payload.target === 'accreditations') {
|
||||
return Vue.set(
|
||||
state.accreditationsFiltersSelected,
|
||||
payload.filterId,
|
||||
Array.isArray(payload.value) ? payload.value : [payload.value]
|
||||
)
|
||||
|
||||
// Workaround because Vuex doesn't recognize changes otherwise
|
||||
// let tmp = Object.assign({}, state.accreditationsFiltersSelected)
|
||||
// state.accreditationsFiltersSelected = {}
|
||||
// state.accreditationsFiltersSelected = Object.assign({}, tmp)
|
||||
|
||||
// return state.accreditationsFiltersSelected[payload.filterId] = Array.isArray(payload.value)
|
||||
// ? payload.value
|
||||
// : [payload.value]
|
||||
}
|
||||
|
||||
if (!state.local['filtersGrouped']) state.local['filtersGrouped'] = {}
|
||||
|
||||
state.local['filtersGrouped'][payload.filterId] = Array.isArray(
|
||||
payload.value
|
||||
)
|
||||
? payload.value
|
||||
: [payload.value]
|
||||
state.local['filterItemsSelected'] = Object.values(
|
||||
state.local.filtersGrouped
|
||||
).flat()
|
||||
},
|
||||
|
||||
ADD_VERSION_LOCAL: (state, payload) => {
|
||||
// Workaround because Vuex doesn't recognize changes otherwise
|
||||
const tmp = [...state.local.versions]
|
||||
tmp.push(payload)
|
||||
|
||||
state.local.versions = []
|
||||
state.remote.versions = []
|
||||
state.local.versions = [...tmp]
|
||||
state.remote.versions = [...tmp]
|
||||
},
|
||||
EDIT_VERSION_LOCAL: (state, payload) => {
|
||||
// Workaround because Vuex doesn't recognize changes otherwise
|
||||
let tmp = [...state.local.versions]
|
||||
tmp[payload.index] = Object.assign({}, payload.version)
|
||||
|
||||
state.local.versions = []
|
||||
state.remote.versions = []
|
||||
state.local.versions = [...tmp]
|
||||
state.remote.versions = [...tmp]
|
||||
},
|
||||
DELETE_VERSION_LOCAL: (state, payload) => {
|
||||
const indexLocal = state.local.versions.indexOf(payload)
|
||||
const indexRemote = state.remote.versions.indexOf(payload)
|
||||
state.local.versions.splice(indexLocal, 1)
|
||||
state.remote.versions.splice(indexRemote, 1)
|
||||
},
|
||||
|
||||
ADD_ACCREDITATION_LOCAL: (state, payload) => {
|
||||
// Workaround because Vuex doesn't recognize changes otherwise
|
||||
const tmp = [...state.local.accreditations]
|
||||
tmp.push(payload)
|
||||
|
||||
state.local.accreditations = []
|
||||
state.local.accreditations = [...tmp]
|
||||
},
|
||||
EDIT_ACCREDITATION_LOCAL: (state, payload) => {
|
||||
// Workaround because Vuex doesn't recognize changes otherwise
|
||||
let tmp = [...state.local.accreditations]
|
||||
tmp[payload.index] = Object.assign({}, payload.accreditation)
|
||||
|
||||
state.local.accreditations = []
|
||||
state.local.accreditations = [...tmp]
|
||||
},
|
||||
DELETE_ACCREDITATION_LOCAL: (state, payload) => {
|
||||
const index = state.local.accreditations.indexOf(payload)
|
||||
state.local.accreditations.splice(index, 1)
|
||||
},
|
||||
ADD_COURSE_NOTIFICATION_LOCAL: (state, payload) => {
|
||||
// Workaround because Vuex doesn't recognize changes otherwise
|
||||
const tmp = [...state.local.notifications]
|
||||
tmp.push(payload)
|
||||
|
||||
state.local.notifications = []
|
||||
state.local.notifications = [...tmp]
|
||||
},
|
||||
EDIT_COURSE_NOTIFICATION_LOCAL: (state, payload) => {
|
||||
// Workaround because Vuex doesn't recognize changes otherwise
|
||||
let tmp = [...state.local.notifications]
|
||||
tmp[payload.index] = Object.assign({}, payload.notification)
|
||||
|
||||
state.local.notifications = []
|
||||
state.local.notifications = [...tmp]
|
||||
},
|
||||
DELETE_COURSE_NOTIFICATION_LOCAL: (state, payload) => {
|
||||
const index = state.local.notifications.indexOf(payload)
|
||||
state.local.notifications.splice(index, 1)
|
||||
},
|
||||
RESET_TILE: (state) => {
|
||||
state.tile = {
|
||||
name: '',
|
||||
url: '',
|
||||
file: null,
|
||||
}
|
||||
},
|
||||
UPDATE_TILE: (state, payload) => {
|
||||
state.tile = payload
|
||||
},
|
||||
RESET_COVER: (state) => {
|
||||
state.cover = {
|
||||
name: '',
|
||||
url: '',
|
||||
file: null,
|
||||
}
|
||||
},
|
||||
UPDATE_COVER: (state, payload) => {
|
||||
state.cover = payload
|
||||
},
|
||||
SELECT_FILTERS: (state, payload) => {
|
||||
state.filtersSelected = payload
|
||||
state.coursesTableOptions.page = 1
|
||||
},
|
||||
REMOVE_SELECTED_FILTER: (state, payload) => {
|
||||
state.filtersSelected = state.filtersSelected.filter(
|
||||
(item) => item !== payload
|
||||
)
|
||||
state.coursesTableOptions.page = 1
|
||||
},
|
||||
|
||||
SET_CHECKLIST: (state, checklists) => {
|
||||
// Workaround because Vuex doesn't recognize changes otherwise
|
||||
let tmp = [...checklists]
|
||||
state.checklists = []
|
||||
state.checklists = [...tmp]
|
||||
},
|
||||
|
||||
RESET_CHECKLIST_SELECTED: (state) => (state.checklistsSelected = []),
|
||||
|
||||
SET_CHECKED_CHECKLISTS: (state, payload) => {
|
||||
state.checklistsSelected = [...payload]
|
||||
},
|
||||
|
||||
SELECT_CHECKLIST: (state, payload) => {
|
||||
state.checklistsSelected = payload
|
||||
},
|
||||
|
||||
SET_SYNONYMS_LIST: (state, payload) => {
|
||||
state.synonyms = [...payload]
|
||||
},
|
||||
|
||||
SELECT_SYNONYM: (state, payload) => {
|
||||
state.synonymsSelected = payload
|
||||
},
|
||||
|
||||
RESET_SELECTED_SYNONYMS: (state) => {
|
||||
state.synonymsSelected = []
|
||||
},
|
||||
|
||||
SET_COURSES_TABLE_OPTIONS: (state, payload) => {
|
||||
state.coursesTableOptions = {}
|
||||
state.coursesTableOptions = payload
|
||||
},
|
||||
}
|
||||
677
store/members.js
Normal file
677
store/members.js
Normal file
@@ -0,0 +1,677 @@
|
||||
import Vue from 'vue'
|
||||
import Util from '@/util'
|
||||
|
||||
export const state = () => ({
|
||||
list: [],
|
||||
remote: {},
|
||||
local: {},
|
||||
logo: {
|
||||
name: '',
|
||||
url: '',
|
||||
file: null,
|
||||
},
|
||||
branches: [],
|
||||
});
|
||||
|
||||
export const getters = {
|
||||
hasMembers: (state) => state.list.length > 0,
|
||||
hasChanges: (state) => {
|
||||
|
||||
if (!Util.areEqualInputs(
|
||||
state.remote,
|
||||
state.local,
|
||||
['summaries', 'addresses', 'contacts', 'contributions']
|
||||
)) return true
|
||||
|
||||
if (state.logo.url) return true
|
||||
|
||||
return false
|
||||
},
|
||||
revision: (state) => {
|
||||
if (!state.local.revision) return false
|
||||
return JSON.parse(state.local.revision.data)
|
||||
},
|
||||
revisionHasChanges: (state, getters) => {
|
||||
if (!getters.revision) return false
|
||||
|
||||
if (Util.areEqualInputs(
|
||||
state.local,
|
||||
getters.revision
|
||||
)) return true
|
||||
|
||||
return false
|
||||
},
|
||||
|
||||
membersFiltered: (state, getters, rootState, rootGetters) => {
|
||||
|
||||
if (rootGetters.isSuperAdmin || rootGetters.isAdmin || rootGetters.isOperator) {
|
||||
return state.list
|
||||
}
|
||||
if (rootGetters.loggedInUser.isMemberEditor) return state.list.filter(
|
||||
(member) => member.user_id === rootGetters.loggedInUser.id
|
||||
)
|
||||
return state.list
|
||||
},
|
||||
|
||||
isSuperAdminAdminOrDelegated: (state, getters, rootState, rootGetters) => {
|
||||
if (rootGetters.isSuperAdmin || rootGetters.isAdmin) return true
|
||||
if (!state.local.user_id) return false
|
||||
return state.local.user_id === rootGetters.loggedInUser.id
|
||||
},
|
||||
|
||||
isMemberValidated: (state) => {
|
||||
return !!state.local.informal_name && !!state.local.formal_name && !!state.local.kvk_number
|
||||
},
|
||||
|
||||
getBranchById: (state) => (id) => state.branches.find(b => b.id === id),
|
||||
}
|
||||
|
||||
/** @type {import('@typedefs/store').ActionTree} */
|
||||
export const actions = {
|
||||
async pullData({ commit, state }) {
|
||||
try {
|
||||
const response = await this.$axios.get('/members')
|
||||
await commit('STORE_MEMBERS', response.data)
|
||||
} catch (error) {
|
||||
console.log("pullMembers -> error", error)
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: error,
|
||||
color: "error",
|
||||
icon: "mdi-close",
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async pullBranches({ commit, state }) {
|
||||
try {
|
||||
const response = await this.$axios.get('members/branches')
|
||||
await commit("STORE_BRANCHES", response.data)
|
||||
} catch (error) {
|
||||
console.log("pullBranches -> error", error)
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: error,
|
||||
color: "error",
|
||||
icon: "mdi-close",
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async pullTypes({ commit }) {
|
||||
try {
|
||||
const response = await this.$axios.get('members/types');
|
||||
await commit('STORE_TYPES', response.data);
|
||||
} catch (error) {
|
||||
console.log('pullTypes -> error', error)
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: error,
|
||||
color: 'error',
|
||||
icon: 'mdi-close',
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async getAndSetMember({ commit, dispatch, state }, url) {
|
||||
try {
|
||||
const response = await dispatch('get', url)
|
||||
await commit('SET_MEMBER', response)
|
||||
} catch (error) {
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: error,
|
||||
color: "error",
|
||||
icon: "mdi-close",
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async get({ state }, url) {
|
||||
try {
|
||||
const response = await this.$axios.get(`/members/${url}`)
|
||||
return response.data
|
||||
} catch (error) {
|
||||
|
||||
$nuxt.error({ statusCode: 401, message: 'Lid niet gevonden' })
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: error,
|
||||
color: "error",
|
||||
icon: "mdi-close",
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async store({ dispatch, commit, state, getters, rootGetters }, revision = false) {
|
||||
const formData = new FormData()
|
||||
|
||||
let data;
|
||||
|
||||
if (revision) {
|
||||
|
||||
data = { ...getters.revision }
|
||||
if (revision.show_on_website) data.show_on_website = 1
|
||||
|
||||
if (data.sub_branches.some(branch => branch.id)) {
|
||||
const subBranchesIds = data.sub_branches.map(({ id }) => id)
|
||||
data.sub_branches = [...subBranchesIds]
|
||||
}
|
||||
|
||||
data.revisor_id = rootGetters.loggedInUser.id
|
||||
|
||||
} else {
|
||||
|
||||
if (state.local.show_on_website) await commit('UPDATE_FIELD', { field: 'show_on_website', value: 1 })
|
||||
if (state.local.sub_branches.some(branch => branch.id)) {
|
||||
const subBranchesIds = state.local.sub_branches.map(({ id }) => id)
|
||||
await commit('UPDATE_FIELD', { field: 'sub_branches', value: subBranchesIds })
|
||||
}
|
||||
|
||||
data = { ...state.local }
|
||||
}
|
||||
|
||||
const fieldsAllowedNull = this.$constants.store.members.fieldsAllowedNull
|
||||
|
||||
for (let key in data) {
|
||||
if ((data[key] && data[key] != "null")
|
||||
|| (data[key] === null && fieldsAllowedNull.indexOf(key) !== -1)
|
||||
) {
|
||||
const value = data[key] ?? ''
|
||||
|
||||
// If value is array/object, stringify that
|
||||
formData.append(
|
||||
key,
|
||||
typeof value === 'object'
|
||||
? JSON.stringify(value)
|
||||
: value
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (state.logo.file) formData.append('logo', state.logo.file)
|
||||
else formData.delete('logo')
|
||||
|
||||
let slug = '';
|
||||
|
||||
// console.log([...formData])
|
||||
|
||||
await this.$axios.post('/members', formData)
|
||||
.then(async response => {
|
||||
Promise.resolve(response)
|
||||
await dispatch('pullData');
|
||||
slug = response.data.slug
|
||||
})
|
||||
.catch(error => Promise.reject(error))
|
||||
|
||||
return slug
|
||||
},
|
||||
|
||||
async storeRevision({ state, rootGetters, dispatch }) {
|
||||
|
||||
const formData = new FormData()
|
||||
|
||||
const tmpObj = { ...state.local }
|
||||
|
||||
// Remove not useful data attached
|
||||
delete tmpObj.revision;
|
||||
delete tmpObj.data;
|
||||
delete tmpObj.addresses;
|
||||
delete tmpObj.summaries;
|
||||
delete tmpObj.contacts;
|
||||
|
||||
const revision = JSON.stringify(tmpObj)
|
||||
|
||||
|
||||
if (state.local.revision) formData.append('id', state.local.revision.id)
|
||||
if (state.logo.file) formData.append('logo', state.logo.file)
|
||||
formData.append('member_id', state.local.id)
|
||||
formData.append('user_id', rootGetters.loggedInUser.id)
|
||||
formData.append('data', revision)
|
||||
|
||||
// console.log([...formData])
|
||||
|
||||
await this.$axios.post('/members/revision', formData)
|
||||
.then(async response => {
|
||||
Promise.resolve(response)
|
||||
await dispatch('pullData');
|
||||
})
|
||||
.catch(error => Promise.reject(error))
|
||||
},
|
||||
|
||||
async deleteMember({ dispatch, state }, memberId = state.remote.id) {
|
||||
|
||||
if (!memberId) return
|
||||
|
||||
try {
|
||||
|
||||
await this.$axios.delete(`/members/${memberId}`)
|
||||
await dispatch('pullData');
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: `Member deleted`,
|
||||
color: 'success',
|
||||
icon: 'mdi-delete',
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.log("deleteMember -> error", error)
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: error,
|
||||
color: "error",
|
||||
icon: "mdi-close",
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
|
||||
async storeSummary({ dispatch, state }, data) {
|
||||
|
||||
if (!state.remote.id) return
|
||||
|
||||
data['member_id'] = state.remote.id
|
||||
|
||||
if (data['toAll'] === false) { delete data['toAll'] }
|
||||
|
||||
await this.$axios.post(`/members/summaries`, data)
|
||||
.then(async response => {
|
||||
|
||||
Promise.resolve(response)
|
||||
|
||||
await dispatch('getAndSetMember', data['member_id'])
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: 'Werknemers opgeslagen',
|
||||
color: 'success',
|
||||
icon: 'mdi-check',
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
Promise.reject(error)
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: error,
|
||||
color: "error",
|
||||
icon: "mdi-close",
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
async storeContribution({ dispatch, state, rootGetters }, data) {
|
||||
|
||||
if (!state.remote.id) return
|
||||
if (!rootGetters.isSuperAdminOrAdmin && data.toAll) return
|
||||
|
||||
data['member_id'] = state.remote.id
|
||||
|
||||
if (data['toAll'] === false) { delete data['toAll'] }
|
||||
|
||||
await this.$axios.post(`/members/contributions`, data)
|
||||
.then(async response => {
|
||||
|
||||
Promise.resolve(response)
|
||||
|
||||
// if (!data.toAll) {
|
||||
await dispatch('getAndSetMember', data['member_id'])
|
||||
// }
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: `Contribution added`,
|
||||
color: 'success',
|
||||
icon: 'mdi-check',
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
Promise.reject(error)
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: error,
|
||||
color: "error",
|
||||
icon: "mdi-close",
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
async storeAddress({ dispatch, state }, data) {
|
||||
|
||||
if (!state.remote.id) return
|
||||
|
||||
data['member_id'] = state.remote.id
|
||||
|
||||
await this.$axios.post(`/members/addresses`, data)
|
||||
.then(async response => {
|
||||
|
||||
Promise.resolve(response)
|
||||
|
||||
await dispatch('getAndSetMember', data['member_id'])
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: `Address added`,
|
||||
color: 'success',
|
||||
icon: 'mdi-check',
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
Promise.reject(error)
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: error,
|
||||
color: "error",
|
||||
icon: "mdi-close",
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
async storeContact({ dispatch, state }, data) {
|
||||
if (!state.remote.id) return
|
||||
|
||||
data['member_id'] = state.remote.id
|
||||
|
||||
await this.$axios.post(`/members/contacts`, data)
|
||||
.then(async response => {
|
||||
|
||||
Promise.resolve(response)
|
||||
|
||||
await dispatch('getAndSetMember', data['member_id'])
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: `Contact added`,
|
||||
color: 'success',
|
||||
icon: 'mdi-check',
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
Promise.reject(error)
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: `${error.response ? error.response.data.message : error}.`,
|
||||
...(error.response && {
|
||||
errors: error.response.data.errors,
|
||||
}),
|
||||
color: "error",
|
||||
icon: "mdi-close",
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
async deleteSummary({ commit, state }, item) {
|
||||
|
||||
if (!item.id) return
|
||||
|
||||
try {
|
||||
|
||||
await this.$axios.delete(`/members/summaries/${item.id}`)
|
||||
|
||||
await commit('DELETE_SUMMARY_LOCAL', item)
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: `Summary deleted`,
|
||||
color: 'success',
|
||||
icon: 'mdi-delete',
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.log("addSummary -> error", error)
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: error,
|
||||
color: "error",
|
||||
icon: "mdi-close",
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
async deleteContribution({ commit, state }, item) {
|
||||
|
||||
if (!item.id) return
|
||||
|
||||
try {
|
||||
|
||||
await this.$axios.delete(`/members/contributions/${item.id}`)
|
||||
|
||||
await commit('DELETE_CONTRIBUTION_LOCAL', item)
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: `Contribution deleted`,
|
||||
color: 'success',
|
||||
icon: 'mdi-delete',
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: error,
|
||||
color: "error",
|
||||
icon: "mdi-close",
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
async addManagementLink({ dispatch, commit, stage }, data) {
|
||||
if (!data) return
|
||||
|
||||
let link = { member_id: data };
|
||||
|
||||
await this.$axios.post(`/members/managementlink/addlink`, link)
|
||||
.then(async response => {
|
||||
|
||||
Promise.resolve(response)
|
||||
|
||||
await dispatch('pullData');
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: `Link added`,
|
||||
color: 'success',
|
||||
icon: 'mdi-check',
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
Promise.reject(error)
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: `${error.response ? error.response.data.message : error}.`,
|
||||
...(error.response && {
|
||||
errors: error.response.data.errors,
|
||||
}),
|
||||
color: "error",
|
||||
icon: "mdi-close",
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
async deleteManagementLink({ dispatch, commit, stage }, data) {
|
||||
if (!data) return
|
||||
|
||||
let link = { link_id: data };
|
||||
|
||||
await this.$axios.post(`/members/managementlink/deletelink`, link)
|
||||
.then(async response => {
|
||||
|
||||
Promise.resolve(response)
|
||||
|
||||
await dispatch('pullData');
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: `Link removed`,
|
||||
color: 'success',
|
||||
icon: 'mdi-check',
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
Promise.reject(error)
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: `${error.response ? error.response.data.message : error}.`,
|
||||
...(error.response && {
|
||||
errors: error.response.data.errors,
|
||||
}),
|
||||
color: "error",
|
||||
icon: "mdi-close",
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
async changeManagementLink({ dispatch, commit, stage }, data) {
|
||||
if (!data) return
|
||||
|
||||
await this.$axios.post(`/members/managementlink/changelink`, data)
|
||||
.then(async response => {
|
||||
|
||||
Promise.resolve(response)
|
||||
|
||||
await dispatch('pullData');
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: `Link added`,
|
||||
color: 'success',
|
||||
icon: 'mdi-check',
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
Promise.reject(error)
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: `${error.response ? error.response.data.message : error}.`,
|
||||
...(error.response && {
|
||||
errors: error.response.data.errors,
|
||||
}),
|
||||
color: "error",
|
||||
icon: "mdi-close",
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
async deleteAddress({ commit, state }, item) {
|
||||
|
||||
if (!item.id) return
|
||||
|
||||
try {
|
||||
|
||||
await this.$axios.delete(`/members/addresses/${item.id}`)
|
||||
|
||||
await commit('DELETE_ADDRESS_LOCAL', item)
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: `Address deleted`,
|
||||
color: 'success',
|
||||
icon: 'mdi-delete',
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.log("deleteAddress -> error", error)
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: error,
|
||||
color: "error",
|
||||
icon: "mdi-close",
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
async deleteContact({ commit, state }, item) {
|
||||
|
||||
if (!item.id) return
|
||||
|
||||
try {
|
||||
|
||||
await this.$axios.delete(`/members/contacts/${item.id}`)
|
||||
|
||||
await commit('DELETE_CONTACT_LOCAL', item)
|
||||
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: `Contact deleted`,
|
||||
color: 'success',
|
||||
icon: 'mdi-delete',
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.log("deleteContact -> error", error)
|
||||
$nuxt.$notifier.showMessage({
|
||||
content: error,
|
||||
color: "error",
|
||||
icon: "mdi-close",
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
async updateManagementLinks({ commit, state }, item) {
|
||||
console.log(item);
|
||||
},
|
||||
|
||||
async resetMember({ commit }) {
|
||||
await commit('RESET_MEMBER');
|
||||
await commit('RESET_LOGO');
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
export const mutations = {
|
||||
STORE_MEMBERS: (state, payload) => state.list = payload,
|
||||
STORE_BRANCHES: (state, payload) => state.branches = payload,
|
||||
STORE_TYPES: (state, payload) => state.types = payload,
|
||||
SET_MEMBER: (state, payload) => {
|
||||
state.remote = { ...payload };
|
||||
state.local = { ...payload };
|
||||
},
|
||||
UPDATE_FIELD: (state, payload) => {
|
||||
|
||||
// Old way with reactivity problems
|
||||
// state.local[payload.field] = payload.value
|
||||
|
||||
// New way that solves with reactivity
|
||||
Vue.set(state.local, payload.field, payload.value)
|
||||
},
|
||||
RESET_MEMBER: (state) => {
|
||||
state.remote = {};
|
||||
state.local = {};
|
||||
},
|
||||
|
||||
RESET_MEMBERS: (state) => state.list = [],
|
||||
|
||||
RESET_LOGO: (state) => {
|
||||
state.logo = {
|
||||
name: '',
|
||||
url: '',
|
||||
file: null,
|
||||
};
|
||||
},
|
||||
UPDATE_LOGO: (state, payload) => {
|
||||
state.logo = payload;
|
||||
},
|
||||
DELETE_ADDRESS_LOCAL: (state, payload) => {
|
||||
// Workaround because Vuex doesn't recognize changes otherwise
|
||||
const tmp = [...state.local.addresses];
|
||||
const index = tmp.indexOf(payload)
|
||||
tmp.splice(index, 1)
|
||||
|
||||
state.local.addresses = []
|
||||
state.local.addresses = [...tmp]
|
||||
},
|
||||
DELETE_CONTACT_LOCAL: (state, payload) => {
|
||||
// Workaround because Vuex doesn't recognize changes otherwise
|
||||
const tmp = [...state.local.contacts];
|
||||
const index = tmp.indexOf(payload)
|
||||
tmp.splice(index, 1)
|
||||
|
||||
state.local.contacts = []
|
||||
state.local.contacts = [...tmp]
|
||||
},
|
||||
DELETE_SUMMARY_LOCAL: (state, payload) => {
|
||||
// Workaround because Vuex doesn't recognize changes otherwise
|
||||
const tmp = [...state.local.summaries];
|
||||
const index = tmp.indexOf(payload)
|
||||
tmp.splice(index, 1)
|
||||
|
||||
state.local.summaries = []
|
||||
state.local.summaries = [...tmp]
|
||||
},
|
||||
|
||||
DELETE_CONTRIBUTION_LOCAL: (state, payload) => {
|
||||
// Workaround because Vuex doesn't recognize changes otherwise
|
||||
const tmp = [...state.local.contributions];
|
||||
const index = tmp.indexOf(payload)
|
||||
tmp.splice(index, 1)
|
||||
|
||||
state.local.contributions = []
|
||||
state.local.contributions = [...tmp]
|
||||
},
|
||||
}
|
||||
25
store/navigation.js
Normal file
25
store/navigation.js
Normal file
@@ -0,0 +1,25 @@
|
||||
export const state = () => ({
|
||||
searchOverlay: false,
|
||||
rightDrawer: {
|
||||
display: false,
|
||||
component: null,
|
||||
subMenu: null,
|
||||
},
|
||||
});
|
||||
|
||||
export const mutations = {
|
||||
|
||||
TOGGLE_SEARCH_OVERLAY: (state, value = null) => {
|
||||
state.searchOverlay = value
|
||||
},
|
||||
|
||||
SWITCH_RIGHT_DRAWER: (state, value = true) => {
|
||||
|
||||
if (typeof value === 'boolean') { state.rightDrawer.display = value }
|
||||
else {
|
||||
state.rightDrawer.component = value.component
|
||||
state.rightDrawer.subMenu = value.subMenu
|
||||
state.rightDrawer.display = true
|
||||
}
|
||||
},
|
||||
};
|
||||
15
store/snackbar.js
Normal file
15
store/snackbar.js
Normal file
@@ -0,0 +1,15 @@
|
||||
export const state = () => ({
|
||||
color: '',
|
||||
content: '',
|
||||
icon: '',
|
||||
errors: []
|
||||
})
|
||||
|
||||
export const mutations = {
|
||||
showMessage(state, payload) {
|
||||
state.content = payload.content
|
||||
state.color = payload.color
|
||||
state.icon = payload.icon;
|
||||
state.errors = payload.errors;
|
||||
}
|
||||
}
|
||||
53
store/utils.js
Normal file
53
store/utils.js
Normal file
@@ -0,0 +1,53 @@
|
||||
import isEqual from 'lodash.isequal';
|
||||
|
||||
// export const state = () => ({});
|
||||
|
||||
export const getters = {
|
||||
// console.log(this.$store.getters['utils/areEquals'](1, 1)) // It works
|
||||
areEquals: (state) => (input1, input2) => isEqual(input1, input2),
|
||||
isNotEmptyObj: (state) => (obj) => Object.keys(obj).length > 0,
|
||||
|
||||
filterArrayObjsByArrayOfProperties: (state) => (arrayObjs, arrayProperties) => {
|
||||
|
||||
const filteredData = arrayObjs.map((row) => {
|
||||
|
||||
const obj = {}
|
||||
|
||||
arrayProperties.forEach(property => obj[property] = row[property]);
|
||||
|
||||
return obj;
|
||||
})
|
||||
|
||||
return filteredData;
|
||||
},
|
||||
|
||||
arrayOfObjectToCsv: (state) => (data) => {
|
||||
const headers = Object.keys(data[0])
|
||||
|
||||
const csvRows = []
|
||||
|
||||
for (const row of data) {
|
||||
const values = headers.map((header) => {
|
||||
|
||||
const tmpArray = []
|
||||
|
||||
if (row[header]) {
|
||||
// Replacing commas with whitespaces
|
||||
tmpArray.push(row[header].replace(/,/g, ""))
|
||||
return tmpArray
|
||||
}
|
||||
return '-'
|
||||
})
|
||||
csvRows.push([values.join(',')])
|
||||
}
|
||||
|
||||
const csvString = [
|
||||
[...headers],
|
||||
...csvRows,
|
||||
]
|
||||
.map(e => e.join(","))
|
||||
.join("\n");
|
||||
|
||||
return csvString
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user