You've already forked microservices
mirror of
https://github.com/ebosas/microservices.git
synced 2025-08-24 20:08:55 +02:00
Edit spacing
This commit is contained in:
@@ -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',
|
||||
})
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
@@ -4,6 +4,6 @@ import App from './app';
|
||||
|
||||
// ReactDOM.hydrate(
|
||||
ReactDOM.render(
|
||||
<App />,
|
||||
document.getElementById('root')
|
||||
<App />,
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
@@ -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[];
|
||||
}
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user