Files
cloudron-box/dashboard/src/Index.vue

183 lines
6.5 KiB
Vue
Raw Normal View History

2025-02-03 19:14:01 +01:00
<script setup>
2024-11-01 14:16:09 +01:00
2025-02-03 19:14:01 +01:00
import { onMounted, ref } from 'vue';
2024-12-27 22:25:00 +01:00
import { Notification } from 'pankow';
2025-03-17 16:53:53 +01:00
import { API_ORIGIN, TOKEN_TYPES } from './constants.js';
2025-03-16 11:12:49 +01:00
import ProfileModel from './models/ProfileModel.js';
import DashboardModel from './models/DashboardModel.js';
import Sidebar from './components/Sidebar.vue';
import Headerbar from './components/Headerbar.vue';
2025-01-21 17:08:09 +01:00
import AppsView from './views/AppsView.vue';
2025-02-20 10:54:43 +01:00
import AppConfigureView from './views/AppConfigureView.vue';
2025-01-21 17:08:09 +01:00
import AppstoreView from './views/AppstoreView.vue';
import BackupsView from './views/BackupsView.vue';
2025-02-10 18:42:02 +01:00
import BrandingView from './views/BrandingView.vue';
import DomainsView from './views/DomainsView.vue';
import EmailView from './views/EmailView.vue';
import EmailDomainView from './views/EmailDomainView.vue';
2025-03-10 16:16:04 +01:00
import EmailsEventlogView from './views/EmailsEventlogView.vue';
2025-01-25 17:09:53 +01:00
import EventlogView from './views/EventlogView.vue';
2025-03-13 16:16:07 +01:00
import MailboxesView from './views/MailboxesView.vue';
2025-03-14 21:51:26 +01:00
import MailinglistsView from './views/MailinglistsView.vue';
2025-01-22 14:46:31 +01:00
import NetworkView from './views/NetworkView.vue';
2025-01-21 17:08:09 +01:00
import ProfileView from './views/ProfileView.vue';
import ServicesView from './views/ServicesView.vue';
2025-01-23 18:36:30 +01:00
import SettingsView from './views/SettingsView.vue';
2025-01-21 17:08:09 +01:00
import SupportView from './views/SupportView.vue';
2025-02-17 11:18:57 +01:00
import SystemView from './views/SystemView.vue';
2025-01-21 17:08:09 +01:00
import UserDirectoryView from './views/UserDirectoryView.vue';
2025-02-11 18:50:10 +01:00
import UsersView from './views/UsersView.vue';
2025-01-21 17:08:09 +01:00
import VolumesView from './views/VolumesView.vue';
2024-11-01 14:16:09 +01:00
const VIEWS = {
2024-12-29 00:36:48 +01:00
APPS: 'apps',
2025-02-20 10:54:43 +01:00
APP: 'app',
2025-01-05 22:47:50 +01:00
APPSTORE: 'appstore',
BACKUPS: 'backups',
2025-02-10 18:42:02 +01:00
BRANDING: 'branding',
DOMAINS: 'domains',
EMAIL: 'email',
EMAIL_DOMAIN: 'email-domain',
2025-03-10 16:16:04 +01:00
EMAILS_EVENTLOG: 'emails-eventlog',
2025-03-13 16:16:07 +01:00
EMAILS_MAILBOXES: 'emails-mailboxes',
2025-03-14 21:51:26 +01:00
EMAILS_MAILINGLISTS: 'emails-mailinglists',
2025-01-25 17:09:53 +01:00
EVENTLOG: 'eventlog',
2025-01-22 14:46:31 +01:00
NETWORK: 'network',
2025-01-14 10:27:27 +01:00
PROFILE: 'profile',
2025-01-21 16:54:56 +01:00
SERVICES: 'services',
2025-01-23 18:36:30 +01:00
SETTINGS: 'settings',
SUPPORT: 'support',
2025-02-17 11:18:57 +01:00
SYSTEM: 'system',
USER_DIRECTORY: 'user-directory',
2025-02-11 18:50:10 +01:00
USERS: 'users',
2024-12-26 12:19:48 +01:00
VOLUMES: 'volumes',
2024-11-01 14:16:09 +01:00
};
2025-03-16 11:12:49 +01:00
const dashboardModel = DashboardModel.create();
const profileModel = ProfileModel.create();
2025-02-03 19:14:01 +01:00
const view = ref('');
2025-03-16 11:12:49 +01:00
const profile = ref({});
const subscription = ref({
plan: {},
});
const config = ref({});
2025-01-03 15:06:41 +01:00
2025-02-03 19:14:01 +01:00
function onHashChange() {
const v = location.hash.slice(2);
2024-11-01 14:16:09 +01:00
2025-02-03 19:14:01 +01:00
if (v === VIEWS.APPS) {
view.value = VIEWS.APPS;
} else if (v.indexOf(VIEWS.APPSTORE) === 0) {
view.value = VIEWS.APPSTORE;
2025-02-20 10:54:43 +01:00
} else if (v.indexOf(VIEWS.APP) === 0) {
view.value = VIEWS.APP;
} else if (v === VIEWS.BACKUPS) {
view.value = VIEWS.BACKUPS;
2025-02-10 18:42:02 +01:00
} else if (v === VIEWS.BRANDING) {
view.value = VIEWS.BRANDING;
2025-02-03 19:14:01 +01:00
} else if (v === VIEWS.DOMAINS) {
view.value = VIEWS.DOMAINS;
} else if (v === VIEWS.EMAIL) {
view.value = VIEWS.EMAIL;
2025-03-10 16:16:04 +01:00
} else if (v === VIEWS.EMAILS_EVENTLOG) {
view.value = VIEWS.EMAILS_EVENTLOG;
2025-03-13 16:16:07 +01:00
} else if (v === VIEWS.EMAILS_MAILBOXES) {
view.value = VIEWS.EMAILS_MAILBOXES;
2025-03-14 21:51:26 +01:00
} else if (v === VIEWS.EMAILS_MAILINGLISTS) {
view.value = VIEWS.EMAILS_MAILINGLISTS;
} else if (v.indexOf(VIEWS.EMAIL) === 0) {
view.value = VIEWS.EMAIL_DOMAIN;
2025-02-03 19:14:01 +01:00
} else if (v === VIEWS.EVENTLOG) {
view.value = VIEWS.EVENTLOG;
} else if (v === VIEWS.NETWORK) {
view.value = VIEWS.NETWORK;
} else if (v === VIEWS.PROFILE) {
view.value = VIEWS.PROFILE;
} else if (v === VIEWS.SERVICES) {
view.value = VIEWS.SERVICES;
} else if (v === VIEWS.SETTINGS) {
view.value = VIEWS.SETTINGS;
} else if (v === VIEWS.SUPPORT) {
view.value = VIEWS.SUPPORT;
2025-02-17 11:18:57 +01:00
} else if (v === VIEWS.SYSTEM) {
view.value = VIEWS.SYSTEM;
2025-02-11 18:50:10 +01:00
} else if (v === VIEWS.USER_DIRECTORY) {
2025-02-03 19:14:01 +01:00
view.value = VIEWS.USER_DIRECTORY;
2025-02-11 18:50:10 +01:00
} else if (v === VIEWS.USERS) {
view.value = VIEWS.USERS;
2025-02-03 19:14:01 +01:00
} else if (v === VIEWS.VOLUMES) {
view.value = VIEWS.VOLUMES;
} else {
2025-03-16 11:12:49 +01:00
window.location.hash = '/' + VIEWS.APPS;
2025-02-03 19:14:01 +01:00
}
}
2024-11-01 14:16:09 +01:00
2025-02-03 19:14:01 +01:00
onMounted(async () => {
if (!localStorage.token) {
2025-03-17 16:53:53 +01:00
localStorage.setItem('redirectToHash', window.location.hash);
// start oidc flow
window.location.href = `${API_ORIGIN}/openid/auth?client_id=` + (API_ORIGIN ? TOKEN_TYPES.ID_DEVELOPMENT : TOKEN_TYPES.ID_WEBADMIN) + '&scope=openid email profile&response_type=code token&redirect_uri=' + window.location.origin + '/authcallback.html';
2025-02-03 19:14:01 +01:00
return;
2024-11-01 14:16:09 +01:00
}
2025-02-03 19:14:01 +01:00
window.addEventListener('hashchange', onHashChange);
onHashChange();
2025-03-16 11:12:49 +01:00
let [error, result] = await profileModel.get();
if (error) return console.error(error);
profile.value = result;
[error, result] = await dashboardModel.config();
if (error) return console.error(error);
config.value = result;
// TODO need to be reactive when name or icon changes
window.document.title = result.cloudronName;
document.getElementById('favicon').href = `${API_ORIGIN}/api/v1/cloudron/avatar?ts=${Date.now()}`;
2025-02-03 19:14:01 +01:00
});
2024-11-01 14:16:09 +01:00
</script>
<template>
2025-03-16 11:12:49 +01:00
<div style="overflow: hidden; height: 100%;">
<Notification />
2025-03-16 11:12:49 +01:00
<div style="display: flex; flex-direction: row; overflow: hidden; height: 100%;">
<Sidebar :profile="profile" :config="config"/>
<div style="flex-grow: 1; display: flex; flex-direction: column; overflow: hidden; height: 100%;">
<Headerbar :subscription="subscription" :profile="profile"/>
<div style="overflow: auto; flex-grow: 1;">
<AppsView v-if="view === VIEWS.APPS" />
2025-03-16 12:11:02 +01:00
<AppConfigureView v-else-if="view === VIEWS.APP" />
2025-03-16 11:12:49 +01:00
<AppstoreView v-else-if="view === VIEWS.APPSTORE" />
<BackupsView v-else-if="view === VIEWS.BACKUPS" />
<BrandingView v-else-if="view === VIEWS.BRANDING" />
<DomainsView v-else-if="view === VIEWS.DOMAINS" />
<EmailView v-else-if="view === VIEWS.EMAIL" />
<EmailDomainView v-else-if="view === VIEWS.EMAIL_DOMAIN" />
<EmailsEventlogView v-else-if="view === VIEWS.EMAILS_EVENTLOG" />
<EventlogView v-else-if="view === VIEWS.EVENTLOG" />
<MailboxesView v-else-if="view === VIEWS.EMAILS_MAILBOXES" />
<MailinglistsView v-else-if="view === VIEWS.EMAILS_MAILINGLISTS" />
<NetworkView v-else-if="view === VIEWS.NETWORK" />
<ProfileView v-else-if="view === VIEWS.PROFILE" />
<ServicesView v-else-if="view === VIEWS.SERVICES" />
<SettingsView v-else-if="view === VIEWS.SETTINGS" />
<SupportView v-else-if="view === VIEWS.SUPPORT" />
<SystemView v-else-if="view === VIEWS.SYSTEM" />
<UserDirectoryView v-else-if="view === VIEWS.USER_DIRECTORY" />
<UsersView v-else-if="view === VIEWS.USERS" />
<VolumesView v-else-if="view === VIEWS.VOLUMES" />
</div>
</div>
</div>
</div>
</template>