Skip to content

Commit

Permalink
Add warning if there is a configuration error
Browse files Browse the repository at this point in the history
  • Loading branch information
breiler committed May 7, 2024
1 parent bdb58be commit 19d0479
Show file tree
Hide file tree
Showing 10 changed files with 197 additions and 35 deletions.
33 changes: 33 additions & 0 deletions src/components/alertmessage/AlertMessage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import { faWarning } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import React from "react";
import { ReactNode } from "react";
import { Alert, Col, Row } from "react-bootstrap";

type AlertMessageProps = {
children: ReactNode;
};
const AlertMessage = ({ children }: AlertMessageProps) => {
return (
<Alert variant="danger">
<Row>
<Col
xs={1}
style={{
marginTop: "auto",
marginBottom: "auto"
}}
>
<FontAwesomeIcon
icon={faWarning as IconDefinition}
size="2x"
/>
</Col>
<Col style={{ textAlign: "left" }}>{children}</Col>
</Row>
</Alert>
);
};

export default AlertMessage;
32 changes: 32 additions & 0 deletions src/components/cards/calibratecard/CalibrateCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from "react";
import Card from "../card";
import Button from "../../button";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faSliders } from "@fortawesome/free-solid-svg-icons";
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";

type CalibrateCardProps = {
disabled?: boolean;
onClick: () => void;
};

export const CalibrateCard = ({
onClick,
disabled = false
}: CalibrateCardProps) => {
return (
<Card
className="select-card"
footer={
<Button onClick={onClick} disabled={disabled}>
<>Calibrate</>
</Button>
}
>
<div className="select-icon">
<FontAwesomeIcon icon={faSliders as IconDefinition} size="4x" />
</div>
<>Calibrate settings on your controller</>
</Card>
);
};
19 changes: 3 additions & 16 deletions src/components/controllerlog/ControllerLog.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { ReactNode, useEffect, useState } from "react";
import { ControllerService } from "../../services";
import Log from "../log/Log";
import { createLogLine } from "../../utils/logutils";

type ControllerLogProps = {
show: boolean;
Expand All @@ -11,20 +12,6 @@ type ControllerLogProps = {

let buffer = "";

const createLine = (line: string) => {
line.replace("<", "&lt;");
line = line.replace(/MSG:ERR/g, "<span class='red'>$&</span>");
line = line.replace(/MSG:INFO/g, "<span class='green'>$&</span>");
line = line.replace(/MSG:WARN/g, "<span class='yellow'>$&</span>");
line = line.replace(/MSG:DBG/g, "<span class='yellow'>$&</span>");
line = line.replace(/&lt;Alarm/g, "&lt;<span class='red'>Alarm</span>");
line = line.replace(/&lt;Run/g, "&lt;<span class='green'>Run</span>");
line = line.replace(/&lt;Idle/g, "&lt;<span class='green'>Idle</span>");
line = line.replace(/error:/g, "<span class='red'>error:</span>");

return <div dangerouslySetInnerHTML={{ __html: line }} />;
};

const ControllerLog = ({
show = false,
onShow,
Expand All @@ -38,7 +25,7 @@ const ControllerLog = ({
const newRows: ReactNode[] = [];
while (buffer.indexOf("\n") > -1) {
const newLineIndex = buffer.indexOf("\n");
newRows.push(createLine(buffer.slice(0, newLineIndex)));
newRows.push(createLogLine(buffer.slice(0, newLineIndex)));
buffer = buffer.slice(newLineIndex + 1);
}
setRows((rows) => [...rows, ...newRows]);
Expand All @@ -56,7 +43,7 @@ const ControllerLog = ({
}, [buffer]);

return (
<Log show={show} onShow={onShow}>
<Log show={show} onShow={onShow} showExpand={true}>
{rows}
</Log>
);
Expand Down
41 changes: 27 additions & 14 deletions src/components/log/Log.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@ import "./Log.scss";

type LogProps = {
show: boolean;
showExpand: boolean;
onShow: (show: boolean) => void;
children: ReactNode;
children?: ReactNode;
};

const Log = ({ show = false, onShow, children }: LogProps) => {
const Log = ({
show = false,
showExpand = true,
onShow,
children
}: LogProps) => {
const bottom = useRef<HTMLDivElement>(null);

useEffect(() => {
Expand All @@ -25,19 +31,26 @@ const Log = ({ show = false, onShow, children }: LogProps) => {
<div ref={bottom} />
</div>
)}
{showExpand && (
<>
{show && (
<a href="#" onClick={() => onShow(false)}>
Hide details{" "}
<FontAwesomeIcon
icon={faChevronUp as IconDefinition}
/>
</a>
)}

{show && (
<a href="#" onClick={() => onShow(false)}>
Hide details{" "}
<FontAwesomeIcon icon={faChevronUp as IconDefinition} />
</a>
)}

{!show && (
<a href="#" onClick={() => onShow(true)}>
Show details{" "}
<FontAwesomeIcon icon={faChevronDown as IconDefinition} />
</a>
{!show && (
<a href="#" onClick={() => onShow(true)}>
Show details{" "}
<FontAwesomeIcon
icon={faChevronDown as IconDefinition}
/>
</a>
)}
</>
)}
</div>
);
Expand Down
37 changes: 37 additions & 0 deletions src/components/logmodal/LogModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from "react";
import { Button } from "../../components";
import { Modal } from "react-bootstrap";
import { faClose } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import Log from "../log/Log";
import { createLogLine } from "../../utils/logutils";

type RestartModalProps = {
show?: boolean;
setShow: (show: boolean) => void;
rows?: string[];
};

const LogModal = ({ show, setShow, rows }: RestartModalProps) => {
return (
<Modal show={show} size="lg" centered>
<Modal.Body>
<Log onShow={() => {}} show={true} showExpand={false}>
{rows?.map(createLogLine)}
</Log>
</Modal.Body>

<Modal.Footer>
<Button onClick={() => setShow(false)}>
<>
<FontAwesomeIcon icon={faClose as IconDefinition} />{" "}
Close
</>
</Button>
</Modal.Footer>
</Modal>
);
};

export default LogModal;
2 changes: 1 addition & 1 deletion src/components/restartmodal/RestartModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const RestartModal = ({ show }: RestartModalProps) => {
</div>
)}

{isConnected && (
{isConnected && !showLog && (
<div className="title">
Connected to the controller{" "}
<span className="success">
Expand Down
3 changes: 2 additions & 1 deletion src/model/Page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ export enum Page {
INSTALLER = "/install",
FILEBROWSER = "/files",
CONFIGURATION = "/configuration",
WIFI = "/wifi"
WIFI = "/wifi",
CALIBRATE = "/calibrate"
}

export default Page;
44 changes: 41 additions & 3 deletions src/pages/selectmode/SelectMode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,38 @@ import PageTitle from "../../components/pagetitle/PageTitle";
import Page from "../../model/Page";
import usePageView from "../../hooks/usePageView";
import { WiFiCard } from "../../components/cards/wificard/WiFiCard";
import { Col } from "react-bootstrap";
import { Col, Row } from "react-bootstrap";
import { sleep } from "../../utils/utils";
import { Spinner } from "../../components";
import { GetStartupShowCommand } from "../../services/controllerservice/commands/GetStartupShowCommand";
import AlertMessage from "../../components/alertmessage/AlertMessage";
import LogModal from "../../components/logmodal/LogModal";

const SelectMode = () => {
usePageView("Home");
const navigate = useNavigate();
const [isLoading, setIsLoading] = useState(false);
const controllerService = useContext(ControllerServiceContext);
const [stats, setStats] = useState<Stats>();
const [isBootError, setBootError] = useState<boolean>(false);
const [showLogModal, setShowLogModal] = useState<boolean>(false);
const [startupLogRows, setStartupLogRows] = useState<string[]>([]);

useEffect(() => {
if (!controllerService) return;
setIsLoading(true);
sleep(1000)
.then(() => controllerService.send(new GetStatsCommand(), 5000))
.then((command) => setStats(command.getStats()))
.then(() => controllerService.send(new GetStartupShowCommand()))
.then((command) => {
setBootError(
!!command.response.find(
(line) => line.indexOf("[MSG:ERR:") > -1
)
);
setStartupLogRows(command.response);
})
.finally(() => setIsLoading(false));
}, [controllerService]);

Expand All @@ -46,12 +61,35 @@ const SelectMode = () => {

return (
<>
<LogModal
show={showLogModal}
setShow={setShowLogModal}
rows={startupLogRows}
/>
<PageTitle>FluidNC Web Installer</PageTitle>
<p>
You are now connected to a device, please choose an action below
</p>
<div className="container text-center select-mode">
<div className="row">
<Row>
<Col xs={12}>
{isBootError && (
<AlertMessage>
{" "}
There was an error during boot, likely due to an
unvalid configuration.
<br />
<a
href="#"
onClick={() => setShowLogModal(true)}
>
Click here to see details
</a>
</AlertMessage>
)}
</Col>
</Row>
<Row>
<Col xs={12} md={6} lg={4}>
<InstallCard onClick={() => navigate(Page.INSTALLER)} />
</Col>
Expand All @@ -76,7 +114,7 @@ const SelectMode = () => {
/>
</Col>
)}
</div>
</Row>
</div>
</>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Command } from "./Command";

export class GetStartupShowCommand extends Command {
constructor() {
super("$Startup/Show");
}
}
14 changes: 14 additions & 0 deletions src/utils/logutils.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from "react";

export const createLogLine = (line: string) => {
line.replace("<", "&lt;");
line = line.replace(/MSG:ERR/g, "<span class='red'>$&</span>");
line = line.replace(/MSG:INFO/g, "<span class='green'>$&</span>");
line = line.replace(/MSG:WARN/g, "<span class='yellow'>$&</span>");
line = line.replace(/MSG:DBG/g, "<span class='yellow'>$&</span>");
line = line.replace(/&lt;Alarm/g, "&lt;<span class='red'>Alarm</span>");
line = line.replace(/&lt;Run/g, "&lt;<span class='green'>Run</span>");
line = line.replace(/&lt;Idle/g, "&lt;<span class='green'>Idle</span>");
line = line.replace(/error:/g, "<span class='red'>error:</span>");
return <div dangerouslySetInnerHTML={{ __html: line }} />;
};

0 comments on commit 19d0479

Please sign in to comment.