Skip to content

Commit c0e1eb9

Browse files
authored
[frontend] update drawer exportfiles (#13303)
- fix on Safari, button in drawer's form are now aligned to the right - fix breaking rule of hooks when there is a controlledDial component in drawer
1 parent d0a32c1 commit c0e1eb9

File tree

8 files changed

+106
-88
lines changed

8 files changed

+106
-88
lines changed

opencti-platform/opencti-front/src/components/common/form/FormButtonContainer.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ const FormButtonContainer = ({ children }: PropsWithChildren) => {
66
<Stack
77
direction="row"
88
gap={1}
9-
justifySelf="flex-end"
10-
sx={{ mt: 4 }}
9+
sx={{ mt: 4, justifyContent: 'flex-end' }}
1110
>
1211
{children}
1312
</Stack>

opencti-platform/opencti-front/src/private/components/common/drawer/Drawer.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,13 @@ const Drawer = forwardRef<HTMLDivElement, DrawerProps>(({
177177

178178
return (
179179
<>
180-
{controlledDial ? controlledDial({ onOpen: () => setOpen(true), onClose: handleClose }) : undefined }
180+
{controlledDial && (
181+
// issue with calling controlledDial as function, so all hooks inside controlledDial func are counted
182+
// as Drawer hook list, when undefined, the hooks disapear, breaks the rules of hooks
183+
// -> creating new element will separate component with isolated hooks tree
184+
React.createElement(controlledDial, { onOpen: () => setOpen(true), onClose: handleClose })
185+
)}
186+
181187
{variant && (
182188
<Fab
183189
onClick={() => setOpen(true)}

opencti-platform/opencti-front/src/private/components/common/stix_core_objects/StixCoreObjectsExports.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const StixCoreObjectsExports = ({
1818
open={open}
1919
title={t_i18n('Exports list')}
2020
onClose={handleToggle}
21+
size="medium"
2122
>
2223
<QueryRenderer
2324
query={stixCoreObjectsExportsContentQuery}

opencti-platform/opencti-front/src/private/components/common/stix_core_relationships/StixCoreRelationshipsExportCreation.jsx

Lines changed: 18 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import Button from '@common/button/Button';
22
import Dialog from '@common/dialog/Dialog';
3-
import { Add, InfoOutlined } from '@mui/icons-material';
3+
import { InfoOutlined } from '@mui/icons-material';
44
import DialogActions from '@mui/material/DialogActions';
5-
import Fab from '@mui/material/Fab';
65
import MenuItem from '@mui/material/MenuItem';
76
import Slide from '@mui/material/Slide';
87
import Tooltip from '@mui/material/Tooltip';
@@ -79,21 +78,13 @@ export const scopesConn = (exportConnectors) => {
7978
class StixCoreRelationshipsExportCreationComponent extends Component {
8079
constructor(props) {
8180
super(props);
82-
this.state = { open: false, selectedContentMaxMarkingsIds: [] };
81+
this.state = { selectedContentMaxMarkingsIds: [] };
8382
}
8483

8584
handleSelectedContentMaxMarkingsChange(values) {
8685
this.setState({ selectedContentMaxMarkingsIds: values.map(({ value }) => value) });
8786
}
8887

89-
handleOpen() {
90-
this.setState({ open: true });
91-
}
92-
93-
handleClose() {
94-
this.setState({ open: false });
95-
}
96-
9788
onSubmit(selectedIds, availableFilterKeys, values, { setSubmitting, resetForm }) {
9889
const { paginationOptions, exportContext } = this.props;
9990
const { orderBy, orderMode, filters, search } = paginationOptions;
@@ -121,22 +112,22 @@ class StixCoreRelationshipsExportCreationComponent extends Component {
121112
setSubmitting(false);
122113
resetForm();
123114
if (this.props.onExportAsk) this.props.onExportAsk();
124-
this.handleClose();
115+
this.props.onClose();
125116
MESSAGING$.notifySuccess('Export successfully started');
126117
},
127118
});
128119
}
129120

130121
render() {
131-
const { classes, t, data } = this.props;
122+
const { t, data, open, onClose } = this.props;
132123
const connectorsExport = data?.connectorsForExport ?? [];
133124
const exportScopes = R.uniq(
134125
R.flatten(R.map((c) => c.connector_scope, connectorsExport)),
135126
);
136127
const exportConnsPerFormat = scopesConn(connectorsExport);
137128

138129
const isExportActive = (format) => exportConnsPerFormat[format].filter((x) => x.data.active).length > 0;
139-
const isExportPossible = exportScopes.filter((x) => isExportActive(x)).length > 0;
130+
140131
return (
141132
<UserContext.Consumer>
142133
{({ schema }) => {
@@ -146,25 +137,6 @@ class StixCoreRelationshipsExportCreationComponent extends Component {
146137
{({ selectedIds }) => {
147138
return (
148139
<div>
149-
<Tooltip
150-
title={
151-
isExportPossible
152-
? t('Generate an export')
153-
: t('No export connector available to generate an export')
154-
}
155-
aria-label="generate-export"
156-
>
157-
<Fab
158-
data-testid="StixCoreRelationshipsExportCreationAddButton"
159-
onClick={this.handleOpen.bind(this)}
160-
color="secondary"
161-
aria-label="Add"
162-
className={classes.createButton}
163-
disabled={!isExportPossible}
164-
>
165-
<Add />
166-
</Fab>
167-
</Tooltip>
168140
<Formik
169141
enableReinitialize={true}
170142
initialValues={{
@@ -174,16 +146,16 @@ class StixCoreRelationshipsExportCreationComponent extends Component {
174146
}}
175147
validationSchema={exportValidation(t)}
176148
onSubmit={this.onSubmit.bind(this, selectedIds, availableFilterKeys)}
177-
onReset={this.handleClose.bind(this)}
149+
onReset={onClose}
178150
>
179151
{({ submitForm, handleReset, isSubmitting, resetForm, setFieldValue }) => (
180152
<Form>
181153
<Dialog
182154
data-testid="StixCoreRelationshipsExportCreationDialog"
183-
open={this.state.open}
155+
open={open}
184156
onClose={() => {
185157
resetForm();
186-
this.handleClose();
158+
onClose();
187159
}}
188160
title={(
189161
<>
@@ -242,7 +214,14 @@ class StixCoreRelationshipsExportCreationComponent extends Component {
242214
}}
243215
/>
244216
<DialogActions>
245-
<Button variant="secondary" onClick={handleReset} disabled={isSubmitting}>
217+
<Button
218+
variant="secondary"
219+
onClick={() => {
220+
handleReset();
221+
onClose();
222+
}}
223+
disabled={isSubmitting}
224+
>
246225
{t('Cancel')}
247226
</Button>
248227
<Button
@@ -291,6 +270,8 @@ StixCoreRelationshipsExportCreations.propTypes = {
291270
exportContext: PropTypes.object,
292271
paginationOptions: PropTypes.object,
293272
onExportAsk: PropTypes.func,
273+
open: PropTypes.boolean,
274+
onClose: PropTypes.func,
294275
};
295276

296277
export default R.compose(
Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,26 @@
11
import React, { Component } from 'react';
22
import * as PropTypes from 'prop-types';
33
import { compose } from 'ramda';
4-
import withStyles from '@mui/styles/withStyles';
54
import Slide from '@mui/material/Slide';
6-
import Drawer from '@mui/material/Drawer';
5+
import Drawer from '../drawer/Drawer';
76
import { QueryRenderer } from '../../../../relay/environment';
87
import StixCoreRelationshipsExportsContent, { stixCoreRelationshipsExportsContentQuery } from './StixCoreRelationshipsExportsContent';
8+
import inject18n from '../../../../components/i18n';
99

1010
const Transition = React.forwardRef((props, ref) => (
1111
<Slide direction="up" ref={ref} {...props} />
1212
));
1313
Transition.displayName = 'TransitionSlide';
1414

15-
const styles = (theme) => ({
16-
drawerPaper: {
17-
minHeight: '100vh',
18-
width: '50%',
19-
position: 'fixed',
20-
transition: theme.transitions.create('width', {
21-
easing: theme.transitions.easing.sharp,
22-
duration: theme.transitions.duration.enteringScreen,
23-
}),
24-
padding: 0,
25-
},
26-
});
27-
2815
class StixCoreRelationshipsExports extends Component {
2916
render() {
30-
const { classes, paginationOptions, open, handleToggle, exportContext } = this.props;
17+
const { t, paginationOptions, open, handleToggle, exportContext } = this.props;
3118
return (
3219
<Drawer
3320
open={open}
34-
anchor="right"
35-
sx={{ zIndex: 1202 }}
36-
elevation={1}
37-
classes={{ paper: classes.drawerPaper }}
3821
onClose={handleToggle.bind(this)}
22+
title={t('Exports list')}
23+
size="medium"
3924
>
4025
<QueryRenderer
4126
query={stixCoreRelationshipsExportsContentQuery}
@@ -56,12 +41,11 @@ class StixCoreRelationshipsExports extends Component {
5641
}
5742

5843
StixCoreRelationshipsExports.propTypes = {
59-
classes: PropTypes.object.isRequired,
6044
open: PropTypes.bool,
6145
handleToggle: PropTypes.func,
6246
paginationOptions: PropTypes.object,
6347
handleApplyListArgs: PropTypes.func,
6448
exportContext: PropTypes.object,
6549
};
6650

67-
export default compose(withStyles(styles))(StixCoreRelationshipsExports);
51+
export default compose(inject18n)(StixCoreRelationshipsExports);

opencti-platform/opencti-front/src/private/components/common/stix_core_relationships/StixCoreRelationshipsExportsContent.jsx

Lines changed: 71 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
1-
import React, { Component } from 'react';
2-
import * as PropTypes from 'prop-types';
3-
import { compose, pathOr } from 'ramda';
4-
import withStyles from '@mui/styles/withStyles';
5-
import Slide from '@mui/material/Slide';
6-
import { graphql, createRefetchContainer } from 'react-relay';
71
import List from '@mui/material/List';
2+
import Slide from '@mui/material/Slide';
3+
import withStyles from '@mui/styles/withStyles';
4+
import * as PropTypes from 'prop-types';
5+
import { compose, pathOr, uniq, flatten, map } from 'ramda';
6+
import React, { Component } from 'react';
7+
import { createRefetchContainer, graphql } from 'react-relay';
88
import { interval } from 'rxjs';
9-
import IconButton from '@common/button/IconButton';
10-
import { Close } from '@mui/icons-material';
11-
import Typography from '@mui/material/Typography';
12-
import StixCoreRelationshipsExportCreation from './StixCoreRelationshipsExportCreation';
13-
import { FIVE_SECONDS } from '../../../../utils/Time';
14-
import FileLine from '../files/FileLine';
159
import inject18n from '../../../../components/i18n';
1610
import Security from '../../../../utils/Security';
11+
import { FIVE_SECONDS } from '../../../../utils/Time';
1712
import { KNOWLEDGE_KNGETEXPORT_KNASKEXPORT } from '../../../../utils/hooks/useGranted';
13+
import FileLine from '../files/FileLine';
14+
import StixCoreRelationshipsExportCreation, { scopesConn } from './StixCoreRelationshipsExportCreation';
15+
import { Stack, Tooltip } from '@mui/material';
16+
import Button from '@common/button/Button';
1817

1918
const interval$ = interval(FIVE_SECONDS);
2019

@@ -46,6 +45,13 @@ const styles = (theme) => ({
4645
});
4746

4847
class StixCoreRelationshipsExportsContentComponent extends Component {
48+
constructor(props) {
49+
super(props);
50+
this.state = {
51+
open: false,
52+
};
53+
}
54+
4955
componentDidMount() {
5056
this.subscription = interval$.subscribe(() => {
5157
if (this.props.isOpen) {
@@ -61,33 +67,60 @@ class StixCoreRelationshipsExportsContentComponent extends Component {
6167
this.subscription.unsubscribe();
6268
}
6369

70+
handleOpen() {
71+
this.setState({ open: true });
72+
}
73+
74+
handleClose() {
75+
this.setState({ open: false });
76+
}
77+
6478
render() {
6579
const {
66-
classes,
6780
t,
6881
data,
6982
exportContext,
7083
paginationOptions,
71-
handleToggle,
7284
} = this.props;
7385
const stixCoreRelationshipsExportFiles = pathOr(
7486
[],
7587
['stixCoreRelationshipsExportFiles', 'edges'],
7688
data,
7789
);
90+
91+
const connectorsExport = data?.connectorsForExport ?? [];
92+
const exportScopes = uniq(
93+
flatten(map((c) => c.connector_scope, connectorsExport)),
94+
);
95+
const exportConnsPerFormat = scopesConn(connectorsExport);
96+
97+
const isExportActive = (format) => exportConnsPerFormat[format].filter((x) => x.data.active).length > 0;
98+
const isExportPossible = exportScopes.filter((x) => isExportActive(x)).length > 0;
99+
78100
return (
79-
<div>
80-
<div className={classes.header}>
81-
<IconButton
82-
aria-label="Close"
83-
className={classes.closeButton}
84-
onClick={handleToggle.bind(this)}
85-
color="primary"
101+
<Stack gap={2}>
102+
<Stack
103+
direction="row"
104+
justifyContent="flex-end"
105+
gap={1}
106+
>
107+
<Tooltip
108+
title={
109+
isExportPossible
110+
? t('Generate an export')
111+
: t('No export connector available to generate an export')
112+
}
113+
aria-label="generate-export"
86114
>
87-
<Close fontSize="small" color="primary" />
88-
</IconButton>
89-
<Typography variant="h6">{t('Exports list')}</Typography>
90-
</div>
115+
<Button
116+
onClick={this.handleOpen.bind(this)}
117+
disabled={!isExportPossible}
118+
>
119+
{t('Generate an export')}
120+
</Button>
121+
</Tooltip>
122+
</Stack>
123+
91124
<List>
92125
{stixCoreRelationshipsExportFiles.length > 0 ? (
93126
stixCoreRelationshipsExportFiles.map((file) => file?.node && (
@@ -119,9 +152,11 @@ class StixCoreRelationshipsExportsContentComponent extends Component {
119152
exportContext={exportContext}
120153
paginationOptions={paginationOptions}
121154
onExportAsk={() => this.props.relay.refetch({ count: 25, exportContext: this.props.exportContext })}
155+
open={this.state.open}
156+
onClose={this.handleClose.bind(this)}
122157
/>
123158
</Security>
124-
</div>
159+
</Stack>
125160
);
126161
}
127162
}
@@ -154,6 +189,13 @@ const StixCoreRelationshipsExportsContent = createRefetchContainer(
154189
}
155190
}
156191
}
192+
connectorsForExport {
193+
id
194+
name
195+
active
196+
connector_scope
197+
updated_at
198+
}
157199
...StixCoreRelationshipsExportCreation_data
158200
}
159201
`,
@@ -170,6 +212,9 @@ StixCoreRelationshipsExportsContent.propTypes = {
170212
paginationOptions: PropTypes.object,
171213
handleApplyListArgs: PropTypes.func,
172214
isOpen: PropTypes.bool,
215+
216+
open: PropTypes.bool,
217+
setOpen: PropTypes.func,
173218
};
174219

175220
export default compose(

opencti-platform/opencti-front/src/private/components/common/stix_domain_objects/StixDomainObjectsExports.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const StixDomainObjectsExports: FunctionComponent<
2424
open={open}
2525
onClose={handleToggle}
2626
title={t_i18n('Exports list')}
27+
size="medium"
2728
>
2829
<QueryRenderer
2930
query={stixDomainObjectsExportsContentQuery}

opencti-platform/opencti-front/src/private/components/observations/stix_cyber_observables/StixCyberObservablesExports.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class StixCyberObservablesExports extends Component {
3636
elevation={1}
3737
onClose={handleToggle.bind(this)}
3838
title={t('Exports list')}
39+
size="medium"
3940
>
4041
<QueryRenderer
4142
query={stixCyberObservablesExportsContentQuery}

0 commit comments

Comments
 (0)