mirror of https://github.com/requarks/wiki
parent
dfde2e10aa
commit
358ad1fdcd
@ -1,56 +0,0 @@
|
||||
const { SchemaDirectiveVisitor } = require('graphql-tools')
|
||||
const { defaultFieldResolver } = require('graphql')
|
||||
const _ = require('lodash')
|
||||
|
||||
class AuthDirective extends SchemaDirectiveVisitor {
|
||||
visitObject(type) {
|
||||
this.ensureFieldsWrapped(type)
|
||||
type._requiredAuthScopes = this.args.requires
|
||||
}
|
||||
// Visitor methods for nested types like fields and arguments
|
||||
// also receive a details object that provides information about
|
||||
// the parent and grandparent types.
|
||||
visitFieldDefinition(field, details) {
|
||||
this.ensureFieldsWrapped(details.objectType)
|
||||
field._requiredAuthScopes = this.args.requires
|
||||
}
|
||||
|
||||
visitArgumentDefinition(argument, details) {
|
||||
this.ensureFieldsWrapped(details.objectType)
|
||||
argument._requiredAuthScopes = this.args.requires
|
||||
}
|
||||
|
||||
ensureFieldsWrapped(objectType) {
|
||||
// Mark the GraphQLObjectType object to avoid re-wrapping:
|
||||
if (objectType._authFieldsWrapped) return
|
||||
objectType._authFieldsWrapped = true
|
||||
|
||||
const fields = objectType.getFields()
|
||||
|
||||
Object.keys(fields).forEach(fieldName => {
|
||||
const field = fields[fieldName]
|
||||
const { resolve = defaultFieldResolver } = field
|
||||
field.resolve = async function (...args) {
|
||||
// Get the required scopes from the field first, falling back
|
||||
// to the objectType if no scopes is required by the field:
|
||||
const requiredScopes = field._requiredAuthScopes || objectType._requiredAuthScopes
|
||||
|
||||
if (!requiredScopes) {
|
||||
return resolve.apply(this, args)
|
||||
}
|
||||
|
||||
const context = args[2]
|
||||
if (!context.req.user) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
if (!_.some(context.req.user.permissions, pm => _.includes(requiredScopes, pm))) {
|
||||
throw new Error('Forbidden')
|
||||
}
|
||||
|
||||
return resolve.apply(this, args)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AuthDirective
|
@ -1,5 +0,0 @@
|
||||
const { createRateLimitDirective } = require('graphql-rate-limit-directive')
|
||||
|
||||
module.exports = createRateLimitDirective({
|
||||
keyGenerator: (directiveArgs, source, args, context, info) => `${context.req.ip}:${info.parentType}.${info.fieldName}`
|
||||
})
|
@ -1,28 +0,0 @@
|
||||
const request = require('request-promise')
|
||||
const _ = require('lodash')
|
||||
|
||||
/* global WIKI */
|
||||
|
||||
module.exports = {
|
||||
Query: {
|
||||
async contribute() { return {} }
|
||||
},
|
||||
ContributeQuery: {
|
||||
async contributors(obj, args, context, info) {
|
||||
try {
|
||||
const resp = await request({
|
||||
method: 'POST',
|
||||
uri: 'https://graph.requarks.io',
|
||||
json: true,
|
||||
body: {
|
||||
query: '{\n sponsors {\n list(kind: BACKER) {\n id\n source\n name\n joined\n website\n twitter\n avatar\n }\n }\n}\n',
|
||||
variables: {}
|
||||
}
|
||||
})
|
||||
return _.get(resp, 'data.sponsors.list', [])
|
||||
} catch (err) {
|
||||
WIKI.logger.warn(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
module.exports = {
|
||||
// Query: {
|
||||
// folders(obj, args, context, info) {
|
||||
// return WIKI.models.Folder.findAll({ where: args })
|
||||
// }
|
||||
// },
|
||||
// Mutation: {
|
||||
// createFolder(obj, args) {
|
||||
// return WIKI.models.Folder.create(args)
|
||||
// },
|
||||
// deleteFolder(obj, args) {
|
||||
// return WIKI.models.Folder.destroy({
|
||||
// where: {
|
||||
// id: args.id
|
||||
// },
|
||||
// limit: 1
|
||||
// })
|
||||
// },
|
||||
// renameFolder(obj, args) {
|
||||
// return WIKI.models.Folder.update({
|
||||
// name: args.name
|
||||
// }, {
|
||||
// where: { id: args.id }
|
||||
// })
|
||||
// }
|
||||
// },
|
||||
// Folder: {
|
||||
// files(grp) {
|
||||
// return grp.getFiles()
|
||||
// }
|
||||
// }
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
module.exports = {
|
||||
// Query: {
|
||||
// tags(obj, args, context, info) {
|
||||
// return WIKI.models.Tag.findAll({ where: args })
|
||||
// }
|
||||
// },
|
||||
// Mutation: {
|
||||
// assignTagToDocument(obj, args) {
|
||||
// return WIKI.models.Tag.findById(args.tagId).then(tag => {
|
||||
// if (!tag) {
|
||||
// throw new gql.GraphQLError('Invalid Tag ID')
|
||||
// }
|
||||
// return WIKI.models.Document.findById(args.documentId).then(doc => {
|
||||
// if (!doc) {
|
||||
// throw new gql.GraphQLError('Invalid Document ID')
|
||||
// }
|
||||
// return tag.addDocument(doc)
|
||||
// })
|
||||
// })
|
||||
// },
|
||||
// createTag(obj, args) {
|
||||
// return WIKI.models.Tag.create(args)
|
||||
// },
|
||||
// deleteTag(obj, args) {
|
||||
// return WIKI.models.Tag.destroy({
|
||||
// where: {
|
||||
// id: args.id
|
||||
// },
|
||||
// limit: 1
|
||||
// })
|
||||
// },
|
||||
// removeTagFromDocument(obj, args) {
|
||||
// return WIKI.models.Tag.findById(args.tagId).then(tag => {
|
||||
// if (!tag) {
|
||||
// throw new gql.GraphQLError('Invalid Tag ID')
|
||||
// }
|
||||
// return WIKI.models.Document.findById(args.documentId).then(doc => {
|
||||
// if (!doc) {
|
||||
// throw new gql.GraphQLError('Invalid Document ID')
|
||||
// }
|
||||
// return tag.removeDocument(doc)
|
||||
// })
|
||||
// })
|
||||
// },
|
||||
// renameTag(obj, args) {
|
||||
// return WIKI.models.Group.update({
|
||||
// key: args.key
|
||||
// }, {
|
||||
// where: { id: args.id }
|
||||
// })
|
||||
// }
|
||||
// },
|
||||
// Tag: {
|
||||
// documents(tag) {
|
||||
// return tag.getDocuments()
|
||||
// }
|
||||
// }
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
const graphHelper = require('../../helpers/graph')
|
||||
const _ = require('lodash')
|
||||
const CleanCSS = require('clean-css')
|
||||
|
||||
/* global WIKI */
|
||||
|
||||
module.exports = {
|
||||
Query: {
|
||||
async theming() { return {} }
|
||||
},
|
||||
Mutation: {
|
||||
async theming() { return {} }
|
||||
},
|
||||
ThemingQuery: {
|
||||
async themes(obj, args, context, info) {
|
||||
return [{ // TODO
|
||||
key: 'default',
|
||||
title: 'Default',
|
||||
author: 'requarks.io'
|
||||
}]
|
||||
},
|
||||
async config(obj, args, context, info) {
|
||||
return {
|
||||
theme: WIKI.config.theming.theme,
|
||||
iconset: WIKI.config.theming.iconset,
|
||||
darkMode: WIKI.config.theming.darkMode,
|
||||
injectCSS: new CleanCSS({ format: 'beautify' }).minify(WIKI.config.theming.injectCSS).styles,
|
||||
injectHead: WIKI.config.theming.injectHead,
|
||||
injectBody: WIKI.config.theming.injectBody
|
||||
}
|
||||
}
|
||||
},
|
||||
ThemingMutation: {
|
||||
async setConfig(obj, args, context, info) {
|
||||
try {
|
||||
if (!_.isEmpty(args.injectCSS)) {
|
||||
args.injectCSS = new CleanCSS({
|
||||
inline: false
|
||||
}).minify(args.injectCSS).styles
|
||||
}
|
||||
|
||||
WIKI.config.theming = {
|
||||
...WIKI.config.theming,
|
||||
theme: args.theme,
|
||||
iconset: args.iconset,
|
||||
darkMode: args.darkMode,
|
||||
injectCSS: args.injectCSS || '',
|
||||
injectHead: args.injectHead || '',
|
||||
injectBody: args.injectBody || ''
|
||||
}
|
||||
|
||||
await WIKI.configSvc.saveToDb(['theming'])
|
||||
|
||||
return {
|
||||
responseResult: graphHelper.generateSuccess('Theme config updated')
|
||||
}
|
||||
} catch (err) {
|
||||
return graphHelper.generateError(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,21 +1,18 @@
|
||||
|
||||
const gql = require('graphql')
|
||||
|
||||
module.exports = {
|
||||
Date: new gql.GraphQLScalarType({
|
||||
name: 'Date',
|
||||
description: 'ISO date-time string at UTC',
|
||||
parseValue(value) {
|
||||
return new Date(value)
|
||||
},
|
||||
serialize(value) {
|
||||
return value.toISOString()
|
||||
},
|
||||
parseLiteral(ast) {
|
||||
if (ast.kind !== gql.Kind.STRING) {
|
||||
throw new TypeError('Date value must be an string!')
|
||||
}
|
||||
return new Date(ast.value)
|
||||
module.exports = new gql.GraphQLScalarType({
|
||||
name: 'Date',
|
||||
description: 'ISO date-time string at UTC',
|
||||
parseValue(value) {
|
||||
return new Date(value)
|
||||
},
|
||||
serialize(value) {
|
||||
return value.toISOString()
|
||||
},
|
||||
parseLiteral(ast) {
|
||||
if (ast.kind !== gql.Kind.STRING) {
|
||||
throw new TypeError('Date value must be an string!')
|
||||
}
|
||||
})
|
||||
}
|
||||
return new Date(ast.value)
|
||||
}
|
||||
})
|
||||
|
@ -1,29 +0,0 @@
|
||||
# ===============================================
|
||||
# CONTRIBUTE
|
||||
# ===============================================
|
||||
|
||||
extend type Query {
|
||||
contribute: ContributeQuery
|
||||
}
|
||||
|
||||
# -----------------------------------------------
|
||||
# QUERIES
|
||||
# -----------------------------------------------
|
||||
|
||||
type ContributeQuery {
|
||||
contributors: [ContributeContributor]
|
||||
}
|
||||
|
||||
# -----------------------------------------------
|
||||
# TYPES
|
||||
# -----------------------------------------------
|
||||
|
||||
type ContributeContributor {
|
||||
id: String!
|
||||
source: String!
|
||||
name: String!
|
||||
joined: Date!
|
||||
website: String
|
||||
twitter: String
|
||||
avatar: String
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
# ===============================================
|
||||
# LOGGING
|
||||
# ===============================================
|
||||
|
||||
extend type Query {
|
||||
logging: LoggingQuery
|
||||
}
|
||||
|
||||
extend type Mutation {
|
||||
logging: LoggingMutation
|
||||
}
|
||||
|
||||
extend type Subscription {
|
||||
loggingLiveTrail: LoggerTrailLine
|
||||
}
|
||||
|
||||
# -----------------------------------------------
|
||||
# QUERIES
|
||||
# -----------------------------------------------
|
||||
|
||||
type LoggingQuery {
|
||||
loggers(
|
||||
filter: String
|
||||
orderBy: String
|
||||
): [Logger] @auth(requires: ["manage:system"])
|
||||
}
|
||||
|
||||
# -----------------------------------------------
|
||||
# MUTATIONS
|
||||
# -----------------------------------------------
|
||||
|
||||
type LoggingMutation {
|
||||
updateLoggers(
|
||||
loggers: [LoggerInput]
|
||||
): DefaultResponse @auth(requires: ["manage:system"])
|
||||
}
|
||||
|
||||
# -----------------------------------------------
|
||||
# TYPES
|
||||
# -----------------------------------------------
|
||||
|
||||
type Logger {
|
||||
isEnabled: Boolean!
|
||||
key: String!
|
||||
title: String!
|
||||
description: String
|
||||
logo: String
|
||||
website: String
|
||||
level: String
|
||||
config: [KeyValuePair]
|
||||
}
|
||||
|
||||
input LoggerInput {
|
||||
isEnabled: Boolean!
|
||||
key: String!
|
||||
level: String!
|
||||
config: [KeyValuePairInput]
|
||||
}
|
||||
|
||||
type LoggerTrailLine {
|
||||
level: String!
|
||||
output: String!
|
||||
timestamp: Date!
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
# ===============================================
|
||||
# THEMES
|
||||
# ===============================================
|
||||
|
||||
extend type Query {
|
||||
theming: ThemingQuery
|
||||
}
|
||||
|
||||
extend type Mutation {
|
||||
theming: ThemingMutation
|
||||
}
|
||||
|
||||
# -----------------------------------------------
|
||||
# QUERIES
|
||||
# -----------------------------------------------
|
||||
|
||||
type ThemingQuery {
|
||||
themes: [ThemingTheme] @auth(requires: ["manage:theme", "manage:system"])
|
||||
config: ThemingConfig @auth(requires: ["manage:theme", "manage:system"])
|
||||
}
|
||||
|
||||
# -----------------------------------------------
|
||||
# MUTATIONS
|
||||
# -----------------------------------------------
|
||||
|
||||
type ThemingMutation {
|
||||
setConfig(
|
||||
theme: String!
|
||||
iconset: String!
|
||||
darkMode: Boolean!
|
||||
injectCSS: String
|
||||
injectHead: String
|
||||
injectBody: String
|
||||
): DefaultResponse @auth(requires: ["manage:theme", "manage:system"])
|
||||
}
|
||||
|
||||
# -----------------------------------------------
|
||||
# TYPES
|
||||
# -----------------------------------------------
|
||||
|
||||
type ThemingConfig {
|
||||
theme: String!
|
||||
iconset: String!
|
||||
darkMode: Boolean!
|
||||
injectCSS: String
|
||||
injectHead: String
|
||||
injectBody: String
|
||||
}
|
||||
|
||||
type ThemingTheme {
|
||||
key: String
|
||||
title: String
|
||||
author: String
|
||||
}
|
@ -1,114 +1,135 @@
|
||||
<template lang="pug">
|
||||
q-dialog(ref='dialog', @hide='onDialogHide')
|
||||
q-dialog(ref='dialogRef', @hide='onDialogHide')
|
||||
q-card(style='min-width: 350px; max-width: 450px;')
|
||||
q-card-section.card-header
|
||||
q-icon(name='img:/_assets/icons/fluent-shutdown.svg', left, size='sm')
|
||||
span {{value ? $t(`admin.sites.activate`) : $t(`admin.sites.deactivate`)}}
|
||||
span {{modelValue ? t(`admin.sites.activate`) : t(`admin.sites.deactivate`)}}
|
||||
q-card-section
|
||||
.text-body2
|
||||
i18n-t(:keypath='value ? `admin.sites.activateConfirm` : `admin.sites.deactivateConfirm`')
|
||||
i18n-t(:keypath='modelValue ? `admin.sites.activateConfirm` : `admin.sites.deactivateConfirm`')
|
||||
template(v-slot:siteTitle)
|
||||
strong {{site.title}}
|
||||
strong {{props.site.title}}
|
||||
q-card-actions.card-actions
|
||||
q-space
|
||||
q-btn.acrylic-btn(
|
||||
flat
|
||||
:label='$t(`common.actions.cancel`)'
|
||||
:label='t(`common.actions.cancel`)'
|
||||
color='grey'
|
||||
padding='xs md'
|
||||
@click='hide'
|
||||
@click='onDialogCancel'
|
||||
)
|
||||
q-btn(
|
||||
unelevated
|
||||
:label='value ? $t(`common.actions.activate`) : $t(`common.actions.deactivate`)'
|
||||
:color='value ? `positive` : `negative`'
|
||||
:label='modelValue ? t(`common.actions.activate`) : t(`common.actions.deactivate`)'
|
||||
:color='modelValue ? `positive` : `negative`'
|
||||
padding='xs md'
|
||||
@click='confirm'
|
||||
:loading='state.isLoading'
|
||||
)
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import gql from 'graphql-tag'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useDialogPluginComponent, useQuasar } from 'quasar'
|
||||
import { reactive, ref } from 'vue'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
site: {
|
||||
type: Object
|
||||
},
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
emits: ['ok', 'hide'],
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
import { useAdminStore } from '../stores/admin'
|
||||
|
||||
// PROPS
|
||||
|
||||
const props = defineProps({
|
||||
site: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
methods: {
|
||||
show () {
|
||||
this.$refs.dialog.show()
|
||||
},
|
||||
hide () {
|
||||
this.$refs.dialog.hide()
|
||||
},
|
||||
onDialogHide () {
|
||||
this.$emit('hide')
|
||||
},
|
||||
async confirm () {
|
||||
try {
|
||||
const siteId = this.site.id
|
||||
const resp = await this.$apollo.mutate({
|
||||
mutation: gql`
|
||||
mutation updateSite (
|
||||
$id: UUID!
|
||||
$newState: Boolean
|
||||
) {
|
||||
updateSite(
|
||||
id: $id
|
||||
patch: {
|
||||
isEnabled: $newState
|
||||
}
|
||||
) {
|
||||
status {
|
||||
succeeded
|
||||
message
|
||||
}
|
||||
}
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
// EMITS
|
||||
|
||||
defineEmits([
|
||||
...useDialogPluginComponent.emits
|
||||
])
|
||||
|
||||
// QUASAR
|
||||
|
||||
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent()
|
||||
const $q = useQuasar()
|
||||
|
||||
// STORES
|
||||
|
||||
const adminStore = useAdminStore()
|
||||
|
||||
// I18N
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
// DATA
|
||||
|
||||
const state = reactive({
|
||||
isLoading: false
|
||||
})
|
||||
|
||||
// METHODS
|
||||
|
||||
async function confirm () {
|
||||
state.isLoading = true
|
||||
try {
|
||||
const resp = await APOLLO_CLIENT.mutate({
|
||||
mutation: gql`
|
||||
mutation updateSite (
|
||||
$id: UUID!
|
||||
$newState: Boolean
|
||||
) {
|
||||
updateSite(
|
||||
id: $id
|
||||
patch: {
|
||||
isEnabled: $newState
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
id: siteId,
|
||||
newState: this.value
|
||||
}
|
||||
})
|
||||
if (resp?.data?.updateSite?.status?.succeeded) {
|
||||
this.$q.notify({
|
||||
type: 'positive',
|
||||
message: this.$t('admin.sites.updateSuccess')
|
||||
})
|
||||
this.$store.set('admin/sites', this.$store.get('admin/sites').map(s => {
|
||||
if (s.id === siteId) {
|
||||
const ns = cloneDeep(s)
|
||||
ns.isEnabled = this.value
|
||||
return ns
|
||||
} else {
|
||||
return s
|
||||
) {
|
||||
operation {
|
||||
succeeded
|
||||
message
|
||||
}
|
||||
}))
|
||||
this.$emit('ok')
|
||||
this.hide()
|
||||
} else {
|
||||
throw new Error(resp?.data?.updateSite?.status?.message || 'An unexpected error occured.')
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
this.$q.notify({
|
||||
type: 'negative',
|
||||
message: err.message
|
||||
})
|
||||
`,
|
||||
variables: {
|
||||
id: props.site.id,
|
||||
newState: props.modelValue
|
||||
}
|
||||
})
|
||||
if (resp?.data?.updateSite?.operation?.succeeded) {
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
message: this.$t('admin.sites.updateSuccess')
|
||||
})
|
||||
adminStore.$patch({
|
||||
sites: adminStore.sites.map(s => {
|
||||
if (s.id === props.site.id) {
|
||||
const ns = cloneDeep(s)
|
||||
ns.isEnabled = props.modelValue
|
||||
return ns
|
||||
} else {
|
||||
return s
|
||||
}
|
||||
})
|
||||
})
|
||||
onDialogOK()
|
||||
} else {
|
||||
throw new Error(resp?.data?.updateSite?.operation?.message || 'An unexpected error occured.')
|
||||
}
|
||||
} catch (err) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: err.message
|
||||
})
|
||||
}
|
||||
state.isLoading = false
|
||||
}
|
||||
</script>
|
||||
|
@ -1,94 +1,115 @@
|
||||
<template lang="pug">
|
||||
q-dialog(ref='dialog', @hide='onDialogHide')
|
||||
q-dialog(ref='dialogRef', @hide='onDialogHide')
|
||||
q-card(style='min-width: 350px; max-width: 450px;')
|
||||
q-card-section.card-header
|
||||
q-icon(name='img:/_assets/icons/fluent-delete-bin.svg', left, size='sm')
|
||||
span {{$t(`admin.sites.delete`)}}
|
||||
span {{t(`admin.sites.delete`)}}
|
||||
q-card-section
|
||||
.text-body2
|
||||
i18n-t(keypath='admin.sites.deleteConfirm')
|
||||
template(v-slot:siteTitle)
|
||||
strong {{site.title}}
|
||||
strong {{props.site.title}}
|
||||
.text-body2.q-mt-md
|
||||
strong.text-negative {{$t(`admin.sites.deleteConfirmWarn`)}}
|
||||
strong.text-negative {{t(`admin.sites.deleteConfirmWarn`)}}
|
||||
q-card-actions.card-actions
|
||||
q-space
|
||||
q-btn.acrylic-btn(
|
||||
flat
|
||||
:label='$t(`common.actions.cancel`)'
|
||||
:label='t(`common.actions.cancel`)'
|
||||
color='grey'
|
||||
padding='xs md'
|
||||
@click='hide'
|
||||
@click='onDialogCancel'
|
||||
)
|
||||
q-btn(
|
||||
unelevated
|
||||
:label='$t(`common.actions.delete`)'
|
||||
:label='t(`common.actions.delete`)'
|
||||
color='negative'
|
||||
padding='xs md'
|
||||
@click='confirm'
|
||||
:loading='state.isLoading'
|
||||
)
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import gql from 'graphql-tag'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useDialogPluginComponent, useQuasar } from 'quasar'
|
||||
import { reactive } from 'vue'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
site: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
emits: ['ok', 'hide'],
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
show () {
|
||||
this.$refs.dialog.show()
|
||||
},
|
||||
hide () {
|
||||
this.$refs.dialog.hide()
|
||||
},
|
||||
onDialogHide () {
|
||||
this.$emit('hide')
|
||||
},
|
||||
async confirm () {
|
||||
try {
|
||||
const siteId = this.site.id
|
||||
const resp = await this.$apollo.mutate({
|
||||
mutation: gql`
|
||||
mutation deleteSite ($id: UUID!) {
|
||||
deleteSite(id: $id) {
|
||||
status {
|
||||
succeeded
|
||||
message
|
||||
}
|
||||
}
|
||||
import { useAdminStore } from '../stores/admin'
|
||||
|
||||
// PROPS
|
||||
|
||||
const props = defineProps({
|
||||
site: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
// EMITS
|
||||
|
||||
defineEmits([
|
||||
...useDialogPluginComponent.emits
|
||||
])
|
||||
|
||||
// QUASAR
|
||||
|
||||
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent()
|
||||
const $q = useQuasar()
|
||||
|
||||
// STORES
|
||||
|
||||
const adminStore = useAdminStore()
|
||||
|
||||
// I18N
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
// DATA
|
||||
|
||||
const state = reactive({
|
||||
isLoading: false
|
||||
})
|
||||
|
||||
// METHODS
|
||||
|
||||
async function confirm () {
|
||||
state.isLoading = true
|
||||
try {
|
||||
const resp = await APOLLO_CLIENT.mutate({
|
||||
mutation: gql`
|
||||
mutation deleteSite ($id: UUID!) {
|
||||
deleteSite(id: $id) {
|
||||
status {
|
||||
succeeded
|
||||
message
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
id: siteId
|
||||
}
|
||||
})
|
||||
if (resp?.data?.deleteSite?.status?.succeeded) {
|
||||
this.$q.notify({
|
||||
type: 'positive',
|
||||
message: this.$t('admin.sites.deleteSuccess')
|
||||
})
|
||||
this.$store.set('admin/sites', this.$store.get('admin/sites').filter(s => s.id !== siteId))
|
||||
this.$emit('ok')
|
||||
this.hide()
|
||||
} else {
|
||||
throw new Error(resp?.data?.deleteSite?.status?.message || 'An unexpected error occured.')
|
||||
}
|
||||
} catch (err) {
|
||||
this.$q.notify({
|
||||
type: 'negative',
|
||||
message: err.message
|
||||
})
|
||||
`,
|
||||
variables: {
|
||||
id: props.site.id
|
||||
}
|
||||
})
|
||||
if (resp?.data?.deleteSite?.status?.succeeded) {
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
message: t('admin.sites.deleteSuccess')
|
||||
})
|
||||
adminStore.$patch({
|
||||
sites: adminStore.sites.filter(s => s.id !== props.site.id)
|
||||
})
|
||||
onDialogOK()
|
||||
} else {
|
||||
throw new Error(resp?.data?.deleteSite?.status?.message || 'An unexpected error occured.')
|
||||
}
|
||||
} catch (err) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
message: err.message
|
||||
})
|
||||
}
|
||||
state.isLoading = false
|
||||
}
|
||||
</script>
|
||||
|
Loading…
Reference in new issue