kopia lustrzana https://dev.funkwhale.audio/funkwhale/funkwhale
				
				
				
			Merge branch '143-themes' into 'develop'
Resolve "External stylesheets" Closes #456 See merge request funkwhale/funkwhale!357merge-requests/363/head
						commit
						74c3be9f75
					
				|  | @ -0,0 +1,8 @@ | |||
| Make funkwhale themable by loading external stylesheets (#456) | ||||
| 
 | ||||
| Custom themes for Funkwhale | ||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||
| 
 | ||||
| If you ever wanted to give a custom look and feel to your instance, this is now possible. | ||||
| 
 | ||||
| Check https://docs.funkwhale.audio/configuration.html#theming if you want to know more! | ||||
|  | @ -158,3 +158,79 @@ permissions are: | |||
| There is no dedicated interface to manage users permissions, but superusers | ||||
| can login on the Django's admin at ``/api/admin/`` and grant permissions | ||||
| to users at ``/api/admin/users/user/``. | ||||
| 
 | ||||
| Theming | ||||
| ------- | ||||
| 
 | ||||
| Funkwhale supports custom themes, which are great if you want to personnalize the | ||||
| look and feel of your instance. Theming is achieved by declaring | ||||
| additionnal stylesheets you want to load in the front-end. | ||||
| 
 | ||||
| Customize the settings | ||||
| ^^^^^^^^^^^^^^^^^^^^^^ | ||||
| 
 | ||||
| In order to know what stylesheets to load, the front-end requests the following | ||||
| url: ``https://your.instance/settings.json``. On typical deployments, this url | ||||
| returns a 404 error, which is simply ignored. | ||||
| 
 | ||||
| However, if you return the appropriate payload on this url, you can make the magic | ||||
| work. We will store the necessary files in the ``/srv/funkwhale/custom`` directory: | ||||
| 
 | ||||
| .. code-block:: shell | ||||
| 
 | ||||
|     cd /srv/funkwhale/ | ||||
|     mkdir custom | ||||
|     cat <<EOF > custom/settings.json | ||||
|     { | ||||
|       "additionalStylesheets": ["/custom/custom.css"] | ||||
|     } | ||||
|     EOF | ||||
|     cat <<EOF > custom/custom.css | ||||
|     body { | ||||
|       background-color: red; | ||||
|     } | ||||
|     EOF | ||||
| 
 | ||||
| By executing the previous commands, you will end up with two files in your ``/srv/funkwhale/custom`` | ||||
| directory: | ||||
| 
 | ||||
| - ``settings.json`` will tell the front-end what stylesheets you want to load (``/custom/custom.css`` in this example) | ||||
| - ``custom.css`` will hold your custom CSS | ||||
| 
 | ||||
| The last step to make this work is to ensure both files are served by the reverse proxy. | ||||
| 
 | ||||
| On nginx, add the following snippet to your vhost config:: | ||||
| 
 | ||||
|     location /settings.json { | ||||
|         alias /srv/funkwhale/custom/settings.json; | ||||
|     } | ||||
|     location /custom { | ||||
|         alias /srv/funkwhale/custom; | ||||
|     } | ||||
| 
 | ||||
| On apache, use the following one:: | ||||
| 
 | ||||
|     Alias /settings.json /srv/funkwhale/custom/settings.json | ||||
|     Alias /custom /srv/funkwhale/custom | ||||
| 
 | ||||
|     <Directory "/srv/funkwhale/custom"> | ||||
|       Options FollowSymLinks | ||||
|       AllowOverride None | ||||
|       Require all granted | ||||
|     </Directory> | ||||
| 
 | ||||
| Once done, reload your reverse proxy, refresh Funkwhale in your web browser, and you should see | ||||
| a red background. | ||||
| 
 | ||||
| .. note:: | ||||
| 
 | ||||
|     You can reference external urls as well in ``settings.json``, simply use | ||||
|     the full urls. Be especially careful with external urls as they may affect your users | ||||
|     privacy. | ||||
| 
 | ||||
| .. warning:: | ||||
| 
 | ||||
|     Loading additional stylesheets and CSS rules can affect the performance and | ||||
|     usability of your instance. If you encounter issues with the interfaces and use | ||||
|     custom stylesheets, try to disable those to ensure the issue is not caused | ||||
|     by your customizations. | ||||
|  |  | |||
|  | @ -29,6 +29,9 @@ module.exports = { | |||
|     assetsSubDirectory: 'static', | ||||
|     assetsPublicPath: '/', | ||||
|     proxyTable: { | ||||
|       '/settings.json': { | ||||
|         target: 'http://127.0.0.1:8000/static/', | ||||
|       }, | ||||
|       '**': { | ||||
|         target: 'http://nginx:6001', | ||||
|         changeOrigin: true, | ||||
|  |  | |||
|  | @ -1,5 +1,7 @@ | |||
| <template> | ||||
|   <div id="app"> | ||||
|     <!-- here, we display custom stylesheets, if any --> | ||||
|     <link v-for="url in customStylesheets" rel="stylesheet" property="stylesheet" :href="url" :key="url"> | ||||
|     <div class="ui main text container instance-chooser" v-if="!$store.state.instance.instanceUrl"> | ||||
|       <div class="ui padded segment"> | ||||
|         <h1 class="ui header"><translate>Choose your instance</translate></h1> | ||||
|  | @ -175,6 +177,11 @@ export default { | |||
|         return null | ||||
|       } | ||||
|       return _.get(this.nodeinfo, 'software.version') | ||||
|     }, | ||||
|     customStylesheets () { | ||||
|       if (this.$store.state.instance.frontSettings) { | ||||
|         return this.$store.state.instance.frontSettings.additionalStylesheets || [] | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   watch: { | ||||
|  |  | |||
|  | @ -126,6 +126,8 @@ axios.interceptors.response.use(function (response) { | |||
|   return Promise.reject(error) | ||||
| }) | ||||
| 
 | ||||
| store.dispatch('instance/fetchFrontSettings') | ||||
| 
 | ||||
| /* eslint-disable no-new */ | ||||
| new Vue({ | ||||
|   el: '#app', | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ export default { | |||
|   namespaced: true, | ||||
|   state: { | ||||
|     maxEvents: 200, | ||||
|     frontSettings: {}, | ||||
|     instanceUrl: process.env.INSTANCE_URL, | ||||
|     events: [], | ||||
|     settings: { | ||||
|  | @ -53,6 +54,9 @@ export default { | |||
|     events: (state, value) => { | ||||
|       state.events = value | ||||
|     }, | ||||
|     frontSettings: (state, value) => { | ||||
|       state.frontSettings = value | ||||
|     }, | ||||
|     instanceUrl: (state, value) => { | ||||
|       if (value && !value.endsWith('/')) { | ||||
|         value = value + '/' | ||||
|  | @ -110,6 +114,13 @@ export default { | |||
|       }, response => { | ||||
|         logger.default.error('Error while fetching settings', response.data) | ||||
|       }) | ||||
|     }, | ||||
|     fetchFrontSettings ({commit}) { | ||||
|       return axios.get('/settings.json').then(response => { | ||||
|         commit('frontSettings', response.data) | ||||
|       }, response => { | ||||
|         logger.default.error('Error when fetching front-end configuration (or no customization available)') | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1 @@ | |||
| /* This is a custom CSS file that can be loaded thanks to settings.json */ | ||||
|  | @ -0,0 +1,3 @@ | |||
| { | ||||
|   "additionalStylesheets": ["/static/custom.css"] | ||||
| } | ||||
		Ładowanie…
	
		Reference in New Issue
	
	 Eliot Berriot
						Eliot Berriot