stitch-ui
Version:
233 lines (220 loc) • 6.5 kB
JavaScript
// TODO proptypes
/* eslint-disable react/prop-types */
import React from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import moment from "moment";
import DateTime from "react-datetime";
import qs from "query-string";
import * as actions from "../actions";
import { Button, Banner, Spinner, Tooltip } from "../../core";
import LogsTable from "./LogsTable";
const RFC3339Format = "YYYY-MM-DDTHH:mm:ssZ";
class LogBrowser extends React.Component {
constructor(props, context) {
super(props, context);
this.setFilter = this.setFilter.bind(this);
}
componentDidMount() {
this.props.initLogs();
if (this.props.location && this.props.location.search) {
this.applyUrl(qs.parse(this.props.location.search));
} else {
this.props.loadLogs(this.props.app.groupId, this.props.app._id, {});
}
}
setFilter() {
const { app, loadLogs } = this.props;
const filter = this.makeFilterObj();
const newUrl = `/groups/${app.groupId}/apps/${app._id}/logs?${qs.stringify(
filter
)}`;
this.context.router.history.replace(newUrl);
loadLogs(app.groupId, app._id, filter);
}
applyUrl(queryObj) {
const { app, loadLogs } = this.props;
const filter = {};
this.props.setUserId(queryObj.user_id || "");
this.props.setCoId(queryObj.co_id || "");
const fields = [
{ key: "before", setter: this.props.setBefore },
{ key: "after", setter: this.props.setAfter }
];
for (let i = 0; i < fields.length; i += 1) {
const field = fields[i];
if (!queryObj[field.key]) {
continue;
}
const parsed = moment(queryObj[field.key], RFC3339Format);
if (!parsed.isValid()) {
continue;
}
filter[field.key] = queryObj[field.key];
field.setter(parsed);
}
this.props.setErrorsOnly(!!queryObj.errors_only);
if (queryObj.user_id) {
filter.user_id = queryObj.user_id;
}
if (queryObj.co_id) {
filter.co_id = queryObj.co_id;
}
if (queryObj.errors_only) {
filter.errors_only = true;
}
loadLogs(app.groupId, app._id, filter);
}
makeFilterObj() {
const { errorsOnly, before, after, userId, coId } = this.props;
const filter = {};
if (userId) {
filter.user_id = userId;
}
if (coId) {
filter.co_id = coId;
}
if (before) {
filter.before = before.format(RFC3339Format);
}
if (after) {
filter.after = after.format(RFC3339Format);
}
if (errorsOnly) {
filter.errors_only = true;
}
return filter;
}
render() {
const {
app,
entries,
errorsOnly,
before,
after,
userId,
coId,
loadingLogs,
error
} = this.props;
const {
setAfter,
setBefore,
setUserId,
setErrorsOnly,
setCoId
} = this.props;
return (
<div>
<div className="section-header">
<div className="section-header-title">
<div className="section-header-title-text">
Logs
<Tooltip
dataFor="logs-tooltip"
place="right"
classNames="tooltip-indicator tooltip-indicator-normal tooltip-indicator-primary"
effect="solid"
>
This is the Logs page.
</Tooltip>
</div>
</div>
</div>
<div className="tabs-content">
<Banner message={error} error />
<div className="logs-filter">
<div className="logs-filter-errorsonly">
<label htmlFor="errors_only">Failed requests only</label>
<input
id="errors_only"
type="checkbox"
name="errors_only"
checked={errorsOnly}
className="slide-toggle-round"
onChange={e => setErrorsOnly(e.target.checked)}
/>
<label htmlFor="errors_only" />
</div>
<div className="logs-filter-field logs-filter-userid">
<label htmlFor="user_id">Filter by user</label>
<input
name="user_id"
value={userId}
className="text-input text-input-for-filter"
onChange={e => setUserId(e.target.value)}
/>
</div>
<div className="logs-filter-field logs-filter-coid">
<label htmlFor="co_id">Filter by request ID</label>
<input
name="co_id"
value={coId}
className="text-input text-input-for-filter"
onChange={e => setCoId(e.target.value)}
/>
</div>
<div className="logs-filter-field logs-filter-before">
<label htmlFor="before">From before</label>
<DateTime onChange={setBefore} value={before} />
</div>
<div className="logs-filter-field logs-filter-after">
<label htmlFor="after">From after</label>
<DateTime onChange={setAfter} value={after} />
</div>
<div>
<Button
primary
small
disabled={loadingLogs}
onClick={this.setFilter}
>
load
</Button>
<Spinner open={loadingLogs} />
</div>
</div>
<LogsTable entries={entries} app={app} />
</div>
</div>
);
}
}
LogBrowser.contextTypes = {
router: PropTypes.object
};
const mapStateToProps = state => {
const {
entries,
errorsOnly,
before,
after,
userId,
coId,
loadingLogs,
error
} = state.logs;
const { app } = state.app.root;
return {
entries,
errorsOnly,
before,
after,
userId,
coId,
loadingLogs,
error,
app
};
};
const mapDispatchToProps = dispatch => ({
initLogs: () => dispatch(actions.initLogs()),
setBefore: b => dispatch(actions.setBefore(b)),
setAfter: a => dispatch(actions.setAfter(a)),
setUserId: uid => dispatch(actions.setUserId(uid)),
setCoId: coId => dispatch(actions.setCoId(coId)),
setErrorsOnly: errorsOnly => dispatch(actions.setErrorsOnly(errorsOnly)),
loadLogs: (groupId, appId, filter) =>
dispatch(actions.loadLogs(groupId, appId, filter))
});
export default connect(mapStateToProps, mapDispatchToProps)(LogBrowser);