diff --git a/cmd/server/api.go b/cmd/server/api.go index ed61894..7b4f730 100644 --- a/cmd/server/api.go +++ b/cmd/server/api.go @@ -9,7 +9,7 @@ import ( "github.com/go-redis/redis/v8" ) -// handleAPICache handles an API call for cached messages +// handleAPICache handles API calls for cached messages func handleAPICache(cr *redis.Client) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { data, err := cache.GetCacheJSON(cr) diff --git a/cmd/server/server.go b/cmd/server/server.go index 315e7b5..7e36c62 100644 --- a/cmd/server/server.go +++ b/cmd/server/server.go @@ -3,6 +3,7 @@ package main import ( "context" "embed" + "encoding/json" "fmt" "html/template" "log" @@ -72,12 +73,31 @@ func handleHome(w http.ResponseWriter, r *http.Request) { // handleMessages handles the messages page. func handleMessages(cr *redis.Client) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { - data, err := cache.GetCache(cr) + cacheJSON, err := cache.GetCacheJSON(cr) if err != nil { log.Printf("get cache: %s", err) return } + var cached cache.Cache + err = json.Unmarshal([]byte(cacheJSON), &cached) + if err != nil { + log.Printf("unmarshal cache: %s", err) + return + } + + data := map[string]interface{}{ + "Data": cached, + "Json": cacheJSON, + } + + // data := struct { + // Data cache.Cache + // Json string + // }{cached, "Hello"} + + // fmt.Println(data.Json) + funcMap := template.FuncMap{"fdate": formatTime} t := template.Must(template.New("").Funcs(funcMap).ParseFS(filesTempl, "template/template.html", "template/navbar.html", "template/messages.html")) t.ExecuteTemplate(w, "layout", data) diff --git a/cmd/server/template/messages.html b/cmd/server/template/messages.html index 61a2668..1d107b9 100644 --- a/cmd/server/template/messages.html +++ b/cmd/server/template/messages.html @@ -1,6 +1,6 @@ {{ define "content" }}
-

Recent messages ({{ .Count }}/{{ .Total }})

+

Recent messages ({{ .Data.Count }}/{{ .Data.Total }})

@@ -10,7 +10,7 @@ - {{ range .Messages }} + {{ range .Data.Messages }} diff --git a/cmd/server/template/template.html b/cmd/server/template/template.html index 70bc464..91ff29f 100644 --- a/cmd/server/template/template.html +++ b/cmd/server/template/template.html @@ -5,13 +5,15 @@ + {{ if and . .Json }}{{ end }}
{{ template "navbar" . }} {{ template "content" . }} -
- - + + + + {{ end }} \ No newline at end of file diff --git a/web/react/package-lock.json b/web/react/package-lock.json index 00ff1a6..211e72c 100644 --- a/web/react/package-lock.json +++ b/web/react/package-lock.json @@ -12,6 +12,11 @@ "regenerator-runtime": "^0.13.4" } }, + "date-fns": { + "version": "2.25.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.25.0.tgz", + "integrity": "sha512-ovYRFnTrbGPD4nqaEqescPEv1mNwvt+UTqI3Ay9SzNtey9NZnYu6E2qCcBBgJ6/2VF1zGGygpyTDITqpQQ5e+w==" + }, "esbuild": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.5.tgz", diff --git a/web/react/package.json b/web/react/package.json index 647cadd..06c851f 100644 --- a/web/react/package.json +++ b/web/react/package.json @@ -11,6 +11,7 @@ "author": "", "license": "ISC", "dependencies": { + "date-fns": "^2.25.0", "esbuild": "^0.12.5", "react": "^17.0.2", "react-dom": "^17.0.2", diff --git a/web/react/src/index.jsx b/web/react/src/index.jsx index 61eca0f..70d31d3 100644 --- a/web/react/src/index.jsx +++ b/web/react/src/index.jsx @@ -2,6 +2,7 @@ import * as React from 'react' import * as ReactDOM from 'react-dom' import App from './app'; +// ReactDOM.hydrate( ReactDOM.render( , document.getElementById('root') diff --git a/web/react/src/messages.jsx b/web/react/src/messages.jsx index 96484b1..6567b9c 100644 --- a/web/react/src/messages.jsx +++ b/web/react/src/messages.jsx @@ -1,57 +1,71 @@ import React from "react"; +import { format } from 'date-fns' + +let data = window.__DATA || null; +data = data ? JSON.parse(data) : null; +window.__DATA = null; function Messages() { - const [error, setError] = React.useState(null); - const [isLoaded, setIsLoaded] = React.useState(false); - const [items, setItems] = React.useState([]); + const [error, setError] = React.useState(data ? false : null); + const [isLoaded, setIsLoaded] = React.useState(data ? true : false); + const [messages, setMessages] = React.useState(data ? data.messages : []); + const [counts, setCounts] = React.useState(data ? {count: data.count, total: data.total} : {}); + + data = null; React.useEffect(() => { - fetch("/api/cache") - .then(res => res.json()) - .then( - (result) => { - setIsLoaded(true); - setItems(result); - console.log(result); - }, - (error) => { - setIsLoaded(true); - setError(error); - } - ) - }, []) + if (isLoaded) return; - return ( -
-

Recent messages (3/67)

-
{{ .Time | fdate }} {{ .Text }}
- - - - - - - - - - - - - - - - - - - - - - - - -
TimeMessageSource
Mar 3, 2021Hello there from the frontendFront end
Mar 3, 2021Hello there from the back endBack end
Mar 3, 2021This is good!Front end
-
- ) + fetch("/api/cache") + .then(res => res.json()) + .then( + (result) => { + setIsLoaded(true); + setMessages(result.messages); + setCounts({count: result.count, total: result.total}); + }, + (error) => { + setIsLoaded(true); + setError(error); + } + ) + }, []); + + if (error){ + return
Something went wrong
; + } else if (!isLoaded){ + return
Loading...
; + } else { + return ( +
+

Recent messages ({counts.count}/{counts.total})

+ + + + + + + + + + {messages.map(msg => ( + + + + + + ))} + +
TimeMessageSource
{formatTime(msg.time)}{msg.text}{msg.source}
+
+ ); + } +} + +function formatTime(timestamp) { + const t = new Date(timestamp); + const fmt = (t.getDate() == new Date().getDate()) ? "h:mmaaa" : "h:mmaaa, MMM d"; + return format(t, fmt); } export default Messages;