feat(admin): migrate theme + api + utilities to vue 3 composition

parent 368493c3
...@@ -12,26 +12,26 @@ ...@@ -12,26 +12,26 @@
}, },
"dependencies": { "dependencies": {
"@apollo/client": "3.6.8", "@apollo/client": "3.6.8",
"@codemirror/autocomplete": "0.20.3", "@codemirror/autocomplete": "6.0.2",
"@codemirror/basic-setup": "0.20.0", "@codemirror/basic-setup": "0.20.0",
"@codemirror/closebrackets": "0.19.2", "@codemirror/closebrackets": "0.19.2",
"@codemirror/commands": "0.20.0", "@codemirror/commands": "6.0.0",
"@codemirror/comment": "0.19.1", "@codemirror/comment": "0.19.1",
"@codemirror/fold": "0.19.4", "@codemirror/fold": "0.19.4",
"@codemirror/gutter": "0.19.9", "@codemirror/gutter": "0.19.9",
"@codemirror/highlight": "0.19.8", "@codemirror/highlight": "0.19.8",
"@codemirror/history": "0.19.2", "@codemirror/history": "0.19.2",
"@codemirror/lang-css": "0.20.0", "@codemirror/lang-css": "6.0.0",
"@codemirror/lang-html": "0.20.0", "@codemirror/lang-html": "6.0.0",
"@codemirror/lang-javascript": "0.20.1", "@codemirror/lang-javascript": "6.0.0",
"@codemirror/lang-json": "0.20.0", "@codemirror/lang-json": "6.0.0",
"@codemirror/lang-markdown": "0.20.1", "@codemirror/lang-markdown": "6.0.0",
"@codemirror/matchbrackets": "0.19.4", "@codemirror/matchbrackets": "0.19.4",
"@codemirror/search": "0.20.1", "@codemirror/search": "6.0.0",
"@codemirror/state": "0.20.1", "@codemirror/state": "6.0.1",
"@codemirror/tooltip": "0.19.16", "@codemirror/tooltip": "0.19.16",
"@codemirror/view": "0.20.7", "@codemirror/view": "6.0.1",
"@lezer/common": "0.16.1", "@lezer/common": "1.0.0",
"@quasar/extras": "1.14.0", "@quasar/extras": "1.14.0",
"@tiptap/core": "2.0.0-beta.176", "@tiptap/core": "2.0.0-beta.176",
"@tiptap/extension-code-block": "2.0.0-beta.37", "@tiptap/extension-code-block": "2.0.0-beta.37",
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
"apollo-upload-client": "17.0.0", "apollo-upload-client": "17.0.0",
"browser-fs-access": "0.29.6", "browser-fs-access": "0.29.6",
"clipboard": "2.0.11", "clipboard": "2.0.11",
"codemirror": "6.0.0",
"filesize": "9.0.9", "filesize": "9.0.9",
"filesize-parser": "1.5.0", "filesize-parser": "1.5.0",
"graphql": "16.5.0", "graphql": "16.5.0",
...@@ -71,12 +72,12 @@ ...@@ -71,12 +72,12 @@
"luxon": "2.4.0", "luxon": "2.4.0",
"pinia": "2.0.14", "pinia": "2.0.14",
"pug": "3.0.2", "pug": "3.0.2",
"quasar": "2.7.2", "quasar": "2.7.3",
"tippy.js": "6.3.7", "tippy.js": "6.3.7",
"uuid": "8.3.2", "uuid": "8.3.2",
"v-network-graph": "0.5.19", "v-network-graph": "0.5.19",
"vue": "3.2.37", "vue": "3.2.37",
"vue-codemirror": "5.1.0", "vue-codemirror": "6.0.0",
"vue-i18n": "9.1.10", "vue-i18n": "9.1.10",
"vue-router": "4.0.16", "vue-router": "4.0.16",
"vuedraggable": "4.1.0", "vuedraggable": "4.1.0",
......
...@@ -178,7 +178,6 @@ defineEmits([ ...@@ -178,7 +178,6 @@ defineEmits([
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent() const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent()
const $q = useQuasar() const $q = useQuasar()
defineExpose({ $q })
// I18N // I18N
......
...@@ -510,7 +510,6 @@ import UtilCodeEditor from './UtilCodeEditor.vue' ...@@ -510,7 +510,6 @@ import UtilCodeEditor from './UtilCodeEditor.vue'
// QUASAR // QUASAR
const $q = useQuasar() const $q = useQuasar()
defineExpose({ $q })
// STORES // STORES
......
...@@ -12,7 +12,6 @@ import { EditorState } from '@codemirror/state' ...@@ -12,7 +12,6 @@ import { EditorState } from '@codemirror/state'
import { defaultKeymap, history, historyKeymap, indentWithTab } from '@codemirror/commands' import { defaultKeymap, history, historyKeymap, indentWithTab } from '@codemirror/commands'
import { defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language' import { defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language'
import { ref, shallowRef, onBeforeMount, onMounted, watch } from 'vue' import { ref, shallowRef, onBeforeMount, onMounted, watch } from 'vue'
import { json } from '@codemirror/lang-json'
// PROPS // PROPS
......
...@@ -218,7 +218,6 @@ defineEmits([ ...@@ -218,7 +218,6 @@ defineEmits([
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent() const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent()
const $q = useQuasar() const $q = useQuasar()
defineExpose({ $q })
// I18N // I18N
......
...@@ -203,7 +203,6 @@ const overlays = { ...@@ -203,7 +203,6 @@ const overlays = {
// QUASAR // QUASAR
const $q = useQuasar() const $q = useQuasar()
defineExpose({ $q })
// STORES // STORES
......
...@@ -4,16 +4,16 @@ q-page.admin-api ...@@ -4,16 +4,16 @@ q-page.admin-api
.col-auto .col-auto
img.admin-icon.animated.fadeInLeft(src='/_assets/icons/fluent-rest-api.svg') img.admin-icon.animated.fadeInLeft(src='/_assets/icons/fluent-rest-api.svg')
.col.q-pl-md .col.q-pl-md
.text-h5.text-primary.animated.fadeInLeft {{ $t('admin.api.title') }} .text-h5.text-primary.animated.fadeInLeft {{ t('admin.api.title') }}
.text-subtitle1.text-grey.animated.fadeInLeft.wait-p2s {{ $t('admin.api.subtitle') }} .text-subtitle1.text-grey.animated.fadeInLeft.wait-p2s {{ t('admin.api.subtitle') }}
.col .col
.flex.items-center .flex.items-center
template(v-if='enabled') template(v-if='state.enabled')
q-spinner-rings.q-mr-sm(color='green') q-spinner-rings.q-mr-sm(color='green')
.text-caption.text-green {{$t('admin.api.enabled')}} .text-caption.text-green {{t('admin.api.enabled')}}
template(v-else) template(v-else)
q-spinner-rings.q-mr-sm(color='red', size='md') q-spinner-rings.q-mr-sm(color='red', size='md')
.text-caption.text-red {{$t('admin.api.disabled')}} .text-caption.text-red {{t('admin.api.disabled')}}
.col-auto .col-auto
q-btn.q-mr-sm.q-ml-md.acrylic-btn( q-btn.q-mr-sm.q-ml-md.acrylic-btn(
icon='las la-question-circle' icon='las la-question-circle'
...@@ -27,24 +27,24 @@ q-page.admin-api ...@@ -27,24 +27,24 @@ q-page.admin-api
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-mr-sm( q-btn.q-mr-sm(
unelevated unelevated
icon='las la-power-off' icon='las la-power-off'
:label='!enabled ? $t(`admin.api.enableButton`) : $t(`admin.api.disableButton`)' :label='!state.enabled ? t(`admin.api.enableButton`) : t(`admin.api.disableButton`)'
:color='!enabled ? `positive` : `negative`' :color='!state.enabled ? `positive` : `negative`'
@click='globalSwitch' @click='globalSwitch'
:disabled='loading > 0' :disabled='state.loading > 0'
) )
q-btn( q-btn(
unelevated unelevated
icon='las la-plus' icon='las la-plus'
:label='$t(`admin.api.newKeyButton`)' :label='t(`admin.api.newKeyButton`)'
color='primary' color='primary'
@click='newKey' @click='newKey'
: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
...@@ -114,29 +114,30 @@ q-page.admin-api ...@@ -114,29 +114,30 @@ q-page.admin-api
//- v-btn(color='red', dark, @click='revokeConfirm', :loading='revokeLoading') {{$t('admin.api.revoke')}} //- v-btn(color='red', dark, @click='revokeConfirm', :loading='revokeLoading') {{$t('admin.api.revoke')}}
</template> </template>
<script> <script setup>
import _get from 'lodash/get'
import cloneDeep from 'lodash/cloneDeep'
import gql from 'graphql-tag' import gql from 'graphql-tag'
import { createMetaMixin } from 'quasar' import cloneDeep from 'lodash/cloneDeep'
// import { StatusIndicator } from 'vue-status-indicator' import { useI18n } from 'vue-i18n'
import { useMeta, useQuasar } from 'quasar'
import { computed, onMounted, reactive, watch } from 'vue'
// import CreateApiKey from './admin-api-create.vue' // QUASAR
export default { const $q = useQuasar()
components: {
// StatusIndicator, // I18N
// CreateApiKey
}, const { t } = useI18n()
mixins: [
createMetaMixin(function () { // META
return {
title: this.$t('admin.api.title') useMeta({
} title: t('admin.api.title')
}) })
],
data () { // DATA
return {
const state = reactive({
enabled: false, enabled: false,
loading: 0, loading: 0,
keys: [], keys: [],
...@@ -144,16 +145,14 @@ export default { ...@@ -144,16 +145,14 @@ export default {
isRevokeConfirmDialogShown: false, isRevokeConfirmDialogShown: false,
revokeLoading: false, revokeLoading: false,
current: {} current: {}
} })
},
mounted () { // METHODS
this.load()
}, async function load () {
methods: { state.loading++
async load () { $q.loading.show()
this.loading++ const resp = await APOLLO_CLIENT.query({
this.$q.loading.show()
const resp = await this.$apollo.query({
query: gql` query: gql`
query getHooks { query getHooks {
apiKeys { apiKeys {
...@@ -170,15 +169,16 @@ export default { ...@@ -170,15 +169,16 @@ export default {
`, `,
fetchPolicy: 'network-only' fetchPolicy: 'network-only'
}) })
this.keys = cloneDeep(resp?.data?.apiKeys) ?? [] state.keys = cloneDeep(resp?.data?.apiKeys) ?? []
this.enabled = resp?.data?.apiState === true state.enabled = resp?.data?.apiState === true
this.$q.loading.hide() $q.loading.hide()
this.loading-- state.loading--
}, }
async globalSwitch () {
this.isToggleLoading = true async function globalSwitch () {
state.isToggleLoading = true
try { try {
const resp = await this.$apollo.mutate({ const resp = await APOLLO_CLIENT.mutate({
mutation: gql` mutation: gql`
mutation ($enabled: Boolean!) { mutation ($enabled: Boolean!) {
authentication { authentication {
...@@ -194,42 +194,41 @@ export default { ...@@ -194,42 +194,41 @@ export default {
} }
`, `,
variables: { variables: {
enabled: !this.enabled enabled: !state.enabled
},
watchLoading (isLoading) {
this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-api-toggle')
} }
}) })
if (_get(resp, 'data.authentication.setApiState.responseResult.succeeded', false)) { if (resp?.data?.setApiState?.operation?.succeeded) {
this.$store.commit('showNotification', { $q.notify({
style: 'success', type: 'positive',
message: this.enabled ? this.$t('admin.api.toggleStateDisabledSuccess') : this.$t('admin.api.toggleStateEnabledSuccess'), message: state.enabled ? t('admin.api.toggleStateDisabledSuccess') : t('admin.api.toggleStateEnabledSuccess')
icon: 'check'
}) })
await this.load() await load()
} else { } else {
this.$store.commit('showNotification', { throw new Error(resp?.data?.setApiState?.operation.message || 'An unexpected error occurred.')
style: 'red',
message: _get(resp, 'data.authentication.setApiState.responseResult.message', 'An unexpected error occurred.'),
icon: 'alert'
})
} }
} catch (err) { } catch (err) {
this.$store.commit('pushGraphError', err) $q.notify({
type: 'negative',
message: 'Failed to switch API state.',
caption: err.message
})
} }
this.isToggleLoading = false state.isToggleLoading = false
}, }
async newKey () {
this.isCreateDialogShown = true async function newKey () {
}, state.isCreateDialogShown = true
revoke (key) { }
this.current = key
this.isRevokeConfirmDialogShown = true function revoke (key) {
}, state.current = key
async revokeConfirm () { state.isRevokeConfirmDialogShown = true
this.revokeLoading = true }
async function revokeConfirm () {
state.revokeLoading = true
try { try {
const resp = await this.$apollo.mutate({ const resp = await APOLLO_CLIENT.mutate({
mutation: gql` mutation: gql`
mutation ($id: Int!) { mutation ($id: Int!) {
authentication { authentication {
...@@ -245,34 +244,36 @@ export default { ...@@ -245,34 +244,36 @@ export default {
} }
`, `,
variables: { variables: {
id: this.current.id id: state.current.id
},
watchLoading (isLoading) {
this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-api-revoke')
} }
}) })
if (_get(resp, 'data.authentication.revokeApiKey.responseResult.succeeded', false)) { // if (_get(resp, 'data.authentication.revokeApiKey.responseResult.succeeded', false)) {
this.$store.commit('showNotification', { // this.$store.commit('showNotification', {
style: 'success', // style: 'success',
message: this.$t('admin.api.revokeSuccess'), // message: this.$t('admin.api.revokeSuccess'),
icon: 'check' // icon: 'check'
}) // })
this.load() // this.load()
} else { // } else {
this.$store.commit('showNotification', { // this.$store.commit('showNotification', {
style: 'red', // style: 'red',
message: _get(resp, 'data.authentication.revokeApiKey.responseResult.message', 'An unexpected error occurred.'), // message: _get(resp, 'data.authentication.revokeApiKey.responseResult.message', 'An unexpected error occurred.'),
icon: 'alert' // icon: 'alert'
}) // })
} // }
} catch (err) { } catch (err) {
this.$store.commit('pushGraphError', err) // this.$store.commit('pushGraphError', err)
}
this.isRevokeConfirmDialogShown = false
this.revokeLoading = false
}
} }
state.isRevokeConfirmDialogShown = false
state.revokeLoading = false
} }
// MOUNTED
onMounted(() => {
load()
})
</script> </script>
<style lang='scss'> <style lang='scss'>
......
...@@ -4,14 +4,14 @@ q-page.admin-utilities ...@@ -4,14 +4,14 @@ q-page.admin-utilities
.col-auto .col-auto
img.admin-icon.animated.fadeInLeft(src='/_assets/icons/fluent-swiss-army-knife.svg') img.admin-icon.animated.fadeInLeft(src='/_assets/icons/fluent-swiss-army-knife.svg')
.col.q-pl-md .col.q-pl-md
.text-h5.text-primary.animated.fadeInLeft {{ $t('admin.utilities.title') }} .text-h5.text-primary.animated.fadeInLeft {{ t('admin.utilities.title') }}
.text-subtitle1.text-grey.animated.fadeInLeft.wait-p2s {{ $t('admin.utilities.subtitle') }} .text-subtitle1.text-grey.animated.fadeInLeft.wait-p2s {{ t('admin.utilities.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'
flat flat
color='grey' color='grey'
href='https://docs.requarks.io/admin/utilities' href='https://docs.js.wiki/admin/utilities'
target='_blank' target='_blank'
type='a' type='a'
) )
...@@ -22,38 +22,31 @@ q-page.admin-utilities ...@@ -22,38 +22,31 @@ q-page.admin-utilities
q-item q-item
blueprint-icon(icon='matches', :hue-rotate='45') blueprint-icon(icon='matches', :hue-rotate='45')
q-item-section q-item-section
q-item-label {{$t(`admin.utilities.invalidAuthCertificates`)}} q-item-label {{t(`admin.utilities.invalidAuthCertificates`)}}
q-item-label(caption) {{$t(`admin.utilities.invalidAuthCertificatesHint`)}} q-item-label(caption) {{t(`admin.utilities.invalidAuthCertificatesHint`)}}
q-item-section(side) q-item-section(side)
q-btn.acrylic-btn( q-btn.acrylic-btn(
flat flat
icon='las la-arrow-circle-right' icon='las la-arrow-circle-right'
color='primary' color='primary'
@click='' @click=''
:label='$t(`common.actions.proceed`)' :label='t(`common.actions.proceed`)'
) )
q-item q-item
blueprint-icon(icon='historical', :hue-rotate='45') blueprint-icon(icon='historical', :hue-rotate='45')
q-item-section q-item-section
q-item-label {{$t(`admin.utilities.purgeHistory`)}} q-item-label {{t(`admin.utilities.purgeHistory`)}}
q-item-label(caption) {{$t(`admin.utilities.purgeHistoryHint`)}} q-item-label(caption) {{t(`admin.utilities.purgeHistoryHint`)}}
q-item-section(side) q-item-section(side)
q-select( q-select(
outlined outlined
:label='$t(`admin.utilities.purgeHistoryTimeframe`)' :label='t(`admin.utilities.purgeHistoryTimeframe`)'
v-model='purgeHistoryTimeframe' v-model='state.purgeHistoryTimeframe'
style='min-width: 175px;' style='min-width: 175px;'
emit-value emit-value
map-options map-options
dense dense
:options=`[ :options='purgeHistoryTimeframes'
{ value: '24h', label: $t('admin.utitilies.purgeHistoryToday') },
{ value: '1m', label: $tc('admin.utitilies.purgeHistoryMonth', 1, { count: 1 }) },
{ value: '3m', label: $tc('admin.utitilies.purgeHistoryMonth', 3, { count: 3 }) },
{ value: '6m', label: $tc('admin.utitilies.purgeHistoryMonth', 6, { count: 6 }) },
{ value: '1y', label: $tc('admin.utitilies.purgeHistoryYear', 1, { count: 1 }) },
{ value: '2y', label: $tc('admin.utitilies.purgeHistoryYear', 2, { count: 2 }) }
]`
) )
q-separator.q-ml-sm(vertical) q-separator.q-ml-sm(vertical)
q-item-section(side) q-item-section(side)
...@@ -62,20 +55,46 @@ q-page.admin-utilities ...@@ -62,20 +55,46 @@ q-page.admin-utilities
icon='las la-arrow-circle-right' icon='las la-arrow-circle-right'
color='primary' color='primary'
@click='' @click=''
:label='$t(`common.actions.proceed`)' :label='t(`common.actions.proceed`)'
) )
</template> </template>
<script> <script setup>
import { computed, reactive } from 'vue'
import { useMeta, useQuasar } from 'quasar'
import { useI18n } from 'vue-i18n'
export default { // QUASAR
data () {
return { const $q = useQuasar()
// STORES / ROUTERS / i18n
const { t } = useI18n()
// META
useMeta({
title: t('admin.utilities.title')
})
// DATA
const state = reactive({
purgeHistoryTimeframe: '1y' purgeHistoryTimeframe: '1y'
} })
}
} // COMPUTED
const purgeHistoryTimeframes = computed(() => ([
{ value: '24h', label: t('admin.utitilies.purgeHistoryToday') },
{ value: '1m', label: t('admin.utitilies.purgeHistoryMonth', 1, { count: 1 }) },
{ value: '3m', label: t('admin.utitilies.purgeHistoryMonth', 3, { count: 3 }) },
{ value: '6m', label: t('admin.utitilies.purgeHistoryMonth', 6, { count: 6 }) },
{ value: '1y', label: t('admin.utitilies.purgeHistoryYear', 1, { count: 1 }) },
{ value: '2y', label: t('admin.utitilies.purgeHistoryYear', 2, { count: 2 }) }
]))
</script> </script>
<style lang='scss'> <style lang='scss'>
......
...@@ -36,20 +36,20 @@ const routes = [ ...@@ -36,20 +36,20 @@ const routes = [
{ 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/storage/:id?', component: () => import('../pages/AdminStorage.vue') },
// { path: ':siteid/rendering', component: () => import('../pages/AdminRendering.vue') }, // { path: ':siteid/rendering', component: () => import('../pages/AdminRendering.vue') },
// { path: ':siteid/theme', component: () => import('../pages/AdminTheme.vue') }, { path: ':siteid/storage/:id?', component: () => import('../pages/AdminStorage.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
// { path: 'api', component: () => import('../pages/AdminApi.vue') }, { path: 'api', component: () => import('../pages/AdminApi.vue') },
{ path: 'extensions', component: () => import('../pages/AdminExtensions.vue') }, { path: 'extensions', component: () => import('../pages/AdminExtensions.vue') },
{ path: 'mail', component: () => import('../pages/AdminMail.vue') }, { path: 'mail', component: () => import('../pages/AdminMail.vue') },
{ path: 'security', component: () => import('../pages/AdminSecurity.vue') }, { path: 'security', component: () => import('../pages/AdminSecurity.vue') },
{ path: 'system', component: () => import('../pages/AdminSystem.vue') }, { path: 'system', component: () => import('../pages/AdminSystem.vue') },
// { path: 'utilities', component: () => import('../pages/AdminUtilities.vue') }, { path: 'utilities', component: () => import('../pages/AdminUtilities.vue') },
{ path: 'webhooks', component: () => import('../pages/AdminWebhooks.vue') }, { path: 'webhooks', component: () => import('../pages/AdminWebhooks.vue') },
{ path: 'flags', component: () => import('../pages/AdminFlags.vue') } { path: 'flags', component: () => import('../pages/AdminFlags.vue') }
] ]
......
This diff was suppressed by a .gitattributes entry.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment