Restyle and support logs.
This commit is contained in:
parent
02e2053bdf
commit
a40bb93abb
@ -41,5 +41,9 @@
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||
"prettier": "^3.2.5"
|
||||
}
|
||||
}
|
||||
|
83
src/App.tsx
83
src/App.tsx
@ -1,53 +1,64 @@
|
||||
import {
|
||||
useQuery,
|
||||
useMutation,
|
||||
useQueryClient,
|
||||
QueryClient,
|
||||
QueryClientProvider,
|
||||
} from '@tanstack/react-query'
|
||||
import {fetchAllStatuses} from './utils/data-utils';
|
||||
import {QueryClient, QueryClientProvider, useQuery, useQueryClient,} from '@tanstack/react-query'
|
||||
import React, {useState} from "react";
|
||||
import {fetchAllStatuses, fetchLogs} from './utils/data-utils';
|
||||
import Modal from './Modal'
|
||||
|
||||
// Create a client
|
||||
const queryClient = new QueryClient()
|
||||
|
||||
function App() {
|
||||
return (
|
||||
// Provide the client to your App
|
||||
return (// Provide the client to your App
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<center>
|
||||
<StatusTable />
|
||||
</center>
|
||||
</QueryClientProvider>
|
||||
)
|
||||
<StatusTable/>
|
||||
</QueryClientProvider>)
|
||||
}
|
||||
|
||||
function StatusTable() {
|
||||
// Access the client
|
||||
const queryClient = useQueryClient()
|
||||
const [logId, setLogId] = useState("");
|
||||
|
||||
// Queries
|
||||
const query = useQuery({ queryKey: ['allStatus'], queryFn: fetchAllStatuses })
|
||||
const query = useQuery({queryKey: ['allStatus'], queryFn: fetchAllStatuses})
|
||||
const queryLog = useQuery({queryKey: ['log', logId], queryFn: () => fetchLogs(logId)});
|
||||
|
||||
return (
|
||||
<table id="all-status">
|
||||
<tr>
|
||||
<th>URL</th>
|
||||
<th>Application</th>
|
||||
<th>Status</th>
|
||||
<th>Last Update</th>
|
||||
<th>Request ID</th>
|
||||
</tr>
|
||||
{query.data?.map((status: any) =>
|
||||
<tr className={"tr-status " + status.lastState.toLowerCase()}>
|
||||
<td className="td-url">{status.deployment && <a href={status.url}>{status.url}</a>}</td>
|
||||
<td className="td-app-crn">{status.app}</td>
|
||||
<td className="td-status">{status.lastState}</td>
|
||||
<td className="td-last-update">{status.lastUpdate}</td>
|
||||
<td className="td-id">{status.id}</td>
|
||||
</tr>
|
||||
)}
|
||||
</table>
|
||||
)
|
||||
return (<div>
|
||||
{logId && (<Modal open={true}>
|
||||
<button className="close" onClick={() => setLogId("")}>CLOSE</button>
|
||||
<div className="log-data">
|
||||
<pre>{queryLog.data}</pre>
|
||||
</div>
|
||||
</Modal>)}
|
||||
<div id="all-status">
|
||||
{query.data?.map((status: any) => <div className={status.lastState.toLowerCase() + " status-row"}>
|
||||
<div className="status-line">
|
||||
<span className="status-key">Request ID:</span>
|
||||
<span className="status-value">{status.id}</span>
|
||||
</div>
|
||||
<div className="status-line">
|
||||
<span className="status-key">Application:</span>
|
||||
<span className="status-value">{status.app}</span>
|
||||
</div>
|
||||
{status.deployment && <div className="status-line">
|
||||
<span className="status-key">URL:</span>
|
||||
<span className="status-value"><a href={status.url}>{status.url}</a></span>
|
||||
</div>}
|
||||
<div className="status-line">
|
||||
<span className="status-key">Last Update:</span>
|
||||
<span className="status-value">{status.lastUpdate}</span>
|
||||
</div>
|
||||
<div className="status-line">
|
||||
<span className="status-key">Last State:</span>
|
||||
<span className="status-value">{(status.logAvailable &&
|
||||
<button className={"button-" + status.lastState.toLowerCase()}
|
||||
onClick={() => {
|
||||
queryClient.invalidateQueries({queryKey: ["log"]}).then(() => setLogId(status.id))
|
||||
}}>{status.lastState}
|
||||
</button>) || status.lastState}</span>
|
||||
</div>
|
||||
</div>)}
|
||||
</div>
|
||||
</div>)
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
37
src/Modal.tsx
Normal file
37
src/Modal.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
import {Component} from "react";
|
||||
|
||||
const MODAL_STYLES = {
|
||||
position: "absolute" as "absolute",
|
||||
backgroundColor: "#FFF",
|
||||
marginTop: "2em",
|
||||
padding: "2em",
|
||||
zIndex: "1000",
|
||||
width: "75%",
|
||||
height: "85%",
|
||||
borderRadius: ".5em",
|
||||
};
|
||||
const OVERLAY_STYLE = {
|
||||
position: "fixed" as "fixed",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
top: "0",
|
||||
left: "0",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
backgroundColor: "rgba(0,0,0, .8)",
|
||||
zIndex: "1000",
|
||||
};
|
||||
|
||||
class Modal extends Component<{ open: any, children: any }> {
|
||||
render() {
|
||||
let {open, children} = this.props;
|
||||
if (!open) return null;
|
||||
return (<>
|
||||
<div style={OVERLAY_STYLE}>
|
||||
<div style={MODAL_STYLES}>{children}</div>
|
||||
</div>
|
||||
</>);
|
||||
}
|
||||
}
|
||||
|
||||
export default Modal;
|
@ -5,6 +5,7 @@ body {
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
code {
|
||||
@ -12,41 +13,60 @@ code {
|
||||
monospace;
|
||||
}
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#all-status {
|
||||
width: 85%;
|
||||
margin: auto;
|
||||
min-width: 50%;
|
||||
max-width: 75%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#all-status td {
|
||||
padding: 0.3em;
|
||||
.log-data {
|
||||
overflow: auto;
|
||||
color: grey;
|
||||
background-color: black;
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
|
||||
width: 98%;
|
||||
height: 95%;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse:separate;
|
||||
border:solid lightblue 1px;
|
||||
border-radius:6px;
|
||||
.status-row {
|
||||
width: auto;
|
||||
background-color: white;
|
||||
padding: 1em;
|
||||
margin: 1em;
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
td, th {
|
||||
border-left:solid lightblue 1px;
|
||||
border-top:solid lightblue 1px;
|
||||
.status-key {
|
||||
font-weight: bold;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
th {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
td:first-child, th:first-child {
|
||||
border-left: none;
|
||||
.status-value {
|
||||
}
|
||||
|
||||
.deployed {
|
||||
background-color: #ddffdd;
|
||||
}
|
||||
|
||||
.button-deployed {
|
||||
background-color: lawngreen;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.error {
|
||||
background-color: #ffdddd;
|
||||
}
|
||||
|
||||
.button-error {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.cancelled {
|
||||
background-color: #efefef;
|
||||
text-color: #dddddd;
|
||||
@ -64,18 +84,3 @@ td:first-child, th:first-child {
|
||||
.deploying {
|
||||
background-color: #fff1dd;
|
||||
}
|
||||
|
||||
.tr-status {
|
||||
font-size: small;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
}
|
||||
|
||||
.td-id {
|
||||
font-size: xx-small;
|
||||
}
|
||||
|
||||
.td-last-update{
|
||||
}
|
||||
|
||||
.td-status{
|
||||
}
|
@ -6,3 +6,16 @@ export const fetchAllStatuses = async () => {
|
||||
}
|
||||
return await res.json();
|
||||
}
|
||||
|
||||
|
||||
export const fetchLogs = async (id: string) => {
|
||||
if (!id) {
|
||||
return "";
|
||||
}
|
||||
let url = `http://localhost:9555/log/${id}`
|
||||
const res = await fetch(url);
|
||||
if (!res.ok) {
|
||||
throw new Error('Network response was not ok')
|
||||
}
|
||||
return await res.text();
|
||||
}
|
32
yarn.lock
32
yarn.lock
@ -87,7 +87,7 @@
|
||||
"@jridgewell/trace-mapping" "^0.3.17"
|
||||
jsesc "^2.5.1"
|
||||
|
||||
"@babel/helper-annotate-as-pure@^7.22.5":
|
||||
"@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.22.5":
|
||||
version "7.22.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882"
|
||||
integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==
|
||||
@ -127,6 +127,21 @@
|
||||
"@babel/helper-split-export-declaration" "^7.22.6"
|
||||
semver "^6.3.1"
|
||||
|
||||
"@babel/helper-create-class-features-plugin@^7.21.0":
|
||||
version "7.23.10"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.10.tgz#25d55fafbaea31fd0e723820bb6cc3df72edf7ea"
|
||||
integrity sha512-2XpP2XhkXzgxecPNEEK8Vz8Asj9aRxt08oKOqtiZoqV2UGZ5T+EkyP9sXQ9nwMxBIG34a7jmasVqoMop7VdPUw==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.22.5"
|
||||
"@babel/helper-environment-visitor" "^7.22.20"
|
||||
"@babel/helper-function-name" "^7.23.0"
|
||||
"@babel/helper-member-expression-to-functions" "^7.23.0"
|
||||
"@babel/helper-optimise-call-expression" "^7.22.5"
|
||||
"@babel/helper-replace-supers" "^7.22.20"
|
||||
"@babel/helper-skip-transparent-expression-wrappers" "^7.22.5"
|
||||
"@babel/helper-split-export-declaration" "^7.22.6"
|
||||
semver "^6.3.1"
|
||||
|
||||
"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.15", "@babel/helper-create-regexp-features-plugin@^7.22.5":
|
||||
version "7.22.15"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz#5ee90093914ea09639b01c711db0d6775e558be1"
|
||||
@ -380,6 +395,16 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703"
|
||||
integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==
|
||||
|
||||
"@babel/plugin-proposal-private-property-in-object@^7.21.11":
|
||||
version "7.21.11"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz#69d597086b6760c4126525cfa154f34631ff272c"
|
||||
integrity sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.18.6"
|
||||
"@babel/helper-create-class-features-plugin" "^7.21.0"
|
||||
"@babel/helper-plugin-utils" "^7.20.2"
|
||||
"@babel/plugin-syntax-private-property-in-object" "^7.14.5"
|
||||
|
||||
"@babel/plugin-syntax-async-generators@^7.8.4":
|
||||
version "7.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d"
|
||||
@ -7676,6 +7701,11 @@ prelude-ls@~1.1.2:
|
||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
|
||||
integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==
|
||||
|
||||
prettier@^3.2.5:
|
||||
version "3.2.5"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368"
|
||||
integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==
|
||||
|
||||
pretty-bytes@^5.3.0, pretty-bytes@^5.4.1:
|
||||
version "5.6.0"
|
||||
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb"
|
||||
|
Loading…
Reference in New Issue
Block a user