add sequence log settings
parent
7c91e51bc6
commit
d6993516e4
|
@ -251,6 +251,15 @@ export namespace ToolTips {
|
|||
// Logs
|
||||
export const LOGS =
|
||||
`View and filter log messages.`;
|
||||
|
||||
export const SEQUENCE_LOG_BEGIN =
|
||||
`Send a log message upon the start of sequence execution.`;
|
||||
|
||||
export const SEQUENCE_LOG_STEP =
|
||||
`Send a log message for each sequence step.`;
|
||||
|
||||
export const SEQUENCE_LOG_END =
|
||||
`Send a log message upon the end of sequence execution.`;
|
||||
}
|
||||
|
||||
export namespace Content {
|
||||
|
|
|
@ -509,6 +509,25 @@ ul {
|
|||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
.settings-menu-button {
|
||||
float: right;
|
||||
margin-left: 1rem;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.logs-settings-menu {
|
||||
label {
|
||||
margin-top: 7px;
|
||||
}
|
||||
.saucer {
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.pt-popover-target {
|
||||
display: inline;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.logs-table {
|
||||
|
|
|
@ -1,14 +1,23 @@
|
|||
const mockDevice = {
|
||||
updateConfig: jest.fn(() => { return Promise.resolve(); }),
|
||||
};
|
||||
jest.mock("../../device", () => ({
|
||||
getDevice: () => (mockDevice)
|
||||
}));
|
||||
|
||||
jest.mock("react-redux", () => ({
|
||||
connect: jest.fn()
|
||||
}));
|
||||
|
||||
import * as React from "react";
|
||||
import { mount } from "enzyme";
|
||||
import { Logs, LogsFilterMenu } from "../index";
|
||||
import { Logs, LogsFilterMenu, LogsSettingsMenu } from "../index";
|
||||
import { ToolTips } from "../../constants";
|
||||
import { TaggedLog, SpecialStatus } from "../../resources/tagged_resources";
|
||||
import { Log } from "../../interfaces";
|
||||
import { generateUuid } from "../../resources/util";
|
||||
import { bot } from "../../__test_support__/fake_state/bot";
|
||||
import { ConfigurationName } from "farmbot";
|
||||
|
||||
describe("<Logs />", () => {
|
||||
function fakeLogs(): TaggedLog[] {
|
||||
|
@ -41,7 +50,7 @@ describe("<Logs />", () => {
|
|||
}
|
||||
|
||||
it("renders", () => {
|
||||
const wrapper = mount(<Logs logs={fakeLogs()} />);
|
||||
const wrapper = mount(<Logs logs={fakeLogs()} bot={bot} />);
|
||||
["Logs", ToolTips.LOGS, "Type", "Message", "Time", "Info",
|
||||
"Fake log message 1", "Success", "Fake log message 2"]
|
||||
.map(string =>
|
||||
|
@ -52,7 +61,7 @@ describe("<Logs />", () => {
|
|||
});
|
||||
|
||||
it("filters logs", () => {
|
||||
const wrapper = mount(<Logs logs={fakeLogs()} />);
|
||||
const wrapper = mount(<Logs logs={fakeLogs()} bot={bot} />);
|
||||
wrapper.setState({ info: false });
|
||||
expect(wrapper.text()).not.toContain("Fake log message 1");
|
||||
const filterBtn = wrapper.find("button").first();
|
||||
|
@ -66,7 +75,7 @@ describe("<Logs />", () => {
|
|||
logs[1].body.meta.x = 0;
|
||||
logs[1].body.meta.y = 1;
|
||||
logs[1].body.meta.z = 2;
|
||||
const wrapper = mount(<Logs logs={logs} />);
|
||||
const wrapper = mount(<Logs logs={logs} bot={bot} />);
|
||||
expect(wrapper.text()).toContain("Unknown");
|
||||
expect(wrapper.text()).toContain("0, 1, 2");
|
||||
});
|
||||
|
@ -94,3 +103,24 @@ describe("<LogsFilterMenu />", () => {
|
|||
expect(toggle).toHaveBeenCalledWith("success");
|
||||
});
|
||||
});
|
||||
|
||||
describe("<LogsSettingsMenu />", () => {
|
||||
it("renders", () => {
|
||||
const wrapper = mount(<LogsSettingsMenu {...bot} />);
|
||||
["begin", "steps", "complete"].map(string =>
|
||||
expect(wrapper.text().toLowerCase()).toContain(string));
|
||||
});
|
||||
|
||||
function testSettingToggle(setting: ConfigurationName, position: number) {
|
||||
it("toggles setting", () => {
|
||||
bot.hardware.configuration[setting] = false;
|
||||
const wrapper = mount(<LogsSettingsMenu {...bot} />);
|
||||
wrapper.find("button").at(position).simulate("click");
|
||||
expect(mockDevice.updateConfig)
|
||||
.toHaveBeenCalledWith({ [setting]: true });
|
||||
});
|
||||
}
|
||||
testSettingToggle("sequence_init_log", 0);
|
||||
testSettingToggle("sequence_body_log", 1);
|
||||
testSettingToggle("sequence_complete_log", 2);
|
||||
});
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
import * as React from "react";
|
||||
import * as moment from "moment";
|
||||
import { connect } from "react-redux";
|
||||
import { Col, Row, Page, ToolTip } from "../ui";
|
||||
import { Col, Row, Page, ToolTip, Help } from "../ui";
|
||||
import { mapStateToProps } from "./state_to_props";
|
||||
import { t } from "i18next";
|
||||
import { Popover, Position } from "@blueprintjs/core";
|
||||
import * as _ from "lodash";
|
||||
import { LogsTableProps, LogsState, LogsFilterMenuProps, LogsProps } from "./interfaces";
|
||||
import {
|
||||
LogsTableProps, LogsState, LogsFilterMenuProps, LogsProps
|
||||
} from "./interfaces";
|
||||
import { ToolTips } from "../constants";
|
||||
import { TaggedLog } from "../resources/tagged_resources";
|
||||
import { ToggleButton } from "../controls/toggle_button";
|
||||
import { noop } from "lodash";
|
||||
import { updateConfig } from "../devices/actions";
|
||||
import { BotState } from "../devices/interfaces";
|
||||
|
||||
export const formatLogTime = (created_at: number) =>
|
||||
moment.unix(created_at).local().format("MMM D, h:mma");
|
||||
|
@ -63,14 +69,13 @@ const LogsRow = (tlog: TaggedLog, state: LogsState) => {
|
|||
|
||||
export const LogsFilterMenu = (props: LogsFilterMenuProps) => {
|
||||
const btnColor = (x: keyof LogsState) => props.state[x] ? "green" : "red";
|
||||
return <div>
|
||||
return <div className={"logs-settings-menu"}>
|
||||
{Object.keys(props.state)
|
||||
.filter(x => { if (!(x == "autoscroll")) { return x; } })
|
||||
.map((logType: keyof LogsState) => {
|
||||
return <fieldset key={logType}>
|
||||
<label style={{ marginTop: "7px" }}>
|
||||
<div className={`saucer ${logType}`}
|
||||
style={{ float: "left", marginRight: "10px" }} />
|
||||
<label>
|
||||
<div className={`saucer ${logType}`} />
|
||||
{_.startCase(logType)}
|
||||
</label>
|
||||
<button
|
||||
|
@ -81,6 +86,47 @@ export const LogsFilterMenu = (props: LogsFilterMenuProps) => {
|
|||
</div>;
|
||||
};
|
||||
|
||||
export const LogsSettingsMenu = (bot: BotState) => {
|
||||
const {
|
||||
sequence_init_log, sequence_body_log, sequence_complete_log
|
||||
} = bot.hardware.configuration;
|
||||
return <div className={"logs-settings-menu"}>
|
||||
{t("Create logs for sequence:")}
|
||||
<fieldset>
|
||||
<label>
|
||||
{t("Begin")}
|
||||
</label>
|
||||
<Help text={t(ToolTips.SEQUENCE_LOG_BEGIN)} />
|
||||
<ToggleButton toggleValue={sequence_init_log}
|
||||
toggleAction={() => {
|
||||
updateConfig({ sequence_init_log: !sequence_init_log })(noop);
|
||||
}} />
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<label>
|
||||
{t("Steps")}
|
||||
</label>
|
||||
<Help text={t(ToolTips.SEQUENCE_LOG_STEP)} />
|
||||
<ToggleButton toggleValue={sequence_body_log}
|
||||
toggleAction={() => {
|
||||
updateConfig({ sequence_body_log: !sequence_body_log })(noop);
|
||||
}} />
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<label>
|
||||
{t("Complete")}
|
||||
</label>
|
||||
<Help text={t(ToolTips.SEQUENCE_LOG_END)} />
|
||||
<ToggleButton toggleValue={sequence_complete_log}
|
||||
toggleAction={() => {
|
||||
updateConfig({
|
||||
sequence_complete_log: !sequence_complete_log
|
||||
})(noop);
|
||||
}} />
|
||||
</fieldset>
|
||||
</div>;
|
||||
};
|
||||
|
||||
@connect(mapStateToProps)
|
||||
export class Logs extends React.Component<LogsProps, Partial<LogsState>> {
|
||||
|
||||
|
@ -117,12 +163,20 @@ export class Logs extends React.Component<LogsProps, Partial<LogsState>> {
|
|||
<ToolTip helpText={ToolTips.LOGS} />
|
||||
</Col>
|
||||
<Col xs={1}>
|
||||
<Popover position={Position.BOTTOM_RIGHT}>
|
||||
<button className={`fb-button ${filterBtnColor}`}>
|
||||
{this.filterActive ? t("Filters active") : t("filter")}
|
||||
</button>
|
||||
<LogsFilterMenu toggle={this.toggle} state={this.state} />
|
||||
</Popover>
|
||||
<div className={"settings-menu-button"}>
|
||||
<Popover position={Position.BOTTOM_RIGHT}>
|
||||
<i className="fa fa-gear" />
|
||||
<LogsSettingsMenu {...this.props.bot} />
|
||||
</Popover>
|
||||
</div>
|
||||
<div className={"settings-menu-button"}>
|
||||
<Popover position={Position.BOTTOM_RIGHT}>
|
||||
<button className={`fb-button ${filterBtnColor}`}>
|
||||
{this.filterActive ? t("Filters active") : t("filter")}
|
||||
</button>
|
||||
<LogsFilterMenu toggle={this.toggle} state={this.state} />
|
||||
</Popover>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import { TaggedLog } from "../resources/tagged_resources";
|
||||
import { BotState } from "../devices/interfaces";
|
||||
|
||||
export interface LogsProps {
|
||||
logs: TaggedLog[]
|
||||
logs: TaggedLog[];
|
||||
bot: BotState;
|
||||
}
|
||||
|
||||
export interface Filters {
|
||||
|
|
|
@ -9,7 +9,8 @@ export function mapStateToProps(props: Everything): LogsProps {
|
|||
logs: _(selectAllLogs(props.resources.index))
|
||||
.sortBy("body.created_at")
|
||||
.reverse()
|
||||
.value()
|
||||
.value(),
|
||||
bot: props.bot
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue