1
0
mirror of https://github.com/ebosas/microservices.git synced 2025-08-24 20:08:55 +02:00

Finish messages page

This commit is contained in:
ebosas
2021-10-08 13:25:43 +03:00
parent 866aff9f75
commit 89536de358
8 changed files with 98 additions and 55 deletions

View File

@@ -9,7 +9,7 @@ import (
"github.com/go-redis/redis/v8" "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) { func handleAPICache(cr *redis.Client) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
data, err := cache.GetCacheJSON(cr) data, err := cache.GetCacheJSON(cr)

View File

@@ -3,6 +3,7 @@ package main
import ( import (
"context" "context"
"embed" "embed"
"encoding/json"
"fmt" "fmt"
"html/template" "html/template"
"log" "log"
@@ -72,12 +73,31 @@ func handleHome(w http.ResponseWriter, r *http.Request) {
// handleMessages handles the messages page. // handleMessages handles the messages page.
func handleMessages(cr *redis.Client) func(w http.ResponseWriter, r *http.Request) { func handleMessages(cr *redis.Client) func(w http.ResponseWriter, r *http.Request) {
return 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 { if err != nil {
log.Printf("get cache: %s", err) log.Printf("get cache: %s", err)
return 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} funcMap := template.FuncMap{"fdate": formatTime}
t := template.Must(template.New("").Funcs(funcMap).ParseFS(filesTempl, "template/template.html", "template/navbar.html", "template/messages.html")) t := template.Must(template.New("").Funcs(funcMap).ParseFS(filesTempl, "template/template.html", "template/navbar.html", "template/messages.html"))
t.ExecuteTemplate(w, "layout", data) t.ExecuteTemplate(w, "layout", data)

View File

@@ -1,6 +1,6 @@
{{ define "content" }} {{ define "content" }}
<div class="container"> <div class="container">
<h3 class="my-4 ps-2">Recent messages ({{ .Count }}/{{ .Total }})</h3> <h3 class="my-4 ps-2">Recent messages ({{ .Data.Count }}/{{ .Data.Total }})</h3>
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
@@ -10,7 +10,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{{ range .Messages }} {{ range .Data.Messages }}
<tr> <tr>
<td>{{ .Time | fdate }}</td> <td>{{ .Time | fdate }}</td>
<td>{{ .Text }}</td> <td>{{ .Text }}</td>

View File

@@ -5,13 +5,15 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="static/build/style.css"> <link rel="stylesheet" href="static/build/style.css">
{{ if and . .Json }}<script>window.__DATA="{{ .Json }}"</script>{{ end }}
</head> </head>
<body> <body>
<div id="root" class="vh-100"> <div id="root" class="vh-100">
{{ template "navbar" . }} {{ template "navbar" . }}
{{ template "content" . }} {{ template "content" . }}
</div> </div>
<script src="http://127.0.0.1:8000/index.js"></script>
<!-- <script src="static/build/index.js"></script> --> <script src="http://127.0.0.1:8000/index.js"></script>
<!-- <script src="static/build/index.js"></script> -->
</body> </body>
</html>{{ end }} </html>{{ end }}

View File

@@ -12,6 +12,11 @@
"regenerator-runtime": "^0.13.4" "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": { "esbuild": {
"version": "0.12.5", "version": "0.12.5",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.5.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.5.tgz",

View File

@@ -11,6 +11,7 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"date-fns": "^2.25.0",
"esbuild": "^0.12.5", "esbuild": "^0.12.5",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",

View File

@@ -2,6 +2,7 @@ import * as React from 'react'
import * as ReactDOM from 'react-dom' import * as ReactDOM from 'react-dom'
import App from './app'; import App from './app';
// ReactDOM.hydrate(
ReactDOM.render( ReactDOM.render(
<App />, <App />,
document.getElementById('root') document.getElementById('root')

View File

@@ -1,57 +1,71 @@
import React from "react"; 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() { function Messages() {
const [error, setError] = React.useState(null); const [error, setError] = React.useState(data ? false : null);
const [isLoaded, setIsLoaded] = React.useState(false); const [isLoaded, setIsLoaded] = React.useState(data ? true : false);
const [items, setItems] = React.useState([]); const [messages, setMessages] = React.useState(data ? data.messages : []);
const [counts, setCounts] = React.useState(data ? {count: data.count, total: data.total} : {});
data = null;
React.useEffect(() => { React.useEffect(() => {
fetch("/api/cache") if (isLoaded) return;
.then(res => res.json())
.then(
(result) => {
setIsLoaded(true);
setItems(result);
console.log(result);
},
(error) => {
setIsLoaded(true);
setError(error);
}
)
}, [])
return ( fetch("/api/cache")
<div className="container"> .then(res => res.json())
<h3 className="my-4 ps-2">Recent messages (3/67)</h3> .then(
<table className="table"> (result) => {
<thead> setIsLoaded(true);
<tr> setMessages(result.messages);
<th scope="col">Time</th> setCounts({count: result.count, total: result.total});
<th scope="col">Message</th> },
<th scope="col">Source</th> (error) => {
</tr> setIsLoaded(true);
</thead> setError(error);
<tbody> }
<tr> )
<td>Mar 3, 2021</td> }, []);
<td>Hello there from the frontend</td>
<td>Front end</td> if (error){
</tr> return <div className="container">Something went wrong</div>;
<tr> } else if (!isLoaded){
<td>Mar 3, 2021</td> return <div className="container">Loading...</div>;
<td>Hello there from the back end</td> } else {
<td>Back end</td> return (
</tr> <div className="container">
<tr> <h3 className="my-4 ps-2">Recent messages ({counts.count}/{counts.total})</h3>
<td>Mar 3, 2021</td> <table className="table">
<td>This is good!</td> <thead>
<td>Front end</td> <tr>
</tr> <th scope="col">Time</th>
</tbody> <th scope="col">Message</th>
</table> <th scope="col">Source</th>
</div> </tr>
) </thead>
<tbody>
{messages.map(msg => (
<tr key={msg.time}>
<td>{formatTime(msg.time)}</td>
<td>{msg.text}</td>
<td>{msg.source}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
}
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; export default Messages;