+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dashboard/src/components/ApiTokens.vue b/dashboard/src/components/ApiTokens.vue
index 46ca8b597..03cc408f1 100644
--- a/dashboard/src/components/ApiTokens.vue
+++ b/dashboard/src/components/ApiTokens.vue
@@ -4,7 +4,7 @@ import { useI18n } from 'vue-i18n';
const i18n = useI18n();
const t = i18n.t;
-import moment from 'moment';
+import moment from 'moment-timezone';
import { ref, onMounted, computed, useTemplateRef } from 'vue';
import { Button, Dialog, InputDialog, FormGroup, Radiobutton, TableView, TextInput } from 'pankow';
import { copyToClipboard, prettyLongDate } from 'pankow/utils';
diff --git a/dashboard/src/components/AppPasswords.vue b/dashboard/src/components/AppPasswords.vue
index 8fb58f707..a04b64dc0 100644
--- a/dashboard/src/components/AppPasswords.vue
+++ b/dashboard/src/components/AppPasswords.vue
@@ -4,7 +4,7 @@ import { useI18n } from 'vue-i18n';
const i18n = useI18n();
const t = i18n.t;
-import moment from 'moment';
+import moment from 'moment-timezone';
import { ref, onMounted, useTemplateRef, computed } from 'vue';
import { Button, Dialog, Dropdown, FormGroup, TextInput, TableView, InputDialog } from 'pankow';
import { prettyLongDate, copyToClipboard } from 'pankow/utils';
diff --git a/dashboard/src/components/CpuUsage.vue b/dashboard/src/components/CpuUsage.vue
index 29b083dcf..845ac1037 100644
--- a/dashboard/src/components/CpuUsage.vue
+++ b/dashboard/src/components/CpuUsage.vue
@@ -2,7 +2,7 @@
import { ref, onMounted, useTemplateRef } from 'vue';
import Chart from 'chart.js/auto';
-import moment from 'moment';
+import moment from 'moment-timezone';
import Section from './Section.vue';
import SystemModel from '../models/SystemModel.js';
diff --git a/dashboard/src/components/Headerbar.vue b/dashboard/src/components/Headerbar.vue
new file mode 100644
index 000000000..22bb42e9e
--- /dev/null
+++ b/dashboard/src/components/Headerbar.vue
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
diff --git a/dashboard/src/components/MemoryUsage.vue b/dashboard/src/components/MemoryUsage.vue
index aaa733320..1a5ed0d6d 100644
--- a/dashboard/src/components/MemoryUsage.vue
+++ b/dashboard/src/components/MemoryUsage.vue
@@ -2,7 +2,7 @@
import { ref, onMounted, useTemplateRef } from 'vue';
import Chart from 'chart.js/auto';
-import moment from 'moment';
+import moment from 'moment-timezone';
import Section from './Section.vue';
import SystemModel from '../models/SystemModel.js';
diff --git a/dashboard/src/components/Sidebar.vue b/dashboard/src/components/Sidebar.vue
new file mode 100644
index 000000000..f7426fd4c
--- /dev/null
+++ b/dashboard/src/components/Sidebar.vue
@@ -0,0 +1,158 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dashboard/src/models/AppsModel.js b/dashboard/src/models/AppsModel.js
index f9ca372e7..fce2a6713 100644
--- a/dashboard/src/models/AppsModel.js
+++ b/dashboard/src/models/AppsModel.js
@@ -2,7 +2,7 @@
import { API_ORIGIN, APP_TYPES, PROXY_APP_ID, HSTATES, ISTATES, RSTATES } from '../constants.js';
import { fetcher } from 'pankow';
import { sleep } from 'pankow/utils';
-import moment from 'moment';
+import moment from 'moment-timezone';
function installationStateLabel(app) {
if (!app) return '';
diff --git a/dashboard/src/models/LogsModel.js b/dashboard/src/models/LogsModel.js
index ff4dc0020..189181b36 100644
--- a/dashboard/src/models/LogsModel.js
+++ b/dashboard/src/models/LogsModel.js
@@ -1,5 +1,5 @@
-import moment from 'moment';
+import moment from 'moment-timezone';
import { ansiToHtml } from 'anser';
import { API_ORIGIN } from '../constants.js';
diff --git a/dashboard/src/models/ProfileModel.js b/dashboard/src/models/ProfileModel.js
index 4391d58a5..76e7d16b7 100644
--- a/dashboard/src/models/ProfileModel.js
+++ b/dashboard/src/models/ProfileModel.js
@@ -30,6 +30,8 @@ function create() {
if (error || result.status !== 200) return [error || result];
+ result.body.isAtLeastUserManager = [ ROLES.OWNER, ROLES.ADMIN, ROLES.MAIL_MANAGER, ROLES.USER_MANAGER ].indexOf(result.body.role) !== -1;
+ result.body.isAtLeastMailManager = [ ROLES.OWNER, ROLES.ADMIN, ROLES.MAIL_MANAGER ].indexOf(result.body.role) !== -1;
result.body.isAtLeastAdmin = [ ROLES.OWNER, ROLES.ADMIN ].indexOf(result.body.role) !== -1;
result.body.isAtLeastOwner = [ ROLES.OWNER ].indexOf(result.body.role) !== -1;
diff --git a/dashboard/src/style.css b/dashboard/src/style.css
index 718b1c38b..3079c13a5 100644
--- a/dashboard/src/style.css
+++ b/dashboard/src/style.css
@@ -1,9 +1,26 @@
+:root {
+ --pankow-color-primary: #0073cf;
+ --font-family: "Noto Sans",Helvetica,Arial,sans-serif;
+ --font-family--header: "Noto Sans Light",Helvetica,Arial,sans-serif;
+ --card-background: #f7f7f8;
+ --navbar-background: #f3f4f6;
+/* --pankow-body-background-color: var(--body-background);*/
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --card-background: #15181f;
+ --navbar-background: #11161f;
+/* --pankow-body-background-color: var(--body-background);*/
+ --pankow-dialog-background-color: var(--navbar-background);
+ --pankow-color-background: var(--navbar-background);
+ --pankow-text-color: white;
+ }
+}
html, body {
- --pankow-color-primary: #0073cf;
-
font-size: 14px; /* this also defines the overall widget size as all sizes are in rem */
- font-family: "Noto Sans";
+ font-family: var(--font-family);
font-weight: 300;
height: 100%;
width: 100%;
@@ -19,12 +36,6 @@ html, body {
}
}
-@media (max-width: 576px) {
- .hide-mobile {
- display: none;
- }
-}
-
.shadow {
box-shadow: 0 2px 5px rgba(0,0,0,.1);
}
@@ -33,8 +44,12 @@ html, body {
height: 100%;
}
-h2 {
+h1, h2, h3, h4, h5 {
+ font-family: var(--font-family--header);
font-weight: 400;
+}
+
+h2 {
font-size: 24px;
}
@@ -43,6 +58,17 @@ a {
color: var(--pankow-color-primary);
}
+fieldset {
+ border: none;
+ margin: 0;
+ padding: 0;
+}
+
+hr {
+ border: 0;
+ border-top: 1px solid rgb(238.425,238.425,238.425);
+}
+
footer {
display: block;
width: 100%;
diff --git a/dashboard/src/views/AppConfigureView.vue b/dashboard/src/views/AppConfigureView.vue
index 135a08dba..4bd363e44 100644
--- a/dashboard/src/views/AppConfigureView.vue
+++ b/dashboard/src/views/AppConfigureView.vue
@@ -293,7 +293,6 @@ onBeforeUnmount(() => {
.titlebar {
display: flex;
justify-content: space-between;
- background-color: var(--pankow-body-background-color);
}
.apptask-progress {
diff --git a/dashboard/src/views/AppsView.vue b/dashboard/src/views/AppsView.vue
index 6d4b0d4d2..5a1c72c65 100644
--- a/dashboard/src/views/AppsView.vue
+++ b/dashboard/src/views/AppsView.vue
@@ -412,12 +412,6 @@ onUnmounted(() => {
color: var(--pankow-text-color);
}
-.grid-item:focus .grid-item-label,
-.grid-item:hover .grid-item-label {
- text-decoration: none;
- color: var(--accent-color);;
-}
-
.config {
position: absolute;
color: var(--pankow-text-color);
@@ -436,8 +430,6 @@ onUnmounted(() => {
.config:focus,
.config:hover {
- text-decoration: none;
- color: var(--accent-color);;
opacity: 1;
}
diff --git a/dashboard/src/views/SettingsView.vue b/dashboard/src/views/SettingsView.vue
index 3f0b7bb23..bf77411d8 100644
--- a/dashboard/src/views/SettingsView.vue
+++ b/dashboard/src/views/SettingsView.vue
@@ -6,6 +6,7 @@ const t = i18n.t;
import { ref, onMounted, watch } from 'vue';
import { Dropdown } from 'pankow';
+import moment from 'moment-timezone';
import Section from '../components/Section.vue';
import CloudronAccount from '../components/CloudronAccount.vue';
import SystemUpdate from '../components/SystemUpdate.vue';
@@ -15,7 +16,7 @@ import CloudronModel from '../models/CloudronModel.js';
const cloudronModel = CloudronModel.create();
// Timezone
-const allTimezones = window.timezones;
+const allTimezones = moment.tz.names().map(t => { return { id: t }; });
const timeZone = ref('');
const currentTimeZone = ref('');
@@ -92,8 +93,8 @@ onMounted(async () => {
diff --git a/dashboard/src/views/SystemView.vue b/dashboard/src/views/SystemView.vue
index f655da782..2399ce4c5 100644
--- a/dashboard/src/views/SystemView.vue
+++ b/dashboard/src/views/SystemView.vue
@@ -2,7 +2,7 @@
import { ref, onMounted } from 'vue';
import { Button } from 'pankow';
-import moment from 'moment';
+import moment from 'moment-timezone';
import { prettyDecimalSize } from 'pankow/utils';
import Section from '../components/Section.vue';
import DiskUsage from '../components/DiskUsage.vue';
@@ -22,6 +22,7 @@ const uptime = ref('');
const activeSince = ref('');
function onReboot() {
+ // TODO ask the user!
systemModel.reboot();
}