diff --git a/dashboard/public/js/index.js b/dashboard/public/js/index.js index 3dfd5165e..8bb5078d0 100644 --- a/dashboard/public/js/index.js +++ b/dashboard/public/js/index.js @@ -71,8 +71,8 @@ app.config(['$routeProvider', function ($routeProvider) { // controller: 'BackupsController', // templateUrl: 'views/backups.html?' + window.VITE_CACHE_ID }).when('/branding', { - controller: 'BrandingController', - templateUrl: 'views/branding.html?' + window.VITE_CACHE_ID + // controller: 'BrandingController', + // templateUrl: 'views/branding.html?' + window.VITE_CACHE_ID }).when('/network', { // controller: 'NetworkController', // templateUrl: 'views/network.html?' + window.VITE_CACHE_ID diff --git a/dashboard/src/Index.vue b/dashboard/src/Index.vue index ec4d6ca2d..8d5448d02 100644 --- a/dashboard/src/Index.vue +++ b/dashboard/src/Index.vue @@ -5,6 +5,7 @@ import { Notification } from 'pankow'; import AppsView from './views/AppsView.vue'; import AppstoreView from './views/AppstoreView.vue'; import BackupsView from './views/BackupsView.vue'; +import BrandingView from './views/BrandingView.vue'; import DomainsView from './views/DomainsView.vue'; import EventlogView from './views/EventlogView.vue'; import NetworkView from './views/NetworkView.vue'; @@ -19,6 +20,7 @@ const VIEWS = { APPS: 'apps', APPSTORE: 'appstore', BACKUPS: 'backups', + BRANDING: 'branding', DOMAINS: 'domains', EVENTLOG: 'eventlog', NETWORK: 'network', @@ -41,6 +43,8 @@ function onHashChange() { view.value = VIEWS.APPSTORE; } else if (v === VIEWS.BACKUPS) { view.value = VIEWS.BACKUPS; + } else if (v === VIEWS.BRANDING) { + view.value = VIEWS.BRANDING; } else if (v === VIEWS.DOMAINS) { view.value = VIEWS.DOMAINS; } else if (v === VIEWS.EVENTLOG) { @@ -86,6 +90,7 @@ onMounted(async () => { + diff --git a/dashboard/src/models/BrandingModel.js b/dashboard/src/models/BrandingModel.js new file mode 100644 index 000000000..c8211ecfc --- /dev/null +++ b/dashboard/src/models/BrandingModel.js @@ -0,0 +1,77 @@ + +import { fetcher } from 'pankow'; + +function create() { + const accessToken = localStorage.token; + const origin = import.meta.env.VITE_API_ORIGIN || window.location.origin; + + return { + async getFooter() { + let error, result; + try { + result = await fetcher.get(`${origin}/api/v1/branding/footer`, { access_token: accessToken }); + } catch (e) { + error = e; + } + + if (error || result.status !== 200) return [error || result]; + return [null, result.body.footer]; + }, + async setFooter(footer) { + let error, result; + try { + result = await fetcher.post(`${origin}/api/v1/branding/footer`, { footer }, { access_token: accessToken }); + } catch (e) { + error = e; + } + + if (error || result.status !== 200) return [error || result]; + return [null]; + }, + async setName(name) { + let error, result; + try { + result = await fetcher.post(`${origin}/api/v1/branding/cloudron_name`, { name }, { access_token: accessToken }); + } catch (e) { + error = e; + } + + if (error || result.status !== 200) return [error || result]; + return [null]; + }, + async setBackground(image) { + // Blob type if object + const fd = new FormData(); + if (image) fd.append('background', image); + + let error, result; + try { + result = await fetcher.post(`${origin}/api/v1/branding/cloudron_background`, fd, { access_token: accessToken }); + } catch (e) { + error = e; + } + + if (error || result.status !== 202) return [error || result]; + return [null]; + }, + async setAvatar(image) { + // Blob type if object + const fd = new FormData(); + if (image) fd.append('avatar', image); + + let error, result; + try { + result = await fetcher.post(`${origin}/api/v1/branding/cloudron_avatar`, fd, { access_token: accessToken }); + } catch (e) { + error = e; + } + + if (error || result.status !== 200) return [error || result]; + return [null]; + }, + }; +} + +export default { + create, +}; diff --git a/dashboard/src/views/BrandingView.vue b/dashboard/src/views/BrandingView.vue new file mode 100644 index 000000000..14c790879 --- /dev/null +++ b/dashboard/src/views/BrandingView.vue @@ -0,0 +1,203 @@ + + + + + + + + + + + {{ $t('branding.cloudronName') }} + + + + + {{ $t('branding.logo') }} + + + + + + + + + {{ $t('branding.backgroundImage') }} + + + + + {{ $t('branding.clearBackgroundImage') }} + + + + + {{ $t('branding.footer.title') }} + {{ $t('branding.footer.description') }} + + + + + + {{ $t('main.dialog.save') }} + + + + +
{{ $t('branding.footer.description') }}