feat: custom javascript and CSS, fix #413

This commit is contained in:
lesion 2024-07-25 16:33:18 +02:00
parent e83558892c
commit ba9ed8af34
No known key found for this signature in database
GPG key ID: 352918250B012177
10 changed files with 113 additions and 9 deletions

View file

@ -1,5 +1,5 @@
<template>
<v-tabs centered background-color='transparent' optional dense icons-and-text class='mt-4'>
<v-tabs id='navbar' centered background-color='transparent' optional dense icons-and-text class='mt-4'>
<v-tab v-if='$auth.loggedIn || settings.allow_anon_event' to='/add' :ripple="false">
<span class='d-none d-sm-flex'>{{$t('common.add_event')}}</span>
<v-icon color='primary' v-text='mdiPlus' />

View file

@ -119,6 +119,16 @@ v-container
v-btn.float-right(icon color='error' @click.stop='removeFooterLink(link)')
v-icon(v-text='mdiDeleteForever')
v-card-title {{$t('admin.custom_js')}}
v-card-subtitle(v-html="$t('admin.custom_js_help')")
v-card-text
v-textarea(:value='custom_js' @change='v => custom_js = v' :label='$t("admin.custom_js")' outlined)
v-card-title {{$t('admin.custom_css')}}
v-card-subtitle(v-html="$t('admin.custom_css_help')")
v-card-text
v-textarea(:value='custom_css' @change='v => custom_css = v' :label='$t("admin.custom_css")' outlined)
</template>
<script>
import { mapActions, mapState } from 'vuex'
@ -158,7 +168,15 @@ export default {
hide_calendar: {
get () { return this.settings.hide_calendar },
set (value) { this.setSetting({ key: 'hide_calendar', value }) }
}
},
custom_js: {
get () { return this.settings.custom_js },
set (value) { this.setSetting({ key: 'custom_js', value })}
},
custom_css: {
get () { return this.settings.custom_css },
set (value) { this.setSetting({ key: 'custom_css', value })}
}
},
methods: {
...mapActions(['setSetting', 'setLocalSetting']),

25
docs/usage/custom_css.md Normal file
View file

@ -0,0 +1,25 @@
---
layout: default
title: Custom CSS
permalink: /usage/custom_css
nav_order: 3
parent: Usage
---
## Custom CSS <span class='label label-yellow'>Since 1.19.0</span> <span class='label label-red'>BETA</span>
Is it possible to modify the style by integrating some custom css.
Don't imagine you can accomplish miracles because the templates are not designed to be easily modified,
but don't be afraid to [open an issue](https://framagit.org/les/gancio/-/issues) or even better a PR to add some css selectors or some usage examples to this page.
### Remove navbar
```css
#navbar {
display: none;
}
```
> info "References"
> [#413](https://framagit.org/les/gancio/-/issues/413)

32
docs/usage/custom_js.md Normal file
View file

@ -0,0 +1,32 @@
---
layout: default
title: Custom Javascript
permalink: /usage/custom_js
nav_order: 3
parent: Usage
---
## Custom Javascript <span class='label label-yellow'>Since 1.19.0</span> <span class='label label-red'>BETA</span>
You can integrate some javascript code that will be loaded for each user.
Don't imagine you can accomplish miracles because the templates are not designed to be easily modified,
but don't be afraid to [open an issue](https://framagit.org/les/gancio/-/issues) or even better a PR to add some usage examples to this page.
## Examples:
### Integrate Plausible
```js
var script = document.createElement('script');
script.defer = true;
script.src = "https://plausible.io/js/script.js";
script.dataset.domain = "yourdomain.com";
document.getElementsByTagName('head')[0].appendChild(script);
```
> info "References"
> [#413](https://framagit.org/les/gancio/-/issues/413), [#320](https://framagit.org/les/gancio/-/issues/320)

View file

@ -23,11 +23,20 @@ import { mapState, mapGetters } from 'vuex'
export default {
head () {
const custom_script = [{ type: 'application/javascript', defer: true, src: '/custom_js', body: true }]
const custom_style = [{ rel: 'stylesheet', href: this.settings.baseurl + '/custom_css'}]
return {
htmlAttrs: {
lang: this.locale
},
link: [{ rel: 'icon', type: 'image/png', href: this.settings.baseurl + '/logo.png' }],
link: [
{ rel: 'icon', type: 'image/png', href: this.settings.baseurl + '/logo.png' },
...custom_style
],
script: [
{ src: '/gancio-events.es.js', body: true, defer: true },
...custom_script
]
}
},
name: 'Default',

View file

@ -343,7 +343,11 @@
"tag_renamed": "Tag \"{oldTag}\" renamed to \"{newTag}\"",
"stats": "{n_followers} \"actors\" are following this instance, there are {n_events} events from the fediverse and {n_resources} comments",
"show_download_media": "Show download media action",
"show_download_media_hint": "Display a download media button in event's page"
"show_download_media_hint": "Display a download media button in event's page",
"custom_js": "Custom Javascript Code",
"custom_css": "Custom CSS Style",
"custom_js_help": "You can integrate some javascript code that will be loaded for each user by writing in this textarea below. You probably want to read the <a href='https://gancio.org/usage/custom_js'>documentation</a> first.",
"custom_css_help": "You can customize some stylesheet too, read some example <a href='https://gancio.org/usage/custom_css'>here</a>."
},
"auth": {
"not_confirmed": "Not confirmed yet…",

View file

@ -16,7 +16,6 @@ module.exports = {
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
],
script: [{ src: '/gancio-events.es.js', async: true, body: true }],
},
dev: isDev,
server: config.server,

View file

@ -55,7 +55,9 @@ const defaultSettings = {
plugins: [],
admin_email: config.admin_email || '',
smtp: config.smtp || {},
collection_in_home: null
collection_in_home: null,
custom_js: '',
custom_css: ''
}
/**

View file

@ -63,7 +63,6 @@ module.exports = {
async initSettings(_req, res, next) {
// initialize settings
// res.locals.settings = cloneDeep(settingsController.settings)
const settings = settingsController.settings
res.locals.settings = {
title: settings.title || config.title,
@ -103,7 +102,9 @@ module.exports = {
footerLinks: settings.footerLinks,
admin_email: settings.admin_email,
about: settings.about,
collection_in_home: settings.collection_in_home
collection_in_home: settings.collection_in_home,
custom_js: settings.custom_js,
custom_css: settings.custom_css
}
next()
},
@ -148,6 +149,14 @@ module.exports = {
return express.static(faviconPath, { immutable: true, maxAge: '10m' })(req, res, next)
})
router.use('/custom_js', (_req, res, next) => {
return res.type('application/javascript').send(res.locals.settings?.custom_js ?? '')
})
router.use('/custom_css', (_req, res, next) => {
return res.type('text/css').send(res.locals.settings?.custom_css ?? '')
})
return router
},

View file

@ -78,8 +78,14 @@ export const mutations = {
export const actions = {
// this method is called server side only for each request for nuxt
// we use it to get configuration from db, set locale, etc...
nuxtServerInit ({ commit }, { res, app }) {
nuxtServerInit ({ commit }, { res, req, app }) {
if (res.locals && res.locals.settings) {
// TODO: this is temporary, see #431
if (!req?.user?.is_admin) {
delete res.locals.settings.custom_js
delete res.locals.settings.custom_css
delete res.locals.settings.admin_email
}
commit('setSettings', res.locals.settings)
commit('setFilter', { type: 'show_recurrent',
value: res.locals.settings.allow_recurrent_event && res.locals.settings.recurrent_event_visible })