UNPKG

stitch-ui

Version:

233 lines (220 loc) 6.5 kB
// 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);