Skip to content

Commit

Permalink
feat(frontend): user prefs
Browse files Browse the repository at this point in the history
  • Loading branch information
thewander02 committed Oct 18, 2024
1 parent eb01a93 commit 1415388
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 42 deletions.
79 changes: 42 additions & 37 deletions apps/frontend/src/components/ui/servers/ServerStats.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
<div
v-for="(metric, index) in metrics"
:key="index"
v-tooltip="memoryTooltip(index)"
class="relative min-h-[150px] w-full overflow-hidden rounded-2xl bg-bg-raised p-8"
>
<div class="relative z-10 flex flex-row items-center gap-2">
<h2 class="m-0 text-3xl font-extrabold text-[var(--color-contrast)]">
{{ metric.value }}
</h2>
<h3 class="relative z-10 text-sm font-normal text-secondary">/ {{ metric.max }}</h3>
</div>
<h3 class="relative z-10 text-base font-normal text-secondary">{{ metric.title }}</h3>

Expand All @@ -27,14 +27,16 @@
</div>

<NuxtLink
v-tooltip="storageTooltip"
:to="`/servers/manage/${serverId}/files`"
class="relative min-h-[150px] w-full overflow-hidden rounded-2xl bg-bg-raised p-8 transition-transform duration-100 hover:scale-105 active:scale-100"
>
<div class="flex flex-row items-center gap-2">
<h2 class="m-0 text-3xl font-extrabold text-[var(--color-contrast)]">
{{ formatBytes(data.current.storage_usage_bytes) }}
</h2>
<h3 class="relative z-10 text-sm font-normal text-secondary">
/ {{ formatBytes(data.current.storage_total_bytes) }}
</h3>
</div>
<h3 class="relative z-10 text-base font-normal text-secondary">Storage usage</h3>

Expand All @@ -44,13 +46,17 @@
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, markRaw, computed } from "vue";
import { FolderOpenIcon, CPUIcon, DBIcon } from "@modrinth/assets";
import { useStorage } from "@vueuse/core";
import type { Stats } from "~/types/servers";
const route = useNativeRoute();
const serverId = route.params.id;
const userPrefrences = useStorage(`pyro-server-${serverId}-preferences`, {
ramAsNumber: false,
});
const VueApexCharts = defineAsyncComponent(() => import("vue3-apexcharts"));
const props = defineProps({
Expand Down Expand Up @@ -82,38 +88,52 @@ const metrics = ref([
{
title: "CPU usage",
value: "0%",
max: "100%",
icon: markRaw(CPUIcon),
data: [] as number[],
},
{
title: "Memory usage",
value: "0%",
max: userPrefrences.value.ramAsNumber
? formatBytes(props.data.current.ram_total_bytes)
: "100%",
icon: markRaw(DBIcon),
data: [] as number[],
},
]);
const updateMetrics = () => {
metrics.value = metrics.value.map((metric, index) => {
const currentValue =
index === 0
? props.data.current.cpu_percent
: Math.min(
(props.data.current.ram_usage_bytes / props.data.current.ram_total_bytes) * 100,
100,
);
const pastValue =
index === 0
? props.data.past.cpu_percent
: Math.min((props.data.past.ram_usage_bytes / props.data.past.ram_total_bytes) * 100, 100);
const newValue = lerp(currentValue, pastValue);
return {
...metric,
value: `${newValue.toFixed(2)}%`,
data: [...metric.data.slice(-10), newValue],
};
if (userPrefrences.value.ramAsNumber && index === 1) {
return {
...metric,
value: formatBytes(props.data.current.ram_usage_bytes),
data: [...metric.data.slice(-10), props.data.current.ram_usage_bytes],
};
} else {
const currentValue =
index === 0
? props.data.current.cpu_percent
: Math.min(
(props.data.current.ram_usage_bytes / props.data.current.ram_total_bytes) * 100,
100,
);
const pastValue =
index === 0
? props.data.past.cpu_percent
: Math.min(
(props.data.past.ram_usage_bytes / props.data.past.ram_total_bytes) * 100,
100,
);
const newValue = lerp(currentValue, pastValue);
return {
...metric,
value: `${newValue.toFixed(2)}%`,
data: [...metric.data.slice(-10), newValue],
};
}
});
};
Expand Down Expand Up @@ -171,21 +191,6 @@ const chartOptions = ref({
tooltip: { enabled: false },
});
const memoryTooltip = (index: number) => {
if (index === 1) {
const used = formatBytes(props.data.current.ram_usage_bytes);
const total = formatBytes(props.data.current.ram_total_bytes);
return `${used} / ${total}`;
}
return "";
};
const storageTooltip = computed(() => {
const used = formatBytes(props.data.current.storage_usage_bytes);
const total = formatBytes(props.data.current.storage_total_bytes);
return `${used} / ${total}`;
});
let interval: number;
onMounted(() => {
Expand Down
17 changes: 12 additions & 5 deletions apps/frontend/src/pages/servers/manage/[id].vue
Original file line number Diff line number Diff line change
Expand Up @@ -446,11 +446,18 @@ const stopPolling = () => {

onMounted(() => {
connectWebSocket();
DOMPurify.addHook("afterSanitizeAttributes", (node) => {
if (node.tagName === "A" && node.getAttribute("target")) {
node.setAttribute("rel", "noopener noreferrer");
}
});
DOMPurify.addHook(
"afterSanitizeAttributes",
(node: {
tagName: string;
getAttribute: (arg0: string) => any;
setAttribute: (arg0: string, arg1: string) => void;
}) => {
if (node.tagName === "A" && node.getAttribute("target")) {
node.setAttribute("rel", "noopener noreferrer");
}
},
);
});

onUnmounted(() => {
Expand Down
6 changes: 6 additions & 0 deletions apps/frontend/src/pages/servers/manage/[id]/options.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
TextQuoteIcon,
VersionIcon,
CardIcon,
UserIcon,
} from "@modrinth/assets";
import type { Server } from "~/composables/pyroServers";
Expand All @@ -36,6 +37,11 @@ const navLinks = [
label: "Billing",
href: `/servers/manage/${serverId}/options/billing`,
},
{
icon: UserIcon,
label: "Preferences",
href: `/servers/manage/${serverId}/options/preferences`,
},
{ icon: InfoIcon, label: "Info", href: `/servers/manage/${serverId}/options/info` },
];
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<template>
<div class="h-full w-full gap-2 overflow-y-auto">
<div class="card flex flex-col gap-4">
<h1 class="m-0 text-2xl font-bold">Server Preferences</h1>
<div v-for="(value, key) in userPrefrences" :key="key" class="flex justify-between">
<label for="server-name-field" class="flex flex-col gap-2">
<span class="text-lg font-bold text-contrast">{{ preferences[key].displayName }}</span>
<span> {{ preferences[key].description }} </span>
</label>
<input v-model="newUserprefrences[key]" class="switch stylized-toggle" type="checkbox" />
</div>
</div>
</div>
<div class="absolute bottom-[2.5%] left-[2.5%] z-10 w-[95%]">
<UiServersSaveBanner
:is-visible="!!hasUnsavedChanges"
:server="props.server"
:is-updating="false"
:save="savePreferences"
:reset="resetPreferences"
/>
</div>
</template>

<script setup lang="ts">
import { useStorage } from "@vueuse/core";
import type { Server } from "~/composables/pyroServers";
const route = useNativeRoute();
const serverId = route.params.id as string;
const props = defineProps<{
server: Server<["general", "mods", "backups", "network", "startup", "ws", "fs"]>;
}>();
const hasUnsavedChanges = computed(() => {
return JSON.stringify(newUserprefrences.value) !== JSON.stringify(userPrefrences.value);
});
const savePreferences = () => {
userPrefrences.value = newUserprefrences.value;
newUserprefrences.value = JSON.parse(JSON.stringify(userPrefrences.value));
addNotification({
group: "serverOptions",
type: "success",
title: "Preferences saved",
text: "Your preferences have been saved.",
});
};
const resetPreferences = () => {
newUserprefrences.value = userPrefrences.value;
};
const preferences = {
ramAsNumber: {
displayName: "RAM as bytes",
description: "Display RAM usage in number of bytes instead of percentage",
},
autoRestart: {
displayName: "Auto restart (not implemented)",
description: "Automatically restart the server if it crashes",
},
backupWhileRunning: {
displayName: "Backup while running (not implemented)",
description:
"Allow creation of a backup without stoping the server. This may lead to corrupted backups, use with caution",
},
};
const defaultPreferences = {
ramAsNumber: false,
autoRestart: false,
backupWhileRunning: false,
};
const userPrefrences = useStorage(`pyro-server-${serverId}-preferences`, defaultPreferences);
const newUserprefrences = ref(JSON.parse(JSON.stringify(userPrefrences.value)));
</script>

0 comments on commit 1415388

Please sign in to comment.