diff --git a/dashboard/public/js/index.js b/dashboard/public/js/index.js index cce21f916..7fd604ae7 100644 --- a/dashboard/public/js/index.js +++ b/dashboard/public/js/index.js @@ -97,8 +97,8 @@ app.config(['$routeProvider', function ($routeProvider) { }).when('/oidc', { redirectTo: '/user-directory' }).when('/settings', { - controller: 'SettingsController', - templateUrl: 'views/settings.html?' + window.VITE_CACHE_ID + // controller: 'SettingsController', + // templateUrl: 'views/settings.html?' + window.VITE_CACHE_ID }).when('/eventlog', { controller: 'EventLogController', templateUrl: 'views/eventlog.html?' + window.VITE_CACHE_ID diff --git a/dashboard/src/Index.vue b/dashboard/src/Index.vue index 6e8fd9368..f45f8edb3 100644 --- a/dashboard/src/Index.vue +++ b/dashboard/src/Index.vue @@ -7,6 +7,7 @@ import AppstoreView from './views/AppstoreView.vue'; import NetworkView from './views/NetworkView.vue'; import ProfileView from './views/ProfileView.vue'; import ServicesView from './views/ServicesView.vue'; +import SettingsView from './views/SettingsView.vue'; import SupportView from './views/SupportView.vue'; import UserDirectoryView from './views/UserDirectoryView.vue'; import VolumesView from './views/VolumesView.vue'; @@ -20,8 +21,9 @@ const VIEWS = { APPSTORE: 'appstore', NETWORK: 'network', PROFILE: 'profile', - SUPPORT: 'support', SERVICES: 'services', + SETTINGS: 'settings', + SUPPORT: 'support', USER_DIRECTORY: 'user-directory', VOLUMES: 'volumes', }; @@ -34,8 +36,9 @@ export default { NetworkView, Notification, ProfileView, - SupportView, ServicesView, + SettingsView, + SupportView, UserDirectoryView, VolumesView, }, @@ -72,6 +75,8 @@ export default { that.view = VIEWS.PROFILE; } else if (view === VIEWS.SERVICES) { that.view = VIEWS.SERVICES; + } else if (view === VIEWS.SETTINGS) { + that.view = VIEWS.SETTINGS; } else if (view === VIEWS.SUPPORT) { that.view = VIEWS.SUPPORT; } else if (view === VIEWS.USER_DIRECTORY) { @@ -102,6 +107,7 @@ export default { + diff --git a/dashboard/src/components/SystemUpdate.vue b/dashboard/src/components/SystemUpdate.vue new file mode 100644 index 000000000..4a121b8f1 --- /dev/null +++ b/dashboard/src/components/SystemUpdate.vue @@ -0,0 +1,21 @@ + + + diff --git a/dashboard/src/models/CloudronModel.js b/dashboard/src/models/CloudronModel.js index e0e92cb39..5250e8236 100644 --- a/dashboard/src/models/CloudronModel.js +++ b/dashboard/src/models/CloudronModel.js @@ -12,12 +12,52 @@ function create(origin, accessToken) { error = e; } - if (error || result.status !== 200) { - console.error('Failed to get languages.', error || result.status); - return []; + if (error || result.status !== 200) return [error || result]; + return [null, result.body.languages]; + }, + async getLanguage() { + let error, result; + try { + result = await fetcher.get(`${origin}/api/v1/cloudron/language`, { access_token: accessToken }); + } catch (e) { + error = e; } - return result.body.languages; + if (error || result.status !== 200) return [error || result]; + return [null, result.body.language]; + }, + async setLanguage(language) { + let error, result; + try { + result = await fetcher.post(`${origin}/api/v1/cloudron/language`, { language }, { access_token: accessToken }); + } catch (e) { + error = e; + } + + if (error || result.status !== 200) return [error || result]; + return [null]; + }, + async getTimeZone() { + let error, result; + try { + result = await fetcher.get(`${origin}/api/v1/cloudron/time_zone`, { access_token: accessToken }); + } catch (e) { + error = e; + } + + if (error || result.status !== 200) return [error || result]; + return [null, result.body.timeZone]; + }, + async setTimeZone(timeZone) { + let error, result; + try { + result = await fetcher.post(`${origin}/api/v1/cloudron/time_zone`, { timeZone }, { access_token: accessToken }); + } catch (e) { + error = e; + } + + if (error || result.status !== 200) return [error || result]; + return [null]; }, }; } diff --git a/dashboard/src/views/ProfileView.vue b/dashboard/src/views/ProfileView.vue index cfe4498cc..1884a96a6 100644 --- a/dashboard/src/views/ProfileView.vue +++ b/dashboard/src/views/ProfileView.vue @@ -204,8 +204,8 @@ async function onTwoFADisable() { onMounted(async () => { user.value = await profileModel.get(); - const langs = await cloudronModel.languages(); - languages.value = langs.map(l => { + let [error, result] = await cloudronModel.languages(); + languages.value = result.map(l => { return { id: l, display: t(`lang.${l}`) @@ -217,12 +217,12 @@ onMounted(async () => { const usedLang = window.localStorage.NG_TRANSLATE_LANG_KEY || 'en'; language.value = languages.value.find(l => l.id === usedLang).id; - const [error, tokens] = await tokensModel.list(); + [error, result] = await tokensModel.list(); if (error) return console.error(error); // dashboard and development clientIds were issued with 7.5.0 - webadminTokens.value = tokens.filter(function (c) { return c.clientId === TOKEN_TYPES.ID_WEBADMIN || c.clientId === TOKEN_TYPES.ID_DEVELOPMENT || c.clientId === 'dashboard' || c.clientId === 'development'; }); - cliTokens.value = tokens.filter(function (c) { return c.clientId === TOKEN_TYPES.ID_CLI; }); + webadminTokens.value = result.filter(function (c) { return c.clientId === TOKEN_TYPES.ID_WEBADMIN || c.clientId === TOKEN_TYPES.ID_DEVELOPMENT || c.clientId === 'dashboard' || c.clientId === 'development'; }); + cliTokens.value = result.filter(function (c) { return c.clientId === TOKEN_TYPES.ID_CLI; }); }); diff --git a/dashboard/src/views/SettingsView.vue b/dashboard/src/views/SettingsView.vue new file mode 100644 index 000000000..27fcc3e49 --- /dev/null +++ b/dashboard/src/views/SettingsView.vue @@ -0,0 +1,111 @@ + + +