From 0d047b28e39eece43138f71501d88626207ebde4 Mon Sep 17 00:00:00 2001 From: VakarisZ <vakarisz@yahoo.com> Date: Tue, 25 Aug 2020 11:30:12 +0300 Subject: [PATCH] More work and styling of monkey run page components --- .../pages/RunMonkeyPage/CommandDisplay.js | 39 ++++++++++++------- .../RunMonkeyPage/LocalManualRunOptions.js | 8 ++-- .../pages/RunMonkeyPage/ManualRunOptions.js | 28 ++++++++----- .../ui-components/DropdownSelect.js | 5 ++- .../inline-selection/BackButton.js | 15 +++++-- .../inline-selection/InlineSelection.js | 5 ++- .../inline-selection/NextSelectionButton.js | 23 ++++++++--- .../monkey_island/cc/ui/src/styles/Main.scss | 4 +- .../styles/components/InlineSelection.scss | 8 ---- .../inline-selection/BackButton.scss | 20 ++++++++++ .../inline-selection/InlineSelection.scss | 12 ++++++ .../inline-selection/NextSelectionButton.scss | 34 ++++++++++++++++ 12 files changed, 152 insertions(+), 49 deletions(-) delete mode 100644 monkey/monkey_island/cc/ui/src/styles/components/InlineSelection.scss create mode 100644 monkey/monkey_island/cc/ui/src/styles/components/inline-selection/BackButton.scss create mode 100644 monkey/monkey_island/cc/ui/src/styles/components/inline-selection/InlineSelection.scss create mode 100644 monkey/monkey_island/cc/ui/src/styles/components/inline-selection/NextSelectionButton.scss diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/CommandDisplay.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/CommandDisplay.js index bf0852c59..b237e25d2 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/CommandDisplay.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/CommandDisplay.js @@ -2,42 +2,53 @@ import {Button, Card, Nav} from 'react-bootstrap'; import CopyToClipboard from 'react-copy-to-clipboard'; import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; import {faClipboard} from '@fortawesome/free-solid-svg-icons/faClipboard'; -import React, {useState} from 'react'; +import React, {useEffect, useState} from 'react'; import PropTypes from 'prop-types'; export default function commandDisplay(props) { - const [selectedVariant, setSelectedVariant] = useState(props.commands[0].name); + const [selectedCommand, setSelectedCommand] = useState(props.commands[0]); + + function setSelectedCommandByName(type){ + setSelectedCommand(getCommandByName(props.commands, type)); + } + + function getCommandByName(commands, type){ + return commands.find((command) => {return command.type === type}); + } + + useEffect(() => { + let sameTypeCommand = getCommandByName(props.commands, selectedCommand.type); + if( sameTypeCommand !== undefined){ + setSelectedCommand(sameTypeCommand); + } else { + setSelectedCommand(props.commands[0]); + } + }, [props.commands]); function renderNav() { return ( - <Nav variant='pills' fill activeKey={selectedVariant} onSelect={setSelectedVariant}> + <Nav variant='pills' fill activeKey={selectedCommand.type} onSelect={setSelectedCommandByName}> {props.commands.map(command => { return ( - <Nav.Item key={command.name}> - <Nav.Link eventKey={command.name}>{command.name}</Nav.Link> + <Nav.Item key={command.type}> + <Nav.Link eventKey={command.type}>{command.type}</Nav.Link> </Nav.Item>); })} </Nav>); } - function getCommandByName(name, commands) { - commands.forEach((command) => { - - }) - } - return ( <> {renderNav()} <Card style={{'margin': '0.5em'}}> <div style={{'overflow': 'auto', 'padding': '0.5em'}}> - <CopyToClipboard text={props.commands[0].name} className="pull-right btn-sm"> + <CopyToClipboard text={selectedCommand.type} className="pull-right btn-sm"> <Button style={{margin: '-0.5em'}} title="Copy to Clipboard"> <FontAwesomeIcon icon={faClipboard}/> </Button> </CopyToClipboard> - <code>{props.commands[0].command}</code> + <code>{selectedCommand.command}</code> </div> </Card> </> @@ -46,7 +57,7 @@ export default function commandDisplay(props) { commandDisplay.propTypes = { commands: PropTypes.arrayOf(PropTypes.exact({ - name: PropTypes.string, + type: PropTypes.string, command: PropTypes.string })) } diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/LocalManualRunOptions.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/LocalManualRunOptions.js index 9680cfbad..9b6783e1b 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/LocalManualRunOptions.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/LocalManualRunOptions.js @@ -37,11 +37,11 @@ const getContents = (props) => { function generateCommands() { if(osType === OS_TYPES.WINDOWS_64 || osType === OS_TYPES.WINDOWS_32) { - return [{name: 'CMD', command: GenerateLocalWindowsCmd(selectedIp, osType)}, - {name: 'Powershell', command: GenerateLocalWindowsPowershell(selectedIp, osType)}] + return [{type: 'CMD', command: GenerateLocalWindowsCmd(selectedIp, osType)}, + {type: 'Powershell', command: GenerateLocalWindowsPowershell(selectedIp, osType)}] } else { - return [{name: 'CURL', command: GenerateLocalLinuxCurl(selectedIp, osType)}, - {name: 'WGET', command: GenerateLocalLinuxWget(selectedIp, osType)}] + return [{type: 'CURL', command: GenerateLocalLinuxCurl(selectedIp, osType)}, + {type: 'WGET', command: GenerateLocalLinuxWget(selectedIp, osType)}] } } diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/ManualRunOptions.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/ManualRunOptions.js index 6874fc2c8..c82fdbebd 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/ManualRunOptions.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/ManualRunOptions.js @@ -3,6 +3,10 @@ import NextSelectionButton from '../../ui-components/inline-selection/NextSelect import LocalManualRunOptions from './LocalManualRunOptions'; import AuthComponent from '../../AuthComponent'; import BackButton from '../../ui-components/inline-selection/BackButton'; +import {faLaptopCode} from '@fortawesome/free-solid-svg-icons/faLaptopCode'; +import {faNetworkWired} from '@fortawesome/free-solid-svg-icons/faNetworkWired'; +import {faCogs} from '@fortawesome/free-solid-svg-icons/faCogs'; +import {Container} from 'react-bootstrap'; function ManualRunOptions(props) { @@ -41,16 +45,22 @@ function ManualRunOptions(props) { function getDefaultContents() { return ( - <div className={`container inline-selection-component`}> - <NextSelectionButton text={'Local'} onButtonClick={() => { - setComponent(LocalManualRunOptions, {ips: ips, setComponent: setComponent}) - }}/> - <NextSelectionButton text={'Remote'} onButtonClick={() => { - }}/> - <NextSelectionButton text={'Automation'} onButtonClick={() => { - }}/> + <Container className={'inline-selection-component'}> + <NextSelectionButton text={'Local'} + description={'Run on a machine via command.'} + icon={faLaptopCode} + onButtonClick={() => {setComponent(LocalManualRunOptions, + {ips: ips, setComponent: setComponent})}}/> + <NextSelectionButton text={'Remote'} + description={'Run using remote command execution.'} + icon={faNetworkWired} + onButtonClick={() => {}}/> + <NextSelectionButton text={'Automation'} + description={'Run using automation tools like ansible or chef.'} + icon={faCogs} + onButtonClick={() => {}}/> <BackButton onClick={props.disableManualOptions} /> - </div> + </Container> ); } diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/DropdownSelect.js b/monkey/monkey_island/cc/ui/src/components/ui-components/DropdownSelect.js index d57f14fe4..f7426fb4f 100644 --- a/monkey/monkey_island/cc/ui/src/components/ui-components/DropdownSelect.js +++ b/monkey/monkey_island/cc/ui/src/components/ui-components/DropdownSelect.js @@ -11,7 +11,7 @@ export default function DropdownSelect(props) { } else if (typeof data === 'object') { return generateDropdownItemsFromObject(data); } else { - throw "Component can only generate dropdown intems from lists and objects." + throw 'Component can only generate dropdown items from arrays and objects.' } } @@ -35,7 +35,8 @@ export default function DropdownSelect(props) { return ( <Dropdown.Item onClick={() => { setSelectedOption(key); props.onClick(key)}} - active={(key === selectedOption)}> + active={(key === selectedOption)} + key={value}> {value} </Dropdown.Item>); } diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/BackButton.js b/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/BackButton.js index eeec63c06..6f2e07bfd 100644 --- a/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/BackButton.js +++ b/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/BackButton.js @@ -1,12 +1,19 @@ -import {Button} from 'react-bootstrap'; +import {Button, Col, Row} from 'react-bootstrap'; import React from 'react'; import PropTypes from 'prop-types'; +import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; +import {faCaretLeft} from '@fortawesome/free-solid-svg-icons/faCaretLeft'; export default function backButton(props) { return ( - <Button variant={'secondary'} onClick={props.onClick}> - Back - </Button> + <Row> + <Col lg={8} md={10} sm={12}> + <Button variant={'outline-dark'} onClick={props.onClick} className={'back-button'}> + <FontAwesomeIcon icon={faCaretLeft} /> + <h1>Back</h1> + </Button> + </Col> + </Row> ) } diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/InlineSelection.js b/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/InlineSelection.js index 2a6dbc897..aa68d0b4e 100644 --- a/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/InlineSelection.js +++ b/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/InlineSelection.js @@ -2,15 +2,16 @@ import React from 'react'; import PropTypes from 'prop-types'; import BackButton from './BackButton'; import ManualRunOptions from '../../pages/RunMonkeyPage/ManualRunOptions'; +import Container from 'react-bootstrap'; export default function InlineSelection(WrappedComponent, props, previousComponent){ return ( - <div className={`container inline-selection-component`}> + <Container className={'inline-selection-component'}> {previousComponent === undefined ? '' : <BackButton onClick={() => {setPreviousComponent(props, previousComponent)}}/>} <WrappedComponent {...props}/> - </div> + </Container> ) } diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/NextSelectionButton.js b/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/NextSelectionButton.js index 6f6ac4cb7..41bd3fb55 100644 --- a/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/NextSelectionButton.js +++ b/monkey/monkey_island/cc/ui/src/components/ui-components/inline-selection/NextSelectionButton.js @@ -1,17 +1,30 @@ -import {Button} from 'react-bootstrap'; +import {Button, Row, Col} from 'react-bootstrap'; import React from 'react'; import PropTypes from 'prop-types'; +import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; +import {faAngleRight} from '@fortawesome/free-solid-svg-icons'; export default function nextSelectionButton(props) { + let description = props.description !== undefined ? (<p>{props.description}</p>) : '' + let icon = props.icon !== undefined ? (<FontAwesomeIcon icon={props.icon}/>) : '' return ( - <Button variant={'outline-monkey'} size='lg' className={'selection-button'} - onClick={props.onButtonClick}> - {props.text} - </Button> + <Row> + <Col lg={8} md={10} sm={12}> + <Button variant={'outline-monkey'} size='lg' className={'selection-button'} + onClick={props.onButtonClick}> + {icon} + <h1>{props.text}</h1> + {description} + <FontAwesomeIcon icon={faAngleRight} className={'angle-right'}/> + </Button> + </Col> + </Row> ) } nextSelectionButton.propTypes = { text: PropTypes.string, + description: PropTypes.string, + icon: FontAwesomeIcon, onButtonClick: PropTypes.func } diff --git a/monkey/monkey_island/cc/ui/src/styles/Main.scss b/monkey/monkey_island/cc/ui/src/styles/Main.scss index 2fb672693..a247b001f 100644 --- a/monkey/monkey_island/cc/ui/src/styles/Main.scss +++ b/monkey/monkey_island/cc/ui/src/styles/Main.scss @@ -11,7 +11,9 @@ @import 'components/InfoPane'; @import 'components/PreviewPane'; @import 'components/AdvancedMultiSelect'; -@import 'components/InlineSelection'; +@import 'components/inline-selection/InlineSelection'; +@import 'components/inline-selection/NextSelectionButton'; +@import 'components/inline-selection/BackButton'; // Define custom elements after bootstrap import diff --git a/monkey/monkey_island/cc/ui/src/styles/components/InlineSelection.scss b/monkey/monkey_island/cc/ui/src/styles/components/InlineSelection.scss deleted file mode 100644 index c264344de..000000000 --- a/monkey/monkey_island/cc/ui/src/styles/components/InlineSelection.scss +++ /dev/null @@ -1,8 +0,0 @@ -.inline-selection-component.container { - display: flex; - justify-content: center; -} - -.inline-selection-component.container .selection-button{ - margin: 0 5px 0 5px; -} diff --git a/monkey/monkey_island/cc/ui/src/styles/components/inline-selection/BackButton.scss b/monkey/monkey_island/cc/ui/src/styles/components/inline-selection/BackButton.scss new file mode 100644 index 000000000..02c5c409e --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/styles/components/inline-selection/BackButton.scss @@ -0,0 +1,20 @@ +.inline-selection-component .back-button { + width: 100%; + text-align: left; +} + +.inline-selection-component .back-button h1{ + font-size: 1.3em; + margin-top: 5px; + margin-bottom: 5px; + text-align: left; + display: inline-block; +} + +.inline-selection-component .back-button svg{ + font-size: 1.5em; + display: inline-block; + margin-right: 10px; + position: relative; + top: 1px; +} diff --git a/monkey/monkey_island/cc/ui/src/styles/components/inline-selection/InlineSelection.scss b/monkey/monkey_island/cc/ui/src/styles/components/inline-selection/InlineSelection.scss new file mode 100644 index 000000000..0deda70db --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/styles/components/inline-selection/InlineSelection.scss @@ -0,0 +1,12 @@ +//.inline-selection-component.container { +// display: flex; +// justify-content: center; +//} +// +//.inline-selection-component.container .selection-button{ +// margin: 0 5px 0 5px; +//} + +.inline-selection-component .selection-button { + width: 100%; +} diff --git a/monkey/monkey_island/cc/ui/src/styles/components/inline-selection/NextSelectionButton.scss b/monkey/monkey_island/cc/ui/src/styles/components/inline-selection/NextSelectionButton.scss new file mode 100644 index 000000000..71bac3053 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/styles/components/inline-selection/NextSelectionButton.scss @@ -0,0 +1,34 @@ +.inline-selection-component .selection-button { + width: 100%; + text-align: left; + margin-bottom: 20px; + padding-right: 40px; +} + +.inline-selection-component .selection-button svg, +.inline-selection-component .selection-button h1 { + display: inline-block; +} + +.inline-selection-component .selection-button h1 { + margin: 0; + font-size: 1.3em; +} + +.inline-selection-component .selection-button p { + margin: 0; + font-size: 0.8em; +} + +.inline-selection-component .selection-button svg { + margin-bottom: 1px; + margin-right: 7px; +} + +.inline-selection-component .selection-button .angle-right { + display: inline-block; + position: absolute; + right: 23px; + top: 22%; + font-size: 1.7em; +}