From eec32aa38a8762eccc8575a37a628bd5ae2cc1d0 Mon Sep 17 00:00:00 2001 From: "Elizabeth (Lizzy) Hunt" Date: Mon, 29 May 2023 16:28:27 -0700 Subject: Bots (#23) * squash all the things for bots * fix warnings * change colors a bit and README updates * fix frontend warnings --- front/src/index.css | 2 +- front/src/index.js | 5 ++ front/src/root.jsx | 24 ++--- front/src/routes/bots.jsx | 194 +++++++++++++++++++++++++++++++++++++++++ front/src/routes/keys.jsx | 10 +-- front/src/routes/man_pages.jsx | 6 +- 6 files changed, 223 insertions(+), 18 deletions(-) create mode 100644 front/src/routes/bots.jsx (limited to 'front') diff --git a/front/src/index.css b/front/src/index.css index f9c4620..fc17142 100644 --- a/front/src/index.css +++ b/front/src/index.css @@ -69,7 +69,7 @@ body { .navbar { display: flex; flex-direction: row; - justify-content: space-between; + justify-content: center; align-items: center; margin-bottom: 1rem; diff --git a/front/src/index.js b/front/src/index.js index eb2801c..fdb7b5a 100644 --- a/front/src/index.js +++ b/front/src/index.js @@ -7,6 +7,7 @@ import { Root } from "./root"; import { Demo } from "./routes/demo"; import { Home } from "./routes/home"; import { Keys } from "./routes/keys"; +import { Bots } from "./routes/bots"; import { ManPages } from "./routes/man_pages"; import { Password } from "./routes/password"; import { AuthSuccessful } from "./routes/auth_successful"; @@ -36,6 +37,10 @@ const router = createBrowserRouter([ path: "auth-successful", element: , }, + { + path: "bots", + element: , + }, { path: "man-pages", element: , diff --git a/front/src/root.jsx b/front/src/root.jsx index 2b1e603..82e79c3 100644 --- a/front/src/root.jsx +++ b/front/src/root.jsx @@ -10,18 +10,18 @@ export const Root = () => { return ( <>
+
+ + CheSSH Logo + +
-
- - CheSSH Logo - -
- - Man Pages - {signedIn ? ( <> + + Sign Out + Home @@ -31,8 +31,8 @@ export const Root = () => { Keys - - Sign Out + + Bots ) : ( @@ -45,6 +45,10 @@ export const Root = () => { )} + + + Man Pages +
diff --git a/front/src/routes/bots.jsx b/front/src/routes/bots.jsx new file mode 100644 index 0000000..c2f1565 --- /dev/null +++ b/front/src/routes/bots.jsx @@ -0,0 +1,194 @@ +import Modal from "react-modal"; +import { useAuthContext } from "../context/auth_context"; +import { useEffect, useState } from "react"; + +Modal.setAppElement("#root"); + +const BotButton = ({ onSave, givenBot }) => { + const [open, setOpen] = useState(false); + const [name, setName] = useState(givenBot?.name || ""); + const [webhook, setWebhook] = useState(givenBot?.webhook || ""); + const [errors, setErrors] = useState(null); + const [isPublic, setIsPublic] = useState(givenBot?.public || false); + + const setDefaults = () => { + setName(""); + setWebhook(""); + setErrors(null); + }; + + const close = () => { + if (!givenBot) { + setDefaults(); + } + setOpen(false); + }; + + const updateBot = () => { + fetch(givenBot ? `/api/player/bots/${givenBot.id}` : "/api/player/bots", { + credentials: "same-origin", + method: givenBot ? "PUT" : "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + webhook: webhook.trim(), + name: name.trim(), + public: isPublic, + }), + }) + .then((r) => r.json()) + .then((d) => { + if (d.success) { + if (onSave) { + onSave(); + } + close(); + } else if (d.errors) { + if (typeof d.errors === "object") { + setErrors( + Object.keys(d.errors).map( + (field) => `${field}: ${d.errors[field].join(",")}` + ) + ); + } else { + setErrors([d.errors]); + } + } + }); + }; + + return ( +
+ + {givenBot && ( + <> + + + + )} + +
+

Add Bot

+
+

Bot Name *

+ setName(e.target.value)} + required + /> +
+
+

Webhook *

+ setWebhook(e.target.value)} + required + /> +
+

+ Public *{" "} + setIsPublic(!isPublic)} + required + /> +

+
+ {errors && ( +
+ {errors.map((error, i) => ( +

{error}

+ ))} +
+ )} +
+
+ + +
+
+
+ ); +}; + +export const BotCard = ({ botStruct, onSave }) => { + const { name } = botStruct; + return ( +
+

{name}

+ +
+ ); +}; + +export const Bots = () => { + const { + player: { id: userId }, + } = useAuthContext(); + const [bots, setBots] = useState(null); + + const refreshBots = () => + fetch("/api/player/bots") + .then((r) => r.json()) + .then((bots) => setBots(bots)); + + useEffect(() => { + if (userId) { + refreshBots(); + } + }, [userId]); + + if (bots === null) return

Loading...

; + + return ( + <> +

Bots

+ + +
+ {bots.length ? ( + bots.map((bot) => ( + + )) + ) : ( +

Looks like you've got no bots, try adding one!

+ )} +
+ + ); +}; diff --git a/front/src/routes/keys.jsx b/front/src/routes/keys.jsx index 5b50fa9..b9d4542 100644 --- a/front/src/routes/keys.jsx +++ b/front/src/routes/keys.jsx @@ -14,16 +14,14 @@ const minimizeKey = (key) => { return key; }; -const KeyCard = ({ onDelete, props }) => { - const { id, name, key } = props; - +const KeyCard = ({ onDelete, keyStruct: { id, name, key } }) => { const deleteThisKey = () => { if ( window.confirm( "Are you sure? This will close all your currently opened ssh sessions." ) ) { - fetch(`/api/keys/${id}`, { + fetch(`/api/player/keys/${id}`, { credentials: "same-origin", method: "DELETE", }) @@ -182,7 +180,7 @@ export const Keys = () => { } }, [userId, refreshKeys]); - if (!keys) return

Loading...

; + if (keys === null) return

Loading...

; if (Array.isArray(keys)) { return ( @@ -192,7 +190,7 @@ export const Keys = () => {
{keys.length ? ( keys.map((key) => ( - + )) ) : (

Looks like you've got no keys, try adding some!

diff --git a/front/src/routes/man_pages.jsx b/front/src/routes/man_pages.jsx index ea03c2a..f904394 100644 --- a/front/src/routes/man_pages.jsx +++ b/front/src/routes/man_pages.jsx @@ -74,7 +74,11 @@ export const ManPages = () => {
  • In the "Previous Games" viewer, use "m" to show the game's move history in UCI notation (which you may convert to PGN{" "} - + here ). -- cgit v1.2.3-70-g09d2