From 1c3c048ed494f8a8574f17c8740131789c867d8b Mon Sep 17 00:00:00 2001 From: ergjustin Date: Tue, 7 Mar 2023 09:33:29 -0600 Subject: [PATCH 1/9] feat:User CRUD --- src/components/MainNavigationDrawer.vue | 10 +- src/components/UserDetail.vue | 169 ++++++++++++++++++++ src/components/UsersSearch.vue | 199 ++++++++++++++++++++++++ src/lib/edit.js | 17 +- src/middleware/check-user.js | 26 ++++ src/pages/users/_userId/index.vue | 156 +++++++++++++++++++ src/pages/users/create.vue | 165 ++++++++++++++++++++ src/pages/users/index.vue | 82 ++++++++++ src/plugins/ability.js | 6 +- src/plugins/global-mixin.js | 4 +- src/store/index.js | 6 + 11 files changed, 835 insertions(+), 5 deletions(-) create mode 100644 src/components/UserDetail.vue create mode 100644 src/components/UsersSearch.vue create mode 100644 src/middleware/check-user.js create mode 100644 src/pages/users/_userId/index.vue create mode 100644 src/pages/users/create.vue create mode 100644 src/pages/users/index.vue diff --git a/src/components/MainNavigationDrawer.vue b/src/components/MainNavigationDrawer.vue index 175f8d2..e0a5525 100644 --- a/src/components/MainNavigationDrawer.vue +++ b/src/components/MainNavigationDrawer.vue @@ -66,7 +66,8 @@ import { mdiNoteOutline, mdiTag, mdiOfficeBuilding, - mdiViewGrid + mdiViewGrid, + mdiAccountGroup } from '@mdi/js' export default { @@ -110,6 +111,13 @@ export default { icon: mdiLoginVariant, title: 'Log in', to: '/login' + }, + { + icon: mdiAccountGroup, + org: false, + title: 'Users', + to: '/users', + auth: true } ] }, diff --git a/src/components/UserDetail.vue b/src/components/UserDetail.vue new file mode 100644 index 0000000..72d45f3 --- /dev/null +++ b/src/components/UserDetail.vue @@ -0,0 +1,169 @@ + + + diff --git a/src/components/UsersSearch.vue b/src/components/UsersSearch.vue new file mode 100644 index 0000000..70968ca --- /dev/null +++ b/src/components/UsersSearch.vue @@ -0,0 +1,199 @@ + + + diff --git a/src/lib/edit.js b/src/lib/edit.js index e4c0f11..5b38a7b 100644 --- a/src/lib/edit.js +++ b/src/lib/edit.js @@ -9,7 +9,8 @@ const arrays = [ 'external_links', 'intervals', 'involved_parties', - 'station_ids' + 'station_ids', + 'roles' ] const booleans = [ 'is_active', @@ -35,7 +36,10 @@ const fields = [ 'thing_type_id', 'time_zone', 'title', - 'url' + 'url', + 'email', + 'password', + 'person_id' ] const objects = [ 'access_levels', @@ -133,6 +137,15 @@ export function defaultThingType() { } } +export function defaultUser() { + return { + email: '', + full_name: '', + name: '', + roles: [] + } +} + export function setData(instance) { const data = _pickBy(instance, (value, key) => { return ( diff --git a/src/middleware/check-user.js b/src/middleware/check-user.js new file mode 100644 index 0000000..4109fa2 --- /dev/null +++ b/src/middleware/check-user.js @@ -0,0 +1,26 @@ +export default async function ({ error, params, store }) { + const { userId } = params + + try { + const res = await store.dispatch('users/find', { + query: { + _id: userId, + $limit: 1 + } + }) + + if (!(res && res.data && res.data.length)) { + return error({ + statusCode: 404, + message: 'User not found.' + }) + } + + store.commit('setUser', res.data[0]) + } catch (err) { + error({ + statusCode: err.statusCode || 500, + message: err.message + }) + } +} diff --git a/src/pages/users/_userId/index.vue b/src/pages/users/_userId/index.vue new file mode 100644 index 0000000..a67956d --- /dev/null +++ b/src/pages/users/_userId/index.vue @@ -0,0 +1,156 @@ + + + diff --git a/src/pages/users/create.vue b/src/pages/users/create.vue new file mode 100644 index 0000000..df0f928 --- /dev/null +++ b/src/pages/users/create.vue @@ -0,0 +1,165 @@ + + + diff --git a/src/pages/users/index.vue b/src/pages/users/index.vue new file mode 100644 index 0000000..d1ecc1a --- /dev/null +++ b/src/pages/users/index.vue @@ -0,0 +1,82 @@ + + + diff --git a/src/plugins/ability.js b/src/plugins/ability.js index 9811901..96aaf06 100644 --- a/src/plugins/ability.js +++ b/src/plugins/ability.js @@ -55,7 +55,11 @@ export default ({ store }, inject) => { inject('canPatch', (name, obj) => store.getters.isAbilityUpdated ? ability.can('patch', as(name, obj)) : false ) - + inject('canRemove', (name, obj) => + store.getters.isAbilityUpdated + ? ability.can('remove', as(name, obj)) + : false + ) inject('cannot', (...args) => store.getters.isAbilityUpdated ? ability.cannot(...args) : true ) diff --git a/src/plugins/global-mixin.js b/src/plugins/global-mixin.js index 3db756b..b95c1c5 100644 --- a/src/plugins/global-mixin.js +++ b/src/plugins/global-mixin.js @@ -64,7 +64,8 @@ import { mdiTwitter, mdiViewAgenda, mdiViewDashboard, - mdiViewList + mdiViewList, + mdiDelete } from '@mdi/js' Vue.mixin({ @@ -134,6 +135,7 @@ Vue.mixin({ mdiViewAgenda, mdiViewDashboard, mdiViewList, + mdiDelete, githubURL: process.env.githubURL, infoEmail: process.env.infoEmail, diff --git a/src/store/index.js b/src/store/index.js index 90d325d..510fa99 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -141,6 +141,9 @@ export const getters = { }, annotationId(state) { return state.annotationId + }, + user(state, { 'users/get': get }) { + return state.userId && get(state.userId) } } @@ -188,5 +191,8 @@ export const mutations = { }, setAnnotation(state, value) { state.annotationId = value && value._id + }, + setUser(state, value) { + state.userId = value && value._id } } From d82ba1a9030b73384043b7c12e5b46f4ced86ac1 Mon Sep 17 00:00:00 2001 From: ergjustin Date: Wed, 8 Mar 2023 14:16:53 -0600 Subject: [PATCH 2/9] fix:review suggession implemented --- src/lib/edit.js | 4 +++- src/pages/users/_userId/index.vue | 26 ++++++++++++++------------ src/pages/users/create.vue | 17 +++++++++-------- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/lib/edit.js b/src/lib/edit.js index 5b38a7b..00e335f 100644 --- a/src/lib/edit.js +++ b/src/lib/edit.js @@ -142,7 +142,9 @@ export function defaultUser() { email: '', full_name: '', name: '', - roles: [] + roles: [], + is_enabled: true, + password: '' } } diff --git a/src/pages/users/_userId/index.vue b/src/pages/users/_userId/index.vue index a67956d..38194d1 100644 --- a/src/pages/users/_userId/index.vue +++ b/src/pages/users/_userId/index.vue @@ -42,6 +42,10 @@ export default { ValidationObserver }, + beforeRouteLeave(_to, _from, next) { + this.$bus.$emit('edit-leave', { next }) + }, + layout: 'editor', middleware: [ @@ -84,10 +88,6 @@ export default { this.$bus.$off('editor-save', this.onSave) }, - beforeRouteLeave(_to, _from, next) { - this.$bus.$emit('edit-leave', { next }) - }, - methods: { ...mapActions({ fetchUsers: 'users/find', @@ -124,15 +124,18 @@ export default { async onSave() { if (!(await this.$refs.observer.validate())) return - const { instance } = this - const data = patchData({ ...instance, roles: [instance.roles] }) + const { + // eslint-disable-next-line camelcase + instance: { _id, email, full_name, name, roles } + } = this + const data = patchData({ email, full_name, name, roles: [roles] }) try { // HACK: Ensure that we have a fresh model afterwards - this.$store.commit('users/removeItem', instance._id) + this.$store.commit('users/removeItem', _id) - await this.patch([instance._id, data, {}]) - await this.fetchUsers({ query: { _id: instance._id } }) + await this.patch([_id, data, {}]) + await this.fetchUsers({ query: { _id } }) this.setEditing(false) this.setEditorDirty(-1) @@ -142,13 +145,12 @@ export default { message: 'User saved.' // TODO: Localize }) } catch (err) { - console.log('error', err) this.$bus.$emit('edit-status', { type: 'error', message: err.message }) // HACK: Ensure that we have a fresh model afterwards - this.$store.commit('users/removeItem', instance._id) + this.$store.commit('users/removeItem', _id) - await this.fetchUsers({ query: { _id: instance._id } }) + await this.fetchUsers({ query: { _id } }) } } } diff --git a/src/pages/users/create.vue b/src/pages/users/create.vue index df0f928..1deb6c8 100644 --- a/src/pages/users/create.vue +++ b/src/pages/users/create.vue @@ -11,7 +11,7 @@ diff --git a/src/components/UserPasswordEdit.vue b/src/components/UserPasswordEdit.vue index 67f2937..a191e4a 100644 --- a/src/components/UserPasswordEdit.vue +++ b/src/components/UserPasswordEdit.vue @@ -8,7 +8,7 @@ { inject('canPatch', (name, obj) => store.getters.isAbilityUpdated ? ability.can('patch', as(name, obj)) : false ) - inject('canRemove', (name, obj) => - store.getters.isAbilityUpdated - ? ability.can('remove', as(name, obj)) - : false - ) inject('cannot', (...args) => store.getters.isAbilityUpdated ? ability.cannot(...args) : true ) diff --git a/src/plugins/global-mixin.js b/src/plugins/global-mixin.js index b95c1c5..3db756b 100644 --- a/src/plugins/global-mixin.js +++ b/src/plugins/global-mixin.js @@ -64,8 +64,7 @@ import { mdiTwitter, mdiViewAgenda, mdiViewDashboard, - mdiViewList, - mdiDelete + mdiViewList } from '@mdi/js' Vue.mixin({ @@ -135,7 +134,6 @@ Vue.mixin({ mdiViewAgenda, mdiViewDashboard, mdiViewList, - mdiDelete, githubURL: process.env.githubURL, infoEmail: process.env.infoEmail, From c2eaabe24baceea6c975204dc11e308e743c31dc Mon Sep 17 00:00:00 2001 From: ergjustin Date: Mon, 20 Mar 2023 15:18:11 -0500 Subject: [PATCH 5/9] fix:user CRUD updated --- src/components/MainNavigationDrawer.vue | 18 +++-- src/components/UserDetail.vue | 48 ++++++++----- src/components/UsersSearch.vue | 91 +++++++++++++++++++++---- src/pages/users/_userId/index.vue | 24 +++---- src/pages/users/create.vue | 9 ++- src/pages/users/index.vue | 9 +-- src/plugins/ability.js | 5 ++ 7 files changed, 142 insertions(+), 62 deletions(-) diff --git a/src/components/MainNavigationDrawer.vue b/src/components/MainNavigationDrawer.vue index e0a5525..312c2a2 100644 --- a/src/components/MainNavigationDrawer.vue +++ b/src/components/MainNavigationDrawer.vue @@ -111,13 +111,6 @@ export default { icon: mdiLoginVariant, title: 'Log in', to: '/login' - }, - { - icon: mdiAccountGroup, - org: false, - title: 'Users', - to: '/users', - auth: true } ] }, @@ -198,6 +191,17 @@ export default { // title: 'Teams' // } ] + }, + { + header: 'Admin section', + items: [ + { + can: ['read', 'users'], + icon: mdiAccountGroup, + title: 'Users', + to: '/users' + } + ] } ] } diff --git a/src/components/UserDetail.vue b/src/components/UserDetail.vue index e6908c0..f8cbe71 100644 --- a/src/components/UserDetail.vue +++ b/src/components/UserDetail.vue @@ -23,18 +23,27 @@ + + + + - - - - + @@ -133,6 +130,21 @@ export default { editing: { default: false, type: Boolean }, value: { type: Object, required: true }, create: { default: false, type: Boolean } + }, + + computed: { + roles() { + const roles = ['user', 'manager'] + if ( + this.$cannotPatch('users', { + _id: this.value._id + }) + ) { + return roles.filter(role => role === this.value.roles) + } + + return roles + } } } diff --git a/src/components/UsersSearch.vue b/src/components/UsersSearch.vue index 70968ca..889efb8 100644 --- a/src/components/UsersSearch.vue +++ b/src/components/UsersSearch.vue @@ -1,5 +1,38 @@