From f87833e03b0ddafe494e997df47f9d5ede898727 Mon Sep 17 00:00:00 2001 From: zyxkad Date: Thu, 6 Jun 2024 07:47:10 -0600 Subject: [PATCH] add log preview --- dashboard.go | 19 +++++- dashboard/src/App.vue | 8 ++- dashboard/src/api/v0.ts | 14 ++++- dashboard/src/assets/base.css | 7 +++ dashboard/src/assets/theme.css | 2 + dashboard/src/components/FileContentCard.vue | 25 ++++++++ dashboard/src/components/FileListCard.vue | 12 ++-- dashboard/src/main.ts | 2 +- dashboard/src/views/LogListView.vue | 63 +++++++++++++++----- 9 files changed, 125 insertions(+), 27 deletions(-) create mode 100644 dashboard/src/assets/theme.css create mode 100644 dashboard/src/components/FileContentCard.vue diff --git a/dashboard.go b/dashboard.go index 1fbfe383..b07b0e8f 100644 --- a/dashboard.go +++ b/dashboard.go @@ -21,6 +21,7 @@ package main import ( "bytes" + "compress/gzip" "embed" "encoding/json" "io" @@ -29,6 +30,8 @@ import ( "net/http" "path" "strings" + + "github.com/LiterMC/go-openbmclapi/utils" ) //go:generate npm -C dashboard ci @@ -63,6 +66,7 @@ func (cr *Cluster) serveDashboard(rw http.ResponseWriter, req *http.Request, pth http.Error(rw, "405 Method Not Allowed", http.StatusMethodNotAllowed) return } + acceptEncoding := utils.SplitCSV(req.Header.Get("Accept-Encoding")) switch pth { case "": break @@ -84,11 +88,13 @@ func (cr *Cluster) serveDashboard(rw http.ResponseWriter, req *http.Request, pth fd, err := dsbDist.Open(pth) if err == nil { defer fd.Close() - if stat, err := fd.Stat(); err != nil || stat.IsDir() { + stat, err := fd.Stat() + if err != nil || stat.IsDir() { http.NotFound(rw, req) return } name := path.Base(pth) + size := stat.Size() typ := mime.TypeByExtension(path.Ext(name)) if typ == "" { typ = "application/octet-stream" @@ -99,6 +105,17 @@ func (cr *Cluster) serveDashboard(rw http.ResponseWriter, req *http.Request, pth rw.Header().Set("Cache-Control", "public, max-age=2592000") } } + if acceptEncoding["gzip"] != 0 && size > 1024 { + buf := bytes.NewBuffer(nil) + gw := gzip.NewWriter(buf) + if _, err := io.Copy(gw, fd); err == nil { + if err = gw.Close(); err == nil { + rw.Header().Set("Content-Encoding", "gzip") + http.ServeContent(rw, req, name, startTime, bytes.NewReader(buf.Bytes())) + return + } + } + } http.ServeContent(rw, req, name, startTime, fd.(io.ReadSeeker)) return } diff --git a/dashboard/src/App.vue b/dashboard/src/App.vue index 5d14f47b..f7961309 100644 --- a/dashboard/src/App.vue +++ b/dashboard/src/App.vue @@ -115,7 +115,7 @@ const selectedLang = computed({ height: 4rem; padding-left: 2rem; padding-right: 1rem; - background-color: color-mix(in srgb, var(--primary-50), transparent); + background-color: color-mix(in srgb, var(--primary-50) 30%, transparent); box-shadow: #0008 0 0 1rem -0.5rem; backdrop-filter: blur(0.4rem); } @@ -214,6 +214,12 @@ const selectedLang = computed({ text-decoration: underline; } +@media (prefers-color-scheme: dark) { + #header { + background-color: color-mix(in srgb, var(--primary-50) 10%, transparent); + } +} + @media (max-width: 60rem) { #header { padding: 0; diff --git a/dashboard/src/api/v0.ts b/dashboard/src/api/v0.ts index a98965b4..bcbf3d4a 100644 --- a/dashboard/src/api/v0.ts +++ b/dashboard/src/api/v0.ts @@ -135,7 +135,7 @@ export async function getChallenge(action: string): Promise { } export function signChallenge(challenge: string, secret: string): string { - const signed = sha256.hmac(sha256(secret), challenge); + const signed = sha256.hmac(sha256(secret), challenge) return signed } @@ -412,7 +412,11 @@ export async function getLogFiles(token: string): Promise { return res.data.files } -export async function getLogFile(token: string, name: string, noEncrypt?: boolean): Promise { +export async function getLogFile( + token: string, + name: string, + noEncrypt?: boolean, +): Promise { const LOGFILE_URL = `${window.location.origin}/api/v0/log_file/` const u = new URL(name.startsWith('/') ? name.substr(1) : name, LOGFILE_URL) if (noEncrypt) { @@ -427,7 +431,11 @@ export async function getLogFile(token: string, name: string, noEncrypt?: boolea return res.data } -export async function getLogFileURL(token: string, name: string, noEncrypt?: boolean): Promise { +export async function getLogFileURL( + token: string, + name: string, + noEncrypt?: boolean, +): Promise { const LOGFILE_URL = `${window.location.origin}/api/v0/log_file/` const u = new URL(name.startsWith('/') ? name.substr(1) : name, LOGFILE_URL) if (noEncrypt) { diff --git a/dashboard/src/assets/base.css b/dashboard/src/assets/base.css index 502cbc87..59d8317b 100644 --- a/dashboard/src/assets/base.css +++ b/dashboard/src/assets/base.css @@ -6,6 +6,7 @@ :root { font-size: 16px; + --dialog-width: 60rem; } body { @@ -19,3 +20,9 @@ body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } + +@media (max-width: 60rem) { + :root { + --dialog-width: 100vw; + } +} diff --git a/dashboard/src/assets/theme.css b/dashboard/src/assets/theme.css new file mode 100644 index 00000000..250da4c1 --- /dev/null +++ b/dashboard/src/assets/theme.css @@ -0,0 +1,2 @@ +@import 'primevue/resources/themes/lara-light-green/theme.css' not (prefers-color-scheme: dark); +@import 'primevue/resources/themes/lara-dark-green/theme.css' (prefers-color-scheme: dark); diff --git a/dashboard/src/components/FileContentCard.vue b/dashboard/src/components/FileContentCard.vue new file mode 100644 index 00000000..3da8c1e1 --- /dev/null +++ b/dashboard/src/components/FileContentCard.vue @@ -0,0 +1,25 @@ + + + diff --git a/dashboard/src/components/FileListCard.vue b/dashboard/src/components/FileListCard.vue index 076cb892..f097dc79 100644 --- a/dashboard/src/components/FileListCard.vue +++ b/dashboard/src/components/FileListCard.vue @@ -9,9 +9,8 @@ defineProps<{ }>() defineEmits<{ - (e: 'click', file: FileInfo, index: number): void, + (e: 'click', file: FileInfo, index: number): void }>() -