A lot of small UI changes, trying to make the report look more polished.

This commit is contained in:
Shay Nehmad 2019-08-27 11:58:15 +03:00
parent 6cd5cff818
commit 07eb9ec32f
7 changed files with 75 additions and 35 deletions

View File

@ -8,7 +8,6 @@ import SinglePillarDirectivesStatus from "../report-components/zerotrust/SingleP
import MonkeysStillAliveWarning from "../report-components/common/MonkeysStillAliveWarning";
import ReportLoader from "../report-components/common/ReportLoader";
import MustRunMonkeyWarning from "../report-components/common/MustRunMonkeyWarning";
import SecurityIssuesGlance from "../report-components/common/SecurityIssuesGlance";
import StatusesToPillarsSummary from "../report-components/zerotrust/StatusesToPillarsSummary";
import PrintReportButton from "../report-components/common/PrintReportButton";
import {extractExecutionStatusFromServerResponse} from "../report-components/common/ExecutionStatus";
@ -94,6 +93,11 @@ class ZeroTrustReportPageComponent extends AuthComponent {
generateFindingsSection() {
return (<div id="findings-overview">
<h2>Findings</h2>
<p>
Deep-dive into the details of each test, and see the explicit events and exact timestamps in which things
happened in your network. This will enable you to match up with your SOC logs and alerts and to gain deeper
insight as to what exactly happened during this test.
</p>
<FindingsTable pillarsToStatuses={this.state.pillars.pillarsToStatuses} findings={this.state.findings}/>
</div>);
}
@ -101,6 +105,10 @@ class ZeroTrustReportPageComponent extends AuthComponent {
generateDirectivesSection() {
return (<div id="directives-overview">
<h2>Directives</h2>
<p>
Analyze each zero trust recommendation by pillar, and see if you've followed through with it. See test results
to understand how the monkey tested your adherence to that recommendation.
</p>
{
Object.keys(this.state.directives).map((pillar) =>
<SinglePillarDirectivesStatus

View File

@ -8,15 +8,15 @@ import * as PropTypes from "prop-types";
const columns = [
{
Header: 'Directives status',
columns: [
{ Header: 'Directive', accessor: 'directive',
style: {'whiteSpace': 'unset'} // This enables word wrap
},
{ Header: 'Status', id: 'status',
accessor: x => {
return <StatusLabel status={x.status} size="fa-3x" showText={false} />;
}
},
maxWidth: 80
},
{ Header: 'Directive', accessor: 'directive',
style: {'whiteSpace': 'unset'} // This enables word wrap
},
{ Header: 'Tests', id: 'tests',
style: {'whiteSpace': 'unset'}, // This enables word wrap
@ -56,7 +56,7 @@ class TestsStatus extends AuthComponent {
return (<li key={test.test}>{test.test}</li>)
});
return <Fragment>
<StatusLabel status={statusToFilter} showText={true}/>
<StatusLabel status={statusToFilter} showText={false}/>
<ul>{listItems}</ul>
</Fragment>;
}

View File

@ -3,6 +3,7 @@ import EventsModal from "./EventsModal";
import {Button} from "react-bootstrap";
import FileSaver from "file-saver";
import * as PropTypes from "prop-types";
import ExportEventsButton from "./ExportEventsButton";
export default class EventsAndButtonComponent extends Component {
constructor(props) {
@ -23,22 +24,17 @@ export default class EventsAndButtonComponent extends Component {
render() {
return (
<div>
<EventsModal events={this.props.events} showEvents={this.state.isShow} hideCallback={this.hide}/>
<p style={{margin: '1px'}}>
<Button className="btn btn-info btn-lg center-block"
onClick={this.show}>
<EventsModal events={this.props.events} showEvents={this.state.isShow} hideCallback={this.hide} exportFilename={this.props.exportFilename} />
<div className="text-center" style={{"display": "grid"}}>
<Button className="btn btn-info btn-lg" onClick={this.show}>
Show Events
</Button>
<Button className="btn btn-primary btn-lg center-block"
onClick={() => {
const content = JSON.stringify(this.props.events, null, 2);
const blob = new Blob([content], {type: "text/plain;charset=utf-8"});
FileSaver.saveAs(blob, this.props.exportFilename + ".json");
}}
>
Export Events
</Button>
</p>
<ExportEventsButton onClick={() => {
const content = JSON.stringify(this.props.events, null, 2);
const blob = new Blob([content], {type: "text/plain;charset=utf-8"});
FileSaver.saveAs(blob, this.props.exportFilename + ".json");
}}/>
</div>
</div>
);
}

View File

@ -2,6 +2,8 @@ import React, {Component} from "react";
import {Modal} from "react-bootstrap";
import EventsTimeline from "./EventsTimeline";
import * as PropTypes from "prop-types";
import FileSaver from "file-saver";
import ExportEventsButton from "./ExportEventsButton";
export default class EventsModal extends Component {
constructor(props) {
@ -24,6 +26,11 @@ export default class EventsModal extends Component {
onClick={() => this.props.hideCallback()}>
Close
</button>
<ExportEventsButton onClick={() => {
const content = JSON.stringify(this.props.events, null, 2);
const blob = new Blob([content], {type: "text/plain;charset=utf-8"});
FileSaver.saveAs(blob, this.props.exportFilename + ".json");
}}/>
</div>
</Modal.Body>
</Modal>

View File

@ -0,0 +1,15 @@
import React, {Component} from "react";
import {Button} from "react-bootstrap";
import * as PropTypes from "prop-types";
export default class ExportEventsButton extends Component {
render() {
return <Button className="btn btn-primary btn-lg"
onClick={this.props.onClick}
>
Export Events
</Button>
}
}
ExportEventsButton.propTypes = {onClick: PropTypes.func};

View File

@ -1,4 +1,4 @@
import React, {Component} from "react";
import React, {Component, Fragment} from "react";
import PillarLabel from "./PillarLabel";
import PaginatedTable from "../common/PaginatedTable";
import EventsAndButtonComponent from "./EventsAndButtonComponent";
@ -6,24 +6,27 @@ import EventsAndButtonComponent from "./EventsAndButtonComponent";
const columns = [
{
Header: 'Findings',
columns: [
{ Header: 'Finding', accessor: 'test',
style: {'whiteSpace': 'unset'} // This enables word wrap
},
{ Header: 'Pillars', id: "pillars",
accessor: x => {
const pillars = x.pillars;
const listItems = pillars.map((pillar) =>
<li key={pillar.name}><PillarLabel pillar={pillar.name} status={pillar.status}/></li>
const pillarLabels = pillars.map((pillar) =>
<PillarLabel key={pillar.name} pillar={pillar.name} status={pillar.status}/>
);
return <ul>{listItems}</ul>;
}
return <Fragment>{pillarLabels}</Fragment>;
},
maxWidth: 200,
style: {'whiteSpace': 'unset'}
},
{ Header: 'Finding', accessor: 'test',
style: {'whiteSpace': 'unset'} // This enables word wrap
},
{ Header: 'Events', id:"events",
accessor: x => {
return <EventsAndButtonComponent events={x.events} exportFilename={"Events_" + x.test_key}/>;
}
},
maxWidth: 160,
}
]
}

View File

@ -3,6 +3,7 @@ import PillarLabel from "./PillarLabel";
import DirectivesStatusTable from "./DirectivesStatusTable";
import React, {Fragment} from "react";
import * as PropTypes from "prop-types";
import {Panel} from "react-bootstrap";
export default class SinglePillarDirectivesStatus extends AuthComponent {
render() {
@ -11,10 +12,20 @@ export default class SinglePillarDirectivesStatus extends AuthComponent {
}
else {
return (
<Fragment>
<h3><PillarLabel pillar={this.props.pillar} status={this.props.pillarsToStatuses[this.props.pillar]} /></h3>
<DirectivesStatusTable directivesStatus={this.props.directivesStatus}/>
</Fragment>
<Panel>
<Panel.Heading>
<Panel.Title toggle>
<h3 style={{"text-align": "center"}}>
🔽 <PillarLabel pillar={this.props.pillar} status={this.props.pillarsToStatuses[this.props.pillar]} />
</h3>
</Panel.Title>
</Panel.Heading>
<Panel.Collapse>
<Panel.Body>
<DirectivesStatusTable directivesStatus={this.props.directivesStatus}/>
</Panel.Body>
</Panel.Collapse>
</Panel>
);
}
}