|
|
|
@ -4,12 +4,12 @@ q-page.admin-groups
|
|
|
|
|
.col-auto
|
|
|
|
|
img.admin-icon.animated.fadeInLeft(src='/_assets/icons/fluent-people.svg')
|
|
|
|
|
.col.q-pl-md
|
|
|
|
|
.text-h5.text-primary.animated.fadeInLeft {{ $t('admin.groups.title') }}
|
|
|
|
|
.text-subtitle1.text-grey.animated.fadeInLeft.wait-p2s {{ $t('admin.groups.subtitle') }}
|
|
|
|
|
.text-h5.text-primary.animated.fadeInLeft {{ t('admin.groups.title') }}
|
|
|
|
|
.text-subtitle1.text-grey.animated.fadeInLeft.wait-p2s {{ t('admin.groups.subtitle') }}
|
|
|
|
|
.col-auto.flex.items-center
|
|
|
|
|
q-input.denser.q-mr-sm(
|
|
|
|
|
outlined
|
|
|
|
|
v-model='search'
|
|
|
|
|
v-model='state.search'
|
|
|
|
|
dense
|
|
|
|
|
:class='$q.dark.isActive ? `bg-dark` : `bg-white`'
|
|
|
|
|
)
|
|
|
|
@ -28,12 +28,12 @@ q-page.admin-groups
|
|
|
|
|
flat
|
|
|
|
|
color='secondary'
|
|
|
|
|
@click='load'
|
|
|
|
|
:loading='loading > 0'
|
|
|
|
|
:loading='state.loading > 0'
|
|
|
|
|
)
|
|
|
|
|
q-btn(
|
|
|
|
|
unelevated
|
|
|
|
|
icon='las la-plus'
|
|
|
|
|
:label='$t(`admin.groups.create`)'
|
|
|
|
|
:label='t(`admin.groups.create`)'
|
|
|
|
|
color='primary'
|
|
|
|
|
@click='createGroup'
|
|
|
|
|
)
|
|
|
|
@ -42,15 +42,15 @@ q-page.admin-groups
|
|
|
|
|
.col-12
|
|
|
|
|
q-card.shadow-1
|
|
|
|
|
q-table(
|
|
|
|
|
:rows='groups'
|
|
|
|
|
:rows='state.groups'
|
|
|
|
|
:columns='headers'
|
|
|
|
|
row-key='id'
|
|
|
|
|
flat
|
|
|
|
|
hide-header
|
|
|
|
|
hide-bottom
|
|
|
|
|
:rows-per-page-options='[0]'
|
|
|
|
|
:loading='loading > 0'
|
|
|
|
|
:filter='search'
|
|
|
|
|
:loading='state.loading > 0'
|
|
|
|
|
:filter='state.search'
|
|
|
|
|
)
|
|
|
|
|
template(v-slot:body-cell-id='props')
|
|
|
|
|
q-td(:props='props')
|
|
|
|
@ -71,7 +71,7 @@ q-page.admin-groups
|
|
|
|
|
:color='$q.dark.isActive ? `dark-6` : `grey-2`'
|
|
|
|
|
:text-color='$q.dark.isActive ? `white` : `grey-8`'
|
|
|
|
|
dense
|
|
|
|
|
) {{$t('admin.groups.usersCount', { count: props.value })}}
|
|
|
|
|
) {{t('admin.groups.usersCount', { count: props.value })}}
|
|
|
|
|
template(v-slot:body-cell-edit='props')
|
|
|
|
|
q-td(:props='props')
|
|
|
|
|
q-btn.acrylic-btn.q-mr-sm(
|
|
|
|
@ -79,7 +79,7 @@ q-page.admin-groups
|
|
|
|
|
:to='`/_admin/groups/` + props.row.id'
|
|
|
|
|
icon='las la-pen'
|
|
|
|
|
color='indigo'
|
|
|
|
|
:label='$t(`common.actions.edit`)'
|
|
|
|
|
:label='t(`common.actions.edit`)'
|
|
|
|
|
no-caps
|
|
|
|
|
)
|
|
|
|
|
q-btn.acrylic-btn(
|
|
|
|
@ -91,136 +91,178 @@ q-page.admin-groups
|
|
|
|
|
)
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
<script setup>
|
|
|
|
|
import gql from 'graphql-tag'
|
|
|
|
|
import cloneDeep from 'lodash/cloneDeep'
|
|
|
|
|
import { createMetaMixin } from 'quasar'
|
|
|
|
|
import { sync } from 'vuex-pathify'
|
|
|
|
|
import { useI18n } from 'vue-i18n'
|
|
|
|
|
import { useMeta, useQuasar } from 'quasar'
|
|
|
|
|
import { computed, onBeforeUnmount, onMounted, reactive, watch } from 'vue'
|
|
|
|
|
import { useRouter, useRoute } from 'vue-router'
|
|
|
|
|
|
|
|
|
|
import { useAdminStore } from 'src/stores/admin'
|
|
|
|
|
|
|
|
|
|
import GroupCreateDialog from '../components/GroupCreateDialog.vue'
|
|
|
|
|
import GroupDeleteDialog from '../components/GroupDeleteDialog.vue'
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
mixins: [
|
|
|
|
|
createMetaMixin(function () {
|
|
|
|
|
return {
|
|
|
|
|
title: this.$t('admin.groups.title')
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
],
|
|
|
|
|
data () {
|
|
|
|
|
return {
|
|
|
|
|
groups: [],
|
|
|
|
|
loading: 0,
|
|
|
|
|
search: ''
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
computed: {
|
|
|
|
|
overlay: sync('admin/overlay', false),
|
|
|
|
|
headers () {
|
|
|
|
|
return [
|
|
|
|
|
{
|
|
|
|
|
align: 'center',
|
|
|
|
|
field: 'id',
|
|
|
|
|
name: 'id',
|
|
|
|
|
sortable: false,
|
|
|
|
|
style: 'width: 20px'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: this.$t('common.field.name'),
|
|
|
|
|
align: 'left',
|
|
|
|
|
field: 'name',
|
|
|
|
|
name: 'name',
|
|
|
|
|
sortable: true
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: this.$t('admin.groups.userCount'),
|
|
|
|
|
align: 'center',
|
|
|
|
|
field: 'userCount',
|
|
|
|
|
name: 'usercount',
|
|
|
|
|
sortable: false,
|
|
|
|
|
style: 'width: 150px'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '',
|
|
|
|
|
align: 'right',
|
|
|
|
|
field: 'edit',
|
|
|
|
|
name: 'edit',
|
|
|
|
|
sortable: false,
|
|
|
|
|
style: 'width: 250px'
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
watch: {
|
|
|
|
|
overlay (newValue, oldValue) {
|
|
|
|
|
if (newValue === '' && oldValue === 'GroupEditOverlay') {
|
|
|
|
|
this.$router.push('/_admin/groups')
|
|
|
|
|
this.load()
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
$route: 'checkOverlay'
|
|
|
|
|
// QUASAR
|
|
|
|
|
|
|
|
|
|
const $q = useQuasar()
|
|
|
|
|
|
|
|
|
|
// STORES
|
|
|
|
|
|
|
|
|
|
const adminStore = useAdminStore()
|
|
|
|
|
|
|
|
|
|
// ROUTER
|
|
|
|
|
|
|
|
|
|
const router = useRouter()
|
|
|
|
|
const route = useRoute()
|
|
|
|
|
|
|
|
|
|
// I18N
|
|
|
|
|
|
|
|
|
|
const { t } = useI18n()
|
|
|
|
|
|
|
|
|
|
// META
|
|
|
|
|
|
|
|
|
|
useMeta({
|
|
|
|
|
title: t('admin.groups.title')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// DATA
|
|
|
|
|
|
|
|
|
|
const state = reactive({
|
|
|
|
|
groups: [],
|
|
|
|
|
loading: 0,
|
|
|
|
|
search: ''
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const headers = [
|
|
|
|
|
{
|
|
|
|
|
align: 'center',
|
|
|
|
|
field: 'id',
|
|
|
|
|
name: 'id',
|
|
|
|
|
sortable: false,
|
|
|
|
|
style: 'width: 20px'
|
|
|
|
|
},
|
|
|
|
|
mounted () {
|
|
|
|
|
this.checkOverlay()
|
|
|
|
|
this.load()
|
|
|
|
|
{
|
|
|
|
|
label: t('common.field.name'),
|
|
|
|
|
align: 'left',
|
|
|
|
|
field: 'name',
|
|
|
|
|
name: 'name',
|
|
|
|
|
sortable: true
|
|
|
|
|
},
|
|
|
|
|
beforeUnmount () {
|
|
|
|
|
this.overlay = ''
|
|
|
|
|
{
|
|
|
|
|
label: t('admin.groups.userCount'),
|
|
|
|
|
align: 'center',
|
|
|
|
|
field: 'userCount',
|
|
|
|
|
name: 'usercount',
|
|
|
|
|
sortable: false,
|
|
|
|
|
style: 'width: 150px'
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
async load () {
|
|
|
|
|
this.loading++
|
|
|
|
|
this.$q.loading.show()
|
|
|
|
|
const resp = await this.$apollo.query({
|
|
|
|
|
query: gql`
|
|
|
|
|
query getGroups {
|
|
|
|
|
groups {
|
|
|
|
|
id
|
|
|
|
|
name
|
|
|
|
|
isSystem
|
|
|
|
|
userCount
|
|
|
|
|
createdAt
|
|
|
|
|
updatedAt
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
label: '',
|
|
|
|
|
align: 'right',
|
|
|
|
|
field: 'edit',
|
|
|
|
|
name: 'edit',
|
|
|
|
|
sortable: false,
|
|
|
|
|
style: 'width: 250px'
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
watch(() => adminStore.overlay, (newValue, oldValue) => {
|
|
|
|
|
if (newValue === '' && oldValue === 'GroupEditOverlay') {
|
|
|
|
|
router.push('/_admin/groups')
|
|
|
|
|
load()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
watch(() => route, () => {
|
|
|
|
|
checkOverlay()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// METHODS
|
|
|
|
|
|
|
|
|
|
async function load () {
|
|
|
|
|
state.loading++
|
|
|
|
|
$q.loading.show()
|
|
|
|
|
try {
|
|
|
|
|
const resp = await APOLLO_CLIENT.query({
|
|
|
|
|
query: gql`
|
|
|
|
|
query getGroups {
|
|
|
|
|
groups {
|
|
|
|
|
id
|
|
|
|
|
name
|
|
|
|
|
isSystem
|
|
|
|
|
userCount
|
|
|
|
|
createdAt
|
|
|
|
|
updatedAt
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
fetchPolicy: 'network-only'
|
|
|
|
|
})
|
|
|
|
|
this.groups = cloneDeep(resp?.data?.groups)
|
|
|
|
|
this.$q.loading.hide()
|
|
|
|
|
this.loading--
|
|
|
|
|
},
|
|
|
|
|
checkOverlay () {
|
|
|
|
|
if (this.$route.params && this.$route.params.id) {
|
|
|
|
|
this.$store.set('admin/overlayOpts', { id: this.$route.params.id })
|
|
|
|
|
this.$store.set('admin/overlay', 'GroupEditOverlay')
|
|
|
|
|
} else {
|
|
|
|
|
this.$store.set('admin/overlay', '')
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
createGroup () {
|
|
|
|
|
this.$q.dialog({
|
|
|
|
|
component: GroupCreateDialog
|
|
|
|
|
}).onOk(() => {
|
|
|
|
|
this.load()
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
editGroup (gr) {
|
|
|
|
|
this.$router.push(`/_admin/groups/${gr.id}`)
|
|
|
|
|
},
|
|
|
|
|
deleteGroup (gr) {
|
|
|
|
|
this.$q.dialog({
|
|
|
|
|
component: GroupDeleteDialog,
|
|
|
|
|
componentProps: {
|
|
|
|
|
group: gr
|
|
|
|
|
}
|
|
|
|
|
}).onOk(() => {
|
|
|
|
|
this.load()
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
fetchPolicy: 'network-only'
|
|
|
|
|
})
|
|
|
|
|
state.groups = cloneDeep(resp?.data?.groups)
|
|
|
|
|
} catch (err) {
|
|
|
|
|
$q.notify({
|
|
|
|
|
type: 'negative',
|
|
|
|
|
message: 'Failed to load groups.',
|
|
|
|
|
caption: err.message
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
$q.loading.hide()
|
|
|
|
|
state.loading--
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function checkOverlay () {
|
|
|
|
|
if (route.params && route.params.id) {
|
|
|
|
|
adminStore.$patch({
|
|
|
|
|
overlayOpts: { id: route.params.id },
|
|
|
|
|
overlay: 'GroupEditOverlay'
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
adminStore.$patch({
|
|
|
|
|
overlay: ''
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function createGroup () {
|
|
|
|
|
$q.dialog({
|
|
|
|
|
component: GroupCreateDialog
|
|
|
|
|
}).onOk(() => {
|
|
|
|
|
load()
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function editGroup (gr) {
|
|
|
|
|
router.push(`/_admin/groups/${gr.id}`)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function deleteGroup (gr) {
|
|
|
|
|
$q.dialog({
|
|
|
|
|
component: GroupDeleteDialog,
|
|
|
|
|
componentProps: {
|
|
|
|
|
group: gr
|
|
|
|
|
}
|
|
|
|
|
}).onOk(() => {
|
|
|
|
|
load()
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MOUNTED
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
checkOverlay()
|
|
|
|
|
load()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// BEFORE UNMOUNT
|
|
|
|
|
|
|
|
|
|
onBeforeUnmount(() => {
|
|
|
|
|
adminStore.$patch({
|
|
|
|
|
overlay: ''
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang='scss'>
|
|
|
|
|