feat(admin): migrate nav + auth to vue 3 composition, convert lodash to lodash-es

pull/5698/head
Nicolas Giard 2 years ago
parent 8fb29cfc21
commit 4675348c43
No known key found for this signature in database
GPG Key ID: 85061B8F9D55B7C8

@ -69,6 +69,7 @@
"js-cookie": "3.0.1", "js-cookie": "3.0.1",
"jwt-decode": "3.1.2", "jwt-decode": "3.1.2",
"lodash": "4.17.21", "lodash": "4.17.21",
"lodash-es": "4.17.21",
"luxon": "2.4.0", "luxon": "2.4.0",
"pinia": "2.0.14", "pinia": "2.0.14",
"pug": "3.0.2", "pug": "3.0.2",

@ -95,7 +95,7 @@ q-layout.admin(view='hHh Lpr lff')
q-item-section(avatar) q-item-section(avatar)
q-icon(name='img:/_assets/icons/fluent-tree-structure.svg') q-icon(name='img:/_assets/icons/fluent-tree-structure.svg')
q-item-section {{ t('admin.navigation.title') }} q-item-section {{ t('admin.navigation.title') }}
q-item(:to='`/_admin/` + adminStore.currentSiteId + `/rendering`', v-ripple, active-class='bg-primary text-white') q-item(:to='`/_admin/` + adminStore.currentSiteId + `/rendering`', v-ripple, active-class='bg-primary text-white', disabled)
q-item-section(avatar) q-item-section(avatar)
q-icon(name='img:/_assets/icons/fluent-rich-text-converter.svg') q-icon(name='img:/_assets/icons/fluent-rich-text-converter.svg')
q-item-section {{ t('admin.rendering.title') }} q-item-section {{ t('admin.rendering.title') }}

@ -116,7 +116,7 @@ q-page.admin-api
<script setup> <script setup>
import gql from 'graphql-tag' import gql from 'graphql-tag'
import cloneDeep from 'lodash/cloneDeep' import { cloneDeep } from 'lodash-es'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useMeta, useQuasar } from 'quasar' import { useMeta, useQuasar } from 'quasar'
import { computed, onMounted, reactive, watch } from 'vue' import { computed, onMounted, reactive, watch } from 'vue'

@ -4,8 +4,8 @@ q-page.admin-mail
.col-auto .col-auto
img.admin-icon.animated.fadeInLeft(src='/_assets/icons/fluent-security-lock.svg') img.admin-icon.animated.fadeInLeft(src='/_assets/icons/fluent-security-lock.svg')
.col.q-pl-md .col.q-pl-md
.text-h5.text-primary.animated.fadeInLeft {{ $t('admin.auth.title') }} .text-h5.text-primary.animated.fadeInLeft {{ t('admin.auth.title') }}
.text-subtitle1.text-grey.animated.fadeInLeft.wait-p2s {{ $t('admin.auth.subtitle') }} .text-subtitle1.text-grey.animated.fadeInLeft.wait-p2s {{ t('admin.auth.subtitle') }}
.col-auto .col-auto
q-btn.q-mr-sm.acrylic-btn( q-btn.q-mr-sm.acrylic-btn(
icon='las la-question-circle' icon='las la-question-circle'
@ -17,11 +17,11 @@ q-page.admin-mail
) )
q-btn( q-btn(
unelevated unelevated
icon='mdi-check' icon='fa-solid fa-check'
:label='$t(`common.actions.apply`)' :label='t(`common.actions.apply`)'
color='secondary' color='secondary'
@click='save' @click='save'
:loading='loading' :loading='state.loading > 0'
) )
q-separator(inset) q-separator(inset)
.row.q-pa-md.q-col-gutter-md .row.q-pa-md.q-col-gutter-md
@ -33,11 +33,11 @@ q-page.admin-mail
dark dark
) )
q-item( q-item(
v-for='str of activeStrategies' v-for='str of state.activeStrategies'
:key='str.key' :key='str.key'
active-class='bg-primary text-white' active-class='bg-primary text-white'
:active='selectedStrategy === str.key' :active='state.selectedStrategy === str.key'
@click='selectedStrategy = str.key' @click='state.selectedStrategy = str.key'
clickable clickable
) )
q-item-section(side) q-item-section(side)
@ -52,7 +52,7 @@ q-page.admin-mail
q-btn.q-mt-sm.full-width( q-btn.q-mt-sm.full-width(
color='primary' color='primary'
icon='las la-plus' icon='las la-plus'
:label='$t(`admin.auth.addStrategy`)' :label='t(`admin.auth.addStrategy`)'
) )
q-menu(auto-close) q-menu(auto-close)
q-list(style='min-width: 350px;') q-list(style='min-width: 350px;')
@ -261,30 +261,43 @@ q-page.admin-mail
//- .body-2 HTTP-POST //- .body-2 HTTP-POST
</template> </template>
<script> <script setup>
import _ from 'lodash'
import gql from 'graphql-tag' import gql from 'graphql-tag'
import { find, reject } from 'lodash-es'
import { v4 as uuid } from 'uuid' import { v4 as uuid } from 'uuid'
import { createMetaMixin } from 'quasar'
import { useI18n } from 'vue-i18n'
import { useMeta, useQuasar } from 'quasar'
import { computed, onMounted, reactive, watch, nextTick } from 'vue'
import { useAdminStore } from 'src/stores/admin'
import { useSiteStore } from 'src/stores/site'
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
export default { // QUASAR
mixins: [
createMetaMixin(function () { const $q = useQuasar()
return {
title: this.$t('admin.auth.title') // STORES
}
const adminStore = useAdminStore()
const siteStore = useSiteStore()
// I18N
const { t } = useI18n()
// META
useMeta({
title: t('admin.auth.title')
}) })
],
components: { // DATA
draggable
}, const state = reactive({
filters: { loading: 0,
startCase (val) { return _.startCase(val) }
},
data () {
return {
groups: [], groups: [],
strategies: [], strategies: [],
activeStrategies: [ activeStrategies: [
@ -345,18 +358,20 @@ export default {
strategy: { strategy: {
strategy: {} strategy: {}
} }
} })
},
watch: { // WATCHERS
selectedStrategy (newValue, oldValue) {
this.strategy = _.find(this.activeStrategies, ['key', newValue]) || {} watch(() => state.selectedStrategy, (newValue, oldValue) => {
}, state.strategy = find(state.activeStrategies, ['key', newValue]) || {}
activeStrategies (newValue, oldValue) { })
this.selectedStrategy = 'local' watch(() => state.activeStrategies, (newValue, oldValue) => {
} state.selectedStrategy = 'local'
}, })
methods: {
async refresh () { // METHODS
async function refresh () {
await this.$apollo.queries.strategies.refetch() await this.$apollo.queries.strategies.refetch()
await this.$apollo.queries.activeStrategies.refetch() await this.$apollo.queries.activeStrategies.refetch()
this.$store.commit('showNotification', { this.$store.commit('showNotification', {
@ -364,8 +379,9 @@ export default {
style: 'success', style: 'success',
icon: 'cached' icon: 'cached'
}) })
}, }
addStrategy (str) {
function addStrategy (str) {
const newStr = { const newStr = {
key: uuid(), key: uuid(),
strategy: str, strategy: str,
@ -376,25 +392,27 @@ export default {
value: c.default value: c.default
} }
})), })),
order: this.activeStrategies.length, order: state.activeStrategies.length,
isEnabled: true, isEnabled: true,
displayName: str.title, displayName: str.title,
selfRegistration: false, selfRegistration: false,
domainWhitelist: [], domainWhitelist: [],
autoEnrollGroups: [] autoEnrollGroups: []
} }
this.activeStrategies = [...this.activeStrategies, newStr] state.activeStrategies = [...state.activeStrategies, newStr]
this.$nextTick(() => { nextTick(() => {
this.selectedStrategy = newStr.key state.selectedStrategy = newStr.key
}) })
}, }
deleteStrategy () {
this.activeStrategies = _.reject(this.activeStrategies, ['key', this.strategy.key]) function deleteStrategy () {
}, state.activeStrategies = reject(state.activeStrategies, ['key', state.strategy.key])
async save () { }
this.$store.commit('loadingStart', 'admin-auth-savestrategies')
async function save () {
state.loading++
try { try {
const resp = await this.$apollo.mutate({ const resp = await APOLLO_CLIENT.mutate({
mutation: gql` mutation: gql`
mutation($strategies: [AuthenticationStrategyInput]!) { mutation($strategies: [AuthenticationStrategyInput]!) {
authentication { authentication {
@ -423,113 +441,114 @@ export default {
})) }))
} }
}) })
if (_.get(resp, 'data.authentication.updateStrategies.responseResult.succeeded', false)) { if (resp?.data?.authentication?.updateStrategies?.operation.succeeded) {
this.$store.commit('showNotification', { $q.notify({
message: this.$t('admin.auth.saveSuccess'), type: 'positive',
style: 'success', message: t('admin.auth.saveSuccess')
icon: 'check'
}) })
} else { } else {
throw new Error(_.get(resp, 'data.authentication.updateStrategies.responseResult.message', this.$t('common.error.unexpected'))) throw new Error(resp?.data?.authentication?.updateStrategies?.operation?.message || t('common.error.unexpected'))
} }
} catch (err) { } catch (err) {
this.$store.commit('pushGraphError', err) $q.notify({
} type: 'negative',
this.$store.commit('loadingStop', 'admin-auth-savestrategies') message: 'Failed to save site theme config',
} caption: err.message
}, })
apollo: {
strategies: {
query: gql`
query {
authentication {
strategies {
key
title
description
isAvailable
useForm
logo
website
props {
key
value
}
}
}
}
`,
skip: true,
fetchPolicy: 'network-only',
update: (data) => _.get(data, 'authentication.strategies', []).map(str => ({
...str,
isDisabled: !str.isAvailable || str.key === 'local',
props: _.sortBy(str.props.map(cfg => ({
key: cfg.key,
...JSON.parse(cfg.value)
})), [t => t.order])
})),
watchLoading (isLoading) {
this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-auth-strategies-refresh')
}
},
activeStrategies: {
query: gql`
query {
authentication {
activeStrategies {
key
strategy {
key
title
description
useForm
logo
website
}
config {
key
value
}
order
isEnabled
displayName
selfRegistration
domainWhitelist
autoEnrollGroups
}
}
}
`,
skip: true,
fetchPolicy: 'network-only',
update: (data) => _.sortBy(_.get(data, 'authentication.activeStrategies', []).map(str => ({
...str,
config: _.sortBy(str.config.map(cfg => ({
...cfg,
value: JSON.parse(cfg.value)
})), [t => t.value.order])
})), ['order']),
watchLoading (isLoading) {
this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-auth-activestrategies-refresh')
}
},
groups: {
query: gql`{ test }`,
fetchPolicy: 'network-only',
update: (data) => data.groups.list,
watchLoading (isLoading) {
this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-auth-groups-refresh')
}
},
host: {
query: gql`{ test }`,
fetchPolicy: 'network-only',
update: (data) => _.cloneDeep(data.site.config.host),
watchLoading (isLoading) {
this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-auth-host-refresh')
}
}
} }
state.loading--
} }
// apollo: {
// strategies: {
// query: gql`
// query {
// authentication {
// strategies {
// key
// title
// description
// isAvailable
// useForm
// logo
// website
// props {
// key
// value
// }
// }
// }
// }
// `,
// skip: true,
// fetchPolicy: 'network-only',
// update: (data) => _.get(data, 'authentication.strategies', []).map(str => ({
// ...str,
// isDisabled: !str.isAvailable || str.key === 'local',
// props: _.sortBy(str.props.map(cfg => ({
// key: cfg.key,
// ...JSON.parse(cfg.value)
// })), [t => t.order])
// })),
// watchLoading (isLoading) {
// this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-auth-strategies-refresh')
// }
// },
// activeStrategies: {
// query: gql`
// query {
// authentication {
// activeStrategies {
// key
// strategy {
// key
// title
// description
// useForm
// logo
// website
// }
// config {
// key
// value
// }
// order
// isEnabled
// displayName
// selfRegistration
// domainWhitelist
// autoEnrollGroups
// }
// }
// }
// `,
// skip: true,
// fetchPolicy: 'network-only',
// update: (data) => _.sortBy(_.get(data, 'authentication.activeStrategies', []).map(str => ({
// ...str,
// config: _.sortBy(str.config.map(cfg => ({
// ...cfg,
// value: JSON.parse(cfg.value)
// })), [t => t.value.order])
// })), ['order']),
// watchLoading (isLoading) {
// this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-auth-activestrategies-refresh')
// }
// },
// groups: {
// query: gql`{ test }`,
// fetchPolicy: 'network-only',
// update: (data) => data.groups.list,
// watchLoading (isLoading) {
// this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-auth-groups-refresh')
// }
// },
// host: {
// query: gql`{ test }`,
// fetchPolicy: 'network-only',
// update: (data) => _.cloneDeep(data.site.config.host),
// watchLoading (isLoading) {
// this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-auth-host-refresh')
// }
// }
</script> </script>

@ -99,7 +99,7 @@ q-page.admin-extensions
<script setup> <script setup>
import gql from 'graphql-tag' import gql from 'graphql-tag'
import cloneDeep from 'lodash/cloneDeep' import { cloneDeep } from 'lodash-es'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useMeta, useQuasar } from 'quasar' import { useMeta, useQuasar } from 'quasar'
import { computed, onMounted, reactive, watch } from 'vue' import { computed, onMounted, reactive, watch } from 'vue'

@ -82,7 +82,7 @@ q-page.admin-flags
<script setup> <script setup>
import gql from 'graphql-tag' import gql from 'graphql-tag'
import { defineAsyncComponent, onMounted, reactive, ref, watch } from 'vue' import { defineAsyncComponent, onMounted, reactive, ref, watch } from 'vue'
import _transform from 'lodash/transform' import { transform } from 'lodash-es'
import { useMeta, useQuasar } from 'quasar' import { useMeta, useQuasar } from 'quasar'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'

@ -391,7 +391,7 @@ q-page.admin-general
<script setup> <script setup>
import gql from 'graphql-tag' import gql from 'graphql-tag'
import cloneDeep from 'lodash/cloneDeep' import { cloneDeep } from 'lodash-es'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useMeta, useQuasar } from 'quasar' import { useMeta, useQuasar } from 'quasar'
import { onMounted, reactive, watch } from 'vue' import { onMounted, reactive, watch } from 'vue'

@ -93,7 +93,7 @@ q-page.admin-groups
<script setup> <script setup>
import gql from 'graphql-tag' import gql from 'graphql-tag'
import cloneDeep from 'lodash/cloneDeep' import { cloneDeep } from 'lodash-es'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useMeta, useQuasar } from 'quasar' import { useMeta, useQuasar } from 'quasar'
import { computed, onBeforeUnmount, onMounted, reactive, watch } from 'vue' import { computed, onBeforeUnmount, onMounted, reactive, watch } from 'vue'

@ -143,9 +143,7 @@ q-page.admin-locale
<script setup> <script setup>
import gql from 'graphql-tag' import gql from 'graphql-tag'
import filter from 'lodash/filter' import { cloneDeep, filter } from 'lodash-es'
import _get from 'lodash/get'
import cloneDeep from 'lodash/cloneDeep'
import LocaleInstallDialog from '../components/LocaleInstallDialog.vue' import LocaleInstallDialog from '../components/LocaleInstallDialog.vue'
@ -278,7 +276,7 @@ async function download (lc) {
locale: lc.code locale: lc.code
} }
}) })
const resp = _get(respRaw, 'data.localization.downloadLocale.responseResult', {}) const resp = respRaw?.data?.localization?.downloadLocale?.responseResult || {}
if (resp.succeeded) { if (resp.succeeded) {
lc.isDownloading = false lc.isDownloading = false
lc.isInstalled = true lc.isInstalled = true
@ -331,7 +329,7 @@ async function save () {
namespaces: state.namespaces namespaces: state.namespaces
} }
}) })
const resp = _get(respRaw, 'data.localization.updateLocale.responseResult', {}) const resp = respRaw?.data?.localization?.updateLocale?.responseResult || {}
if (resp.succeeded) { if (resp.succeeded) {
// Change UI language // Change UI language
this.$i18n.locale = state.selectedLocale this.$i18n.locale = state.selectedLocale

@ -176,8 +176,7 @@ q-page.admin-login
</template> </template>
<script setup> <script setup>
import { get } from 'vuex-pathify' import { cloneDeep } from 'lodash-es'
import cloneDeep from 'lodash/cloneDeep'
import gql from 'graphql-tag' import gql from 'graphql-tag'
import draggable from 'vuedraggable' import draggable from 'vuedraggable'

@ -298,9 +298,7 @@ q-page.admin-mail
</template> </template>
<script setup> <script setup>
import toSafeInteger from 'lodash/toSafeInteger' import { cloneDeep, toSafeInteger } from 'lodash-es'
import _get from 'lodash/get'
import cloneDeep from 'lodash/cloneDeep'
import gql from 'graphql-tag' import gql from 'graphql-tag'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
@ -477,7 +475,7 @@ async function sendTest () {
sendMailTest( sendMailTest(
recipientEmail: $recipientEmail recipientEmail: $recipientEmail
) { ) {
status { operation {
succeeded succeeded
slug slug
message message
@ -489,8 +487,8 @@ async function sendTest () {
recipientEmail: state.testEmail recipientEmail: state.testEmail
} }
}) })
if (!_get(resp, 'data.sendMailTest.status.succeeded', false)) { if (!resp?.data?.sendMailTest?.operation?.succeeded) {
throw new Error(_get(resp, 'data.sendMailTest.status.message', 'An unexpected error occurred.')) throw new Error(resp?.data?.sendMailTest?.operation?.message || 'An unexpected error occurred.')
} }
state.testEmail = '' state.testEmail = ''

@ -4,8 +4,8 @@ q-page.admin-navigation
.col-auto .col-auto
img.admin-icon.animated.fadeInLeft(src='/_assets/icons/fluent-tree-structure.svg') img.admin-icon.animated.fadeInLeft(src='/_assets/icons/fluent-tree-structure.svg')
.col.q-pl-md .col.q-pl-md
.text-h5.text-primary.animated.fadeInLeft {{ $t('admin.navigation.title') }} .text-h5.text-primary.animated.fadeInLeft {{ t('admin.navigation.title') }}
.text-subtitle1.text-grey.animated.fadeInLeft.wait-p2s {{ $t('admin.navigation.subtitle') }} .text-subtitle1.text-grey.animated.fadeInLeft.wait-p2s {{ t('admin.navigation.subtitle') }}
.col-auto .col-auto
q-btn.acrylic-btn.q-mr-sm( q-btn.acrylic-btn.q-mr-sm(
icon='las la-question-circle' icon='las la-question-circle'
@ -19,16 +19,16 @@ q-page.admin-navigation
icon='las la-redo-alt' icon='las la-redo-alt'
flat flat
color='secondary' color='secondary'
:loading='loading > 0' :loading='state.loading > 0'
@click='load' @click='load'
) )
q-btn( q-btn(
unelevated unelevated
icon='mdi-check' icon='fa-solid fa-check'
:label='$t(`common.actions.apply`)' :label='t(`common.actions.apply`)'
color='secondary' color='secondary'
@click='save' @click='save'
:disabled='loading > 0' :disabled='state.loading > 0'
) )
q-separator(inset) q-separator(inset)
.row.q-pa-md.q-col-gutter-md .row.q-pa-md.q-col-gutter-md
@ -306,36 +306,46 @@ q-page.admin-navigation
//- page-selector(mode='select', v-model='selectPageModal', :open-handler='selectPageHandle', path='home', :locale='currentLang') //- page-selector(mode='select', v-model='selectPageModal', :open-handler='selectPageHandle', path='home', :locale='currentLang')
</template> </template>
<script> <script setup>
import _ from 'lodash'
import gql from 'graphql-tag' import gql from 'graphql-tag'
import { find, intersectionBy, pull, unionBy } from 'lodash-es'
import { v4 as uuid } from 'uuid' import { v4 as uuid } from 'uuid'
import { createMetaMixin } from 'quasar'
import { useI18n } from 'vue-i18n'
import { useMeta, useQuasar } from 'quasar'
import { computed, onMounted, reactive, watch, nextTick } from 'vue'
import { useAdminStore } from 'src/stores/admin'
import { useSiteStore } from 'src/stores/site'
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
// QUASAR
const $q = useQuasar()
// STORES
const adminStore = useAdminStore()
const siteStore = useSiteStore()
// I18N
const { t } = useI18n()
// META
useMeta({
title: t('admin.navigation.title')
})
// DATA
const siteConfig = { lang: 'en' } const siteConfig = { lang: 'en' }
const siteLangs = [{ code: 'en' }] const siteLangs = [{ code: 'en' }]
export default { const state = reactive({
mixins: [ loading: 0,
createMetaMixin(function () {
return {
title: this.$t('admin.navigation.title')
}
})
],
components: {
draggable
},
meta () {
return {
title: this.$t('admin.navigation.title')
}
},
data () {
return {
loading: false,
selectPageModal: false, selectPageModal: false,
trees: [], trees: [],
current: {}, current: {},
@ -347,54 +357,58 @@ export default {
}, },
allLocales: [], allLocales: [],
copyFromLocaleCode: 'en' copyFromLocaleCode: 'en'
} })
},
computed: { // COMPUTED
navTypes () {
return [ const navTypes = computed(() => ([
{ text: this.$t('navigation.navType.external'), value: 'external' }, { text: t('navigation.navType.external'), value: 'external' },
{ text: this.$t('navigation.navType.externalblank'), value: 'externalblank' }, { text: t('navigation.navType.externalblank'), value: 'externalblank' },
{ text: this.$t('navigation.navType.home'), value: 'home' }, { text: t('navigation.navType.home'), value: 'home' },
{ text: this.$t('navigation.navType.page'), value: 'page' } { text: t('navigation.navType.page'), value: 'page' }
// { text: this.$t('navigation.navType.searchQuery'), value: 'search' } // { text: t('navigation.navType.searchQuery'), value: 'search' }
] ]))
},
locales () { const locales = computed(() => {
return _.intersectionBy(this.allLocales, _.unionBy(siteLangs, [{ code: 'en' }, { code: siteConfig.lang }], 'code'), 'code') return intersectionBy(state.allLocales, unionBy(siteLangs, [{ code: 'en' }, { code: siteConfig.lang }], 'code'), 'code')
}, })
currentTree: {
const currentTree = computed({
get () { get () {
return _.get(_.find(this.trees, ['locale', this.currentLang]), 'items', null) || [] return find(state.trees, ['locale', state.currentLang])?.items || []
}, },
set (val) { set (val) {
const tree = _.find(this.trees, ['locale', this.currentLang]) const tree = find(state.trees, ['locale', state.currentLang])
if (tree) { if (tree) {
tree.items = val tree.items = val
} else { } else {
this.trees = [...this.trees, { state.trees = [...state.trees, {
locale: this.currentLang, locale: state.currentLang,
items: val items: val
}] }]
} }
} }
} })
},
watch: { // WATCHERS
currentLang (newValue, oldValue) {
this.$nextTick(() => { watch(() => state.currentLang, (newValue, oldValue) => {
if (this.currentTree.length > 0) { nextTick(() => {
this.current = this.currentTree[0] if (state.currentTree.length > 0) {
state.current = state.currentTree[0]
} else { } else {
this.current = {} state.current = {}
} }
}) })
})
// METHODS
async function load () {
} }
},
methods: {
async load () {
}, function addItem (kind) {
addItem (kind) {
let newItem = { let newItem = {
id: uuid(), id: uuid(),
kind, kind,
@ -405,40 +419,46 @@ export default {
case 'link': case 'link':
newItem = { newItem = {
...newItem, ...newItem,
label: this.$t('navigation.untitled', { kind: this.$t('navigation.link') }), label: t('navigation.untitled', { kind: t('navigation.link') }),
icon: 'mdi-chevron-right', icon: 'mdi-chevron-right',
targetType: 'home', targetType: 'home',
target: '' target: ''
} }
break break
case 'header': case 'header':
newItem.label = this.$t('navigation.untitled', { kind: this.$t('navigation.header') }) newItem.label = t('navigation.untitled', { kind: t('navigation.header') })
break break
} }
this.currentTree = [...this.currentTree, newItem] state.currentTree = [...state.currentTree, newItem]
this.current = newItem state.current = newItem
}, }
deleteItem (item) {
this.currentTree = _.pull(this.currentTree, item) function deleteItem (item) {
this.current = {} state.currentTree = pull(state.currentTree, item)
}, state.current = {}
selectItem (item) { }
this.current = item
}, function selectItem (item) {
selectPage () { state.current = item
this.selectPageModal = true }
},
selectPageHandle ({ path, locale }) { function selectPage () {
this.current.target = `/${locale}/${path}` state.selectPageModal = true
}, }
copyFromLocale () {
this.copyFromLocaleDialogIsShown = false function selectPageHandle ({ path, locale }) {
this.currentTree = [...this.currentTree, ..._.get(_.find(this.trees, ['locale', this.copyFromLocaleCode]), 'items', null) || []] state.current.target = `/${locale}/${path}`
}, }
async save () {
function copyFromLocale () {
state.copyFromLocaleDialogIsShown = false
state.currentTree = [...state.currentTree, ...find(state.trees, ['locale', state.copyFromLocaleCode])?.items || []]
}
async function save () {
this.$store.commit('loadingStart', 'admin-navigation-save') this.$store.commit('loadingStart', 'admin-navigation-save')
try { try {
const resp = await this.$apollo.mutate({ const resp = await APOLLO_CLIENT.mutate({
mutation: gql` mutation: gql`
mutation ($tree: [NavigationTreeInput]!, $mode: NavigationMode!) { mutation ($tree: [NavigationTreeInput]!, $mode: NavigationMode!) {
navigation{ navigation{
@ -462,34 +482,35 @@ export default {
} }
`, `,
variables: { variables: {
tree: this.trees, tree: state.trees,
mode: this.config.mode mode: state.config.mode
} }
}) })
if (_.get(resp, 'data.navigation.updateTree.responseResult.succeeded', false) && _.get(resp, 'data.navigation.updateConfig.responseResult.succeeded', false)) { if (resp?.data.navigation.updateTree.responseResult.succeeded && resp?.data.navigation.updateConfig.responseResult.succeeded) {
this.$store.commit('showNotification', { this.$store.commit('showNotification', {
message: this.$t('navigation.saveSuccess'), message: t('navigation.saveSuccess'),
style: 'success', style: 'success',
icon: 'check' icon: 'check'
}) })
} else { } else {
throw new Error(_.get(resp, 'data.navigation.updateTree.responseResult.message', 'An unexpected error occurred.')) throw new Error(resp?.data.navigation.updateTree.operation.message || 'An unexpected error occurred.')
} }
} catch (err) { } catch (err) {
this.$store.commit('pushGraphError', err) this.$store.commit('pushGraphError', err)
} }
this.$store.commit('loadingStop', 'admin-navigation-save') this.$store.commit('loadingStop', 'admin-navigation-save')
}, }
async refresh () {
await this.$apollo.queries.trees.refetch() async function refresh () {
this.current = {} load()
state.current = {}
this.$store.commit('showNotification', { this.$store.commit('showNotification', {
message: 'Navigation has been refreshed.', message: 'Navigation has been refreshed.',
style: 'success', style: 'success',
icon: 'cached' icon: 'cached'
}) })
} }
}
// apollo: { // apollo: {
// config: { // config: {
// query: gql` // query: gql`
@ -573,11 +594,9 @@ export default {
// } // }
// } // }
// } // }
}
</script> </script>
<style lang='scss' scoped> <style lang='scss' scoped>
.clickable { .clickable {
cursor: pointer; cursor: pointer;

@ -323,9 +323,8 @@ q-page.admin-mail
</template> </template>
<script setup> <script setup>
import cloneDeep from 'lodash/cloneDeep' import { cloneDeep } from 'lodash-es'
import gql from 'graphql-tag' import gql from 'graphql-tag'
import _get from 'lodash/get'
import filesize from 'filesize' import filesize from 'filesize'
import filesizeParser from 'filesize-parser' import filesizeParser from 'filesize-parser'
@ -492,7 +491,7 @@ async function save () {
uploadMaxFileSize: filesizeParser(state.humanUploadMaxFileSize || '0') uploadMaxFileSize: filesizeParser(state.humanUploadMaxFileSize || '0')
} }
}) })
const resp = _get(respRaw, 'data.updateSystemSecurity.status', {}) const resp = respRaw?.data?.updateSystemSecurity?.status || {}
if (resp.succeeded) { if (resp.succeeded) {
$q.notify({ $q.notify({
type: 'positive', type: 'positive',

@ -583,10 +583,8 @@ q-page.admin-storage
</template> </template>
<script setup> <script setup>
import find from 'lodash/find' import { cloneDeep, find, transform } from 'lodash-es'
import cloneDeep from 'lodash/cloneDeep'
import gql from 'graphql-tag' import gql from 'graphql-tag'
import transform from 'lodash/transform'
import * as VNetworkGraph from 'v-network-graph' import * as VNetworkGraph from 'v-network-graph'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'

@ -227,7 +227,7 @@ q-page.admin-system
</template> </template>
<script setup> <script setup>
import cloneDeep from 'lodash/cloneDeep' import { cloneDeep } from 'lodash-es'
import gql from 'graphql-tag' import gql from 'graphql-tag'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useMeta, useQuasar } from 'quasar' import { useMeta, useQuasar } from 'quasar'

@ -203,8 +203,7 @@ q-page.admin-theme
<script setup> <script setup>
import gql from 'graphql-tag' import gql from 'graphql-tag'
import cloneDeep from 'lodash/cloneDeep' import { cloneDeep, startCase } from 'lodash-es'
import startCase from 'lodash/startCase'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useMeta, useQuasar } from 'quasar' import { useMeta, useQuasar } from 'quasar'
import { onMounted, reactive, watch } from 'vue' import { onMounted, reactive, watch } from 'vue'

@ -106,7 +106,7 @@ q-page.admin-groups
<script setup> <script setup>
import gql from 'graphql-tag' import gql from 'graphql-tag'
import cloneDeep from 'lodash/cloneDeep' import { cloneDeep } from 'lodash-es'
import { DateTime } from 'luxon' import { DateTime } from 'luxon'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useMeta, useQuasar } from 'quasar' import { useMeta, useQuasar } from 'quasar'

@ -92,7 +92,7 @@ q-page.admin-webhooks
</template> </template>
<script setup> <script setup>
import cloneDeep from 'lodash/cloneDeep' import { cloneDeep } from 'lodash-es'
import gql from 'graphql-tag' import gql from 'graphql-tag'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'

@ -35,12 +35,12 @@ const routes = [
{ path: ':siteid/editors', component: () => import('../pages/AdminEditors.vue') }, { path: ':siteid/editors', component: () => import('../pages/AdminEditors.vue') },
{ path: ':siteid/locale', component: () => import('../pages/AdminLocale.vue') }, { path: ':siteid/locale', component: () => import('../pages/AdminLocale.vue') },
{ path: ':siteid/login', component: () => import('../pages/AdminLogin.vue') }, { path: ':siteid/login', component: () => import('../pages/AdminLogin.vue') },
// { path: ':siteid/navigation', component: () => import('../pages/AdminNavigation.vue') }, { path: ':siteid/navigation', component: () => import('../pages/AdminNavigation.vue') },
// { path: ':siteid/rendering', component: () => import('../pages/AdminRendering.vue') }, // { path: ':siteid/rendering', component: () => import('../pages/AdminRendering.vue') },
{ path: ':siteid/storage/:id?', component: () => import('../pages/AdminStorage.vue') }, { path: ':siteid/storage/:id?', component: () => import('../pages/AdminStorage.vue') },
{ path: ':siteid/theme', component: () => import('../pages/AdminTheme.vue') }, { path: ':siteid/theme', component: () => import('../pages/AdminTheme.vue') },
// -> Users // -> Users
// { path: 'auth', component: () => import('../pages/AdminAuth.vue') }, { path: 'auth', component: () => import('../pages/AdminAuth.vue') },
{ path: 'groups/:id?/:section?', component: () => import('../pages/AdminGroups.vue') }, { path: 'groups/:id?/:section?', component: () => import('../pages/AdminGroups.vue') },
{ path: 'users/:id?/:section?', component: () => import('../pages/AdminUsers.vue') }, { path: 'users/:id?/:section?', component: () => import('../pages/AdminUsers.vue') },
// -> System // -> System

@ -4702,6 +4702,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"lodash-es@npm:4.17.21":
version: 4.17.21
resolution: "lodash-es@npm:4.17.21"
checksum: 05cbffad6e2adbb331a4e16fbd826e7faee403a1a04873b82b42c0f22090f280839f85b95393f487c1303c8a3d2a010048bf06151a6cbe03eee4d388fb0a12d2
languageName: node
linkType: hard
"lodash._reinterpolate@npm:^3.0.0": "lodash._reinterpolate@npm:^3.0.0":
version: 3.0.0 version: 3.0.0
resolution: "lodash._reinterpolate@npm:3.0.0" resolution: "lodash._reinterpolate@npm:3.0.0"
@ -6844,6 +6851,7 @@ __metadata:
js-cookie: 3.0.1 js-cookie: 3.0.1
jwt-decode: 3.1.2 jwt-decode: 3.1.2
lodash: 4.17.21 lodash: 4.17.21
lodash-es: 4.17.21
luxon: 2.4.0 luxon: 2.4.0
pinia: 2.0.14 pinia: 2.0.14
pug: 3.0.2 pug: 3.0.2

Loading…
Cancel
Save