gancio-upstream/components/admin/Theme.vue

266 lines
8.9 KiB
Vue
Raw Normal View History

2020-07-28 12:24:39 +02:00
<template lang="pug">
2022-07-01 15:55:09 +02:00
v-container
v-card-title {{$t('common.theme')}}
v-card-text
2020-07-28 12:24:39 +02:00
2022-07-01 15:55:09 +02:00
v-switch.mt-5(v-model='is_dark'
inset
:label="$t('admin.is_dark')")
v-switch.mt-5(v-model='hide_thumbs'
inset
:label="$t('admin.hide_thumbs')")
v-switch.mt-5(v-model='hide_calendar'
inset
:label="$t('admin.hide_calendar')")
2020-07-28 12:24:39 +02:00
v-card-title {{$t('admin.default_images')}}
2022-11-29 23:03:36 +01:00
v-card-subtitle(v-html="$t('admin.default_images_help')")
v-card-text
2022-10-28 12:01:59 +02:00
v-row
v-col(cols='4')
2022-10-28 12:01:59 +02:00
//- LOGO
v-file-input.mt-5(ref='upload'
:label="$t('admin.favicon')"
@change='uploadLogo'
accept='image/*')
template(slot='append-outer')
v-btn(color='warning' text @click='resetLogo') <v-icon v-text='mdiRestore'></v-icon> {{$t('common.reset')}}
v-img.mt-2(:src='`/logo.png?${logoKey}`' max-height="60px" contain)
v-col(cols='4')
//- FALLBACK IMAGE
2022-10-28 12:01:59 +02:00
v-file-input.mt-5(ref='upload'
:label="$t('admin.fallback_image')"
2022-10-28 12:01:59 +02:00
persistent-hint
@change='uploadFallbackImage'
accept='image/*')
template(slot='append-outer')
v-btn(color='warning' text @click='resetFallbackImage') <v-icon v-text='mdiRestore'></v-icon> {{$t('common.reset')}}
v-img.mt-2(:src='`/fallbackimage.png?${fallbackImageKey}`' max-height="150px" contain)
v-col(cols='4')
//- HEADER IMAGE
v-file-input.mt-5(ref='upload'
:label="$t('admin.header_image')"
persistent-hint
@change='uploadHeaderImage'
accept='image/*')
template(slot='append-outer')
v-btn(color='warning' text @click='resetHeaderImage') <v-icon v-text='mdiRestore'></v-icon> {{$t('common.reset')}}
v-img.mt-2(:src='`/headerimage.png?${headerImageKey}`' max-height="150px" contain)
2023-03-10 21:58:02 +01:00
v-card-title {{$t('admin.colors')}}
v-card-text
//- choose theme colors
v-row
v-col(v-for='(color, i) in colors' :key='i')
v-menu(v-model='menu[i]'
:close-on-content-click="false"
transition="slide-x-transition"
offset-y
absolute
bottom
max-width="290px"
min-width="290px")
template(v-slot:activator='{ on }')
v-btn(:color='i' small v-on='on') {{i}}
v-color-picker(light :value='color' @update:color='c => updateColor(i, c)')
2022-07-01 15:55:09 +02:00
v-dialog(v-model='linkModal' width='500' :fullscreen='$vuetify.breakpoint.xsOnly')
2021-09-27 11:10:11 +02:00
v-card
2022-07-01 15:55:09 +02:00
v-card-title {{$t('admin.footer_links')}}
v-card-text
v-form(v-model='valid' ref='linkModalForm')
v-text-field(v-model='link.label'
:rules="[$validators.required('common.label')]"
label='Label')
v-text-field(v-model='link.href'
:rules="[$validators.required('common.url')]"
:label="$t('common.url')")
v-card-actions
v-spacer
2022-11-25 09:47:46 +01:00
v-btn(outlined @click='linkModal=false' color='error') {{$t('common.cancel')}}
v-btn(outlined @click='addFooterLink' color='primary' :disabled='!valid') {{$t('common.add')}}
2022-07-01 15:55:09 +02:00
v-card-title {{$t('admin.footer_links')}}
v-card-text
v-btn(color='primary' text @click='openLinkModal') <v-icon v-text='mdiPlus'></v-icon> {{$t('admin.add_link')}}
v-btn(color='warning' text @click='reset') <v-icon v-text='mdiRestore'></v-icon> {{$t('common.reset')}}
v-card
v-list.mt-1(two-line subheader)
v-list-item(v-for='(link, idx) in settings.footerLinks'
:key='`${link.label}`' @click='editFooterLink(link)')
v-list-item-content
v-list-item-title {{link.label}}
v-list-item-subtitle {{link.href}}
v-list-item-action
v-btn.left(v-if='idx !== 0' icon color='warn' @click.stop='moveUpFooterLink(link, idx)')
v-icon(v-text='mdiChevronUp')
v-btn.float-right(icon color='error' @click.stop='removeFooterLink(link)')
v-icon(v-text='mdiDeleteForever')
2020-07-28 12:24:39 +02:00
</template>
<script>
import { mapActions, mapState } from 'vuex'
2022-05-20 14:38:44 +02:00
import { mdiDeleteForever, mdiRestore, mdiPlus, mdiChevronUp } from '@mdi/js'
2023-03-10 21:58:02 +01:00
import debounce from 'lodash/debounce'
2020-07-28 12:24:39 +02:00
export default {
name: 'Theme',
2023-03-10 21:58:02 +01:00
data ({ $store }) {
2022-11-29 23:03:36 +01:00
const t = new Date().getMilliseconds()
2020-07-28 12:24:39 +02:00
return {
2022-05-20 14:38:44 +02:00
mdiDeleteForever, mdiRestore, mdiPlus, mdiChevronUp,
valid: false,
2022-11-29 23:03:36 +01:00
logoKey: t,
fallbackImageKey: t,
headerImageKey: t,
link: { href: '', label: '' },
2023-03-10 21:58:02 +01:00
linkModal: false,
menu: [false, false, false, false],
colors: {
primary: $store.state.settings['theme.primary'],
secondary: $store.state.settings['theme.secondary'],
error: $store.state.settings['theme.error'],
warning: $store.state.settings['theme.warning'],
success: $store.state.settings['theme.success'],
}
2020-07-28 12:24:39 +02:00
}
},
computed: {
...mapState(['settings']),
is_dark: {
get () { return this.settings['theme.is_dark'] },
set (value) {
this.$vuetify.theme.dark = value
this.setSetting({ key: 'theme.is_dark', value })
}
},
hide_thumbs: {
get () { return this.settings.hide_thumbs },
set (value) { this.setSetting({ key: 'hide_thumbs', value }) }
},
hide_calendar: {
get () { return this.settings.hide_calendar },
set (value) { this.setSetting({ key: 'hide_calendar', value }) }
2023-03-10 21:58:02 +01:00
}
2020-07-28 12:24:39 +02:00
},
methods: {
...mapActions(['setSetting']),
2020-10-07 10:06:49 +02:00
reset () {
2021-05-19 16:15:25 +02:00
this.setSetting({
key: 'footerLinks',
value: [
2022-11-25 09:47:46 +01:00
{ href: '/', label: 'common.home' },
{ href: '/about', label: 'common.about' }
]
2021-05-19 16:15:25 +02:00
})
},
2020-07-28 12:24:39 +02:00
forceLogoReload () {
this.logoKey++
},
2022-10-28 12:01:59 +02:00
forceFallbackImageReload () {
this.fallbackImageKey++
},
forceHeaderImageReload () {
this.headerImageKey++
},
2020-07-28 12:24:39 +02:00
resetLogo (e) {
this.setSetting({ key: 'logo', value: null })
.then(this.forceLogoReload)
e.stopPropagation()
},
2022-10-28 12:01:59 +02:00
resetFallbackImage (e) {
this.setSetting({ key: 'fallback_image', value: null })
2022-10-28 12:01:59 +02:00
.then(this.forceFallbackImageReload)
e.stopPropagation()
},
resetHeaderImage (e) {
this.setSetting({ key: 'header_image', value: null })
.then(this.forceHeaderImageReload)
e.stopPropagation()
2023-03-10 21:58:02 +01:00
},
updateSettingColor: debounce( async function (i, value) { this.setSetting({ key: `theme.${i}`, value: value.hex }) }, 200),
updateColor (i, value) {
this.$vuetify.theme.themes.dark[i] = this.$vuetify.theme.themes.light[i] = value.hex
this.updateSettingColor(i, value)
},
2020-10-07 10:06:49 +02:00
openLinkModal () {
// this.link = { href: '', label: '' }
this.linkModal = true
2020-11-04 10:55:30 +01:00
this.$nextTick(() => this.$refs.linkModalForm.reset())
2020-10-07 10:06:49 +02:00
},
addFooterLink () {
const link = Object.assign({}, this.link)
this.setSetting({ key: 'footerLinks', value: this.settings.footerLinks.concat(link) })
// this.link = { href: '', label: '' }
this.$refs.linkModalForm.reset()
this.linkModal = false
},
async removeFooterLink (item) {
2020-10-07 13:05:19 +02:00
const ret = await this.$root.$confirm('admin.delete_footer_link_confirm')
if (!ret) { return }
const footerLinks = this.settings.footerLinks.filter(l => l.label !== item.label)
this.setSetting({ key: 'footerLinks', value: footerLinks })
},
2022-05-20 14:38:44 +02:00
async moveUpFooterLink (item, idx) {
const footerLinks = [...this.settings.footerLinks]
footerLinks[idx] = footerLinks[idx-1]
footerLinks[idx-1] = this.settings.footerLinks[idx]
this.setSetting({ key: 'footerLinks', value: footerLinks })
},
2020-10-07 10:06:49 +02:00
editFooterLink (item) {
this.link = { href: item.href, label: item.label }
this.linkModal = true
},
2020-07-28 12:24:39 +02:00
async uploadLogo (file) {
const formData = new FormData()
formData.append('logo', file)
try {
await this.$axios.$post('/settings/logo', formData)
this.$root.$emit('message', {
message: 'Logo updated'
})
this.forceLogoReload()
} catch (e) {
}
},
2022-10-28 12:01:59 +02:00
async uploadFallbackImage (file) {
const formData = new FormData()
formData.append('fallbackImage', file)
try {
await this.$axios.$post('/settings/fallbackImage', formData)
this.$root.$emit('message', {
message: 'Fallback image updated'
})
this.forceFallbackImageReload()
} catch (e) {
}
2022-10-28 12:01:59 +02:00
},
async uploadHeaderImage (file) {
const formData = new FormData()
formData.append('headerImage', file)
try {
await this.$axios.$post('/settings/headerImage', formData)
this.$root.$emit('message', {
message: 'Header image updated'
})
this.forceHeaderImageReload()
} catch (e) {
}
},
2020-07-28 12:24:39 +02:00
save (key, value) {
if (this.settings[key] !== value) {
this.setSetting({ key, value })
}
}
}
}
</script>