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

Edit spacing

This commit is contained in:
ebosas
2021-12-02 13:47:53 +02:00
parent 348f960570
commit cc6c8213e7
8 changed files with 220 additions and 220 deletions

View File

@@ -1,8 +1,8 @@
require('esbuild').buildSync({
entryPoints: ['src/index.tsx'],
bundle: true,
minify: true,
sourcemap: false,
// target: ['chrome58', 'firefox57', 'safari11', 'edge16'],
outdir: 'build',
})
entryPoints: ['src/index.tsx'],
bundle: true,
minify: true,
sourcemap: false,
// target: ['chrome58', 'firefox57', 'safari11', 'edge16'],
outdir: 'build',
})

View File

@@ -2,21 +2,21 @@ import React from "react";
import { Message } from "./interfaces";
interface alertProps {
alert: Message;
alert: Message;
}
function Alert({alert}: alertProps) {
const alertType = alert.source == "back" ? "success" : "primary";
const alertLabel = alert.source == "back" ? "Received" : "Sent";
const alertType = alert.source == "back" ? "success" : "primary";
const alertLabel = alert.source == "back" ? "Received" : "Sent";
return (
<div
className={"alert alert-"+alertType}
role="alert"
>
<em>{alertLabel}</em>: {alert.text}
</div>
);
return (
<div
className={"alert alert-"+alertType}
role="alert"
>
<em>{alertLabel}</em>: {alert.text}
</div>
);
}
export default Alert;

View File

@@ -1,39 +1,39 @@
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
NavLink
} from "react-router-dom";
BrowserRouter as Router,
Switch,
Route,
NavLink
} from "react-router-dom";
import Home from './home';
import Messages from './messages';
function App() {
return (
<Router>
<nav className="navbar navbar-expand navbar-light bg-transparent">
<div className="container-fluid">
<ul className="navbar-nav">
<li className="nav-item">
<NavLink className="nav-link" to="/" activeClassName="active" exact={true}>Home</NavLink>
</li>
<li className="nav-item">
<NavLink className="nav-link" to="/messages" activeClassName="active">Messages</NavLink>
</li>
</ul>
</div>
</nav>
<Switch>
<Route path="/messages">
<Messages />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</Router>
)
return (
<Router>
<nav className="navbar navbar-expand navbar-light bg-transparent">
<div className="container-fluid">
<ul className="navbar-nav">
<li className="nav-item">
<NavLink className="nav-link" to="/" activeClassName="active" exact={true}>Home</NavLink>
</li>
<li className="nav-item">
<NavLink className="nav-link" to="/messages" activeClassName="active">Messages</NavLink>
</li>
</ul>
</div>
</nav>
<Switch>
<Route path="/messages">
<Messages />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</Router>
)
}
export default App;

View File

@@ -1,46 +1,46 @@
import React from "react";
interface formProps {
sendMessage(s: string): boolean;
sendMessage(s: string): boolean;
}
function Form({sendMessage}: formProps) {
const [message, setMessage] = React.useState<string>('');
const [message, setMessage] = React.useState<string>('');
const submitMessage = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const submitMessage = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (!message) {
return;
}
if (sendMessage(message)) {
setMessage('');
}
if (!message) {
return;
}
return (
<form onSubmit={submitMessage}>
<div className="input-group">
<input
type="text"
className="form-control"
placeholder="Enter message"
aria-label="Enter message"
aria-describedby="button-send"
value={message}
onChange={(e) => setMessage(e.target.value)}
/>
<button
id="button-send"
className="btn btn-success"
type="submit"
>
Send
</button>
</div>
</form>
)
if (sendMessage(message)) {
setMessage('');
}
}
return (
<form onSubmit={submitMessage}>
<div className="input-group">
<input
type="text"
className="form-control"
placeholder="Enter message"
aria-label="Enter message"
aria-describedby="button-send"
value={message}
onChange={(e) => setMessage(e.target.value)}
/>
<button
id="button-send"
className="btn btn-success"
type="submit"
>
Send
</button>
</div>
</form>
)
}
export default Form;

View File

@@ -4,89 +4,89 @@ import Alert from './alert';
import { Message } from "./interfaces";
function Home() {
const [alerts, setAlerts] = React.useState<Message[]>([]);
const ws = React.useRef<WebSocket | null>(null);
const timeout = React.useRef<number | undefined>(undefined);
const [alerts, setAlerts] = React.useState<Message[]>([]);
const ws = React.useRef<WebSocket | null>(null);
const timeout = React.useRef<number | undefined>(undefined);
const sendMessage = (message: string): boolean => {
if (!ws.current || ws.current.readyState != 1) {
return false;
}
let msg: string = JSON.stringify({
text: message,
source: "front",
time: Date.now()
});
ws.current.send(msg);
addAlert(msg);
return true;
const sendMessage = (message: string): boolean => {
if (!ws.current || ws.current.readyState != 1) {
return false;
}
const addAlert = (msg: string) => {
let item: Message = JSON.parse(msg);
setAlerts([item, ...alerts.slice(0, 2)]);
let msg: string = JSON.stringify({
text: message,
source: "front",
time: Date.now()
});
ws.current.send(msg);
addAlert(msg);
return true;
}
const addAlert = (msg: string) => {
let item: Message = JSON.parse(msg);
setAlerts([item, ...alerts.slice(0, 2)]);
}
// Sets up a WebSocket connection
React.useEffect(() => {
ws.current = new WebSocket("ws://" + window.location.host + "/ws");
ws.current.onopen = () => {
console.log('Connected');
// ws.current.send("Hello from the client!");
}
ws.current.onclose = () => console.log('Disconnected');
ws.current.onerror = () => console.log('Websocket error')
return () => {
if (ws.current) { ws.current.close() }
}
}, []);
// Sets up a WebSocket connection
React.useEffect(() => {
ws.current = new WebSocket("ws://" + window.location.host + "/ws");
ws.current.onopen = () => {
console.log('Connected');
// ws.current.send("Hello from the client!");
}
ws.current.onclose = () => console.log('Disconnected');
ws.current.onerror = () => console.log('Websocket error')
return () => {
if (ws.current) { ws.current.close() }
}
}, []);
// Sets a received message handler, only once.
React.useEffect(() => {
if (!ws.current) return;
// Sets a received message handler, only once.
React.useEffect(() => {
if (!ws.current) return;
ws.current.onmessage = (e: MessageEvent<string>) => {
const msg: string = e.data;
addAlert(msg);
}
}, [alerts]);
ws.current.onmessage = (e: MessageEvent<string>) => {
const msg: string = e.data;
addAlert(msg);
}
}, [alerts]);
// Clears out alerts with a delay,
// resets after each message
React.useEffect(() => {
clearTimeout(timeout.current);
timeout.current = setTimeout(() => {setAlerts([])}, 20000);
// Clears out alerts with a delay,
// resets after each message
React.useEffect(() => {
clearTimeout(timeout.current);
timeout.current = setTimeout(() => {setAlerts([])}, 20000);
return () => {
clearTimeout(timeout.current);
}
}, [alerts]);
return () => {
clearTimeout(timeout.current);
}
}, [alerts]);
return (
<div className="container position-relative h-75">
<div className="position-absolute bottom-50 start-0 w-100 translate-middle-y">
<div className="row">
<div className="col col-md-8 col-lg-6 mx-auto">
<Form sendMessage={sendMessage} />
</div>
</div>
</div>
<div id="notifications" className="position-absolute top-0 start-0 w-100">
<div className="row">
<div className="col col-md-8 col-lg-6 mx-auto">
{alerts.map((alert) => (
// TODO: duplicate keys possible
<Alert key={alert.time} alert={alert} />
))}
</div>
</div>
</div>
return (
<div className="container position-relative h-75">
<div className="position-absolute bottom-50 start-0 w-100 translate-middle-y">
<div className="row">
<div className="col col-md-8 col-lg-6 mx-auto">
<Form sendMessage={sendMessage} />
</div>
</div>
)
</div>
<div id="notifications" className="position-absolute top-0 start-0 w-100">
<div className="row">
<div className="col col-md-8 col-lg-6 mx-auto">
{alerts.map((alert) => (
// TODO: duplicate keys possible
<Alert key={alert.time} alert={alert} />
))}
</div>
</div>
</div>
</div>
)
}
export default Home;

View File

@@ -4,6 +4,6 @@ import App from './app';
// ReactDOM.hydrate(
ReactDOM.render(
<App />,
document.getElementById('root')
<App />,
document.getElementById('root')
);

View File

@@ -1,15 +1,15 @@
export interface Message {
text: string;
source: string;
time: number;
text: string;
source: string;
time: number;
}
export interface MessageCache extends Message {
timefmt: string;
timefmt: string;
}
export interface Cache {
count: number;
total: number;
messages: MessageCache[];
count: number;
total: number;
messages: MessageCache[];
}

View File

@@ -2,72 +2,72 @@ import React from "react";
import { Cache, MessageCache } from "./interfaces";
declare global {
interface Window { __DATA: string | null; }
interface Window { __DATA: string | null; }
}
let data: Cache | null = window.__DATA ? JSON.parse(window.__DATA) : null;
window.__DATA = null;
function Messages() {
const [error, setError] = React.useState(data ? false : null);
const [isLoaded, setIsLoaded] = React.useState<boolean>(data ? true : false);
const [messages, setMessages] = React.useState<MessageCache[]>(data ? data.messages : []);
const [count, setCount] = React.useState<number>(data ? data.count : 0);
const [total, setTotal] = React.useState<number>(data ? data.total : 0);
data = null;
const [error, setError] = React.useState(data ? false : null);
const [isLoaded, setIsLoaded] = React.useState<boolean>(data ? true : false);
const [messages, setMessages] = React.useState<MessageCache[]>(data ? data.messages : []);
const [count, setCount] = React.useState<number>(data ? data.count : 0);
const [total, setTotal] = React.useState<number>(data ? data.total : 0);
data = null;
React.useEffect(() => {
if (isLoaded) return;
React.useEffect(() => {
if (isLoaded) return;
fetch("/api/cache")
.then(res => res.json())
.then(
(result) => {
setIsLoaded(true);
setMessages(result.messages);
setCount(result.count);
setTotal(result.total);
},
(error) => {
setIsLoaded(true);
setError(error);
}
)
}, []);
fetch("/api/cache")
.then(res => res.json())
.then(
(result) => {
setIsLoaded(true);
setMessages(result.messages);
setCount(result.count);
setTotal(result.total);
},
(error) => {
setIsLoaded(true);
setError(error);
}
)
}, []);
if (error) {
return <div className="container">Something went wrong</div>;
} else if (!isLoaded) {
return <div className="container">Loading...</div>;
} else {
return (
<div className="container">
<h3 className="my-4 ps-2">Recent messages ({count}/{total})</h3>
<table className="table">
<thead>
<tr>
<th scope="col">Time</th>
<th scope="col">Message</th>
<th scope="col">Source</th>
</tr>
</thead>
<tbody>
{messages.map(msg => (
<tr key={msg.time}>
<td>{msg.timefmt} ago</td>
<td>{msg.text}</td>
<td>{msg.source}</td>
</tr>
))}
{!messages.length && (
<tr>
<td colSpan={3}>No messages</td>
</tr>
)}
</tbody>
</table>
</div>
);
}
if (error) {
return <div className="container">Something went wrong</div>;
} else if (!isLoaded) {
return <div className="container">Loading...</div>;
} else {
return (
<div className="container">
<h3 className="my-4 ps-2">Recent messages ({count}/{total})</h3>
<table className="table">
<thead>
<tr>
<th scope="col">Time</th>
<th scope="col">Message</th>
<th scope="col">Source</th>
</tr>
</thead>
<tbody>
{messages.map(msg => (
<tr key={msg.time}>
<td>{msg.timefmt} ago</td>
<td>{msg.text}</td>
<td>{msg.source}</td>
</tr>
))}
{!messages.length && (
<tr>
<td colSpan={3}>No messages</td>
</tr>
)}
</tbody>
</table>
</div>
);
}
}
export default Messages;