bug fixes, half-finished admin ui, and a more

This commit is contained in:
Zoe
2024-09-23 01:21:28 -05:00
parent 6e6bc1c45b
commit 66f8437351
35 changed files with 1039 additions and 141 deletions

View File

@@ -0,0 +1,10 @@
<script setup lang="ts">
definePageMeta({
middleware: ["auth", "admin"],
layout: "admin"
});
</script>
<template>
Hey
</template>

156
ui/pages/admin/index.vue Normal file
View File

@@ -0,0 +1,156 @@
<script setup lang="ts">
import { useUser } from '~/composables/useUser'
const { getUser } = useUser()
definePageMeta({
middleware: ["auth", "admin"],
layout: "admin"
});
let systemStatusData = await $fetch("/api/admin/system-status")
const calculateTimeSince = (time) => {
const now = new Date();
const date = new Date(time);
const diffInSeconds = Math.floor((now - date) / 1000);
const days = Math.floor(diffInSeconds / (3600 * 24));
const hours = Math.floor((diffInSeconds % (3600 * 24)) / 3600);
const minutes = Math.floor((diffInSeconds % 3600) / 60);
const seconds = diffInSeconds % 60;
// Constructing the output based on non-zero values
const timeParts = [];
if (days > 0) timeParts.push(`${days} days`);
if (hours > 0 || days > 0) timeParts.push(`${hours} hours`);
if (minutes > 0 || hours > 0 || days > 0) timeParts.push(`${minutes} minutes`);
timeParts.push(`${seconds} seconds`);
return timeParts.join(', ');
}
let uptime = ref('');
let lastGcTime = ref('');
let systemStatusInterval;
let timeInterval;
const updateTime = () => {
uptime.value = calculateTimeSince(systemStatusData.uptime);
lastGcTime.value = calculateTimeSince(systemStatusData.last_gc_time)
};
onMounted(() => {
updateTime();
systemStatusInterval = setInterval(async () => {
console.log("refresh")
systemStatusData = await $fetch("/api/admin/system-status")
}, 5000);
timeInterval = setInterval(updateTime, 1000);
});
onUnmounted(() => {
clearInterval(systemStatusInterval);
clearInterval(timeInterval);
});
</script>
<template>
<div class="w-full overflow-hidden rounded-md border h-fit text-[15px]">
<h4 class="bg-surface px-3.5 py-3 border-b">System Status</h4>
<div class="p-3.5 text-sm">
<dl class="flex-wrap">
<dt>Server Uptime</dt>
<dd>{{ uptime }}</dd>
<dt>Current Goroutine</dt>
<dd>{{ systemStatusData.num_goroutine }}</dd>
<hr />
<dt>Current Memory Usage</dt>
<dd>{{ systemStatusData.cur_mem_usage }}</dd>
<dt>Total Memory Allocated</dt>
<dd>{{ systemStatusData.total_mem_usage }}</dd>
<dt>Memory Obtained</dt>
<dd>{{ systemStatusData.mem_obtained }}</dd>
<dt>Pointer Lookup Times</dt>
<dd>{{ systemStatusData.ptr_lookup_times }}</dd>
<dt>Memory Allocations</dt>
<dd>{{ systemStatusData.mem_allocations }}</dd>
<dt>Memory Frees</dt>
<dd>{{ systemStatusData.mem_frees }}</dd>
<hr />
<dt>Current Heap Usage</dt>
<dd>{{ systemStatusData.cur_heap_usage }}</dd>
<dt>Heap Memory Obtained</dt>
<dd>{{ systemStatusData.heap_mem_obtained }}</dd>
<dt>Heap Memory Idle</dt>
<dd>{{ systemStatusData.heap_mem_idle }}</dd>
<dt>Heap Memory In Use</dt>
<dd>{{ systemStatusData.heap_mem_inuse }}</dd>
<dt>Heap Memory Released</dt>
<dd>{{ systemStatusData.heap_mem_release }}</dd>
<dt>Heap Objects</dt>
<dd>{{ systemStatusData.heap_objects }}</dd>
<hr />
<dt>Bootstrap Stack Usage</dt>
<dd>{{ systemStatusData.bootstrap_stack_usage }}</dd>
<dt>Stack Memory Obtained</dt>
<dd>{{ systemStatusData.stack_mem_obtained }}</dd>
<dt>MSpan Structures Usage</dt>
<dd>{{ systemStatusData.mspan_structures_usage }}</dd>
<dt>MSpan Structures Obtained</dt>
<dd>{{ systemStatusData.mspan_structures_obtained }}</dd>
<dt>MCache Structures Usage</dt>
<dd>{{ systemStatusData.mcache_structures_usage }}</dd>
<dt>MCache Structures Obtained</dt>
<dd>{{ systemStatusData.mcache_structures_obtained }}</dd>
<dt>Profiling Bucket Hash Table Obtained</dt>
<dd>{{ systemStatusData.buck_hash_sys }}</dd>
<dt>GC Metadata Obtained</dt>
<dd>{{ systemStatusData.gc_sys }}</dd>
<dt>Other System Allocation Obtained</dt>
<dd>{{ systemStatusData.other_sys }}</dd>
<hr />
<dt>Next GC Recycle</dt>
<dd>{{ systemStatusData.next_gc }}</dd>
<dt>Since Last GC Time</dt>
<dd>{{ lastGcTime }}</dd>
<dt>Total GC Pause</dt>
<dd>{{ systemStatusData.pause_total_ns }}</dd>
<dt>Last GC Pause</dt>
<dd>{{ systemStatusData.pause_ns }}</dd>
<dt>GC Times</dt>
<dd>{{ systemStatusData.num_gc }}</dd>
</dl>
</div>
</div>
</template>
<style>
dl {
display: flex;
flex-wrap: wrap;
}
dt {
font-weight: 600;
width: 300px;
max-width: calc(100% - 100px - 1em);
padding-top: 5px;
padding-bottom: 5px;
}
dd {
padding-top: 5px;
padding-bottom: 5px;
width: calc(100% - 300px);
min-width: 100px;
}
hr {
width: 100%;
margin-top: 4px;
margin-bottom: 4px;
}
</style>

View File

@@ -0,0 +1,92 @@
<script setup lang="ts">
import { useUser } from "~/composables/useUser"
import type { User } from "~/types/user";
const { getUser } = useUser()
definePageMeta({
middleware: ["auth", "admin"],
layout: "admin"
});
let page = ref(0)
const { data: users } = await useFetch<User[]>('/api/admin/get-users/' + page.value);
const { data: usersCount } = await useFetch<{ total_users: number }>('/api/admin/get-total-users');
const fetchNextPage = async () => {
page.value += 1;
let moreUsers = await $fetch('/api/admin/get-users/' + page.value);
console.log(moreUsers)
users.value = users.value?.concat(moreUsers)
}
</script>
<template>
<div class="w-full h-fit mb-4">
<div class="overflow-hidden rounded-md border text-[15px]">
<h4 class="bg-surface px-3.5 py-3 border-b">User Account Management (Total: {{ usersCount.total_users }})
</h4>
<div class="overflow-x-scroll max-w-full">
<table class="min-w-full">
<thead>
<tr class="text-left">
<th class="py-2 px-4">ID</th>
<th class="py-2 px-4">Username</th>
<th class="py-2 px-4">Email Address</th>
<th class="py-2 px-4">Restricted</th>
<th class="py-2 px-4">Created</th>
<th class="py-2 px-4 text-right">Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="user in users" class="border-t">
<td class="py-2 px-4 max-w-44" :title="user.id">{{ user.id }}</td>
<td class="py-2 px-4">
{{ user.username }}
<span v-if="user.is_admin"
class="ml-2 text-xs bg-accent/10 text-accent py-1 px-2 rounded">Admin</span>
</td>
<td class="py-2 px-4">{{ user.email }} </td>
<td class="py-2 px-4">
<svg v-if="true" xmlns="http://www.w3.org/2000/svg" width="16" height="16"
viewBox="0 0 24 24">
<path fill="none" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2" d="M18 6L6 18M6 6l12 12" />
</svg>
<svg v-else xmlns="http://www.w3.org/2000/svg" width="16" height="16"
viewBox="0 0 24 24">
<path fill="none" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2" d="m5 12l5 5L20 7" />
</svg>
</td>
<td class="py-2 px-4">{{ new Date(user.created_at).toLocaleDateString('en-US', {
year:
'numeric', month: 'short', day: 'numeric'
}) }}</td>
<td class="py-2 px-4 h-full">
<div class="flex items-center justify-end">
<NuxtLink :to="`/admin/users/${user.id}/edit`"></NuxtLink>
<button
class="my-auto hover:bg-muted/10 p-1 transition-bg active:bg-muted/20 rounded-md">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"
viewBox="0 0 24 24">
<g class="stroke-blue-400/90" fill="none" stroke="currentColor"
stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M7 7H6a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2v-1" />
<path d="M20.385 6.585a2.1 2.1 0 0 0-2.97-2.97L9 12v3h3zM16 5l3 3" />
</g>
</svg>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="w-full h-full flex justify-center mt-4" v-if="users?.length != usersCount.total_users">
<button class="bg-accent/10 text-accent px-2 py-1 rounded-md hover:" v-on:click="fetchNextPage()">Load
More</button>
</div>
</div>
</template>