You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
wiki/frontend/src/components/EditorMarkdownUserSettingsO...

184 lines
5.3 KiB

<template>
<w-layout view="hHh lpR fFf" container>
<w-header class="card-header px-4 py-2">
<w-icon name="img:/_assets/icons/ultraviolet-markdown.svg" left size="md" />
<span>{{t('editor.settings.markdown')}}</span>
<w-space />
<w-btn
class="mr-2"
flat
rounded
color="white"
:aria-label="t(`common.actions.refresh`)"
icon="la:question-circle"
:href="siteStore.docsBase + `/editor/markdown`"
target="_blank"
type="a" />
<w-btn-group push>
<w-btn
push
color="grey-6"
text-color="white"
:aria-label="t(`common.actions.refresh`)"
icon="la:redo-alt"
@click="load"
:loading="state.loading > 0">
<w-tooltip anchor="center left" self="center right">{{t(`common.actions.refresh`)}}</w-tooltip>
</w-btn>
<w-btn
push
color="white"
text-color="grey-7"
:label="t(`common.actions.cancel`)"
:aria-label="t(`common.actions.cancel`)"
icon="la:times"
@click="close" />
<w-btn
push
color="positive"
text-color="white"
:label="t(`common.actions.apply`)"
:aria-label="t(`common.actions.apply`)"
icon="la:check"
@click="save"
:disabled="state.loading > 0" />
</w-btn-group>
</w-header>
<w-page-container>
<w-page class="p-4" style="max-width: 1200px; margin: 0 auto;">
<w-card class="shadow-1 py-2">
<w-item tag="label">
<blueprint-icon icon="enter-key" />
<w-item-section>
<w-item-label>{{t(`editor.settings.markdownPreviewShown`)}}</w-item-label>
<w-item-label caption>{{t(`editor.settings.markdownPreviewShownHint`)}}</w-item-label>
</w-item-section>
<w-item-section avatar>
<w-toggle
v-model="state.config.previewShown"
color="primary"
checked-icon="la:check"
unchecked-icon="la:times"
:aria-label="t(`editor.settings.markdownPreviewShown`)" />
</w-item-section>
</w-item>
<w-separator class="my-2" inset />
<w-item>
<blueprint-icon icon="width" />
<w-item-section>
<w-item-label>{{t(`editor.settings.markdownFontSize`)}}</w-item-label>
<w-item-label caption>{{t(`editor.settings.markdownFontSizeHint`)}}</w-item-label>
</w-item-section>
<w-item-section side>
<w-input
type="number"
min="10"
max="32"
style="width: 100px;"
outlined
v-model="state.config.fontSize"
dense
:aria-label="t(`editor.settings.markdownFontSize`)" />
</w-item-section>
</w-item>
</w-card>
<w-inner-loading :showing="state.loading > 0">
<w-spinner color="accent" size="lg" />
</w-inner-loading>
</w-page>
</w-page-container>
</w-layout>
</template>
<script setup>
import { useI18n } from 'vue-i18n'
import { onMounted, reactive } from 'vue'
import { loading } from '@/composables/loading'
import { notify } from '@/composables/notify'
import { useEditorStore } from '@/stores/editor'
import { useSiteStore } from '@/stores/site'
import { useUserStore } from '@/stores/user'
import { apiErrorMessage } from '@/helpers/apiError'
// STORES
const editorStore = useEditorStore()
const siteStore = useSiteStore()
const userStore = useUserStore()
// I18N
const { t } = useI18n()
// DATA
const state = reactive({
config: {
previewShown: false,
fontSize: 16
},
loading: 0
})
// METHODS
function close() {
siteStore.$patch({ overlay: '' })
}
async function load() {
state.loading++
loading.show()
try {
// -> An empty object is the correct answer for a user who has never saved any settings, so the
// defaults live here rather than being treated as a failure
const conf = (await API_CLIENT.get('users/profile/editor-settings/markdown').json()) ?? {}
state.config.previewShown = conf.previewShown ?? true
state.config.fontSize = conf.fontSize ?? 16
} catch (err) {
notify({
type: 'negative',
message: 'Failed to fetch Markdown editor settings.',
caption: err.message
})
}
loading.hide()
state.loading--
}
async function save() {
state.loading++
try {
const resp = await API_CLIENT.put('users/profile/editor-settings/markdown', {
json: {
previewShown: state.config.previewShown,
// -> A number input hands back a string; the editor reads this as a pixel size
fontSize: Number.parseInt(state.config.fontSize, 10)
}
}).json()
if (!resp?.ok) {
throw new Error(resp?.message || 'An unexpected error occured.')
}
notify({
type: 'positive',
message: t('admin.editors.markdown.saveSuccess')
})
close()
} catch (err) {
// -> ky throws above 400, with the reason in the body
notify({
type: 'negative',
message: 'Failed to save Markdown editor settings.',
caption: apiErrorMessage(err)
})
}
state.loading--
}
onMounted(() => {
load()
})
</script>