Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Advanced json editor in admin #122

Merged
merged 4 commits into from
Oct 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ build_version=dev
npm.download=true
org.gradle.parallel=true
org.gradle.caching=true
live.dev.embedFrontend=true
live.dev.embedFrontend=true
live.dev.embedSchema=true
14 changes: 14 additions & 0 deletions src/backend/src/main/kotlin/org/icpclive/admin/Routing.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.icpclive.admin
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.websocket.*
Expand Down Expand Up @@ -92,6 +93,19 @@ fun Route.configureAdminApiRouting() {
}
}
}

route("/advancedJson") {
get {
call.respondFile(Config.advancedJsonPath.toFile())
}
post {
call.adminApiAction {
val text = call.receiveText()
Config.advancedJsonPath.toFile().writeText(text)
}
}
}

webSocket("/advancedProperties") { sendJsonFlow(DataBus.advancedPropertiesFlow.await()) }
webSocket("/backendLog") { sendFlow(DataBus.loggerFlow) }
webSocket("/adminActions") { sendFlow(DataBus.adminActionsFlow) }
Expand Down
2 changes: 2 additions & 0 deletions src/frontend/admin/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import Analytics from "./components/Analytics";
import TeamSpotlight from "./components/TeamSpotlight";
import { useLocalStorageState } from "./utils";
import FullScreenClockManager from "./components/FullScreenClockManager";
import AdvancedJson from "./components/AdvancedJson";

const dashboard_elements = {
"Controls": <Controls/>,
Expand Down Expand Up @@ -58,6 +59,7 @@ function App() {
<Route path="/log" element={<BackendLog/>}/>
<Route path="/analytics" element={<Analytics/>}/>
<Route path="/teamSpotlight" element={<TeamSpotlight/>}/>
<Route path="/advancedJson" element={<AdvancedJson/>}/>
{/* <Route path="/advancedproperties" element={<AdvancedProperties/>}/> */}
</Routes>
<Overlay isOverlayPreviewShown={isOverlayPreviewShown}/>
Expand Down
1 change: 1 addition & 0 deletions src/frontend/admin/src/AppNav.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const pages = {
"Backend Log": "log",
"Analytics": "analytics",
"Spotlight": "teamSpotlight",
"Advanced": "advancedJson",
// "Advanced Properties": "AdvancedProperties",
};

Expand Down
65 changes: 65 additions & 0 deletions src/frontend/admin/src/components/AdvancedJson.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React, { useState, useEffect } from "react";
import { Button, Container, TextField } from "@mui/material";
import { errorHandlerWithSnackbar } from "../errors";
import { useSnackbar } from "notistack";
import { BASE_URL_BACKEND, SCHEMAS_LOCATION } from "../config";
import Typography from "@mui/material/Typography";
import { createApiGet, createApiPost } from "../utils";

function AdvancedJson() {
const { enqueueSnackbar } = useSnackbar();
const errorHandler = errorHandlerWithSnackbar(enqueueSnackbar);

const schemaUrl = SCHEMAS_LOCATION + "/advanced.schema.json";
const apiUrl = BASE_URL_BACKEND + "/advancedJson";

const schemaGet = createApiGet(schemaUrl);
const apiGet = createApiGet(apiUrl);
const apiPost = createApiPost(apiUrl);

const [schema, setSchema] = useState();
const [data, setData] = useState();

useEffect(() => {
schemaGet("")
.then(data => setSchema(data))
.catch(errorHandler("Failed to load advanced json schema"));
}, [schemaUrl]);

useEffect(() => {
apiGet("")
.then(data => setData(JSON.stringify(data, null, 2)))
.catch(errorHandler("Failed to load advanced json data"));
}, [apiUrl]);

const onSubmit = () => {
const dataJson = JSON.parse(data);
console.log(dataJson);
apiPost("", dataJson)
.catch(errorHandler("Failed to save advanced json data"));
};

if (schema === undefined || data === undefined) {
return (
<Container maxWidth="md" sx={{ pt: 2 }}>
<Typography variant="h6">Loading...</Typography>
</Container>
);
}

return (
<Container maxWidth="md" sx={{ pt: 2 }}>
<TextField
value={data}
onChange={(e) => setData(e.target.value)}
fullWidth
multiline
/>
<Button type="submit" onClick={onSubmit}>
Save
</Button>
</Container>
);
}

export default AdvancedJson;
3 changes: 1 addition & 2 deletions src/frontend/admin/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ const BACKEND_PROTO = window.location.protocol === "https:" ? "https://" : "http
const BACKEND_PORT = process.env.REACT_APP_BACKEND_PORT ?? window.location.port;
export const BASE_URL_BACKEND = process.env.REACT_APP_BACKEND_URL ?? (BACKEND_PROTO + window.location.hostname + ":" + BACKEND_PORT + "/api/admin");
export const OVERLAY_LOCATION = process.env.REACT_APP_OVERLAY_LOCATION ?? (BACKEND_PROTO + window.location.hostname + ":" + BACKEND_PORT + "/overlay");
export const SCHEMAS_LOCATION = process.env.REACT_APP_SCHEMAS_LOCATION ?? (BACKEND_PROTO + window.location.hostname + ":" + BACKEND_PORT + "/schemas");

const WS_PROTO = window.location.protocol === "https:" ? "wss://" : "ws://";
export const BASE_URL_WS = process.env.REACT_APP_WEBSOCKET_URL ?? (WS_PROTO + window.location.hostname + ":" + BACKEND_PORT + "/api/admin");

export const WEBSOCKET_RECONNECT_TIME = 5000;

export const ADMIN_ACTIONS_WS_URL = BASE_URL_WS + "/adminActions";