From 8aba5305d87bea8841e414735da9fa46e9f3debb Mon Sep 17 00:00:00 2001 From: NGPixel Date: Sat, 18 Apr 2020 18:25:16 -0400 Subject: [PATCH] feat: sidebar item permissions + admin nav edit --- client/client-app.js | 1 + .../admin/admin-groups-edit-rules.vue | 22 +- client/components/admin/admin-navigation.vue | 54 +++- .../themes/default/components/nav-sidebar.vue | 21 +- package.json | 28 +- server/controllers/auth.js | 2 +- server/controllers/common.js | 2 +- server/core/db.js | 1 + server/core/telemetry.js | 15 +- server/graph/resolvers/navigation.js | 6 +- server/graph/schemas/navigation.graphql | 4 + server/models/navigation.js | 26 +- server/setup.js | 17 +- yarn.lock | 244 ++++++++---------- 14 files changed, 239 insertions(+), 204 deletions(-) diff --git a/client/client-app.js b/client/client-app.js index 9d53901d..2b4b6254 100644 --- a/client/client-app.js +++ b/client/client-app.js @@ -215,6 +215,7 @@ let bootstrap = () => { // Load theme-specific code // ==================================== + // eslint-disable-next-line no-unused-expressions import(/* webpackChunkName: "theme-page" */ './themes/' + process.env.CURRENT_THEME + '/js/app.js') } diff --git a/client/components/admin/admin-groups-edit-rules.vue b/client/components/admin/admin-groups-edit-rules.vue index 6cd8f92c..0cdcedf4 100644 --- a/client/components/admin/admin-groups-edit-rules.vue +++ b/client/components/admin/admin-groups-edit-rules.vue @@ -118,6 +118,8 @@ :items='locales' v-model='rule.locales' placeholder='Any Locale' + item-value='code' + item-text='name' multiple hide-details height='48px' @@ -126,7 +128,7 @@ style='flex: 0 1 150px;' ) template(slot='selection', slot-scope='{ item, index }') - v-chip.white--text.ml-0(v-if='rule.locales.length === 1', small, label, :color='rule.deny ? `red` : `green`').caption {{ item.value.toUpperCase() }} + v-chip.white--text.ml-0(v-if='rule.locales.length === 1', small, label, :color='rule.deny ? `red` : `green`').caption {{ item.code.toUpperCase() }} v-chip.white--text.ml-0(v-else-if='index === 0', small, label, :color='rule.deny ? `red` : `green`').caption {{ rule.locales.length }} locales v-list-item(slot='prepend-item', @click='rule.locales = []') v-list-item-action(style='min-width: 30px;') @@ -149,8 +151,8 @@ ) v-icon.mr-2(:color='rule.deny ? `red` : `green`') mdi-web v-list-item-content - v-list-item-title.body-2 {{props.item.text}} - v-chip.mr-2.grey--text(label, small, :color='$vuetify.theme.dark ? `grey darken-4` : `grey lighten-4`').caption {{props.item.value.toUpperCase()}} + v-list-item-title.body-2 {{props.item.name}} + v-chip.mr-2.grey--text(label, small, :color='$vuetify.theme.dark ? `grey darken-4` : `grey lighten-4`').caption {{props.item.code.toUpperCase()}} //- Path v-text-field( @@ -197,6 +199,8 @@ import _ from 'lodash' import { customAlphabet } from 'nanoid/non-secure' +/* global siteLangs */ + const nanoid = customAlphabet('1234567890abcdef', 10) export default { @@ -209,10 +213,10 @@ export default { data() { return { roles: [ - { text: 'Read Pages', value: 'read:pages', icon: 'mdi-file-document-box-search-outline' }, - { text: 'Create Pages', value: 'write:pages', icon: 'mdi-file-document-box-plus-outline' }, + { text: 'Read Pages', value: 'read:pages', icon: 'mdi-file-eye-outline' }, + { text: 'Create Pages', value: 'write:pages', icon: 'mdi-file-plus-outline' }, { text: 'Edit + Move Pages', value: 'manage:pages', icon: 'mdi-file-document-edit-outline' }, - { text: 'Delete Pages', value: 'delete:pages', icon: 'mdi-file-document-box-remove-outline' }, + { text: 'Delete Pages', value: 'delete:pages', icon: 'mdi-file-remove-outline' }, { text: 'View Pages Source', value: 'read:source', icon: 'mdi-code-tags' }, { text: 'View Pages History', value: 'read:history', icon: 'mdi-history' }, { text: 'Read / Use Assets', value: 'read:assets', icon: 'mdi-image-search-outline' }, @@ -228,9 +232,6 @@ export default { { text: 'Path Ends With...', value: 'END', icon: '.../' }, { text: 'Path Matches Regex...', value: 'REGEX', icon: '$.*' }, { text: 'Tag Matches...', value: 'TAG', icon: 'T' } - ], - locales: [ - { text: 'English', value: 'en' } ] } }, @@ -238,7 +239,8 @@ export default { group: { get() { return this.value }, set(val) { this.$set('input', val) } - } + }, + locales() { return siteLangs } }, methods: { addRule(group) { diff --git a/client/components/admin/admin-navigation.vue b/client/components/admin/admin-navigation.vue index 4f9bdb00..5bbb2671 100644 --- a/client/components/admin/admin-navigation.vue +++ b/client/components/admin/admin-navigation.vue @@ -69,12 +69,12 @@ item-value='code' ) v-list.py-2(dense, nav, dark, class='blue darken-2', style='border-radius: 0;') - v-list-item(v-if='navTree.length < 1') + v-list-item(v-if='currentTree.length < 1') v-list-item-avatar(size='24'): v-icon(color='blue lighten-3') mdi-alert v-list-item-content em.caption.blue--text.text--lighten-4 {{$t('navigation.emptyList')}} - draggable(v-model='navTree') - template(v-for='navItem in navTree') + draggable(v-model='currentTree') + template(v-for='navItem in currentTree') v-list-item( v-if='navItem.kind === "link"' :key='navItem.id' @@ -223,7 +223,7 @@ ) template(v-else) v-toolbar(height='56', color='teal lighten-1', flat, dark) - v-card-text.grey--text(v-if='navTree.length > 0') {{$t('navigation.noSelectionText')}} + v-card-text.grey--text(v-if='currentTree.length > 0') {{$t('navigation.noSelectionText')}} v-card-text.grey--text(v-else) {{$t('navigation.noItemsText')}} page-selector(mode='select', v-model='selectPageModal', :open-handler='selectPageHandle', path='home', :locale='currentLang') @@ -247,9 +247,9 @@ export default { data() { return { selectPageModal: false, - navTree: [], + trees: [], current: {}, - currentLang: 'en', + currentLang: siteConfig.lang, groups: [], config: { mode: 'NONE' @@ -267,6 +267,33 @@ export default { }, locales () { return siteLangs + }, + currentTree: { + get () { + return _.get(_.find(this.trees, ['locale', this.currentLang]), 'items', null) || [] + }, + set (val) { + const tree = _.find(this.trees, ['locale', this.currentLang]) + if (tree) { + tree.items = val + } else { + this.trees = [...this.trees, { + locale: this.currentLang, + items: val + }] + } + } + } + }, + watch: { + currentLang (newValue, oldValue) { + this.$nextTick(() => { + if (this.currentTree.length > 0) { + this.current = this.currentTree[0] + } else { + this.current = {} + } + }) } }, methods: { @@ -291,11 +318,11 @@ export default { newItem.label = this.$t('navigation.untitled', { kind: this.$t(`navigation.header`) }) break } - this.navTree.push(newItem) + this.currentTree = [...this.currentTree, newItem] this.current = newItem }, deleteItem(item) { - this.navTree = _.pull(this.navTree, item) + this.currentTree = _.pull(this.currentTree, item) this.current = {} }, selectItem(item) { @@ -326,7 +353,7 @@ export default { } `, variables: { - tree: this.navTree + tree: this.trees } }) if (_.get(resp, 'data.navigation.updateTree.responseResult.succeeded', false)) { @@ -344,7 +371,7 @@ export default { this.$store.commit(`loadingStop`, 'admin-navigation-save') }, async refresh() { - await this.$apollo.queries.navTree.refetch() + await this.$apollo.queries.trees.refetch() this.current = {} this.$store.commit('showNotification', { message: 'Navigation has been refreshed.', @@ -353,9 +380,6 @@ export default { }) } }, - mounted () { - this.currentLang = siteConfig.lang - }, apollo: { config: { query: gql` @@ -373,7 +397,7 @@ export default { this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-navigation-config') } }, - navTree: { + trees: { query: gql` { navigation { @@ -386,6 +410,8 @@ export default { icon targetType target + visibilityMode + visibilityGroups } } } diff --git a/client/themes/default/components/nav-sidebar.vue b/client/themes/default/components/nav-sidebar.vue index ca13c8c6..d754dcf2 100644 --- a/client/themes/default/components/nav-sidebar.vue +++ b/client/themes/default/components/nav-sidebar.vue @@ -1,14 +1,14 @@