Farmbot-Web-App/frontend/logs/index.tsx

146 lines
5.5 KiB
TypeScript
Raw Normal View History

2017-11-07 18:16:38 -07:00
import * as React from "react";
2019-02-04 13:54:17 -07:00
import moment from "moment";
2017-11-07 18:16:38 -07:00
import { connect } from "react-redux";
import { Col, Row, Page, ToolTip } from "../ui/index";
2017-11-07 18:16:38 -07:00
import { mapStateToProps } from "./state_to_props";
import { Popover, Position } from "@blueprintjs/core";
2018-05-17 14:12:33 -06:00
import { LogsState, LogsProps, Filters } from "./interfaces";
2017-11-08 15:51:46 -07:00
import { ToolTips } from "../constants";
2017-12-01 22:02:18 -07:00
import { LogsSettingsMenu } from "./components/settings_menu";
2019-08-26 17:19:16 -06:00
import { LogsFilterMenu, filterStateKeys } from "./components/filter_menu";
2017-12-01 22:02:18 -07:00
import { LogsTable } from "./components/logs_table";
2018-08-27 14:09:27 -06:00
import { safeNumericSetting } from "../session";
2017-12-11 04:50:41 -07:00
import { isUndefined } from "lodash";
import { NumericSetting } from "../session_keys";
2018-08-27 14:09:27 -06:00
import { setWebAppConfigValue } from "../config_storage/actions";
2018-10-22 09:35:44 -06:00
import { NumberConfigKey } from "farmbot/dist/resources/configs/web_app";
2019-04-02 13:59:37 -06:00
import { t } from "../i18next_wrapper";
2019-04-09 23:17:03 -06:00
import { TimeSettings } from "../interfaces";
import { timeFormatString } from "../util";
2020-04-13 19:15:11 -06:00
import { SearchField } from "../ui/search_field";
2017-11-07 18:16:38 -07:00
2018-05-17 14:12:33 -06:00
/** Format log date and time for display in the app. */
2019-04-09 23:17:03 -06:00
export const formatLogTime =
(created_at: number, timeSettings: TimeSettings) =>
moment.unix(created_at)
.utcOffset(timeSettings.utcOffset)
.format(`MMM D, ${timeFormatString(timeSettings)}`);
2017-11-07 18:16:38 -07:00
2019-09-19 13:09:00 -06:00
export class RawLogs extends React.Component<LogsProps, Partial<LogsState>> {
2018-05-17 14:12:33 -06:00
/** Initialize log type verbosity level to the configured or default value. */
2020-02-28 09:34:28 -07:00
initialize = (key: NumberConfigKey, defaultValue: number): number => {
const currentValue = this.props.getConfigValue(safeNumericSetting(key));
2017-12-11 04:50:41 -07:00
if (isUndefined(currentValue)) {
2018-08-27 14:09:27 -06:00
this.props.dispatch(
2020-02-28 09:34:28 -07:00
setWebAppConfigValue(safeNumericSetting(key), defaultValue));
2017-12-11 04:50:41 -07:00
return defaultValue;
} else {
2018-08-27 14:09:27 -06:00
return currentValue as number;
2017-12-11 04:50:41 -07:00
}
};
2017-12-11 04:50:41 -07:00
2017-11-07 18:16:38 -07:00
state: LogsState = {
autoscroll: false,
success: this.initialize(NumericSetting.success_log, 1),
busy: this.initialize(NumericSetting.busy_log, 1),
warn: this.initialize(NumericSetting.warn_log, 1),
error: this.initialize(NumericSetting.error_log, 1),
info: this.initialize(NumericSetting.info_log, 1),
fun: this.initialize(NumericSetting.fun_log, 1),
debug: this.initialize(NumericSetting.debug_log, 1),
2019-08-23 11:55:11 -06:00
assertion: this.initialize(NumericSetting.assertion_log, 1),
2020-02-26 11:10:59 -07:00
searchTerm: "",
2019-09-17 09:53:18 -06:00
markdown: true,
2017-11-07 18:16:38 -07:00
};
2018-05-17 14:12:33 -06:00
/** Toggle display of a log type. Verbosity level 0 hides all, 3 shows all.*/
2020-02-28 09:34:28 -07:00
toggle = (key: keyof Filters) => {
2018-05-17 14:12:33 -06:00
// If log type is off, set it to verbosity level 1, otherwise turn it off
2020-02-28 09:34:28 -07:00
const newSetting = this.state[key] === 0 ? 1 : 0;
2018-05-17 14:12:33 -06:00
return () => {
2020-02-28 09:34:28 -07:00
this.setState({ [key]: newSetting });
2018-08-27 14:09:27 -06:00
this.props.dispatch(
2020-02-28 09:34:28 -07:00
setWebAppConfigValue(safeNumericSetting(key + "_log"), newSetting));
2018-05-17 14:12:33 -06:00
};
};
2017-12-11 04:50:41 -07:00
2018-05-17 14:12:33 -06:00
/** Set log type filter level. i.e., level 2 shows verbosity 2 and lower.*/
2020-02-28 09:34:28 -07:00
setFilterLevel = (key: keyof Filters) => {
2017-12-11 04:50:41 -07:00
return (value: number) => {
2020-02-28 09:34:28 -07:00
this.setState({ [key]: value });
2018-08-27 14:09:27 -06:00
this.props.dispatch(
2020-02-28 09:34:28 -07:00
setWebAppConfigValue(safeNumericSetting(key + "_log"), value));
2017-12-11 04:50:41 -07:00
};
};
2017-11-07 18:16:38 -07:00
2018-05-17 14:12:33 -06:00
/** Determine if log type filters are active. */
2017-11-08 15:51:46 -07:00
get filterActive() {
2020-04-23 13:11:25 -06:00
const filterKeys = filterStateKeys(this.state);
2017-11-08 15:51:46 -07:00
const filterValues = filterKeys
2018-05-17 14:12:33 -06:00
.map((key: keyof Filters) => this.state[key]);
// Filters active if every log type level is not equal to 3 (max verbosity)
2017-12-11 04:50:41 -07:00
return !filterValues.every(x => x == 3);
2017-11-08 15:51:46 -07:00
}
2017-11-07 18:16:38 -07:00
render() {
2017-11-08 15:51:46 -07:00
const filterBtnColor = this.filterActive ? "green" : "gray";
2019-02-06 18:36:11 -07:00
return <Page className="logs-page">
2017-11-07 18:16:38 -07:00
<Row>
2020-02-26 11:10:59 -07:00
<Col xs={6}>
2017-11-07 18:16:38 -07:00
<h3>
<i>{t("Logs")}</i>
</h3>
2017-11-08 15:51:46 -07:00
<ToolTip helpText={ToolTips.LOGS} />
2017-11-07 18:16:38 -07:00
</Col>
2020-02-26 11:10:59 -07:00
<Col xs={6}>
2017-12-01 21:47:57 -07:00
<div className={"settings-menu-button"}>
2018-07-27 15:42:45 -06:00
<Popover position={Position.TOP_RIGHT}>
2017-12-01 21:47:57 -07:00
<i className="fa fa-gear" />
2017-12-11 04:50:41 -07:00
<LogsSettingsMenu
2018-01-27 02:29:13 -07:00
setFilterLevel={this.setFilterLevel}
dispatch={this.props.dispatch}
2018-08-27 14:09:27 -06:00
sourceFbosConfig={this.props.sourceFbosConfig}
getConfigValue={this.props.getConfigValue} />
2017-12-01 21:47:57 -07:00
</Popover>
</div>
<div className={"settings-menu-button"}>
2018-07-27 15:42:45 -06:00
<Popover position={Position.TOP_RIGHT}>
2020-02-28 09:34:28 -07:00
<button className={`fb-button ${filterBtnColor}`}
title={t("edit filter settings")}>
2017-12-01 21:47:57 -07:00
{this.filterActive ? t("Filters active") : t("filter")}
</button>
2017-12-11 04:50:41 -07:00
<LogsFilterMenu
toggle={this.toggle} state={this.state}
2019-08-23 15:19:22 -06:00
shouldDisplay={this.props.shouldDisplay}
2017-12-11 04:50:41 -07:00
setFilterLevel={this.setFilterLevel} />
2017-12-01 21:47:57 -07:00
</Popover>
</div>
2019-09-16 15:22:20 -06:00
<div className="fa-stack fa-2x"
title={this.state.markdown ? t("display raw") : t("display markdown")}
onClick={() => this.setState({ markdown: !this.state.markdown })}>
<i className="fa fa-font fa-stack-1x" />
{this.state.markdown && <i className="fa fa-ban fa-stack-2x" />}
</div>
2017-11-07 18:16:38 -07:00
</Col>
</Row>
2020-02-26 11:10:59 -07:00
<Row>
<Col xs={12} md={5} lg={4}>
2020-04-13 19:15:11 -06:00
<SearchField
placeholder={t("Search logs...")}
searchTerm={this.state.searchTerm}
onChange={searchTerm => this.setState({ searchTerm })} />
2020-02-26 11:10:59 -07:00
</Col>
</Row>
2017-11-07 18:16:38 -07:00
<Row>
2017-12-28 12:33:11 -07:00
<LogsTable logs={this.props.logs}
2019-08-26 12:20:46 -06:00
dispatch={this.props.dispatch}
2017-12-28 12:33:11 -07:00
state={this.state}
2019-04-09 23:17:03 -06:00
timeSettings={this.props.timeSettings} />
2017-11-07 18:16:38 -07:00
</Row>
</Page>;
}
}
2019-09-19 13:09:00 -06:00
export const Logs = connect(mapStateToProps)(RawLogs);