■ ■ ■ ■ ■ ■
opencti-platform/opencti-front/src/private/components/techniques/data_components/AddDataSource.js
| 1 | + | import React, { Component } from 'react'; |
| 2 | + | import * as PropTypes from 'prop-types'; |
| 3 | + | import { compose } from 'ramda'; |
| 4 | + | import withStyles from '@mui/styles/withStyles'; |
| 5 | + | import Drawer from '@mui/material/Drawer'; |
| 6 | + | import IconButton from '@mui/material/IconButton'; |
| 7 | + | import List from '@mui/material/List'; |
| 8 | + | import ListItem from '@mui/material/ListItem'; |
| 9 | + | import ListItemIcon from '@mui/material/ListItemIcon'; |
| 10 | + | import ListItemText from '@mui/material/ListItemText'; |
| 11 | + | import Typography from '@mui/material/Typography'; |
| 12 | + | import { Add, Close } from '@mui/icons-material'; |
| 13 | + | import Skeleton from '@mui/material/Skeleton'; |
| 14 | + | import inject18n from '../../../../components/i18n'; |
| 15 | + | import SearchInput from '../../../../components/SearchInput'; |
| 16 | + | import { QueryRenderer } from '../../../../relay/environment'; |
| 17 | + | import AddCoursesOfActionLines, { |
| 18 | + | addCoursesOfActionLinesQuery, |
| 19 | + | } from './AddCoursesOfActionLines'; |
| 20 | + | import CourseOfActionCreation from '../courses_of_action/CourseOfActionCreation'; |
| 21 | + | |
| 22 | + | const styles = (theme) => ({ |
| 23 | + | drawerPaper: { |
| 24 | + | minHeight: '100vh', |
| 25 | + | width: '50%', |
| 26 | + | position: 'fixed', |
| 27 | + | transition: theme.transitions.create('width', { |
| 28 | + | easing: theme.transitions.easing.sharp, |
| 29 | + | duration: theme.transitions.duration.enteringScreen, |
| 30 | + | }), |
| 31 | + | padding: 0, |
| 32 | + | }, |
| 33 | + | createButton: { |
| 34 | + | float: 'left', |
| 35 | + | marginTop: -15, |
| 36 | + | }, |
| 37 | + | title: { |
| 38 | + | float: 'left', |
| 39 | + | }, |
| 40 | + | search: { |
| 41 | + | float: 'right', |
| 42 | + | }, |
| 43 | + | header: { |
| 44 | + | backgroundColor: theme.palette.background.nav, |
| 45 | + | padding: '20px 20px 20px 60px', |
| 46 | + | }, |
| 47 | + | closeButton: { |
| 48 | + | position: 'absolute', |
| 49 | + | top: 12, |
| 50 | + | left: 5, |
| 51 | + | color: 'inherit', |
| 52 | + | }, |
| 53 | + | container: { |
| 54 | + | padding: 0, |
| 55 | + | }, |
| 56 | + | placeholder: { |
| 57 | + | display: 'inline-block', |
| 58 | + | height: '1em', |
| 59 | + | backgroundColor: theme.palette.grey[700], |
| 60 | + | }, |
| 61 | + | avatar: { |
| 62 | + | width: 24, |
| 63 | + | height: 24, |
| 64 | + | }, |
| 65 | + | }); |
| 66 | + | |
| 67 | + | class AddCoursesOfAction extends Component { |
| 68 | + | constructor(props) { |
| 69 | + | super(props); |
| 70 | + | this.state = { open: false, search: '' }; |
| 71 | + | } |
| 72 | + | |
| 73 | + | handleOpen() { |
| 74 | + | this.setState({ open: true }); |
| 75 | + | } |
| 76 | + | |
| 77 | + | handleClose() { |
| 78 | + | this.setState({ open: false, search: '' }); |
| 79 | + | } |
| 80 | + | |
| 81 | + | handleSearch(keyword) { |
| 82 | + | this.setState({ search: keyword }); |
| 83 | + | } |
| 84 | + | |
| 85 | + | render() { |
| 86 | + | const { t, classes, attackPatternId, attackPatternCoursesOfAction } = this.props; |
| 87 | + | const paginationOptions = { |
| 88 | + | search: this.state.search, |
| 89 | + | }; |
| 90 | + | return ( |
| 91 | + | <div> |
| 92 | + | <IconButton |
| 93 | + | color="secondary" |
| 94 | + | aria-label="Add" |
| 95 | + | onClick={this.handleOpen.bind(this)} |
| 96 | + | classes={{ root: classes.createButton }} |
| 97 | + | size="large" |
| 98 | + | > |
| 99 | + | <Add fontSize="small" /> |
| 100 | + | </IconButton> |
| 101 | + | <Drawer |
| 102 | + | open={this.state.open} |
| 103 | + | anchor="right" |
| 104 | + | elevation={1} |
| 105 | + | sx={{ zIndex: 1202 }} |
| 106 | + | classes={{ paper: classes.drawerPaper }} |
| 107 | + | onClose={this.handleClose.bind(this)} |
| 108 | + | > |
| 109 | + | <div className={classes.header}> |
| 110 | + | <IconButton |
| 111 | + | aria-label="Close" |
| 112 | + | className={classes.closeButton} |
| 113 | + | onClick={this.handleClose.bind(this)} |
| 114 | + | size="large" |
| 115 | + | color="primary" |
| 116 | + | > |
| 117 | + | <Close fontSize="small" color="primary" /> |
| 118 | + | </IconButton> |
| 119 | + | <Typography variant="h6" classes={{ root: classes.title }}> |
| 120 | + | {t('Add courses of action')} |
| 121 | + | </Typography> |
| 122 | + | <div className={classes.search}> |
| 123 | + | <SearchInput |
| 124 | + | variant="inDrawer" |
| 125 | + | placeholder={`${t('Search')}...`} |
| 126 | + | onSubmit={this.handleSearch.bind(this)} |
| 127 | + | /> |
| 128 | + | </div> |
| 129 | + | </div> |
| 130 | + | <div className={classes.container}> |
| 131 | + | <QueryRenderer |
| 132 | + | query={addCoursesOfActionLinesQuery} |
| 133 | + | variables={{ |
| 134 | + | search: this.state.search, |
| 135 | + | count: 20, |
| 136 | + | }} |
| 137 | + | render={({ props }) => { |
| 138 | + | if (props) { |
| 139 | + | return ( |
| 140 | + | <AddCoursesOfActionLines |
| 141 | + | attackPatternId={attackPatternId} |
| 142 | + | attackPatternCoursesOfAction={ |
| 143 | + | attackPatternCoursesOfAction |
| 144 | + | } |
| 145 | + | data={props} |
| 146 | + | /> |
| 147 | + | ); |
| 148 | + | } |
| 149 | + | return ( |
| 150 | + | <List> |
| 151 | + | {Array.from(Array(20), (e, i) => ( |
| 152 | + | <ListItem key={i} divider={true} button={false}> |
| 153 | + | <ListItemIcon> |
| 154 | + | <Skeleton |
| 155 | + | animation="wave" |
| 156 | + | variant="circular" |
| 157 | + | width={30} |
| 158 | + | height={30} |
| 159 | + | /> |
| 160 | + | </ListItemIcon> |
| 161 | + | <ListItemText |
| 162 | + | primary={ |
| 163 | + | <Skeleton |
| 164 | + | animation="wave" |
| 165 | + | variant="rectangular" |
| 166 | + | width="90%" |
| 167 | + | height={15} |
| 168 | + | style={{ marginBottom: 10 }} |
| 169 | + | /> |
| 170 | + | } |
| 171 | + | secondary={ |
| 172 | + | <Skeleton |
| 173 | + | animation="wave" |
| 174 | + | variant="rectangular" |
| 175 | + | width="90%" |
| 176 | + | height={15} |
| 177 | + | /> |
| 178 | + | } |
| 179 | + | /> |
| 180 | + | </ListItem> |
| 181 | + | ))} |
| 182 | + | </List> |
| 183 | + | ); |
| 184 | + | }} |
| 185 | + | /> |
| 186 | + | </div> |
| 187 | + | </Drawer> |
| 188 | + | <CourseOfActionCreation |
| 189 | + | display={this.state.open} |
| 190 | + | contextual={true} |
| 191 | + | inputValue={this.state.search} |
| 192 | + | paginationOptions={paginationOptions} |
| 193 | + | /> |
| 194 | + | </div> |
| 195 | + | ); |
| 196 | + | } |
| 197 | + | } |
| 198 | + | |
| 199 | + | AddCoursesOfAction.propTypes = { |
| 200 | + | attackPatternId: PropTypes.string, |
| 201 | + | attackPatternCoursesOfAction: PropTypes.array, |
| 202 | + | classes: PropTypes.object, |
| 203 | + | t: PropTypes.func, |
| 204 | + | }; |
| 205 | + | |
| 206 | + | export default compose(inject18n, withStyles(styles))(AddCoursesOfAction); |
| 207 | + | |