Projects STRLCPY opencti Commits fc37c3f1
🤬
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/components/ExpandableMarkdown.js opencti-platform/opencti-front/src/components/ExpandableMarkdown.tsx
    1  -import React, { useState } from 'react';
    2  -import * as PropTypes from 'prop-types';
     1 +import React, { FunctionComponent, useState } from 'react';
    3 2  import Markdown from 'react-markdown';
    4 3  import remarkGfm from 'remark-gfm';
    5 4  import remarkParse from 'remark-parse';
    6  -import { ExpandMore, ExpandLess } from '@mui/icons-material';
     5 +import { ExpandLess, ExpandMore } from '@mui/icons-material';
    7 6  import IconButton from '@mui/material/IconButton';
    8  -import { compose } from 'ramda';
    9  -import withTheme from '@mui/styles/withTheme';
     7 +import { useTheme } from '@mui/styles';
    10 8  import { truncate } from '../utils/String';
     9 +import { Theme } from './Theme';
    11 10   
    12  -export const MarkDownComponents = (theme) => ({
    13  - table: ({ node, ...tableProps }) => (
     11 +// eslint-disable-next-line @typescript-eslint/no-explicit-any
     12 +export const MarkDownComponents = (theme: Theme): Record<string, FunctionComponent<any>> => ({
     13 + table: ({ tableProps }) => (
    14 14   <table
    15 15   style={{
    16 16   border: `1px solid ${theme.palette.divider}`,
    skipped 2 lines
    19 19   {...tableProps}
    20 20   />
    21 21   ),
    22  - tr: ({ node, ...trProps }) => (
     22 + tr: ({ trProps }) => (
    23 23   <tr style={{ border: `1px solid ${theme.palette.divider}` }} {...trProps} />
    24 24   ),
    25  - td: ({ node, ...tdProps }) => (
     25 + td: ({ tdProps }) => (
    26 26   <td
    27 27   style={{
    28 28   border: `1px solid ${theme.palette.divider}`,
    skipped 2 lines
    31 31   {...tdProps}
    32 32   />
    33 33   ),
    34  - th: ({ node, ...tdProps }) => (
     34 + th: ({ tdProps }) => (
    35 35   <th
    36 36   style={{
    37 37   border: `1px solid ${theme.palette.divider}`,
    skipped 4 lines
    42 42   ),
    43 43  });
    44 44   
    45  -const ExpandableMarkdown = ({ source, limit, theme, ...props }) => {
     45 +interface ExpandableMarkdownProps {
     46 + source: string,
     47 + limit: number,
     48 +}
     49 + 
     50 +const ExpandableMarkdown: FunctionComponent<ExpandableMarkdownProps> = ({ source, limit }) => {
     51 + const theme = useTheme<Theme>();
    46 52   const [expand, setExpand] = useState(false);
     53 + 
    47 54   const onClick = () => setExpand(!expand);
    48 55   const shouldBeTruncated = (source || '').length > limit;
     56 + 
    49 57   return (
    50 58   <div style={{ position: 'relative' }}>
    51 59   {shouldBeTruncated && (
    skipped 6 lines
    58 66   <div style={{ marginTop: 10 }}>
    59 67   <Markdown
    60 68   remarkPlugins={[remarkGfm, remarkParse]}
    61  - parserOptions={{ commonmark: true }}
    62 69   components={MarkDownComponents(theme)}
    63 70   className="markdown"
    64  - {...props}
    65 71   >
    66 72   {expand ? source : truncate(source, limit)}
    67 73   </Markdown>
    skipped 3 lines
    71 77   );
    72 78  };
    73 79   
    74  -ExpandableMarkdown.propTypes = {
    75  - source: PropTypes.string.isRequired,
    76  - limit: PropTypes.number.isRequired,
    77  -};
    78  - 
    79  -export default compose(withTheme)(ExpandableMarkdown);
     80 +export default ExpandableMarkdown;
    80 81   
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/components/SelectField.js
    skipped 7 lines
    8 8   
    9 9  const fieldToSelect = ({
    10 10   disabled,
    11  - field: { onBlur: _onBlur, onChange: fieldOnChange, ...field },
     11 + field: { onChange: fieldOnChange, ...field },
    12 12   form: { isSubmitting, touched, errors, setTouched, setFieldValue },
    13 13   onClose,
    14 14   ...props
    skipped 90 lines
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/components/Transition.js
    1  -import React from 'react';
    2  -import Slide from '@mui/material/Slide';
    3  - 
    4  -const Transition = React.forwardRef((props, ref) => (
    5  - <Slide direction="up" ref={ref} {...props} />
    6  -));
    7  -Transition.displayName = 'TransitionSlide';
    8  - 
    9  -export default Transition;
    10  - 
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/components/Transition.tsx
     1 +/* eslint-disable @typescript-eslint/no-explicit-any */
     2 +import React from 'react';
     3 +import Slide from '@mui/material/Slide';
     4 +import { TransitionProps } from '@mui/material/transitions';
     5 + 
     6 +const Transition = React.forwardRef((
     7 + { children, ...props }: TransitionProps & {
     8 + children: React.ReactElement<any, any>;
     9 + },
     10 + ref: React.Ref<unknown>,
     11 +) => {
     12 + return <Slide direction="up" ref={ref} {...props}>{children}</Slide>;
     13 +});
     14 +Transition.displayName = 'TransitionSlide';
     15 + 
     16 +export default Transition;
     17 + 
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/analysis/external_references/ExternalReferenceCreation.js
    skipped 22 lines
    23 23  import inject18n from '../../../../components/i18n';
    24 24  import TextField from '../../../../components/TextField';
    25 25  import MarkDownField from '../../../../components/MarkDownField';
    26  -import { insertNode } from '../../../../utils/Store';
     26 +import { insertNode } from '../../../../utils/store';
    27 27   
    28 28  const styles = (theme) => ({
    29 29   drawerPaper: {
    skipped 419 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/analysis/groupings/GroupingCreation.js
    skipped 22 lines
    23 23  import ExternalReferencesField from '../../common/form/ExternalReferencesField';
    24 24  import OpenVocabField from '../../common/form/OpenVocabField';
    25 25  import { useFormatter } from '../../../../components/i18n';
    26  -import { insertNode } from '../../../../utils/Store';
     26 +import { insertNode } from '../../../../utils/store';
    27 27  import { fieldSpacingContainerStyle } from '../../../../utils/field';
    28 28   
    29 29  const useStyles = makeStyles((theme) => ({
    skipped 245 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/analysis/groupings/GroupingEditionOverview.js
    skipped 17 lines
    18 18   convertCreatedBy,
    19 19   convertMarkings,
    20 20   convertStatus,
    21  -} from '../../../../utils/Edition';
     21 +} from '../../../../utils/edition';
    22 22  import OpenVocabField from '../../common/form/OpenVocabField';
    23 23  import { fieldSpacingContainerStyle } from '../../../../utils/field';
    24 24   
    skipped 344 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/analysis/notes/NoteEditionOverview.js
    skipped 9 lines
    10 10  import ObjectMarkingField from '../../common/form/ObjectMarkingField';
    11 11  import ConfidenceField from '../../common/form/ConfidenceField';
    12 12  import TextField from '../../../../components/TextField';
    13  -import { convertMarkings, convertStatus } from '../../../../utils/Edition';
     13 +import { convertMarkings, convertStatus } from '../../../../utils/edition';
    14 14  import StatusField from '../../common/form/StatusField';
    15 15  import DateTimePickerField from '../../../../components/DateTimePickerField';
    16 16  import { buildDate } from '../../../../utils/Time';
    skipped 283 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/analysis/opinions/OpinionEditionOverview.js
    skipped 16 lines
    17 17   convertCreatedBy,
    18 18   convertMarkings,
    19 19   convertStatus,
    20  -} from '../../../../utils/Edition';
     20 +} from '../../../../utils/edition';
    21 21  import StatusField from '../../common/form/StatusField';
    22 22  import { fieldSpacingContainerStyle } from '../../../../utils/field';
    23 23   
    skipped 323 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/analysis/reports/ReportEditionOverview.js
    skipped 26 lines
    27 27   convertCreatedBy,
    28 28   convertMarkings,
    29 29   convertStatus,
    30  -} from '../../../../utils/Edition';
     30 +} from '../../../../utils/edition';
    31 31  import DateTimePickerField from '../../../../components/DateTimePickerField';
    32 32  import { fieldSpacingContainerStyle } from '../../../../utils/field';
    33 33   
    skipped 525 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/arsenal/attack_patterns/AttackPatternEditionOverview.js
    skipped 27 lines
    28 28   convertCreatedBy,
    29 29   convertMarkings,
    30 30   convertStatus,
    31  -} from '../../../../utils/Edition';
     31 +} from '../../../../utils/edition';
    32 32   
    33 33  const styles = (theme) => ({
    34 34   drawerPaper: {
    skipped 386 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/arsenal/channels/ChannelEditionOverview.js
    skipped 27 lines
    28 28   convertCreatedBy,
    29 29   convertMarkings,
    30 30   convertStatus,
    31  -} from '../../../../utils/Edition';
     31 +} from '../../../../utils/edition';
    32 32  import { QueryRenderer, commitMutation } from '../../../../relay/environment';
    33 33  import Security, { SETTINGS_SETLABELS } from '../../../../utils/Security';
    34 34  import { attributesQuery } from '../../settings/attributes/AttributesLines';
    skipped 474 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/arsenal/courses_of_action/CourseOfActionEditionOverview.js
    skipped 25 lines
    26 26   convertCreatedBy,
    27 27   convertMarkings,
    28 28   convertStatus,
    29  -} from '../../../../utils/Edition';
     29 +} from '../../../../utils/edition';
    30 30  import StatusField from '../../common/form/StatusField';
    31 31   
    32 32  const styles = (theme) => ({
    skipped 380 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/arsenal/malwares/MalwareCreation.js
    skipped 24 lines
    25 25  import ConfidenceField from '../../common/form/ConfidenceField';
    26 26  import OpenVocabField from '../../common/form/OpenVocabField';
    27 27  import ExternalReferencesField from '../../common/form/ExternalReferencesField';
    28  -import { insertNode } from '../../../../utils/Store';
     28 +import { insertNode } from '../../../../utils/store';
    29 29  import { fieldSpacingContainerStyle } from '../../../../utils/field';
    30 30   
    31 31  const styles = (theme) => ({
    skipped 275 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/arsenal/malwares/MalwareEditionOverview.js
    skipped 15 lines
    16 16  import OpenVocabField from '../../common/form/OpenVocabField';
    17 17  import { adaptFieldValue } from '../../../../utils/String';
    18 18  import CommitMessage from '../../common/form/CommitMessage';
    19  -import { convertCreatedBy, convertMarkings, convertStatus } from '../../../../utils/Edition';
     19 +import { convertCreatedBy, convertMarkings, convertStatus } from '../../../../utils/edition';
    20 20  import StatusField from '../../common/form/StatusField';
    21 21  import { fieldSpacingContainerStyle } from '../../../../utils/field';
    22 22   
    skipped 449 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/arsenal/narratives/NarrativeEditionOverview.js
    skipped 28 lines
    29 29   convertCreatedBy,
    30 30   convertMarkings,
    31 31   convertStatus,
    32  -} from '../../../../utils/Edition';
     32 +} from '../../../../utils/edition';
    33 33   
    34 34  const styles = (theme) => ({
    35 35   drawerPaper: {
    skipped 362 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolEditionOverview.js
    skipped 29 lines
    30 30   convertCreatedBy,
    31 31   convertMarkings,
    32 32   convertStatus,
    33  -} from '../../../../utils/Edition';
     33 +} from '../../../../utils/edition';
    34 34   
    35 35  const styles = (theme) => ({
    36 36   drawerPaper: {
    skipped 436 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/arsenal/vulnerabilities/VulnerabilityEditionOverview.js
    skipped 29 lines
    30 30   convertCreatedBy,
    31 31   convertMarkings,
    32 32   convertStatus,
    33  -} from '../../../../utils/Edition';
     33 +} from '../../../../utils/edition';
    34 34  import { fieldSpacingContainerStyle } from '../../../../utils/field';
    35 35   
    36 36  const styles = (theme) => ({
    skipped 383 lines
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/common/form/ArtifactField.tsx
    skipped 32 lines
    33 33   .filter((f) => Boolean(f)) as StixCyberObservablesFiltering[];
    34 34   const data = useLazyLoadQuery<ArtifactFieldGetQuery>(artifactQuery, { filters });
    35 35   
    36  - const options = (data.stixCyberObservables?.edges ?? []).map((node) => ({
    37  - label: node?.node.observable_value ?? node?.node.id,
    38  - value: node?.node.id,
     36 + const options = (data.stixCyberObservables?.edges ?? []).map(({ node }) => ({
     37 + label: node.observable_value ?? node.id,
     38 + value: node.id,
    39 39   }));
    40 40   return (
    41 41   <ReferenceField
    skipped 13 lines
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/common/form/ReferenceField.tsx
    skipped 18 lines
    19 19  }));
    20 20   
    21 21  export interface Option {
    22  - value: unknown
    23  - label?: string
     22 + value: string
     23 + label: string
    24 24   color?: string
    25 25  }
    26 26   
    skipped 57 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/common/stix_core_relationships/StixCoreRelationshipCreationFromEntity.js
    skipped 54 lines
    55 55  import StixCyberObservableCreation from '../../observations/stix_cyber_observables/StixCyberObservableCreation';
    56 56  import ExternalReferencesField from '../form/ExternalReferencesField';
    57 57  import { defaultValue } from '../../../../utils/Graph';
    58  -import { isNodeInConnection } from '../../../../utils/Store';
     58 +import { isNodeInConnection } from '../../../../utils/store';
    59 59  import DateTimePickerField from '../../../../components/DateTimePickerField';
    60 60  import { fieldSpacingContainerStyle } from '../../../../utils/field';
    61 61   
    skipped 938 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/common/stix_core_relationships/StixCoreRelationshipEditionOverview.js
    skipped 32 lines
    33 33   convertCreatedBy,
    34 34   convertMarkings,
    35 35   convertStatus,
    36  -} from '../../../../utils/Edition';
     36 +} from '../../../../utils/edition';
    37 37  import StatusField from '../form/StatusField';
    38 38  import DateTimePickerField from '../../../../components/DateTimePickerField';
    39 39   
    skipped 593 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/common/stix_domain_objects/StixDomainObjectBookmark.js
    skipped 14 lines
    15 15  import inject18n from '../../../../components/i18n';
    16 16  import { resolveLink } from '../../../../utils/Entity';
    17 17  import { commitMutation } from '../../../../relay/environment';
    18  -import { deleteNode, insertNode } from '../../../../utils/Store';
     18 +import { deleteNode, insertNode } from '../../../../utils/store';
    19 19  import ItemIcon from '../../../../components/ItemIcon';
    20 20   
    21 21  const stixDomainObjectBookmarkCreateMutation = graphql`
    skipped 338 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/common/stix_domain_objects/StixDomainObjectHeader.js
    skipped 297 lines
    298 298   </Tooltip>
    299 299   <Security needs={[KNOWLEDGE_KNUPDATE]}>
    300 300   <div className={classes.popover}>
    301  - {React.cloneElement(PopoverComponent, {
     301 + {/* TODO remove this when all components are pure function without compose() */}
     302 + {!React.isValidElement(PopoverComponent) ? (
     303 + <PopoverComponent disabled={disablePopover} id={stixDomainObject.id} />
     304 + ) : React.cloneElement(PopoverComponent, {
    302 305   id: stixDomainObject.id,
    303 306   disabled: disablePopover,
    304 307   })}
    skipped 360 lines
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/cities/City.js
    1  -import React, { Component } from 'react';
    2  -import PropTypes from 'prop-types';
    3  -import { compose } from 'ramda';
    4  -import { graphql, createFragmentContainer } from 'react-relay';
    5  -import withStyles from '@mui/styles/withStyles';
    6  -import Grid from '@mui/material/Grid';
    7  -import inject18n from '../../../../components/i18n';
    8  -import CityEdition from './CityEdition';
    9  -import CityPopover from './CityPopover';
    10  -import StixCoreObjectOrStixCoreRelationshipLastReports from '../../analysis/reports/StixCoreObjectOrStixCoreRelationshipLastReports';
    11  -import StixDomainObjectHeader from '../../common/stix_domain_objects/StixDomainObjectHeader';
    12  -import Security, { KNOWLEDGE_KNUPDATE } from '../../../../utils/Security';
    13  -import StixCoreObjectOrStixCoreRelationshipNotes from '../../analysis/notes/StixCoreObjectOrStixCoreRelationshipNotes';
    14  -import StixDomainObjectOverview from '../../common/stix_domain_objects/StixDomainObjectOverview';
    15  -import StixCoreObjectExternalReferences from '../../analysis/external_references/StixCoreObjectExternalReferences';
    16  -import StixCoreObjectLatestHistory from '../../common/stix_core_objects/StixCoreObjectLatestHistory';
    17  -import SimpleStixObjectOrStixRelationshipStixCoreRelationships from '../../common/stix_core_relationships/SimpleStixObjectOrStixRelationshipStixCoreRelationships';
    18  -import LocationMiniMap from '../../common/location/LocationMiniMap';
    19  - 
    20  -const styles = () => ({
    21  - container: {
    22  - margin: 0,
    23  - },
    24  - gridContainer: {
    25  - marginBottom: 20,
    26  - },
    27  -});
    28  - 
    29  -class CityComponent extends Component {
    30  - render() {
    31  - const { classes, city } = this.props;
    32  - return (
    33  - <div className={classes.container}>
    34  - <StixDomainObjectHeader
    35  - disableSharing={true}
    36  - stixDomainObject={city}
    37  - isOpenctiAlias={true}
    38  - PopoverComponent={<CityPopover />}
    39  - />
    40  - <Grid
    41  - container={true}
    42  - spacing={3}
    43  - classes={{ container: classes.gridContainer }}
    44  - >
    45  - <Grid item={true} xs={6} style={{ paddingTop: 10 }}>
    46  - <StixDomainObjectOverview stixDomainObject={city} />
    47  - </Grid>
    48  - <Grid item={true} xs={6} style={{ paddingTop: 10 }}>
    49  - <LocationMiniMap
    50  - center={
    51  - city.latitude && city.longitude
    52  - ? [city.latitude, city.longitude]
    53  - : [48.8566969, 2.3514616]
    54  - }
    55  - city={city}
    56  - zoom={5}
    57  - />
    58  - </Grid>
    59  - </Grid>
    60  - <Grid
    61  - container={true}
    62  - spacing={3}
    63  - classes={{ container: classes.gridContainer }}
    64  - style={{ marginTop: 25 }}
    65  - >
    66  - <Grid item={true} xs={6}>
    67  - <SimpleStixObjectOrStixRelationshipStixCoreRelationships
    68  - stixObjectOrStixRelationshipId={city.id}
    69  - stixObjectOrStixRelationshipLink={`/dashboard/entities/cities/${city.id}/knowledge`}
    70  - />
    71  - </Grid>
    72  - <Grid item={true} xs={6}>
    73  - <StixCoreObjectOrStixCoreRelationshipLastReports
    74  - stixCoreObjectOrStixCoreRelationshipId={city.id}
    75  - />
    76  - </Grid>
    77  - </Grid>
    78  - <Grid
    79  - container={true}
    80  - spacing={3}
    81  - classes={{ container: classes.gridContainer }}
    82  - style={{ marginTop: 25 }}
    83  - >
    84  - <Grid item={true} xs={6}>
    85  - <StixCoreObjectExternalReferences stixCoreObjectId={city.id} />
    86  - </Grid>
    87  - <Grid item={true} xs={6}>
    88  - <StixCoreObjectLatestHistory stixCoreObjectId={city.id} />
    89  - </Grid>
    90  - </Grid>
    91  - <StixCoreObjectOrStixCoreRelationshipNotes
    92  - stixCoreObjectOrStixCoreRelationshipId={city.id}
    93  - />
    94  - <Security needs={[KNOWLEDGE_KNUPDATE]}>
    95  - <CityEdition cityId={city.id} />
    96  - </Security>
    97  - </div>
    98  - );
    99  - }
    100  -}
    101  - 
    102  -CityComponent.propTypes = {
    103  - city: PropTypes.object,
    104  - classes: PropTypes.object,
    105  - t: PropTypes.func,
    106  -};
    107  - 
    108  -const City = createFragmentContainer(CityComponent, {
    109  - city: graphql`
    110  - fragment City_city on City {
    111  - id
    112  - standard_id
    113  - x_opencti_stix_ids
    114  - spec_version
    115  - revoked
    116  - confidence
    117  - created
    118  - modified
    119  - created_at
    120  - updated_at
    121  - createdBy {
    122  - ... on Identity {
    123  - id
    124  - name
    125  - entity_type
    126  - }
    127  - }
    128  - creator {
    129  - id
    130  - name
    131  - }
    132  - objectMarking {
    133  - edges {
    134  - node {
    135  - id
    136  - definition
    137  - x_opencti_color
    138  - }
    139  - }
    140  - }
    141  - objectLabel {
    142  - edges {
    143  - node {
    144  - id
    145  - value
    146  - color
    147  - }
    148  - }
    149  - }
    150  - name
    151  - latitude
    152  - longitude
    153  - x_opencti_aliases
    154  - status {
    155  - id
    156  - order
    157  - template {
    158  - name
    159  - color
    160  - }
    161  - }
    162  - workflowEnabled
    163  - }
    164  - `,
    165  -});
    166  - 
    167  -export default compose(inject18n, withStyles(styles))(City);
    168  - 
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/cities/City.tsx
     1 +import React from 'react';
     2 +import { graphql, useFragment } from 'react-relay';
     3 +import Grid from '@mui/material/Grid';
     4 +import makeStyles from '@mui/styles/makeStyles';
     5 +import CityEdition from './CityEdition';
     6 +import CityPopover from './CityPopover';
     7 +import StixCoreObjectOrStixCoreRelationshipLastReports
     8 + from '../../analysis/reports/StixCoreObjectOrStixCoreRelationshipLastReports';
     9 +import StixDomainObjectHeader from '../../common/stix_domain_objects/StixDomainObjectHeader';
     10 +import Security, { KNOWLEDGE_KNUPDATE } from '../../../../utils/Security';
     11 +import StixCoreObjectOrStixCoreRelationshipNotes from '../../analysis/notes/StixCoreObjectOrStixCoreRelationshipNotes';
     12 +import StixDomainObjectOverview from '../../common/stix_domain_objects/StixDomainObjectOverview';
     13 +import StixCoreObjectExternalReferences from '../../analysis/external_references/StixCoreObjectExternalReferences';
     14 +import StixCoreObjectLatestHistory from '../../common/stix_core_objects/StixCoreObjectLatestHistory';
     15 +import SimpleStixObjectOrStixRelationshipStixCoreRelationships
     16 + from '../../common/stix_core_relationships/SimpleStixObjectOrStixRelationshipStixCoreRelationships';
     17 +import LocationMiniMap from '../../common/location/LocationMiniMap';
     18 +import { City_city$key } from './__generated__/City_city.graphql';
     19 + 
     20 +const useStyles = makeStyles(() => ({
     21 + container: {
     22 + margin: 0,
     23 + },
     24 + gridContainer: {
     25 + marginBottom: 20,
     26 + },
     27 +}));
     28 + 
     29 +const cityFragment = graphql`
     30 + fragment City_city on City {
     31 + id
     32 + standard_id
     33 + x_opencti_stix_ids
     34 + spec_version
     35 + revoked
     36 + confidence
     37 + created
     38 + modified
     39 + created_at
     40 + updated_at
     41 + createdBy {
     42 + ... on Identity {
     43 + id
     44 + name
     45 + entity_type
     46 + }
     47 + }
     48 + creator {
     49 + id
     50 + name
     51 + }
     52 + objectMarking {
     53 + edges {
     54 + node {
     55 + id
     56 + definition
     57 + x_opencti_color
     58 + }
     59 + }
     60 + }
     61 + objectLabel {
     62 + edges {
     63 + node {
     64 + id
     65 + value
     66 + color
     67 + }
     68 + }
     69 + }
     70 + name
     71 + latitude
     72 + longitude
     73 + x_opencti_aliases
     74 + status {
     75 + id
     76 + order
     77 + template {
     78 + name
     79 + color
     80 + }
     81 + }
     82 + workflowEnabled
     83 + }
     84 +`;
     85 + 
     86 +const City = ({ cityData }: { cityData: City_city$key }) => {
     87 + const classes = useStyles();
     88 + 
     89 + const city = useFragment<City_city$key>(cityFragment, cityData);
     90 + 
     91 + return (
     92 + <div className={classes.container}>
     93 + <StixDomainObjectHeader
     94 + disableSharing={true}
     95 + stixDomainObject={city}
     96 + isOpenctiAlias={true}
     97 + PopoverComponent={CityPopover}
     98 + />
     99 + <Grid
     100 + container={true}
     101 + spacing={3}
     102 + classes={{ container: classes.gridContainer }}
     103 + >
     104 + <Grid item={true} xs={6} style={{ paddingTop: 10 }}>
     105 + <StixDomainObjectOverview stixDomainObject={city} />
     106 + </Grid>
     107 + <Grid item={true} xs={6} style={{ paddingTop: 10 }}>
     108 + <LocationMiniMap
     109 + center={
     110 + city.latitude && city.longitude
     111 + ? [city.latitude, city.longitude]
     112 + : [48.8566969, 2.3514616]
     113 + }
     114 + city={city}
     115 + zoom={5}
     116 + />
     117 + </Grid>
     118 + </Grid>
     119 + <Grid
     120 + container={true}
     121 + spacing={3}
     122 + classes={{ container: classes.gridContainer }}
     123 + style={{ marginTop: 25 }}
     124 + >
     125 + <Grid item={true} xs={6}>
     126 + <SimpleStixObjectOrStixRelationshipStixCoreRelationships
     127 + stixObjectOrStixRelationshipId={city.id}
     128 + stixObjectOrStixRelationshipLink={`/dashboard/entities/cities/${city.id}/knowledge`}
     129 + />
     130 + </Grid>
     131 + <Grid item={true} xs={6}>
     132 + <StixCoreObjectOrStixCoreRelationshipLastReports
     133 + stixCoreObjectOrStixCoreRelationshipId={city.id}
     134 + />
     135 + </Grid>
     136 + </Grid>
     137 + <Grid
     138 + container={true}
     139 + spacing={3}
     140 + classes={{ container: classes.gridContainer }}
     141 + style={{ marginTop: 25 }}
     142 + >
     143 + <Grid item={true} xs={6}>
     144 + <StixCoreObjectExternalReferences stixCoreObjectId={city.id} />
     145 + </Grid>
     146 + <Grid item={true} xs={6}>
     147 + <StixCoreObjectLatestHistory stixCoreObjectId={city.id} />
     148 + </Grid>
     149 + </Grid>
     150 + <StixCoreObjectOrStixCoreRelationshipNotes
     151 + stixCoreObjectOrStixCoreRelationshipId={city.id}
     152 + />
     153 + <Security needs={[KNOWLEDGE_KNUPDATE]}>
     154 + <CityEdition cityId={city.id} />
     155 + </Security>
     156 + </div>
     157 + );
     158 +};
     159 + 
     160 +export default City;
     161 + 
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/cities/CityCreation.tsx
    skipped 7 lines
    8 8  import { Add, Close } from '@mui/icons-material';
    9 9  import * as Yup from 'yup';
    10 10  import { graphql, useMutation } from 'react-relay';
    11  -import * as R from 'ramda';
    12 11  import makeStyles from '@mui/styles/makeStyles';
    13 12  import { FormikConfig } from 'formik/dist/types';
    14  -import { Optionals } from 'yup/es/types';
    15 13  import { useFormatter } from '../../../../components/i18n';
    16 14  import TextField from '../../../../components/TextField';
    17 15  import CreatedByField from '../../common/form/CreatedByField';
    skipped 1 lines
    19 17  import MarkDownField from '../../../../components/MarkDownField';
    20 18  import ExternalReferencesField from '../../common/form/ExternalReferencesField';
    21 19  import { Theme } from '../../../../components/Theme';
    22  -import { insertNode } from '../../../../utils/Store';
     20 +import { insertNode } from '../../../../utils/store';
    23 21  import { CitiesLinesPaginationQuery$variables } from './__generated__/CitiesLinesPaginationQuery.graphql';
     22 +import { CityCreationMutation$variables } from './__generated__/CityCreationMutation.graphql';
    24 23   
    25 24  const useStyles = makeStyles<Theme>((theme) => ({
    26 25   drawerPaper: {
    skipped 58 lines
    85 84  });
    86 85   
    87 86  interface CityAddInput {
     87 + name: string,
     88 + description: string,
    88 89   latitude: string
    89 90   longitude: string
    90 91   createdBy?: { value: string, label?: string }
    skipped 1 lines
    92 93   externalReferences: { value: string }[]
    93 94  }
    94 95   
    95  -const CityCreation = ({ paginationOptions } : { paginationOptions: CitiesLinesPaginationQuery$variables }) => {
     96 +const CityCreation = ({ paginationOptions }: { paginationOptions: CitiesLinesPaginationQuery$variables }) => {
    96 97   const classes = useStyles();
    97 98   const { t } = useFormatter();
    98 99   
    skipped 4 lines
    103 104   const [commit] = useMutation(cityMutation);
    104 105   
    105 106   const onSubmit: FormikConfig<CityAddInput>['onSubmit'] = (values, { setSubmitting, resetForm }) => {
    106  - const finalValues = R.pipe(
    107  - R.assoc('latitude', parseFloat(values.latitude)),
    108  - R.assoc('longitude', parseFloat(values.longitude)),
    109  - R.assoc('createdBy', values.createdBy?.value),
    110  - R.assoc('objectMarking', R.pluck('value', values.objectMarking)),
    111  - R.assoc('externalReferences', R.pluck('value', values.externalReferences)),
    112  - )(values);
     107 + const finalValues: CityCreationMutation$variables['input'] = {
     108 + name: values.name,
     109 + latitude: parseFloat(values.latitude),
     110 + longitude: parseFloat(values.longitude),
     111 + objectMarking: values.objectMarking.map(({ value }) => value),
     112 + externalReferences: values.externalReferences.map(({ value }) => value),
     113 + createdBy: values.createdBy?.value,
     114 + };
    113 115   commit({
    114 116   variables: {
    115 117   input: finalValues,
    116 118   },
    117 119   updater: (store) => {
    118  - try {
    119  - console.log('paginationOptions', paginationOptions);
    120  - insertNode(store, 'Pagination_cities', {
    121  - filters: paginationOptions.filters,
    122  - orderBy: paginationOptions.orderBy,
    123  - orderMode: paginationOptions.orderMode,
    124  - search: paginationOptions.search,
    125  - }, 'cityAdd');
    126  - } catch (e) {
    127  - console.log('Error', e);
    128  - }
     120 + insertNode(store, 'Pagination_cities', paginationOptions, 'cityAdd');
    129 121   },
    130 122   onCompleted: () => {
    131 123   setSubmitting(false);
    skipped 34 lines
    166 158   <Typography variant="h6">{t('Create a city')}</Typography>
    167 159   </div>
    168 160   <div className={classes.container}>
    169  - <Formik
     161 + <Formik<CityAddInput>
    170 162   initialValues={{
    171 163   name: '',
    172 164   description: '',
    skipped 96 lines
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/cities/CityEdition.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 Fab from '@mui/material/Fab';
    7  -import { Edit } from '@mui/icons-material';
    8  -import { graphql } from 'react-relay';
    9  -import { commitMutation, QueryRenderer } from '../../../../relay/environment';
    10  -import inject18n from '../../../../components/i18n';
    11  -import CityEditionContainer from './CityEditionContainer';
    12  -import { cityEditionOverviewFocus } from './CityEditionOverview';
    13  -import Loader from '../../../../components/Loader';
    14  - 
    15  -const styles = (theme) => ({
    16  - editButton: {
    17  - position: 'fixed',
    18  - bottom: 30,
    19  - right: 30,
    20  - zIndex: 400,
    21  - },
    22  - drawerPaper: {
    23  - minHeight: '100vh',
    24  - width: '50%',
    25  - position: 'fixed',
    26  - overflow: 'auto',
    27  - transition: theme.transitions.create('width', {
    28  - easing: theme.transitions.easing.sharp,
    29  - duration: theme.transitions.duration.enteringScreen,
    30  - }),
    31  - padding: 0,
    32  - },
    33  -});
    34  - 
    35  -export const cityEditionQuery = graphql`
    36  - query CityEditionContainerQuery($id: String!) {
    37  - city(id: $id) {
    38  - ...CityEditionContainer_city
    39  - }
    40  - settings {
    41  - platform_enable_reference
    42  - }
    43  - }
    44  -`;
    45  - 
    46  -class CityEdition extends Component {
    47  - constructor(props) {
    48  - super(props);
    49  - this.state = { open: false };
    50  - }
    51  - 
    52  - handleOpen() {
    53  - this.setState({ open: true });
    54  - }
    55  - 
    56  - handleClose() {
    57  - commitMutation({
    58  - mutation: cityEditionOverviewFocus,
    59  - variables: {
    60  - id: this.props.cityId,
    61  - input: { focusOn: '' },
    62  - },
    63  - });
    64  - this.setState({ open: false });
    65  - }
    66  - 
    67  - render() {
    68  - const { classes, cityId } = this.props;
    69  - return (
    70  - <div>
    71  - <Fab
    72  - onClick={this.handleOpen.bind(this)}
    73  - color="secondary"
    74  - aria-label="Edit"
    75  - className={classes.editButton}
    76  - >
    77  - <Edit />
    78  - </Fab>
    79  - <Drawer
    80  - open={this.state.open}
    81  - anchor="right"
    82  - elevation={1}
    83  - sx={{ zIndex: 1202 }}
    84  - classes={{ paper: classes.drawerPaper }}
    85  - onClose={this.handleClose.bind(this)}
    86  - >
    87  - <QueryRenderer
    88  - query={cityEditionQuery}
    89  - variables={{ id: cityId }}
    90  - render={({ props }) => {
    91  - if (props) {
    92  - return (
    93  - <CityEditionContainer
    94  - city={props.city}
    95  - enableReferences={props.settings.platform_enable_reference?.includes(
    96  - 'City',
    97  - )}
    98  - handleClose={this.handleClose.bind(this)}
    99  - />
    100  - );
    101  - }
    102  - return <Loader variant="inElement" />;
    103  - }}
    104  - />
    105  - </Drawer>
    106  - </div>
    107  - );
    108  - }
    109  -}
    110  - 
    111  -CityEdition.propTypes = {
    112  - cityId: PropTypes.string,
    113  - classes: PropTypes.object,
    114  - theme: PropTypes.object,
    115  - t: PropTypes.func,
    116  -};
    117  - 
    118  -export default compose(
    119  - inject18n,
    120  - withStyles(styles, { withTheme: true }),
    121  -)(CityEdition);
    122  - 
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/cities/CityEdition.tsx
     1 +import React, { useState } from 'react';
     2 +import Drawer from '@mui/material/Drawer';
     3 +import Fab from '@mui/material/Fab';
     4 +import { Edit } from '@mui/icons-material';
     5 +import { useMutation } from 'react-relay';
     6 +import makeStyles from '@mui/styles/makeStyles';
     7 +import CityEditionContainer, { cityEditionQuery } from './CityEditionContainer';
     8 +import { cityEditionOverviewFocus } from './CityEditionOverview';
     9 +import Loader, { LoaderVariant } from '../../../../components/Loader';
     10 +import { Theme } from '../../../../components/Theme';
     11 +import useQueryLoading from '../../../../utils/hooks/useQueryLoading';
     12 +import { CityEditionContainerQuery } from './__generated__/CityEditionContainerQuery.graphql';
     13 + 
     14 +const useStyles = makeStyles<Theme>((theme) => ({
     15 + editButton: {
     16 + position: 'fixed',
     17 + bottom: 30,
     18 + right: 30,
     19 + zIndex: 400,
     20 + },
     21 + drawerPaper: {
     22 + minHeight: '100vh',
     23 + width: '50%',
     24 + position: 'fixed',
     25 + overflow: 'auto',
     26 + transition: theme.transitions.create('width', {
     27 + easing: theme.transitions.easing.sharp,
     28 + duration: theme.transitions.duration.enteringScreen,
     29 + }),
     30 + padding: 0,
     31 + },
     32 +}));
     33 + 
     34 +const CityEdition = ({ cityId }: { cityId: string }) => {
     35 + const classes = useStyles();
     36 + 
     37 + const [open, setOpen] = useState<boolean>(false);
     38 + const [commit] = useMutation(cityEditionOverviewFocus);
     39 + 
     40 + const handleOpen = () => setOpen(true);
     41 + const handleClose = () => {
     42 + commit({
     43 + variables: {
     44 + id: cityId,
     45 + input: { focusOn: '' },
     46 + },
     47 + });
     48 + setOpen(false);
     49 + };
     50 + 
     51 + const queryRef = useQueryLoading<CityEditionContainerQuery>(cityEditionQuery, { id: cityId });
     52 + 
     53 + return (
     54 + <div>
     55 + <Fab
     56 + onClick={handleOpen}
     57 + color="secondary"
     58 + aria-label="Edit"
     59 + className={classes.editButton}
     60 + >
     61 + <Edit />
     62 + </Fab>
     63 + <Drawer
     64 + open={open}
     65 + anchor="right"
     66 + elevation={1}
     67 + sx={{ zIndex: 1202 }}
     68 + classes={{ paper: classes.drawerPaper }}
     69 + onClose={handleClose}
     70 + >
     71 + {queryRef && (
     72 + <React.Suspense fallback={<Loader variant={LoaderVariant.inElement} />}>
     73 + <CityEditionContainer
     74 + queryRef={queryRef}
     75 + handleClose={handleClose}
     76 + />
     77 + </React.Suspense>
     78 + )}
     79 + </Drawer>
     80 + </div>
     81 + );
     82 +};
     83 + 
     84 +export default CityEdition;
     85 + 
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/cities/CityEditionContainer.js
    1  -import React, { Component } from 'react';
    2  -import PropTypes from 'prop-types';
    3  -import { graphql, createFragmentContainer } from 'react-relay';
    4  -import { compose } from 'ramda';
    5  -import withStyles from '@mui/styles/withStyles';
    6  -import Typography from '@mui/material/Typography';
    7  -import IconButton from '@mui/material/IconButton';
    8  -import { Close } from '@mui/icons-material';
    9  -import inject18n from '../../../../components/i18n';
    10  -import { SubscriptionAvatars } from '../../../../components/Subscription';
    11  -import CityEditionOverview from './CityEditionOverview';
    12  - 
    13  -const styles = (theme) => ({
    14  - header: {
    15  - backgroundColor: theme.palette.background.nav,
    16  - padding: '20px 20px 20px 60px',
    17  - },
    18  - closeButton: {
    19  - position: 'absolute',
    20  - top: 12,
    21  - left: 5,
    22  - color: 'inherit',
    23  - },
    24  - importButton: {
    25  - position: 'absolute',
    26  - top: 15,
    27  - right: 20,
    28  - },
    29  - container: {
    30  - padding: '10px 20px 20px 20px',
    31  - },
    32  - appBar: {
    33  - width: '100%',
    34  - zIndex: theme.zIndex.drawer + 1,
    35  - borderBottom: '1px solid #5c5c5c',
    36  - },
    37  - title: {
    38  - float: 'left',
    39  - },
    40  -});
    41  - 
    42  -class CityEditionContainer extends Component {
    43  - render() {
    44  - const { t, classes, handleClose, city } = this.props;
    45  - const { editContext } = city;
    46  - return (
    47  - <div>
    48  - <div className={classes.header}>
    49  - <IconButton
    50  - aria-label="Close"
    51  - className={classes.closeButton}
    52  - onClick={handleClose.bind(this)}
    53  - size="large"
    54  - color="primary"
    55  - >
    56  - <Close fontSize="small" color="primary" />
    57  - </IconButton>
    58  - <Typography variant="h6" classes={{ root: classes.title }}>
    59  - {t('Update a city')}
    60  - </Typography>
    61  - <SubscriptionAvatars context={editContext} />
    62  - <div className="clearfix" />
    63  - </div>
    64  - <div className={classes.container}>
    65  - <CityEditionOverview
    66  - city={this.props.city}
    67  - enableReferences={this.props.enableReferences}
    68  - context={editContext}
    69  - handleClose={handleClose.bind(this)}
    70  - />
    71  - </div>
    72  - </div>
    73  - );
    74  - }
    75  -}
    76  - 
    77  -CityEditionContainer.propTypes = {
    78  - handleClose: PropTypes.func,
    79  - classes: PropTypes.object,
    80  - city: PropTypes.object,
    81  - theme: PropTypes.object,
    82  - t: PropTypes.func,
    83  -};
    84  - 
    85  -const CityEditionFragment = createFragmentContainer(CityEditionContainer, {
    86  - city: graphql`
    87  - fragment CityEditionContainer_city on City {
    88  - id
    89  - ...CityEditionOverview_city
    90  - editContext {
    91  - name
    92  - focusOn
    93  - }
    94  - }
    95  - `,
    96  -});
    97  - 
    98  -export default compose(
    99  - inject18n,
    100  - withStyles(styles, { withTheme: true }),
    101  -)(CityEditionFragment);
    102  - 
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/cities/CityEditionContainer.tsx
     1 +import React, { FunctionComponent } from 'react';
     2 +import { graphql, PreloadedQuery, usePreloadedQuery } from 'react-relay';
     3 +import Typography from '@mui/material/Typography';
     4 +import IconButton from '@mui/material/IconButton';
     5 +import { Close } from '@mui/icons-material';
     6 +import makeStyles from '@mui/styles/makeStyles';
     7 +import { SubscriptionAvatars } from '../../../../components/Subscription';
     8 +import CityEditionOverview from './CityEditionOverview';
     9 +import { Theme } from '../../../../components/Theme';
     10 +import { useFormatter } from '../../../../components/i18n';
     11 +import { CityEditionContainerQuery } from './__generated__/CityEditionContainerQuery.graphql';
     12 +import ErrorNotFound from '../../../../components/ErrorNotFound';
     13 + 
     14 +const useStyles = makeStyles<Theme>((theme) => ({
     15 + header: {
     16 + backgroundColor: theme.palette.background.nav,
     17 + padding: '20px 20px 20px 60px',
     18 + },
     19 + closeButton: {
     20 + position: 'absolute',
     21 + top: 12,
     22 + left: 5,
     23 + color: 'inherit',
     24 + },
     25 + importButton: {
     26 + position: 'absolute',
     27 + top: 15,
     28 + right: 20,
     29 + },
     30 + container: {
     31 + padding: '10px 20px 20px 20px',
     32 + },
     33 + appBar: {
     34 + width: '100%',
     35 + zIndex: theme.zIndex.drawer + 1,
     36 + borderBottom: '1px solid #5c5c5c',
     37 + },
     38 + title: {
     39 + float: 'left',
     40 + },
     41 +}));
     42 + 
     43 +interface CityEditionContainerProps {
     44 + queryRef: PreloadedQuery<CityEditionContainerQuery>
     45 + handleClose: () => void,
     46 +}
     47 + 
     48 +export const cityEditionQuery = graphql`
     49 + query CityEditionContainerQuery($id: String!) {
     50 + city(id: $id) {
     51 + ...CityEditionOverview_city
     52 + editContext {
     53 + name
     54 + focusOn
     55 + }
     56 + }
     57 + settings {
     58 + platform_enable_reference
     59 + }
     60 + }
     61 +`;
     62 +const CityEditionContainer: FunctionComponent<CityEditionContainerProps> = ({ queryRef, handleClose }) => {
     63 + const classes = useStyles();
     64 + const { t } = useFormatter();
     65 + 
     66 + const queryData = usePreloadedQuery(cityEditionQuery, queryRef);
     67 + 
     68 + if (queryData.city === null) {
     69 + return (<ErrorNotFound />);
     70 + }
     71 + return (
     72 + <div>
     73 + <div className={classes.header}>
     74 + <IconButton
     75 + aria-label="Close"
     76 + className={classes.closeButton}
     77 + onClick={handleClose}
     78 + size="large"
     79 + color="primary"
     80 + >
     81 + <Close fontSize="small" color="primary" />
     82 + </IconButton>
     83 + <Typography variant="h6" classes={{ root: classes.title }}>
     84 + {t('Update a city')}
     85 + </Typography>
     86 + <SubscriptionAvatars context={queryData.city.editContext} />
     87 + <div className="clearfix" />
     88 + </div>
     89 + <div className={classes.container}>
     90 + <CityEditionOverview
     91 + cityRef={queryData.city}
     92 + enableReferences={queryData.settings.platform_enable_reference?.includes('City')}
     93 + context={queryData.city.editContext}
     94 + handleClose={handleClose}
     95 + />
     96 + </div>
     97 + </div>
     98 + );
     99 +};
     100 + 
     101 +export default CityEditionContainer;
     102 + 
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/cities/CityEditionOverview.js
    1  -import React, { Component } from 'react';
    2  -import * as PropTypes from 'prop-types';
    3  -import { graphql, createFragmentContainer } from 'react-relay';
    4  -import { Formik, Form, Field } from 'formik';
    5  -import withStyles from '@mui/styles/withStyles';
    6  -import * as Yup from 'yup';
    7  -import * as R from 'ramda';
    8  -import inject18n from '../../../../components/i18n';
    9  -import TextField from '../../../../components/TextField';
    10  -import { SubscriptionFocus } from '../../../../components/Subscription';
    11  -import { commitMutation } from '../../../../relay/environment';
    12  -import CreatedByField from '../../common/form/CreatedByField';
    13  -import ObjectMarkingField from '../../common/form/ObjectMarkingField';
    14  -import MarkDownField from '../../../../components/MarkDownField';
    15  -import CommitMessage from '../../common/form/CommitMessage';
    16  -import { adaptFieldValue } from '../../../../utils/String';
    17  -import StatusField from '../../common/form/StatusField';
    18  -import {
    19  - convertCreatedBy,
    20  - convertMarkings,
    21  - convertStatus,
    22  -} from '../../../../utils/Edition';
    23  - 
    24  -const styles = (theme) => ({
    25  - drawerPaper: {
    26  - minHeight: '100vh',
    27  - width: '50%',
    28  - position: 'fixed',
    29  - overflow: 'hidden',
    30  - 
    31  - transition: theme.transitions.create('width', {
    32  - easing: theme.transitions.easing.sharp,
    33  - duration: theme.transitions.duration.enteringScreen,
    34  - }),
    35  - padding: '30px 30px 30px 30px',
    36  - },
    37  - createButton: {
    38  - position: 'fixed',
    39  - bottom: 30,
    40  - right: 30,
    41  - },
    42  - importButton: {
    43  - position: 'absolute',
    44  - top: 30,
    45  - right: 30,
    46  - },
    47  -});
    48  - 
    49  -const cityMutationFieldPatch = graphql`
    50  - mutation CityEditionOverviewFieldPatchMutation(
    51  - $id: ID!
    52  - $input: [EditInput]!
    53  - $commitMessage: String
    54  - $references: [String]
    55  - ) {
    56  - cityEdit(id: $id) {
    57  - fieldPatch(
    58  - input: $input
    59  - commitMessage: $commitMessage
    60  - references: $references
    61  - ) {
    62  - ...CityEditionOverview_city
    63  - ...City_city
    64  - }
    65  - }
    66  - }
    67  -`;
    68  - 
    69  -export const cityEditionOverviewFocus = graphql`
    70  - mutation CityEditionOverviewFocusMutation($id: ID!, $input: EditContext!) {
    71  - cityEdit(id: $id) {
    72  - contextPatch(input: $input) {
    73  - id
    74  - }
    75  - }
    76  - }
    77  -`;
    78  - 
    79  -const cityMutationRelationAdd = graphql`
    80  - mutation CityEditionOverviewRelationAddMutation(
    81  - $id: ID!
    82  - $input: StixMetaRelationshipAddInput!
    83  - ) {
    84  - cityEdit(id: $id) {
    85  - relationAdd(input: $input) {
    86  - from {
    87  - ...CityEditionOverview_city
    88  - }
    89  - }
    90  - }
    91  - }
    92  -`;
    93  - 
    94  -const cityMutationRelationDelete = graphql`
    95  - mutation CityEditionOverviewRelationDeleteMutation(
    96  - $id: ID!
    97  - $toId: StixRef!
    98  - $relationship_type: String!
    99  - ) {
    100  - cityEdit(id: $id) {
    101  - relationDelete(toId: $toId, relationship_type: $relationship_type) {
    102  - ...CityEditionOverview_city
    103  - }
    104  - }
    105  - }
    106  -`;
    107  - 
    108  -const cityValidation = (t) => Yup.object().shape({
    109  - name: Yup.string().required(t('This field is required')),
    110  - description: Yup.string()
    111  - .min(3, t('The value is too short'))
    112  - .max(5000, t('The value is too long'))
    113  - .required(t('This field is required')),
    114  - latitude: Yup.number().typeError(t('This field must be a number')),
    115  - longitude: Yup.number().typeError(t('This field must be a number')),
    116  - x_opencti_workflow_id: Yup.object(),
    117  -});
    118  - 
    119  -class CityEditionOverviewComponent extends Component {
    120  - handleChangeFocus(name) {
    121  - commitMutation({
    122  - mutation: cityEditionOverviewFocus,
    123  - variables: {
    124  - id: this.props.city.id,
    125  - input: {
    126  - focusOn: name,
    127  - },
    128  - },
    129  - });
    130  - }
    131  - 
    132  - onSubmit(values, { setSubmitting }) {
    133  - const commitMessage = values.message;
    134  - const references = R.pluck('value', values.references || []);
    135  - const inputValues = R.pipe(
    136  - R.dissoc('message'),
    137  - R.dissoc('references'),
    138  - R.assoc('x_opencti_workflow_id', values.x_opencti_workflow_id?.value),
    139  - R.assoc('createdBy', values.createdBy?.value),
    140  - R.assoc('objectMarking', R.pluck('value', values.objectMarking)),
    141  - R.toPairs,
    142  - R.map((n) => ({
    143  - key: n[0],
    144  - value: adaptFieldValue(n[1]),
    145  - })),
    146  - )(values);
    147  - commitMutation({
    148  - mutation: cityMutationFieldPatch,
    149  - variables: {
    150  - id: this.props.city.id,
    151  - input: inputValues,
    152  - commitMessage:
    153  - commitMessage && commitMessage.length > 0 ? commitMessage : null,
    154  - references,
    155  - },
    156  - setSubmitting,
    157  - onCompleted: () => {
    158  - setSubmitting(false);
    159  - this.props.handleClose();
    160  - },
    161  - });
    162  - }
    163  - 
    164  - handleSubmitField(name, value) {
    165  - if (!this.props.enableReferences) {
    166  - let finalValue = value;
    167  - if (name === 'x_opencti_workflow_id') {
    168  - finalValue = value.value;
    169  - }
    170  - cityValidation(this.props.t)
    171  - .validateAt(name, { [name]: value })
    172  - .then(() => {
    173  - commitMutation({
    174  - mutation: cityMutationFieldPatch,
    175  - variables: {
    176  - id: this.props.city.id,
    177  - input: { key: name, value: finalValue ?? '' },
    178  - },
    179  - });
    180  - })
    181  - .catch(() => false);
    182  - }
    183  - }
    184  - 
    185  - handleChangeCreatedBy(name, value) {
    186  - if (!this.props.enableReferences) {
    187  - commitMutation({
    188  - mutation: cityMutationRelationAdd,
    189  - variables: {
    190  - id: this.props.city.id,
    191  - input: { key: 'createdBy', value: value.value || '' },
    192  - },
    193  - });
    194  - }
    195  - }
    196  - 
    197  - handleChangeObjectMarking(name, values) {
    198  - if (!this.props.enableReferences) {
    199  - const { city } = this.props;
    200  - const currentMarkingDefinitions = R.pipe(
    201  - R.pathOr([], ['objectMarking', 'edges']),
    202  - R.map((n) => ({
    203  - label: n.node.definition,
    204  - value: n.node.id,
    205  - })),
    206  - )(city);
    207  - const added = R.difference(values, currentMarkingDefinitions);
    208  - const removed = R.difference(currentMarkingDefinitions, values);
    209  - if (added.length > 0) {
    210  - commitMutation({
    211  - mutation: cityMutationRelationAdd,
    212  - variables: {
    213  - id: this.props.city.id,
    214  - input: {
    215  - toId: R.head(added).value,
    216  - relationship_type: 'object-marking',
    217  - },
    218  - },
    219  - });
    220  - }
    221  - if (removed.length > 0) {
    222  - commitMutation({
    223  - mutation: cityMutationRelationDelete,
    224  - variables: {
    225  - id: this.props.city.id,
    226  - toId: R.head(removed).value,
    227  - relationship_type: 'object-marking',
    228  - },
    229  - });
    230  - }
    231  - }
    232  - }
    233  - 
    234  - render() {
    235  - const { t, city, context, enableReferences } = this.props;
    236  - const createdBy = convertCreatedBy(city);
    237  - const objectMarking = convertMarkings(city);
    238  - const status = convertStatus(t, city);
    239  - const initialValues = R.pipe(
    240  - R.assoc('createdBy', createdBy),
    241  - R.assoc('objectMarking', objectMarking),
    242  - R.assoc('x_opencti_workflow_id', status),
    243  - R.pick([
    244  - 'name',
    245  - 'description',
    246  - 'latitude',
    247  - 'longitude',
    248  - 'createdBy',
    249  - 'objectMarking',
    250  - 'x_opencti_workflow_id',
    251  - ]),
    252  - )(city);
    253  - return (
    254  - <Formik
    255  - enableReinitialize={true}
    256  - initialValues={initialValues}
    257  - validationSchema={cityValidation(t)}
    258  - onSubmit={this.onSubmit.bind(this)}
    259  - >
    260  - {({
    261  - submitForm,
    262  - isSubmitting,
    263  - validateForm,
    264  - setFieldValue,
    265  - values,
    266  - }) => (
    267  - <Form style={{ margin: '20px 0 20px 0' }}>
    268  - <Field
    269  - component={TextField}
    270  - variant="standard"
    271  - name="name"
    272  - label={t('Name')}
    273  - fullWidth={true}
    274  - onFocus={this.handleChangeFocus.bind(this)}
    275  - onSubmit={this.handleSubmitField.bind(this)}
    276  - helperText={
    277  - <SubscriptionFocus context={context} fieldName="name" />
    278  - }
    279  - />
    280  - <Field
    281  - component={MarkDownField}
    282  - name="description"
    283  - label={t('Description')}
    284  - fullWidth={true}
    285  - multiline={true}
    286  - rows="4"
    287  - style={{ marginTop: 20 }}
    288  - onFocus={this.handleChangeFocus.bind(this)}
    289  - onSubmit={this.handleSubmitField.bind(this)}
    290  - helperText={
    291  - <SubscriptionFocus context={context} fieldName="description" />
    292  - }
    293  - />
    294  - <Field
    295  - component={TextField}
    296  - variant="standard"
    297  - style={{ marginTop: 20 }}
    298  - name="latitude"
    299  - label={t('Latitude')}
    300  - fullWidth={true}
    301  - onFocus={this.handleChangeFocus.bind(this)}
    302  - onSubmit={this.handleSubmitField.bind(this)}
    303  - helperText={
    304  - <SubscriptionFocus context={context} fieldName="latitude" />
    305  - }
    306  - />
    307  - <Field
    308  - component={TextField}
    309  - variant="standard"
    310  - style={{ marginTop: 20 }}
    311  - name="longitude"
    312  - label={t('Longitude')}
    313  - fullWidth={true}
    314  - onFocus={this.handleChangeFocus.bind(this)}
    315  - onSubmit={this.handleSubmitField.bind(this)}
    316  - helperText={
    317  - <SubscriptionFocus context={context} fieldName="longitude" />
    318  - }
    319  - />
    320  - {city.workflowEnabled && (
    321  - <StatusField
    322  - name="x_opencti_workflow_id"
    323  - type="City"
    324  - onFocus={this.handleChangeFocus.bind(this)}
    325  - onChange={this.handleSubmitField.bind(this)}
    326  - setFieldValue={setFieldValue}
    327  - style={{ marginTop: 20 }}
    328  - helpertext={
    329  - <SubscriptionFocus
    330  - context={context}
    331  - fieldName="x_opencti_workflow_id"
    332  - />
    333  - }
    334  - />
    335  - )}
    336  - <CreatedByField
    337  - name="createdBy"
    338  - style={{ marginTop: 20, width: '100%' }}
    339  - setFieldValue={setFieldValue}
    340  - helpertext={
    341  - <SubscriptionFocus context={context} fieldName="createdBy" />
    342  - }
    343  - onChange={this.handleChangeCreatedBy.bind(this)}
    344  - />
    345  - <ObjectMarkingField
    346  - name="objectMarking"
    347  - style={{ marginTop: 20, width: '100%' }}
    348  - helpertext={
    349  - <SubscriptionFocus
    350  - context={context}
    351  - fieldname="objectMarking"
    352  - />
    353  - }
    354  - onChange={this.handleChangeObjectMarking.bind(this)}
    355  - />
    356  - {enableReferences && (
    357  - <CommitMessage
    358  - submitForm={submitForm}
    359  - disabled={isSubmitting}
    360  - validateForm={validateForm}
    361  - setFieldValue={setFieldValue}
    362  - values={values}
    363  - id={city.id}
    364  - />
    365  - )}
    366  - </Form>
    367  - )}
    368  - </Formik>
    369  - );
    370  - }
    371  -}
    372  - 
    373  -CityEditionOverviewComponent.propTypes = {
    374  - classes: PropTypes.object,
    375  - theme: PropTypes.object,
    376  - t: PropTypes.func,
    377  - city: PropTypes.object,
    378  - context: PropTypes.array,
    379  -};
    380  - 
    381  -const CityEditionOverview = createFragmentContainer(
    382  - CityEditionOverviewComponent,
    383  - {
    384  - city: graphql`
    385  - fragment CityEditionOverview_city on City {
    386  - id
    387  - name
    388  - description
    389  - latitude
    390  - longitude
    391  - createdBy {
    392  - ... on Identity {
    393  - id
    394  - name
    395  - entity_type
    396  - }
    397  - }
    398  - objectMarking {
    399  - edges {
    400  - node {
    401  - id
    402  - definition
    403  - definition_type
    404  - }
    405  - }
    406  - }
    407  - status {
    408  - id
    409  - order
    410  - template {
    411  - name
    412  - color
    413  - }
    414  - }
    415  - workflowEnabled
    416  - }
    417  - `,
    418  - },
    419  -);
    420  - 
    421  -export default R.compose(
    422  - inject18n,
    423  - withStyles(styles, { withTheme: true }),
    424  -)(CityEditionOverview);
    425  - 
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/cities/CityEditionOverview.tsx
     1 +import React, { FunctionComponent } from 'react';
     2 +import { graphql, useFragment, useMutation } from 'react-relay';
     3 +import { Field, Form, Formik } from 'formik';
     4 +import * as Yup from 'yup';
     5 +import * as R from 'ramda';
     6 +import { FormikConfig } from 'formik/dist/types';
     7 +import TextField from '../../../../components/TextField';
     8 +import { SubscriptionFocus } from '../../../../components/Subscription';
     9 +import CreatedByField from '../../common/form/CreatedByField';
     10 +import ObjectMarkingField from '../../common/form/ObjectMarkingField';
     11 +import MarkDownField from '../../../../components/MarkDownField';
     12 +import CommitMessage from '../../common/form/CommitMessage';
     13 +import { adaptFieldValue } from '../../../../utils/String';
     14 +import StatusField from '../../common/form/StatusField';
     15 +import { convertCreatedBy, convertMarkings, convertStatus } from '../../../../utils/edition';
     16 +import { useFormatter } from '../../../../components/i18n';
     17 +import { Option } from '../../common/form/ReferenceField';
     18 +import { CityEditionOverview_city$key } from './__generated__/CityEditionOverview_city.graphql';
     19 +import { CityAddInput } from './__generated__/CityCreationMutation.graphql';
     20 +import { CityEditionOverviewRelationAddMutation } from './__generated__/CityEditionOverviewRelationAddMutation.graphql';
     21 +import {
     22 + CityEditionOverviewRelationDeleteMutation,
     23 +} from './__generated__/CityEditionOverviewRelationDeleteMutation.graphql';
     24 +import { CityEditionOverviewFieldPatchMutation } from './__generated__/CityEditionOverviewFieldPatchMutation.graphql';
     25 +import { CityEditionOverviewFocusMutation } from './__generated__/CityEditionOverviewFocusMutation.graphql';
     26 + 
     27 +const cityMutationFieldPatch = graphql`
     28 + mutation CityEditionOverviewFieldPatchMutation(
     29 + $id: ID!
     30 + $input: [EditInput]!
     31 + $commitMessage: String
     32 + $references: [String]
     33 + ) {
     34 + cityEdit(id: $id) {
     35 + fieldPatch(
     36 + input: $input
     37 + commitMessage: $commitMessage
     38 + references: $references
     39 + ) {
     40 + ...CityEditionOverview_city
     41 + ...City_city
     42 + }
     43 + }
     44 + }
     45 +`;
     46 + 
     47 +export const cityEditionOverviewFocus = graphql`
     48 + mutation CityEditionOverviewFocusMutation($id: ID!, $input: EditContext!) {
     49 + cityEdit(id: $id) {
     50 + contextPatch(input: $input) {
     51 + id
     52 + }
     53 + }
     54 + }
     55 +`;
     56 + 
     57 +const cityMutationRelationAdd = graphql`
     58 + mutation CityEditionOverviewRelationAddMutation(
     59 + $id: ID!
     60 + $input: StixMetaRelationshipAddInput!
     61 + ) {
     62 + cityEdit(id: $id) {
     63 + relationAdd(input: $input) {
     64 + from {
     65 + ...CityEditionOverview_city
     66 + }
     67 + }
     68 + }
     69 + }
     70 +`;
     71 + 
     72 +const cityMutationRelationDelete = graphql`
     73 + mutation CityEditionOverviewRelationDeleteMutation(
     74 + $id: ID!
     75 + $toId: StixRef!
     76 + $relationship_type: String!
     77 + ) {
     78 + cityEdit(id: $id) {
     79 + relationDelete(toId: $toId, relationship_type: $relationship_type) {
     80 + ...CityEditionOverview_city
     81 + }
     82 + }
     83 + }
     84 +`;
     85 + 
     86 +export const cityEditionOverviewFragment = graphql`
     87 + fragment CityEditionOverview_city on City {
     88 + id
     89 + name
     90 + description
     91 + latitude
     92 + longitude
     93 + createdBy {
     94 + ... on Identity {
     95 + id
     96 + name
     97 + entity_type
     98 + }
     99 + }
     100 + objectMarking {
     101 + edges {
     102 + node {
     103 + id
     104 + definition
     105 + definition_type
     106 + }
     107 + }
     108 + }
     109 + status {
     110 + id
     111 + order
     112 + template {
     113 + name
     114 + color
     115 + }
     116 + }
     117 + workflowEnabled
     118 + }
     119 +`;
     120 + 
     121 +const cityValidation = (t: (v: string) => string) => Yup.object().shape({
     122 + name: Yup.string().required(t('This field is required')),
     123 + description: Yup.string()
     124 + .min(3, t('The value is too short'))
     125 + .max(5000, t('The value is too long'))
     126 + .required(t('This field is required')),
     127 + latitude: Yup.number().typeError(t('This field must be a number')),
     128 + longitude: Yup.number().typeError(t('This field must be a number')),
     129 +});
     130 + 
     131 +interface CityEditionOverviewProps {
     132 + cityRef: CityEditionOverview_city$key,
     133 + context: ReadonlyArray<{
     134 + readonly focusOn: string | null;
     135 + readonly name: string;
     136 + } | null> | null
     137 + enableReferences?: boolean
     138 + handleClose: () => void
     139 +}
     140 + 
     141 +interface CityEditionFormValues {
     142 + message?: string
     143 + references?: Option[]
     144 + createdBy?: Option
     145 + objectMarking?: Option[]
     146 +}
     147 + 
     148 +const CityEditionOverview: FunctionComponent<CityEditionOverviewProps> = ({ cityRef, context, enableReferences = false, handleClose }) => {
     149 + const { t } = useFormatter();
     150 + 
     151 + const city = useFragment(cityEditionOverviewFragment, cityRef);
     152 + 
     153 + const createdBy = convertCreatedBy(city);
     154 + const objectMarking = convertMarkings(city);
     155 + const status = convertStatus(t, city);
     156 + 
     157 + const [commitRelationAdd] = useMutation<CityEditionOverviewRelationAddMutation>(cityMutationRelationAdd);
     158 + const [commitRelationDelete] = useMutation<CityEditionOverviewRelationDeleteMutation>(cityMutationRelationDelete);
     159 + const [commitFieldPatch] = useMutation<CityEditionOverviewFieldPatchMutation>(cityMutationFieldPatch);
     160 + const [commitEditionFocus] = useMutation<CityEditionOverviewFocusMutation>(cityEditionOverviewFocus);
     161 + 
     162 + const handleChangeCreatedBy = (_: string, value: Option) => {
     163 + if (!enableReferences) {
     164 + commitFieldPatch({
     165 + variables: {
     166 + id: city.id,
     167 + input: [{ key: 'createdBy', value: [value.value] }],
     168 + },
     169 + });
     170 + }
     171 + };
     172 + const handleChangeObjectMarking = (_: string, values: Option[]) => {
     173 + if (!enableReferences) {
     174 + const currentMarkingDefinitions = (city.objectMarking?.edges ?? []).map(({ node }) => ({ label: node.definition, value: node.id }));
     175 + const added = R.difference(values, currentMarkingDefinitions).at(0);
     176 + const removed = R.difference(currentMarkingDefinitions, values).at(0);
     177 + if (added) {
     178 + commitRelationAdd({
     179 + variables: {
     180 + id: city.id,
     181 + input: {
     182 + toId: added.value,
     183 + relationship_type: 'object-marking',
     184 + },
     185 + },
     186 + });
     187 + }
     188 + if (removed) {
     189 + commitRelationDelete({
     190 + variables: {
     191 + id: city.id,
     192 + toId: removed.value,
     193 + relationship_type: 'object-marking',
     194 + },
     195 + });
     196 + }
     197 + }
     198 + };
     199 + 
     200 + const handleSubmitField = (name: keyof CityAddInput, value: Option | string) => {
     201 + if (!enableReferences) {
     202 + const finalValue: string = value as string;
     203 + cityValidation(t)
     204 + .validateAt(name, { [name]: value })
     205 + .then(() => {
     206 + commitFieldPatch({
     207 + variables: {
     208 + id: city.id,
     209 + input: [{ key: name, value: [finalValue ?? ''] }],
     210 + },
     211 + });
     212 + })
     213 + .catch(() => false);
     214 + }
     215 + };
     216 + 
     217 + const handleChangeFocus = (name: string) => {
     218 + commitEditionFocus({
     219 + variables: {
     220 + id: city.id,
     221 + input: {
     222 + focusOn: name,
     223 + },
     224 + },
     225 + });
     226 + };
     227 + 
     228 + const onSubmit: FormikConfig<CityEditionFormValues>['onSubmit'] = (values, { setSubmitting }) => {
     229 + const { message, references, ...otherValues } = values;
     230 + const commitMessage = message ?? '';
     231 + const commitReferences = (references ?? []).map(({ value }) => value);
     232 + 
     233 + const inputValues = Object.entries({
     234 + ...otherValues,
     235 + createdBy: values.createdBy?.value,
     236 + objectMarking: (values.objectMarking ?? []).map(({ value }) => value),
     237 + }).map(([key, value]) => ({ key, value: adaptFieldValue(value) }));
     238 + 
     239 + commitFieldPatch({
     240 + variables: {
     241 + id: city.id,
     242 + input: inputValues,
     243 + commitMessage: commitMessage.length > 0 ? commitMessage : null,
     244 + references: commitReferences,
     245 + },
     246 + onCompleted: () => {
     247 + setSubmitting(false);
     248 + handleClose();
     249 + },
     250 + });
     251 + };
     252 + 
     253 + const initialValues = {
     254 + name: city.name,
     255 + description: city.description,
     256 + latitude: city.latitude,
     257 + longitude: city.longitude,
     258 + createdBy,
     259 + objectMarking,
     260 + status,
     261 + };
     262 + 
     263 + return (
     264 + <Formik
     265 + enableReinitialize={true}
     266 + initialValues={initialValues}
     267 + validationSchema={cityValidation(t)}
     268 + onSubmit={onSubmit}
     269 + >
     270 + {({
     271 + submitForm,
     272 + isSubmitting,
     273 + validateForm,
     274 + setFieldValue,
     275 + values,
     276 + }) => (
     277 + <Form style={{ margin: '20px 0 20px 0' }}>
     278 + <Field
     279 + component={TextField}
     280 + variant="standard"
     281 + name="name"
     282 + label={t('Name')}
     283 + fullWidth={true}
     284 + onFocus={handleChangeFocus}
     285 + onSubmit={handleSubmitField}
     286 + helperText={
     287 + <SubscriptionFocus context={context} fieldName="name" />
     288 + }
     289 + />
     290 + <Field
     291 + component={MarkDownField}
     292 + name="description"
     293 + label={t('Description')}
     294 + fullWidth={true}
     295 + multiline={true}
     296 + rows="4"
     297 + style={{ marginTop: 20 }}
     298 + onFocus={handleChangeFocus}
     299 + onSubmit={handleSubmitField}
     300 + helperText={
     301 + <SubscriptionFocus context={context} fieldName="description" />
     302 + }
     303 + />
     304 + <Field
     305 + component={TextField}
     306 + variant="standard"
     307 + style={{ marginTop: 20 }}
     308 + name="latitude"
     309 + label={t('Latitude')}
     310 + fullWidth={true}
     311 + onFocus={handleChangeFocus}
     312 + onSubmit={handleSubmitField}
     313 + helperText={
     314 + <SubscriptionFocus context={context} fieldName="latitude" />
     315 + }
     316 + />
     317 + <Field
     318 + component={TextField}
     319 + variant="standard"
     320 + style={{ marginTop: 20 }}
     321 + name="longitude"
     322 + label={t('Longitude')}
     323 + fullWidth={true}
     324 + onFocus={handleChangeFocus}
     325 + onSubmit={handleSubmitField}
     326 + helperText={
     327 + <SubscriptionFocus context={context} fieldName="longitude" />
     328 + }
     329 + />
     330 + {city?.workflowEnabled && (
     331 + <StatusField
     332 + name="x_opencti_workflow_id"
     333 + type="City"
     334 + onFocus={handleChangeFocus}
     335 + onChange={handleSubmitField}
     336 + setFieldValue={setFieldValue}
     337 + style={{ marginTop: 20 }}
     338 + helpertext={
     339 + <SubscriptionFocus
     340 + context={context}
     341 + fieldName="x_opencti_workflow_id"
     342 + />
     343 + }
     344 + />
     345 + )}
     346 + <CreatedByField
     347 + name="createdBy"
     348 + style={{ marginTop: 20, width: '100%' }}
     349 + setFieldValue={setFieldValue}
     350 + helpertext={
     351 + <SubscriptionFocus context={context} fieldName="createdBy" />
     352 + }
     353 + onChange={handleChangeCreatedBy}
     354 + />
     355 + <ObjectMarkingField
     356 + name="objectMarking"
     357 + style={{ marginTop: 20, width: '100%' }}
     358 + helpertext={
     359 + <SubscriptionFocus
     360 + context={context}
     361 + fieldname="objectMarking"
     362 + />
     363 + }
     364 + onChange={handleChangeObjectMarking}
     365 + />
     366 + {enableReferences && (
     367 + <CommitMessage
     368 + submitForm={submitForm}
     369 + disabled={isSubmitting}
     370 + validateForm={validateForm}
     371 + setFieldValue={setFieldValue}
     372 + values={values}
     373 + id={city.id}
     374 + />
     375 + )}
     376 + </Form>
     377 + )}
     378 + </Formik>
     379 + );
     380 +};
     381 + 
     382 +export default CityEditionOverview;
     383 + 
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/cities/CityKnowledge.js
    1  -import React, { Component } from 'react';
    2  -import * as PropTypes from 'prop-types';
    3  -import { Route, Switch, withRouter } from 'react-router-dom';
    4  -import { compose } from 'ramda';
    5  -import { graphql, createFragmentContainer } from 'react-relay';
    6  -import withStyles from '@mui/styles/withStyles';
    7  -import inject18n from '../../../../components/i18n';
    8  -import EntityStixCoreRelationships from '../../common/stix_core_relationships/EntityStixCoreRelationships';
    9  -import StixDomainObjectKnowledge from '../../common/stix_domain_objects/StixDomainObjectKnowledge';
    10  -import StixCoreRelationship from '../../common/stix_core_relationships/StixCoreRelationship';
    11  -import CityPopover from './CityPopover';
    12  -import StixDomainObjectHeader from '../../common/stix_domain_objects/StixDomainObjectHeader';
    13  -import StixCoreObjectStixCyberObservables from '../../observations/stix_cyber_observables/StixCoreObjectStixCyberObservables';
    14  -import StixSightingRelationship from '../../events/stix_sighting_relationships/StixSightingRelationship';
    15  - 
    16  -const styles = () => ({
    17  - container: {
    18  - margin: 0,
    19  - padding: '0 200px 0 0',
    20  - },
    21  -});
    22  - 
    23  -class CityKnowledgeComponent extends Component {
    24  - render() {
    25  - const { classes, city } = this.props;
    26  - const link = `/dashboard/entities/cities/${city.id}/knowledge`;
    27  - return (
    28  - <div className={classes.container}>
    29  - <StixDomainObjectHeader
    30  - disableSharing={true}
    31  - stixDomainObject={city}
    32  - PopoverComponent={<CityPopover />}
    33  - />
    34  - <Switch>
    35  - <Route
    36  - exact
    37  - path="/dashboard/entities/cities/:cityId/knowledge/relations/:relationId"
    38  - render={(routeProps) => (
    39  - <StixCoreRelationship
    40  - entityId={city.id}
    41  - paddingRight={true}
    42  - {...routeProps}
    43  - />
    44  - )}
    45  - />
    46  - <Route
    47  - exact
    48  - path="/dashboard/entities/cities/:cityId/knowledge/sightings/:sightingId"
    49  - render={(routeProps) => (
    50  - <StixSightingRelationship
    51  - entityId={city.id}
    52  - paddingRight={true}
    53  - {...routeProps}
    54  - />
    55  - )}
    56  - />
    57  - <Route
    58  - exact
    59  - path="/dashboard/entities/cities/:cityId/knowledge/overview"
    60  - render={(routeProps) => (
    61  - <StixDomainObjectKnowledge
    62  - stixDomainObjectId={city.id}
    63  - stixDomainObjectType="City"
    64  - {...routeProps}
    65  - />
    66  - )}
    67  - />
    68  - <Route
    69  - exact
    70  - path="/dashboard/entities/cities/:cityId/knowledge/related"
    71  - render={(routeProps) => (
    72  - <EntityStixCoreRelationships
    73  - entityId={city.id}
    74  - relationshipTypes={['related-to']}
    75  - targetStixDomainObjectTypes={[
    76  - 'Threat-Actor',
    77  - 'Intrusion-Set',
    78  - 'Campaign',
    79  - 'Incident',
    80  - 'Malware',
    81  - 'Tool',
    82  - 'Vulnerability',
    83  - 'Individual',
    84  - 'Organization',
    85  - 'Sector',
    86  - 'Region',
    87  - 'Country',
    88  - 'City',
    89  - 'Position',
    90  - ]}
    91  - entityLink={link}
    92  - allDirections={true}
    93  - {...routeProps}
    94  - />
    95  - )}
    96  - />
    97  - <Route
    98  - exact
    99  - path="/dashboard/entities/cities/:cityId/knowledge/organizations"
    100  - render={(routeProps) => (
    101  - <EntityStixCoreRelationships
    102  - entityId={city.id}
    103  - relationshipTypes={['located-at']}
    104  - targetStixDomainObjectTypes={['Organization']}
    105  - entityLink={link}
    106  - isRelationReversed={true}
    107  - {...routeProps}
    108  - />
    109  - )}
    110  - />
    111  - <Route
    112  - exact
    113  - path="/dashboard/entities/cities/:cityId/knowledge/countries"
    114  - render={(routeProps) => (
    115  - <EntityStixCoreRelationships
    116  - entityId={city.id}
    117  - relationshipTypes={['located-at']}
    118  - targetStixDomainObjectTypes={['Country']}
    119  - entityLink={link}
    120  - isRelationReversed={false}
    121  - {...routeProps}
    122  - />
    123  - )}
    124  - />
    125  - <Route
    126  - exact
    127  - path="/dashboard/entities/cities/:cityId/knowledge/threat_actors"
    128  - render={(routeProps) => (
    129  - <EntityStixCoreRelationships
    130  - entityId={city.id}
    131  - relationshipTypes={['targets']}
    132  - targetStixDomainObjectTypes={['Threat-Actor']}
    133  - entityLink={link}
    134  - isRelationReversed={true}
    135  - {...routeProps}
    136  - />
    137  - )}
    138  - />
    139  - <Route
    140  - exact
    141  - path="/dashboard/entities/cities/:cityId/knowledge/intrusion_sets"
    142  - render={(routeProps) => (
    143  - <EntityStixCoreRelationships
    144  - entityId={city.id}
    145  - relationshipTypes={['targets']}
    146  - targetStixDomainObjectTypes={['Intrusion-Set']}
    147  - entityLink={link}
    148  - isRelationReversed={true}
    149  - {...routeProps}
    150  - />
    151  - )}
    152  - />
    153  - <Route
    154  - exact
    155  - path="/dashboard/entities/cities/:cityId/knowledge/campaigns"
    156  - render={(routeProps) => (
    157  - <EntityStixCoreRelationships
    158  - entityId={city.id}
    159  - relationshipTypes={['targets']}
    160  - targetStixDomainObjectTypes={['Campaign']}
    161  - entityLink={link}
    162  - isRelationReversed={true}
    163  - {...routeProps}
    164  - />
    165  - )}
    166  - />
    167  - <Route
    168  - exact
    169  - path="/dashboard/entities/cities/:cityId/knowledge/incidents"
    170  - render={(routeProps) => (
    171  - <EntityStixCoreRelationships
    172  - entityId={city.id}
    173  - relationshipTypes={['targets']}
    174  - targetStixDomainObjectTypes={['Incident']}
    175  - entityLink={link}
    176  - isRelationReversed={true}
    177  - {...routeProps}
    178  - />
    179  - )}
    180  - />
    181  - <Route
    182  - exact
    183  - path="/dashboard/entities/cities/:cityId/knowledge/malwares"
    184  - render={(routeProps) => (
    185  - <EntityStixCoreRelationships
    186  - entityId={city.id}
    187  - relationshipTypes={['targets']}
    188  - targetStixDomainObjectTypes={['Malware']}
    189  - entityLink={link}
    190  - isRelationReversed={true}
    191  - {...routeProps}
    192  - />
    193  - )}
    194  - />
    195  - <Route
    196  - exact
    197  - path="/dashboard/entities/cities/:cityId/knowledge/attack_patterns"
    198  - render={(routeProps) => (
    199  - <EntityStixCoreRelationships
    200  - entityId={city.id}
    201  - relationshipTypes={['targets']}
    202  - targetStixDomainObjectTypes={['Attack-Pattern']}
    203  - entityLink={link}
    204  - isRelationReversed={true}
    205  - {...routeProps}
    206  - />
    207  - )}
    208  - />
    209  - <Route
    210  - exact
    211  - path="/dashboard/entities/cities/:cityId/knowledge/tools"
    212  - render={(routeProps) => (
    213  - <EntityStixCoreRelationships
    214  - entityId={city.id}
    215  - relationshipTypes={['targets']}
    216  - targetStixDomainObjectTypes={['Tool']}
    217  - entityLink={link}
    218  - isRelationReversed={true}
    219  - {...routeProps}
    220  - />
    221  - )}
    222  - />
    223  - <Route
    224  - exact
    225  - path="/dashboard/entities/cities/:cityId/knowledge/observables"
    226  - render={(routeProps) => (
    227  - <StixCoreObjectStixCyberObservables
    228  - stixCoreObjectId={city.id}
    229  - stixCoreObjectLink={link}
    230  - noRightBar={true}
    231  - {...routeProps}
    232  - />
    233  - )}
    234  - />
    235  - </Switch>
    236  - </div>
    237  - );
    238  - }
    239  -}
    240  - 
    241  -CityKnowledgeComponent.propTypes = {
    242  - city: PropTypes.object,
    243  - classes: PropTypes.object,
    244  - t: PropTypes.func,
    245  -};
    246  - 
    247  -const CityKnowledge = createFragmentContainer(CityKnowledgeComponent, {
    248  - city: graphql`
    249  - fragment CityKnowledge_city on City {
    250  - id
    251  - name
    252  - x_opencti_aliases
    253  - }
    254  - `,
    255  -});
    256  - 
    257  -export default compose(
    258  - inject18n,
    259  - withRouter,
    260  - withStyles(styles),
    261  -)(CityKnowledge);
    262  - 
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/cities/CityKnowledge.tsx
     1 +/* eslint-disable @typescript-eslint/no-explicit-any */
     2 +// TODO Remove this when V6
     3 +// eslint-disable-next-line @typescript-eslint/ban-ts-comment
     4 +// @ts-nocheck
     5 +import React from 'react';
     6 +import { Route, Switch } from 'react-router-dom';
     7 +import { graphql, useFragment } from 'react-relay';
     8 +import makeStyles from '@mui/styles/makeStyles';
     9 +import EntityStixCoreRelationships from '../../common/stix_core_relationships/EntityStixCoreRelationships';
     10 +import StixDomainObjectKnowledge from '../../common/stix_domain_objects/StixDomainObjectKnowledge';
     11 +import StixCoreRelationship from '../../common/stix_core_relationships/StixCoreRelationship';
     12 +import CityPopover from './CityPopover';
     13 +import StixDomainObjectHeader from '../../common/stix_domain_objects/StixDomainObjectHeader';
     14 +import StixCoreObjectStixCyberObservables
     15 + from '../../observations/stix_cyber_observables/StixCoreObjectStixCyberObservables';
     16 +import StixSightingRelationship from '../../events/stix_sighting_relationships/StixSightingRelationship';
     17 +import { CityKnowledge_city$key } from './__generated__/CityKnowledge_city.graphql';
     18 + 
     19 +const useStyles = makeStyles(() => ({
     20 + container: {
     21 + margin: 0,
     22 + padding: '0 200px 0 0',
     23 + },
     24 +}));
     25 + 
     26 +const cityKnowledgeFragment = graphql`
     27 + fragment CityKnowledge_city on City {
     28 + id
     29 + name
     30 + x_opencti_aliases
     31 + }
     32 +`;
     33 + 
     34 +const CityKnowledge = ({ cityData }: { cityData: CityKnowledge_city$key }) => {
     35 + const classes = useStyles();
     36 + 
     37 + const city = useFragment<CityKnowledge_city$key>(cityKnowledgeFragment, cityData);
     38 + const link = `/dashboard/entities/cities/${city.id}/knowledge`;
     39 + 
     40 + return (
     41 + <div className={classes.container}>
     42 + <StixDomainObjectHeader
     43 + disableSharing={true}
     44 + stixDomainObject={city}
     45 + PopoverComponent={CityPopover}
     46 + variant="noaliases"
     47 + />
     48 + <Switch>
     49 + <Route
     50 + exact
     51 + path="/dashboard/entities/cities/:cityId/knowledge/relations/:relationId"
     52 + render={(routeProps: any) => (
     53 + <StixCoreRelationship
     54 + entityId={city.id}
     55 + paddingRight={true}
     56 + {...routeProps}
     57 + />
     58 + )}
     59 + />
     60 + <Route
     61 + exact
     62 + path="/dashboard/entities/cities/:cityId/knowledge/sightings/:sightingId"
     63 + render={(routeProps: any) => (
     64 + <StixSightingRelationship
     65 + entityId={city.id}
     66 + paddingRight={true}
     67 + {...routeProps}
     68 + />
     69 + )}
     70 + />
     71 + <Route
     72 + exact
     73 + path="/dashboard/entities/cities/:cityId/knowledge/overview"
     74 + render={(routeProps: any) => (
     75 + <StixDomainObjectKnowledge
     76 + stixDomainObjectId={city.id}
     77 + stixDomainObjectType="City"
     78 + {...routeProps}
     79 + />
     80 + )}
     81 + />
     82 + <Route
     83 + exact
     84 + path="/dashboard/entities/cities/:cityId/knowledge/related"
     85 + render={(routeProps: any) => (
     86 + <EntityStixCoreRelationships
     87 + entityId={city.id}
     88 + relationshipTypes={['related-to']}
     89 + targetStixDomainObjectTypes={[
     90 + 'Threat-Actor',
     91 + 'Intrusion-Set',
     92 + 'Campaign',
     93 + 'Incident',
     94 + 'Malware',
     95 + 'Tool',
     96 + 'Vulnerability',
     97 + 'Individual',
     98 + 'Organization',
     99 + 'Sector',
     100 + 'Region',
     101 + 'Country',
     102 + 'City',
     103 + 'Position',
     104 + ]}
     105 + entityLink={link}
     106 + allDirections={true}
     107 + {...routeProps}
     108 + />
     109 + )}
     110 + />
     111 + <Route
     112 + exact
     113 + path="/dashboard/entities/cities/:cityId/knowledge/organizations"
     114 + render={(routeProps: any) => (
     115 + <EntityStixCoreRelationships
     116 + entityId={city.id}
     117 + relationshipTypes={['located-at']}
     118 + targetStixDomainObjectTypes={['Organization']}
     119 + entityLink={link}
     120 + isRelationReversed={true}
     121 + {...routeProps}
     122 + />
     123 + )}
     124 + />
     125 + <Route
     126 + exact
     127 + path="/dashboard/entities/cities/:cityId/knowledge/countries"
     128 + render={(routeProps: any) => (
     129 + <EntityStixCoreRelationships
     130 + entityId={city.id}
     131 + relationshipTypes={['located-at']}
     132 + targetStixDomainObjectTypes={['Country']}
     133 + entityLink={link}
     134 + isRelationReversed={false}
     135 + {...routeProps}
     136 + />
     137 + )}
     138 + />
     139 + <Route
     140 + exact
     141 + path="/dashboard/entities/cities/:cityId/knowledge/threat_actors"
     142 + render={(routeProps: any) => (
     143 + <EntityStixCoreRelationships
     144 + entityId={city.id}
     145 + relationshipTypes={['targets']}
     146 + targetStixDomainObjectTypes={['Threat-Actor']}
     147 + entityLink={link}
     148 + isRelationReversed={true}
     149 + {...routeProps}
     150 + />
     151 + )}
     152 + />
     153 + <Route
     154 + exact
     155 + path="/dashboard/entities/cities/:cityId/knowledge/intrusion_sets"
     156 + render={(routeProps: any) => (
     157 + <EntityStixCoreRelationships
     158 + entityId={city.id}
     159 + relationshipTypes={['targets']}
     160 + targetStixDomainObjectTypes={['Intrusion-Set']}
     161 + entityLink={link}
     162 + isRelationReversed={true}
     163 + {...routeProps}
     164 + />
     165 + )}
     166 + />
     167 + <Route
     168 + exact
     169 + path="/dashboard/entities/cities/:cityId/knowledge/campaigns"
     170 + render={(routeProps: any) => (
     171 + <EntityStixCoreRelationships
     172 + entityId={city.id}
     173 + relationshipTypes={['targets']}
     174 + targetStixDomainObjectTypes={['Campaign']}
     175 + entityLink={link}
     176 + isRelationReversed={true}
     177 + {...routeProps}
     178 + />
     179 + )}
     180 + />
     181 + <Route
     182 + exact
     183 + path="/dashboard/entities/cities/:cityId/knowledge/incidents"
     184 + render={(routeProps: any) => (
     185 + <EntityStixCoreRelationships
     186 + entityId={city.id}
     187 + relationshipTypes={['targets']}
     188 + targetStixDomainObjectTypes={['Incident']}
     189 + entityLink={link}
     190 + isRelationReversed={true}
     191 + {...routeProps}
     192 + />
     193 + )}
     194 + />
     195 + <Route
     196 + exact
     197 + path="/dashboard/entities/cities/:cityId/knowledge/malwares"
     198 + render={(routeProps: any) => (
     199 + <EntityStixCoreRelationships
     200 + entityId={city.id}
     201 + relationshipTypes={['targets']}
     202 + targetStixDomainObjectTypes={['Malware']}
     203 + entityLink={link}
     204 + isRelationReversed={true}
     205 + {...routeProps}
     206 + />
     207 + )}
     208 + />
     209 + <Route
     210 + exact
     211 + path="/dashboard/entities/cities/:cityId/knowledge/attack_patterns"
     212 + render={(routeProps: any) => (
     213 + <EntityStixCoreRelationships
     214 + entityId={city.id}
     215 + relationshipTypes={['targets']}
     216 + targetStixDomainObjectTypes={['Attack-Pattern']}
     217 + entityLink={link}
     218 + isRelationReversed={true}
     219 + {...routeProps}
     220 + />
     221 + )}
     222 + />
     223 + <Route
     224 + exact
     225 + path="/dashboard/entities/cities/:cityId/knowledge/tools"
     226 + render={(routeProps: any) => (
     227 + <EntityStixCoreRelationships
     228 + entityId={city.id}
     229 + relationshipTypes={['targets']}
     230 + targetStixDomainObjectTypes={['Tool']}
     231 + entityLink={link}
     232 + isRelationReversed={true}
     233 + {...routeProps}
     234 + />
     235 + )}
     236 + />
     237 + <Route
     238 + exact
     239 + path="/dashboard/entities/cities/:cityId/knowledge/observables"
     240 + render={(routeProps: any) => (
     241 + <StixCoreObjectStixCyberObservables
     242 + stixCoreObjectId={city.id}
     243 + stixCoreObjectLink={link}
     244 + noRightBar={true}
     245 + {...routeProps}
     246 + />
     247 + )}
     248 + />
     249 + </Switch>
     250 + </div>
     251 + );
     252 +};
     253 + 
     254 +export default CityKnowledge;
     255 + 
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/cities/CityOverview.js
    1  -import React, { Component } from 'react';
    2  -import * as PropTypes from 'prop-types';
    3  -import { compose, propOr } from 'ramda';
    4  -import { graphql, createFragmentContainer } from 'react-relay';
    5  -import Markdown from 'react-markdown';
    6  -import withStyles from '@mui/styles/withStyles';
    7  -import Paper from '@mui/material/Paper';
    8  -import Typography from '@mui/material/Typography';
    9  -import remarkGfm from 'remark-gfm';
    10  -import remarkParse from 'remark-parse';
    11  -import inject18n from '../../../../components/i18n';
    12  -import ItemAuthor from '../../../../components/ItemAuthor';
    13  - 
    14  -const styles = () => ({
    15  - paper: {
    16  - height: '100%',
    17  - minHeight: '100%',
    18  - margin: '10px 0 0 0',
    19  - padding: '15px',
    20  - borderRadius: 6,
    21  - },
    22  -});
    23  - 
    24  -class CityOverviewComponent extends Component {
    25  - render() {
    26  - const { t, fldt, classes, city } = this.props;
    27  - return (
    28  - <div style={{ height: '100%' }} className="break">
    29  - <Typography variant="h4" gutterBottom={true}>
    30  - {t('Information')}
    31  - </Typography>
    32  - <Paper classes={{ root: classes.paper }} variant="outlined">
    33  - <Typography variant="h3" gutterBottom={true}>
    34  - {t('Creation date')}
    35  - </Typography>
    36  - {fldt(city.created)}
    37  - <Typography
    38  - variant="h3"
    39  - gutterBottom={true}
    40  - style={{ marginTop: 20 }}
    41  - >
    42  - {t('Modification date')}
    43  - </Typography>
    44  - {fldt(city.modified)}
    45  - <Typography
    46  - variant="h3"
    47  - gutterBottom={true}
    48  - style={{ marginTop: 20 }}
    49  - >
    50  - {t('Author')}
    51  - </Typography>
    52  - <ItemAuthor createdBy={propOr(null, 'createdBy', city)} />
    53  - <Typography
    54  - variant="h3"
    55  - gutterBottom={true}
    56  - style={{ marginTop: 20 }}
    57  - >
    58  - {t('Description')}
    59  - </Typography>
    60  - <Markdown
    61  - remarkPlugins={[remarkGfm, remarkParse]}
    62  - parserOptions={{ commonmark: true }}
    63  - className="markdown"
    64  - >
    65  - {city.description}
    66  - </Markdown>
    67  - </Paper>
    68  - </div>
    69  - );
    70  - }
    71  -}
    72  - 
    73  -CityOverviewComponent.propTypes = {
    74  - city: PropTypes.object,
    75  - classes: PropTypes.object,
    76  - t: PropTypes.func,
    77  - fldt: PropTypes.func,
    78  -};
    79  - 
    80  -const CityOverview = createFragmentContainer(CityOverviewComponent, {
    81  - city: graphql`
    82  - fragment CityOverview_city on City {
    83  - id
    84  - name
    85  - description
    86  - created
    87  - modified
    88  - createdBy {
    89  - ... on Identity {
    90  - id
    91  - name
    92  - entity_type
    93  - }
    94  - }
    95  - }
    96  - `,
    97  -});
    98  - 
    99  -export default compose(inject18n, withStyles(styles))(CityOverview);
    100  - 
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/cities/CityPopover.js
    1  -import React, { Component } from 'react';
    2  -import * as PropTypes from 'prop-types';
    3  -import { compose } from 'ramda';
    4  -import { withRouter } from 'react-router-dom';
    5  -import withStyles from '@mui/styles/withStyles';
    6  -import Menu from '@mui/material/Menu';
    7  -import MenuItem from '@mui/material/MenuItem';
    8  -import Button from '@mui/material/Button';
    9  -import IconButton from '@mui/material/IconButton';
    10  -import Drawer from '@mui/material/Drawer';
    11  -import Dialog from '@mui/material/Dialog';
    12  -import DialogActions from '@mui/material/DialogActions';
    13  -import DialogContent from '@mui/material/DialogContent';
    14  -import DialogContentText from '@mui/material/DialogContentText';
    15  -import Slide from '@mui/material/Slide';
    16  -import MoreVert from '@mui/icons-material/MoreVert';
    17  -import { graphql } from 'react-relay';
    18  -import inject18n from '../../../../components/i18n';
    19  -import { QueryRenderer, commitMutation } from '../../../../relay/environment';
    20  -import { cityEditionQuery } from './CityEdition';
    21  -import CityEditionContainer from './CityEditionContainer';
    22  -import Loader from '../../../../components/Loader';
    23  -import Security, {
    24  - KNOWLEDGE_KNUPDATE_KNDELETE,
    25  -} from '../../../../utils/Security';
    26  - 
    27  -const styles = (theme) => ({
    28  - container: {
    29  - margin: 0,
    30  - },
    31  - drawerPaper: {
    32  - minHeight: '100vh',
    33  - width: '50%',
    34  - position: 'fixed',
    35  - overflow: 'auto',
    36  - transition: theme.transitions.create('width', {
    37  - easing: theme.transitions.easing.sharp,
    38  - duration: theme.transitions.duration.enteringScreen,
    39  - }),
    40  - padding: 0,
    41  - },
    42  -});
    43  - 
    44  -const Transition = React.forwardRef((props, ref) => (
    45  - <Slide direction="up" ref={ref} {...props} />
    46  -));
    47  -Transition.displayName = 'TransitionSlide';
    48  - 
    49  -const CityPopoverDeletionMutation = graphql`
    50  - mutation CityPopoverDeletionMutation($id: ID!) {
    51  - cityEdit(id: $id) {
    52  - delete
    53  - }
    54  - }
    55  -`;
    56  - 
    57  -class CityPopover extends Component {
    58  - constructor(props) {
    59  - super(props);
    60  - this.state = {
    61  - anchorEl: null,
    62  - displayDelete: false,
    63  - displayEdit: false,
    64  - deleting: false,
    65  - };
    66  - }
    67  - 
    68  - handleOpen(event) {
    69  - this.setState({ anchorEl: event.currentTarget });
    70  - }
    71  - 
    72  - handleClose() {
    73  - this.setState({ anchorEl: null });
    74  - }
    75  - 
    76  - handleOpenDelete() {
    77  - this.setState({ displayDelete: true });
    78  - this.handleClose();
    79  - }
    80  - 
    81  - handleCloseDelete() {
    82  - this.setState({ displayDelete: false });
    83  - }
    84  - 
    85  - submitDelete() {
    86  - this.setState({ deleting: true });
    87  - commitMutation({
    88  - mutation: CityPopoverDeletionMutation,
    89  - variables: {
    90  - id: this.props.id,
    91  - },
    92  - onCompleted: () => {
    93  - this.setState({ deleting: false });
    94  - this.handleClose();
    95  - this.props.history.push('/dashboard/entities/cities');
    96  - },
    97  - });
    98  - }
    99  - 
    100  - handleOpenEdit() {
    101  - this.setState({ displayEdit: true });
    102  - this.handleClose();
    103  - }
    104  - 
    105  - handleCloseEdit() {
    106  - this.setState({ displayEdit: false });
    107  - }
    108  - 
    109  - render() {
    110  - const { classes, t, id } = this.props;
    111  - return (
    112  - <div className={classes.container}>
    113  - <IconButton
    114  - onClick={this.handleOpen.bind(this)}
    115  - aria-haspopup="true"
    116  - style={{ marginTop: 3 }}
    117  - size="large"
    118  - >
    119  - <MoreVert />
    120  - </IconButton>
    121  - <Menu
    122  - anchorEl={this.state.anchorEl}
    123  - open={Boolean(this.state.anchorEl)}
    124  - onClose={this.handleClose.bind(this)}
    125  - >
    126  - <MenuItem onClick={this.handleOpenEdit.bind(this)}>
    127  - {t('Update')}
    128  - </MenuItem>
    129  - <Security needs={[KNOWLEDGE_KNUPDATE_KNDELETE]}>
    130  - <MenuItem onClick={this.handleOpenDelete.bind(this)}>
    131  - {t('Delete')}
    132  - </MenuItem>
    133  - </Security>
    134  - </Menu>
    135  - <Dialog
    136  - PaperProps={{ elevation: 1 }}
    137  - open={this.state.displayDelete}
    138  - keepMounted={true}
    139  - TransitionComponent={Transition}
    140  - onClose={this.handleCloseDelete.bind(this)}
    141  - >
    142  - <DialogContent>
    143  - <DialogContentText>
    144  - {t('Do you want to delete this city?')}
    145  - </DialogContentText>
    146  - </DialogContent>
    147  - <DialogActions>
    148  - <Button
    149  - onClick={this.handleCloseDelete.bind(this)}
    150  - disabled={this.state.deleting}
    151  - >
    152  - {t('Cancel')}
    153  - </Button>
    154  - <Button
    155  - color="secondary"
    156  - onClick={this.submitDelete.bind(this)}
    157  - disabled={this.state.deleting}
    158  - >
    159  - {t('Delete')}
    160  - </Button>
    161  - </DialogActions>
    162  - </Dialog>
    163  - <Drawer
    164  - open={this.state.displayEdit}
    165  - anchor="right"
    166  - elevation={1}
    167  - sx={{ zIndex: 1202 }}
    168  - classes={{ paper: classes.drawerPaper }}
    169  - onClose={this.handleCloseEdit.bind(this)}
    170  - >
    171  - <QueryRenderer
    172  - query={cityEditionQuery}
    173  - variables={{ id }}
    174  - render={({ props }) => {
    175  - if (props) {
    176  - return (
    177  - <CityEditionContainer
    178  - city={props.city}
    179  - handleClose={this.handleCloseEdit.bind(this)}
    180  - />
    181  - );
    182  - }
    183  - return <Loader variant="inElement" />;
    184  - }}
    185  - />
    186  - </Drawer>
    187  - </div>
    188  - );
    189  - }
    190  -}
    191  - 
    192  -CityPopover.propTypes = {
    193  - id: PropTypes.string,
    194  - classes: PropTypes.object,
    195  - t: PropTypes.func,
    196  - history: PropTypes.object,
    197  -};
    198  - 
    199  -export default compose(inject18n, withRouter, withStyles(styles))(CityPopover);
    200  - 
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/cities/CityPopover.tsx
     1 +import React, { useState } from 'react';
     2 +import Menu from '@mui/material/Menu';
     3 +import MenuItem from '@mui/material/MenuItem';
     4 +import Button from '@mui/material/Button';
     5 +import IconButton from '@mui/material/IconButton';
     6 +import Drawer from '@mui/material/Drawer';
     7 +import Dialog from '@mui/material/Dialog';
     8 +import DialogActions from '@mui/material/DialogActions';
     9 +import DialogContent from '@mui/material/DialogContent';
     10 +import DialogContentText from '@mui/material/DialogContentText';
     11 +import MoreVert from '@mui/icons-material/MoreVert';
     12 +import { graphql, useMutation } from 'react-relay';
     13 +import makeStyles from '@mui/styles/makeStyles';
     14 +import { useNavigate } from 'react-router-dom-v5-compat';
     15 +import { useFormatter } from '../../../../components/i18n';
     16 +import CityEditionContainer, { cityEditionQuery } from './CityEditionContainer';
     17 +import Loader, { LoaderVariant } from '../../../../components/Loader';
     18 +import Security, { KNOWLEDGE_KNUPDATE_KNDELETE } from '../../../../utils/Security';
     19 +import { Theme } from '../../../../components/Theme';
     20 +import useQueryLoading from '../../../../utils/hooks/useQueryLoading';
     21 +import { CityEditionContainerQuery } from './__generated__/CityEditionContainerQuery.graphql';
     22 +import Transition from '../../../../components/Transition';
     23 + 
     24 +const useStyles = makeStyles<Theme>((theme) => ({
     25 + container: {
     26 + margin: 0,
     27 + },
     28 + drawerPaper: {
     29 + minHeight: '100vh',
     30 + width: '50%',
     31 + position: 'fixed',
     32 + overflow: 'auto',
     33 + transition: theme.transitions.create('width', {
     34 + easing: theme.transitions.easing.sharp,
     35 + duration: theme.transitions.duration.enteringScreen,
     36 + }),
     37 + padding: 0,
     38 + },
     39 +}));
     40 + 
     41 +const CityPopoverDeletionMutation = graphql`
     42 + mutation CityPopoverDeletionMutation($id: ID!) {
     43 + cityEdit(id: $id) {
     44 + delete
     45 + }
     46 + }
     47 +`;
     48 + 
     49 +const CityPopover = ({ id }: { id: string }) => {
     50 + const classes = useStyles();
     51 + const { t } = useFormatter();
     52 + 
     53 + const navigate = useNavigate();
     54 + 
     55 + const [anchorEl, setAnchorEl] = useState<Element>();
     56 + const [displayEdit, setDisplayEdit] = useState<boolean>(false);
     57 + const [deleting, setDeleting] = useState<boolean>(false);
     58 + const [displayDelete, setDisplayDelete] = useState<boolean>(false);
     59 + 
     60 + const [commit] = useMutation(CityPopoverDeletionMutation);
     61 + const queryRef = useQueryLoading<CityEditionContainerQuery>(cityEditionQuery, { id });
     62 + 
     63 + const handleOpen = (event: React.SyntheticEvent) => {
     64 + setAnchorEl(event.currentTarget);
     65 + };
     66 + 
     67 + const handleClose = () => {
     68 + setAnchorEl(undefined);
     69 + };
     70 + 
     71 + const handleOpenDelete = () => {
     72 + setDisplayDelete(true);
     73 + handleClose();
     74 + };
     75 + 
     76 + const handleCloseDelete = () => {
     77 + setDisplayDelete(false);
     78 + };
     79 + 
     80 + const handleOpenEdit = () => {
     81 + setDisplayEdit(true);
     82 + handleClose();
     83 + };
     84 + 
     85 + const handleCloseEdit = () => {
     86 + setDisplayEdit(false);
     87 + };
     88 + 
     89 + const submitDelete = () => {
     90 + setDeleting(true);
     91 + commit({
     92 + variables: {
     93 + id,
     94 + },
     95 + onCompleted: () => {
     96 + setDeleting(false);
     97 + handleClose();
     98 + navigate('/dashboard/entities/cities');
     99 + },
     100 + });
     101 + };
     102 + 
     103 + return (
     104 + <div className={classes.container}>
     105 + <IconButton
     106 + onClick={handleOpen}
     107 + aria-haspopup="true"
     108 + style={{ marginTop: 3 }}
     109 + size="large"
     110 + >
     111 + <MoreVert />
     112 + </IconButton>
     113 + <Menu
     114 + anchorEl={anchorEl}
     115 + open={Boolean(anchorEl)}
     116 + onClose={handleClose}
     117 + >
     118 + <MenuItem onClick={handleOpenEdit}>
     119 + {t('Update')}
     120 + </MenuItem>
     121 + <Security needs={[KNOWLEDGE_KNUPDATE_KNDELETE]}>
     122 + <MenuItem onClick={handleOpenDelete}>
     123 + {t('Delete')}
     124 + </MenuItem>
     125 + </Security>
     126 + </Menu>
     127 + <Dialog
     128 + PaperProps={{ elevation: 1 }}
     129 + open={displayDelete}
     130 + keepMounted={true}
     131 + TransitionComponent={Transition}
     132 + onClose={handleCloseDelete}
     133 + >
     134 + <DialogContent>
     135 + <DialogContentText>
     136 + {t('Do you want to delete this city?')}
     137 + </DialogContentText>
     138 + </DialogContent>
     139 + <DialogActions>
     140 + <Button
     141 + onClick={handleCloseDelete}
     142 + disabled={deleting}
     143 + >
     144 + {t('Cancel')}
     145 + </Button>
     146 + <Button
     147 + color="secondary"
     148 + onClick={submitDelete}
     149 + disabled={deleting}
     150 + >
     151 + {t('Delete')}
     152 + </Button>
     153 + </DialogActions>
     154 + </Dialog>
     155 + <Drawer
     156 + open={displayEdit}
     157 + anchor="right"
     158 + elevation={1}
     159 + sx={{ zIndex: 1202 }}
     160 + classes={{ paper: classes.drawerPaper }}
     161 + onClose={handleCloseEdit}
     162 + >
     163 + {queryRef && (
     164 + <React.Suspense fallback={<Loader variant={LoaderVariant.inElement} />}>
     165 + <CityEditionContainer
     166 + queryRef={queryRef}
     167 + handleClose={handleClose}
     168 + />
     169 + </React.Suspense>
     170 + )}
     171 + </Drawer>
     172 + </div>
     173 + );
     174 +};
     175 + 
     176 +export default CityPopover;
     177 + 
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/cities/Root.js
    1  -import React, { Component } from 'react';
    2  -import * as PropTypes from 'prop-types';
    3  -import { Route, Redirect, withRouter, Switch } from 'react-router-dom';
    4  -import { graphql } from 'react-relay';
    5  -import {
    6  - QueryRenderer,
    7  - requestSubscription,
    8  -} from '../../../../relay/environment';
    9  -import TopBar from '../../nav/TopBar';
    10  -import City from './City';
    11  -import CityKnowledge from './CityKnowledge';
    12  -import StixDomainObjectHeader from '../../common/stix_domain_objects/StixDomainObjectHeader';
    13  -import FileManager from '../../common/files/FileManager';
    14  -import CityPopover from './CityPopover';
    15  -import Loader from '../../../../components/Loader';
    16  -import StixCoreObjectHistory from '../../common/stix_core_objects/StixCoreObjectHistory';
    17  -import StixCoreObjectOrStixCoreRelationshipContainers from '../../common/containers/StixCoreObjectOrStixCoreRelationshipContainers';
    18  -import StixCoreObjectKnowledgeBar from '../../common/stix_core_objects/StixCoreObjectKnowledgeBar';
    19  -import ErrorNotFound from '../../../../components/ErrorNotFound';
    20  -import EntityStixSightingRelationships from '../../events/stix_sighting_relationships/EntityStixSightingRelationships';
    21  - 
    22  -const subscription = graphql`
    23  - subscription RootCitiesSubscription($id: ID!) {
    24  - stixDomainObject(id: $id) {
    25  - ... on City {
    26  - ...City_city
    27  - ...CityEditionContainer_city
    28  - }
    29  - ...FileImportViewer_entity
    30  - ...FileExportViewer_entity
    31  - ...FileExternalReferencesViewer_entity
    32  - ...WorkbenchFileViewer_entity
    33  - }
    34  - }
    35  -`;
    36  - 
    37  -const cityQuery = graphql`
    38  - query RootCityQuery($id: String!) {
    39  - city(id: $id) {
    40  - id
    41  - name
    42  - x_opencti_aliases
    43  - x_opencti_graph_data
    44  - ...City_city
    45  - ...CityKnowledge_city
    46  - ...FileImportViewer_entity
    47  - ...FileExportViewer_entity
    48  - ...FileExternalReferencesViewer_entity
    49  - ...WorkbenchFileViewer_entity
    50  - }
    51  - connectorsForExport {
    52  - ...FileManager_connectorsExport
    53  - }
    54  - settings {
    55  - platform_enable_reference
    56  - }
    57  - }
    58  -`;
    59  - 
    60  -class RootCity extends Component {
    61  - constructor(props) {
    62  - super(props);
    63  - const {
    64  - match: {
    65  - params: { cityId },
    66  - },
    67  - } = props;
    68  - this.sub = requestSubscription({
    69  - subscription,
    70  - variables: { id: cityId },
    71  - });
    72  - }
    73  - 
    74  - componentWillUnmount() {
    75  - this.sub.dispose();
    76  - }
    77  - 
    78  - render() {
    79  - const {
    80  - me,
    81  - match: {
    82  - params: { cityId },
    83  - },
    84  - } = this.props;
    85  - const link = `/dashboard/entities/cities/${cityId}/knowledge`;
    86  - return (
    87  - <div>
    88  - <TopBar me={me || null} />
    89  - <Route path="/dashboard/entities/cities/:cityId/knowledge">
    90  - <StixCoreObjectKnowledgeBar
    91  - stixCoreObjectLink={link}
    92  - availableSections={[
    93  - 'organizations',
    94  - 'countries',
    95  - 'regions',
    96  - 'threat_actors',
    97  - 'intrusion_sets',
    98  - 'campaigns',
    99  - 'incidents',
    100  - 'malwares',
    101  - 'attack_patterns',
    102  - 'tools',
    103  - 'observables',
    104  - ]}
    105  - />
    106  - </Route>
    107  - <QueryRenderer
    108  - query={cityQuery}
    109  - variables={{ id: cityId }}
    110  - render={({ props }) => {
    111  - if (props) {
    112  - if (props.city) {
    113  - return (
    114  - <Switch>
    115  - <Route
    116  - exact
    117  - path="/dashboard/entities/cities/:cityId"
    118  - render={(routeProps) => (
    119  - <City {...routeProps} city={props.city} />
    120  - )}
    121  - />
    122  - <Route
    123  - exact
    124  - path="/dashboard/entities/cities/:cityId/knowledge"
    125  - render={() => (
    126  - <Redirect
    127  - to={`/dashboard/entities/cities/${cityId}/knowledge/overview`}
    128  - />
    129  - )}
    130  - />
    131  - <Route
    132  - path="/dashboard/entities/cities/:cityId/knowledge"
    133  - render={(routeProps) => (
    134  - <CityKnowledge {...routeProps} city={props.city} />
    135  - )}
    136  - />
    137  - <Route
    138  - exact
    139  - path="/dashboard/entities/cities/:cityId/analysis"
    140  - render={(routeProps) => (
    141  - <React.Fragment>
    142  - <StixDomainObjectHeader
    143  - disableSharing={true}
    144  - stixDomainObject={props.city}
    145  - PopoverComponent={<CityPopover />}
    146  - />
    147  - <StixCoreObjectOrStixCoreRelationshipContainers
    148  - {...routeProps}
    149  - stixDomainObjectOrStixCoreRelationship={props.city}
    150  - />
    151  - </React.Fragment>
    152  - )}
    153  - />
    154  - <Route
    155  - exact
    156  - path="/dashboard/entities/cities/:cityId/sightings"
    157  - render={(routeProps) => (
    158  - <EntityStixSightingRelationships
    159  - entityId={props.city.id}
    160  - entityLink={link}
    161  - noPadding={true}
    162  - isTo={true}
    163  - {...routeProps}
    164  - />
    165  - )}
    166  - />
    167  - <Route
    168  - exact
    169  - path="/dashboard/entities/cities/:cityId/files"
    170  - render={(routeProps) => (
    171  - <React.Fragment>
    172  - <StixDomainObjectHeader
    173  - disableSharing={true}
    174  - stixDomainObject={props.city}
    175  - PopoverComponent={<CityPopover />}
    176  - />
    177  - <FileManager
    178  - {...routeProps}
    179  - id={cityId}
    180  - connectorsImport={[]}
    181  - connectorsExport={props.connectorsForExport}
    182  - entity={props.city}
    183  - />
    184  - </React.Fragment>
    185  - )}
    186  - />
    187  - <Route
    188  - exact
    189  - path="/dashboard/entities/cities/:cityId/history"
    190  - render={(routeProps) => (
    191  - <React.Fragment>
    192  - <StixDomainObjectHeader
    193  - disableSharing={true}
    194  - stixDomainObject={props.city}
    195  - PopoverComponent={<CityPopover />}
    196  - />
    197  - <StixCoreObjectHistory
    198  - {...routeProps}
    199  - stixCoreObjectId={cityId}
    200  - />
    201  - </React.Fragment>
    202  - )}
    203  - />
    204  - </Switch>
    205  - );
    206  - }
    207  - return <ErrorNotFound />;
    208  - }
    209  - return <Loader />;
    210  - }}
    211  - />
    212  - </div>
    213  - );
    214  - }
    215  -}
    216  - 
    217  -RootCity.propTypes = {
    218  - children: PropTypes.node,
    219  - match: PropTypes.object,
    220  - me: PropTypes.object,
    221  -};
    222  - 
    223  -export default withRouter(RootCity);
    224  - 
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/cities/Root.tsx
     1 +// TODO Remove this when V6
     2 +// eslint-disable-next-line @typescript-eslint/ban-ts-comment
     3 +// @ts-nocheck
     4 +import React, { useContext, useMemo } from 'react';
     5 +import { Redirect, Route, Switch, useParams } from 'react-router-dom';
     6 +import { graphql, usePreloadedQuery, useSubscription } from 'react-relay';
     7 +import { GraphQLSubscriptionConfig } from 'relay-runtime';
     8 +import TopBar from '../../nav/TopBar';
     9 +import City from './City';
     10 +import CityKnowledge from './CityKnowledge';
     11 +import StixDomainObjectHeader from '../../common/stix_domain_objects/StixDomainObjectHeader';
     12 +import FileManager from '../../common/files/FileManager';
     13 +import CityPopover from './CityPopover';
     14 +import StixCoreObjectHistory from '../../common/stix_core_objects/StixCoreObjectHistory';
     15 +import StixCoreObjectOrStixCoreRelationshipContainers
     16 + from '../../common/containers/StixCoreObjectOrStixCoreRelationshipContainers';
     17 +import StixCoreObjectKnowledgeBar from '../../common/stix_core_objects/StixCoreObjectKnowledgeBar';
     18 +import ErrorNotFound from '../../../../components/ErrorNotFound';
     19 +import EntityStixSightingRelationships from '../../events/stix_sighting_relationships/EntityStixSightingRelationships';
     20 +import { UserContext } from '../../../../utils/Security';
     21 +import { RootCityQuery } from './__generated__/RootCityQuery.graphql';
     22 +import { RootCitiesSubscription } from './__generated__/RootCitiesSubscription.graphql';
     23 +import useQueryLoading from '../../../../utils/hooks/useQueryLoading';
     24 +import Loader, { LoaderVariant } from '../../../../components/Loader';
     25 + 
     26 +const subscription = graphql`
     27 + subscription RootCitiesSubscription($id: ID!) {
     28 + stixDomainObject(id: $id) {
     29 + ... on City {
     30 + ...City_city
     31 + ...CityEditionOverview_city
     32 + }
     33 + ...FileImportViewer_entity
     34 + ...FileExportViewer_entity
     35 + ...FileExternalReferencesViewer_entity
     36 + ...WorkbenchFileViewer_entity
     37 + }
     38 + }
     39 +`;
     40 + 
     41 +const cityQuery = graphql`
     42 + query RootCityQuery($id: String!) {
     43 + city(id: $id) {
     44 + id
     45 + name
     46 + x_opencti_aliases
     47 + x_opencti_graph_data
     48 + ...City_city
     49 + ...CityKnowledge_city
     50 + ...FileImportViewer_entity
     51 + ...FileExportViewer_entity
     52 + ...FileExternalReferencesViewer_entity
     53 + ...WorkbenchFileViewer_entity
     54 + }
     55 + connectorsForExport {
     56 + ...FileManager_connectorsExport
     57 + }
     58 + settings {
     59 + platform_enable_reference
     60 + }
     61 + }
     62 +`;
     63 + 
     64 +const RootCityComponent = ({ queryRef }) => {
     65 + const { me } = useContext(UserContext);
     66 + 
     67 + const { cityId } = useParams() as { cityId: string };
     68 + const link = `/dashboard/entities/cities/${cityId}/knowledge`;
     69 + 
     70 + const subConfig = useMemo<GraphQLSubscriptionConfig<RootCitiesSubscription>>(() => ({
     71 + subscription,
     72 + variables: { id: cityId },
     73 + }), [cityId]);
     74 + useSubscription(subConfig);
     75 + 
     76 + const data = usePreloadedQuery(cityQuery, queryRef);
     77 + const { city, connectorsForExport } = data;
     78 + 
     79 + return (
     80 + <div>
     81 + <TopBar me={me || null} />
     82 + <Route path="/dashboard/entities/cities/:cityId/knowledge">
     83 + <StixCoreObjectKnowledgeBar
     84 + stixCoreObjectLink={link}
     85 + availableSections={[
     86 + 'organizations',
     87 + 'countries',
     88 + 'regions',
     89 + 'threat_actors',
     90 + 'intrusion_sets',
     91 + 'campaigns',
     92 + 'incidents',
     93 + 'malwares',
     94 + 'attack_patterns',
     95 + 'tools',
     96 + 'observables',
     97 + ]}
     98 + />
     99 + </Route>
     100 + <>
     101 + {city ? (
     102 + <Switch>
     103 + <Route
     104 + exact
     105 + path="/dashboard/entities/cities/:cityId"
     106 + render={() => (<City cityData={city} />)}
     107 + />
     108 + <Route
     109 + exact
     110 + path="/dashboard/entities/cities/:cityId/knowledge"
     111 + render={() => (
     112 + <Redirect
     113 + to={`/dashboard/entities/cities/${cityId}/knowledge/overview`}
     114 + />
     115 + )}
     116 + />
     117 + <Route
     118 + path="/dashboard/entities/cities/:cityId/knowledge"
     119 + render={() => (<CityKnowledge cityData={city} />)}
     120 + />
     121 + <Route
     122 + exact
     123 + path="/dashboard/entities/cities/:cityId/analysis"
     124 + render={(routeProps) => (
     125 + <React.Fragment>
     126 + <StixDomainObjectHeader
     127 + disableSharing={true}
     128 + stixDomainObject={city}
     129 + PopoverComponent={CityPopover}
     130 + />
     131 + <StixCoreObjectOrStixCoreRelationshipContainers
     132 + {...routeProps}
     133 + stixDomainObjectOrStixCoreRelationship={city}
     134 + />
     135 + </React.Fragment>
     136 + )}
     137 + />
     138 + <Route
     139 + exact
     140 + path="/dashboard/entities/cities/:cityId/sightings"
     141 + render={(routeProps) => (
     142 + <EntityStixSightingRelationships
     143 + entityId={city.id}
     144 + entityLink={link}
     145 + noPadding={true}
     146 + isTo={true}
     147 + {...routeProps}
     148 + />
     149 + )}
     150 + />
     151 + <Route
     152 + exact
     153 + path="/dashboard/entities/cities/:cityId/files"
     154 + render={(routeProps) => (
     155 + <React.Fragment>
     156 + <StixDomainObjectHeader
     157 + disableSharing={true}
     158 + stixDomainObject={city}
     159 + PopoverComponent={CityPopover}
     160 + />
     161 + <FileManager
     162 + {...routeProps}
     163 + id={cityId}
     164 + connectorsImport={[]}
     165 + connectorsExport={connectorsForExport}
     166 + entity={city}
     167 + />
     168 + </React.Fragment>
     169 + )}
     170 + />
     171 + <Route
     172 + exact
     173 + path="/dashboard/entities/cities/:cityId/history"
     174 + render={(routeProps) => (
     175 + <React.Fragment>
     176 + <StixDomainObjectHeader
     177 + disableSharing={true}
     178 + stixDomainObject={city}
     179 + PopoverComponent={CityPopover}
     180 + />
     181 + <StixCoreObjectHistory
     182 + {...routeProps}
     183 + stixCoreObjectId={cityId}
     184 + />
     185 + </React.Fragment>
     186 + )}
     187 + />
     188 + </Switch>
     189 + ) : <ErrorNotFound />}
     190 + </>
     191 + </div>
     192 + );
     193 +};
     194 + 
     195 +const RootCity = () => {
     196 + const { cityId } = useParams() as { cityId: string };
     197 + 
     198 + const queryRef = useQueryLoading<RootCityQuery>(cityQuery, { id: cityId });
     199 + return queryRef ? <RootCityComponent queryRef={queryRef} /> : <Loader variant={LoaderVariant.inElement} />;
     200 +};
     201 + 
     202 +export default RootCity;
     203 + 
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/countries/CountryEditionOverview.js
    skipped 24 lines
    25 25   convertCreatedBy,
    26 26   convertMarkings,
    27 27   convertStatus,
    28  -} from '../../../../utils/Edition';
     28 +} from '../../../../utils/edition';
    29 29  import StatusField from '../../common/form/StatusField';
    30 30   
    31 31  const styles = (theme) => ({
    skipped 313 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/events/EventEditionOverview.js
    skipped 18 lines
    19 19   convertCreatedBy,
    20 20   convertMarkings,
    21 21   convertStatus,
    22  -} from '../../../../utils/Edition';
     22 +} from '../../../../utils/edition';
    23 23  import { buildDate } from '../../../../utils/Time';
    24 24  import DateTimePickerField from '../../../../components/DateTimePickerField';
    25 25  import OpenVocabField from '../../common/form/OpenVocabField';
    skipped 418 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/individuals/IndividualEditionOverview.js
    skipped 27 lines
    28 28   convertCreatedBy,
    29 29   convertMarkings,
    30 30   convertStatus,
    31  -} from '../../../../utils/Edition';
     31 +} from '../../../../utils/edition';
    32 32  import StatusField from '../../common/form/StatusField';
    33 33   
    34 34  const styles = (theme) => ({
    skipped 399 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/organizations/OrganizationEditionOverview.js
    skipped 29 lines
    30 30   convertCreatedBy,
    31 31   convertMarkings,
    32 32   convertStatus,
    33  -} from '../../../../utils/Edition';
     33 +} from '../../../../utils/edition';
    34 34  import StatusField from '../../common/form/StatusField';
    35 35   
    36 36  const styles = (theme) => ({
    skipped 454 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/positions/PositionEditionOverview.js
    skipped 17 lines
    18 18   convertCreatedBy,
    19 19   convertMarkings,
    20 20   convertStatus,
    21  -} from '../../../../utils/Edition';
     21 +} from '../../../../utils/edition';
    22 22  import StatusField from '../../common/form/StatusField';
    23 23   
    24 24  const styles = (theme) => ({
    skipped 403 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/regions/RegionEditionOverview.js
    skipped 24 lines
    25 25   convertCreatedBy,
    26 26   convertMarkings,
    27 27   convertStatus,
    28  -} from '../../../../utils/Edition';
     28 +} from '../../../../utils/edition';
    29 29  import StatusField from '../../common/form/StatusField';
    30 30   
    31 31  const styles = (theme) => ({
    skipped 318 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/sectors/SectorEditionOverview.js
    skipped 17 lines
    18 18   convertCreatedBy,
    19 19   convertMarkings,
    20 20   convertStatus,
    21  -} from '../../../../utils/Edition';
     21 +} from '../../../../utils/edition';
    22 22  import StatusField from '../../common/form/StatusField';
    23 23   
    24 24  const sectorMutationFieldPatch = graphql`
    skipped 345 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/entities/systems/SystemEditionOverview.js
    skipped 24 lines
    25 25   convertCreatedBy,
    26 26   convertMarkings,
    27 27   convertStatus,
    28  -} from '../../../../utils/Edition';
     28 +} from '../../../../utils/edition';
    29 29  import StatusField from '../../common/form/StatusField';
    30 30   
    31 31  const styles = (theme) => ({
    skipped 337 lines
  • ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/events/StixSightingRelationships.tsx
    skipped 6 lines
    7 7  } from './stix_sighting_relationships/StixSightingRelationshipsLines';
    8 8  import { convertFilters } from '../../../utils/ListParameters';
    9 9  import useLocalStorage, { localStorageToPaginationOptions } from '../../../utils/hooks/useLocalStorage';
    10  -import { Filters, PaginationOptions } from '../../../components/list_lines';
     10 +import { Filters } from '../../../components/list_lines';
     11 +import {
     12 + StixSightingRelationshipsLinesPaginationQuery$variables,
     13 +} from './stix_sighting_relationships/__generated__/StixSightingRelationshipsLinesPaginationQuery.graphql';
    11 14   
    12 15  const dataColumns = {
    13 16   x_opencti_negative: {
    skipped 63 lines
    77 80   openExports,
    78 81   } = viewStorage;
    79 82   
    80  - const renderLines = (paginationOptions: PaginationOptions) => (
     83 + const renderLines = (paginationOptions: StixSightingRelationshipsLinesPaginationQuery$variables) => (
    81 84   <ListLines
    82 85   sortBy={sortBy}
    83 86   orderAsc={orderAsc}
    skipped 23 lines
    107 110   >
    108 111   <QueryRenderer
    109 112   query={stixSightingRelationshipsLinesQuery}
    110  - variables={{ count: 25, ...paginationOptions }}
     113 + variables={paginationOptions}
    111 114   render={({ props }: { props: unknown }) => (
    112 115   <StixSightingRelationshipsLines
    113 116   // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    skipped 17 lines
    131 134   processedFilters = R.dissoc<Filters, string>('toSightingId', processedFilters);
    132 135   }
    133 136   const finalFilters = convertFilters(processedFilters) as unknown as Filters;
    134  - const paginationOptions = localStorageToPaginationOptions({ ...viewStorage, toId: toSightingId, filters: finalFilters });
     137 + const paginationOptions = localStorageToPaginationOptions<StixSightingRelationshipsLinesPaginationQuery$variables>({
     138 + ...viewStorage,
     139 + toId: toSightingId,
     140 + filters: finalFilters,
     141 + count: viewStorage.count ?? 25,
     142 + });
    135 143   return (
    136 144   <div>{renderLines(paginationOptions)}</div>
    137 145   );
    skipped 4 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/events/incidents/IncidentCreation.js
    skipped 18 lines
    19 19  import MarkDownField from '../../../../components/MarkDownField';
    20 20  import ConfidenceField from '../../common/form/ConfidenceField';
    21 21  import ExternalReferencesField from '../../common/form/ExternalReferencesField';
    22  -import { insertNode } from '../../../../utils/Store';
     22 +import { insertNode } from '../../../../utils/store';
    23 23  import OpenVocabField from '../../common/form/OpenVocabField';
    24 24  import { fieldSpacingContainerStyle } from '../../../../utils/field';
    25 25  import { isEmptyField } from '../../../../utils/utils';
    skipped 250 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/events/incidents/IncidentEditionOverview.js
    skipped 14 lines
    15 15  import CommitMessage from '../../common/form/CommitMessage';
    16 16  import { adaptFieldValue } from '../../../../utils/String';
    17 17  import StatusField from '../../common/form/StatusField';
    18  -import { convertCreatedBy, convertMarkings, convertStatus } from '../../../../utils/Edition';
     18 +import { convertCreatedBy, convertMarkings, convertStatus } from '../../../../utils/edition';
    19 19  import OpenVocabField from '../../common/form/OpenVocabField';
    20 20   
    21 21  import { fieldSpacingContainerStyle } from '../../../../utils/field';
    skipped 398 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/events/observed_data/ObservedDataCreation.js
    skipped 28 lines
    29 29  import { dayStartDate, parse } from '../../../../utils/Time';
    30 30  import ConfidenceField from '../../common/form/ConfidenceField';
    31 31  import StixCoreObjectsField from '../../common/form/StixCoreObjectsField';
    32  -import { insertNode } from '../../../../utils/Store';
     32 +import { insertNode } from '../../../../utils/store';
    33 33  import ExternalReferencesField from '../../common/form/ExternalReferencesField';
    34 34  import DateTimePickerField from '../../../../components/DateTimePickerField';
    35 35  import { fieldSpacingContainerStyle } from '../../../../utils/field';
    skipped 400 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/events/observed_data/ObservedDataEditionOverview.js
    skipped 18 lines
    19 19   convertCreatedBy,
    20 20   convertMarkings,
    21 21   convertStatus,
    22  -} from '../../../../utils/Edition';
     22 +} from '../../../../utils/edition';
    23 23  import DateTimePickerField from '../../../../components/DateTimePickerField';
    24 24  import { fieldSpacingContainerStyle } from '../../../../utils/field';
    25 25   
    skipped 394 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/events/stix_sighting_relationships/StixSightingRelationshipEditionOverview.js
    skipped 21 lines
    22 22  import SwitchField from '../../../../components/SwitchField';
    23 23  import MarkDownField from '../../../../components/MarkDownField';
    24 24  import StatusField from '../../common/form/StatusField';
    25  -import { convertCreatedBy, convertMarkings, convertStatus } from '../../../../utils/Edition';
     25 +import { convertCreatedBy, convertMarkings, convertStatus } from '../../../../utils/edition';
    26 26  import DateTimePickerField from '../../../../components/DateTimePickerField';
    27 27  import { fieldSpacingContainerStyle } from '../../../../utils/field';
    28 28   
    skipped 499 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/events/stix_sighting_relationships/StixSightingRelationshipPopover.js
    skipped 15 lines
    16 16  import inject18n from '../../../../components/i18n';
    17 17  import { commitMutation } from '../../../../relay/environment';
    18 18  import StixSightingRelationshipEdition from './StixSightingRelationshipEdition';
    19  -import { deleteNode } from '../../../../utils/Store';
     19 +import { deleteNode } from '../../../../utils/store';
    20 20   
    21 21  const styles = (theme) => ({
    22 22   container: {
    skipped 172 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/observations/indicators/IndicatorEditionOverview.js
    skipped 18 lines
    19 19  import OpenVocabField from '../../common/form/OpenVocabField';
    20 20  import { adaptFieldValue } from '../../../../utils/String';
    21 21  import CommitMessage from '../../common/form/CommitMessage';
    22  -import { convertCreatedBy, convertMarkings, convertStatus } from '../../../../utils/Edition';
     22 +import { convertCreatedBy, convertMarkings, convertStatus } from '../../../../utils/edition';
    23 23  import StatusField from '../../common/form/StatusField';
    24 24  import { buildDate, parse } from '../../../../utils/Time';
    25 25  import DateTimePickerField from '../../../../components/DateTimePickerField';
    skipped 582 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/observations/infrastructures/InfrastructureEditionOverview.js
    skipped 13 lines
    14 14  import DateTimePickerField from '../../../../components/DateTimePickerField';
    15 15  import KillChainPhasesField from '../../common/form/KillChainPhasesField';
    16 16  import OpenVocabField from '../../common/form/OpenVocabField';
    17  -import { convertCreatedBy, convertMarkings, convertStatus } from '../../../../utils/Edition';
     17 +import { convertCreatedBy, convertMarkings, convertStatus } from '../../../../utils/edition';
    18 18  import StatusField from '../../common/form/StatusField';
    19 19  import { buildDate } from '../../../../utils/Time';
    20 20  import { adaptFieldValue } from '../../../../utils/String';
    skipped 466 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/settings/users/UserEditionOverview.js
    skipped 25 lines
    26 26  import { commitMutation, fetchQuery } from '../../../../relay/environment';
    27 27  import MarkDownField from '../../../../components/MarkDownField';
    28 28  import ObjectOrganizationField from '../../common/form/ObjectOrganizationField';
    29  -import { convertOrganizations } from '../../../../utils/Edition';
     29 +import { convertOrganizations } from '../../../../utils/edition';
    30 30   
    31 31  const styles = () => ({
    32 32   icon: {
    skipped 439 lines
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/settings/workflow/StatusTemplateCreation.tsx
    skipped 18 lines
    19 19  import ColorPickerField from '../../../../components/ColorPickerField';
    20 20  import { commitMutation } from '../../../../relay/environment';
    21 21  import { useFormatter } from '../../../../components/i18n';
    22  -import { insertNode } from '../../../../utils/Store';
     22 +import { insertNode } from '../../../../utils/store';
    23 23  import { Theme } from '../../../../components/Theme';
    24 24  import {
    25 25   StatusTemplateCreationContextualMutation$data,
    26 26  } from './__generated__/StatusTemplateCreationContextualMutation.graphql';
     27 +import {
     28 + StatusTemplatesLinesPaginationQuery$variables,
     29 +} from './__generated__/StatusTemplatesLinesPaginationQuery.graphql';
    27 30   
    28 31  const useStyles = makeStyles<Theme>((theme) => ({
    29 32   drawerPaper: {
    skipped 69 lines
    99 102   creationCallback: (data: StatusTemplateCreationContextualMutation$data) => void,
    100 103   handleCloseContextual: () => void,
    101 104   openContextual: boolean,
    102  - paginationOptions?: { search: string, orderMode: string, orderBy: string },
     105 + paginationOptions?: StatusTemplatesLinesPaginationQuery$variables,
    103 106  }
    104 107   
    105 108  const StatusTemplateCreation: FunctionComponent<StatusTemplateCreationProps> = ({
    skipped 211 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/settings/workflow/StatusTemplatePopover.tsx
    skipped 17 lines
    18 18  import { commitMutation, QueryRenderer } from '../../../../relay/environment';
    19 19  import Loader, { LoaderVariant } from '../../../../components/Loader';
    20 20  import StatusTemplateEdition from './StatusTemplateEdition';
    21  -import { deleteNode } from '../../../../utils/Store';
     21 +import { deleteNode } from '../../../../utils/store';
    22 22  import { Theme } from '../../../../components/Theme';
    23 23  import { StatusTemplatePopoverEditionQuery$data } from './__generated__/StatusTemplatePopoverEditionQuery.graphql';
    24 24   
    skipped 174 lines
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/settings/workflow/StatusTemplates.tsx
    skipped 4 lines
    5 5  import WorkflowsStatusesMenu from './WorkflowsStatusesMenu';
    6 6  import StatusTemplateCreation from './StatusTemplateCreation';
    7 7  import StatusTemplatesLines, { statusTemplatesLinesQuery } from './StatusTemplatesLines';
    8  -import useLocalStorage from '../../../../utils/hooks/useLocalStorage';
    9  -import { StatusTemplatesLinesPaginationQuery$data } from './__generated__/StatusTemplatesLinesPaginationQuery.graphql';
     8 +import useLocalStorage, { localStorageToPaginationOptions } from '../../../../utils/hooks/useLocalStorage';
     9 +import {
     10 + StatusTemplatesLinesPaginationQuery$data,
     11 + StatusTemplatesLinesPaginationQuery$variables,
     12 +} from './__generated__/StatusTemplatesLinesPaginationQuery.graphql';
    10 13   
    11 14  const useStyles = makeStyles(() => ({
    12 15   container: {
    skipped 13 lines
    26 29   orderAsc: false,
    27 30   });
    28 31   const { sortBy, orderAsc, searchTerm } = viewStorage;
    29  - const queryVars = { search: searchTerm, orderMode: orderAsc ? 'asc' : 'desc', orderBy: sortBy };
     32 + const queryVars = localStorageToPaginationOptions<StatusTemplatesLinesPaginationQuery$variables>({ count: 25, ...viewStorage });
    30 33   
    31 34   const handleSearch = (value: string) => setViewStorage((c) => ({ ...c, searchTerm: value }));
    32 35   
    skipped 28 lines
    61 64   keyword={searchTerm}>
    62 65   <QueryRenderer
    63 66   query={statusTemplatesLinesQuery}
    64  - variables={{ count: 25, ...queryVars }}
     67 + variables={queryVars}
    65 68   render={({ props }: { props: StatusTemplatesLinesPaginationQuery$data }) => (
    66 69   <StatusTemplatesLines
    67 70   data={props}
    skipped 27 lines
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/settings/workflow/StatusTemplatesLines.tsx
    1 1  import React, { FunctionComponent } from 'react';
    2  -import { graphql, createPaginationContainer, RelayPaginationProp } from 'react-relay';
     2 +import { createPaginationContainer, graphql, RelayPaginationProp } from 'react-relay';
    3 3  import ListLinesContent from '../../../../components/list_lines/ListLinesContent';
    4 4  import StatusTemplateLine, { DataColumnsType } from './StatusTemplateLine';
    5 5  import StatusTemplateLineDummy from './StatusTemplateLineDummy';
    6 6  import { StatusTemplatesLines_data$data } from './__generated__/StatusTemplatesLines_data.graphql';
     7 +import {
     8 + StatusTemplatesLinesPaginationQuery$variables,
     9 +} from './__generated__/StatusTemplatesLinesPaginationQuery.graphql';
    7 10   
    8 11  const nbOfRowsToLoad = 50;
    9 12   
    10 13  interface StatusTemplatesLinesProps {
    11 14   relay: RelayPaginationProp,
    12  - paginationOptions: { search: string, orderMode: string, orderBy: string },
     15 + paginationOptions: StatusTemplatesLinesPaginationQuery$variables,
    13 16   dataColumns: DataColumnsType,
    14 17   data: StatusTemplatesLines_data$data,
    15 18   initialLoading: boolean,
    skipped 96 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/threats/campaigns/CampaignEditionOverview.js
    skipped 14 lines
    15 15  import CommitMessage from '../../common/form/CommitMessage';
    16 16  import { adaptFieldValue } from '../../../../utils/String';
    17 17  import StatusField from '../../common/form/StatusField';
    18  -import { convertCreatedBy, convertMarkings, convertStatus } from '../../../../utils/Edition';
     18 +import { convertCreatedBy, convertMarkings, convertStatus } from '../../../../utils/edition';
    19 19  import { fieldSpacingContainerStyle } from '../../../../utils/field';
    20 20   
    21 21  const campaignMutationFieldPatch = graphql`
    skipped 360 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/threats/intrusion_sets/IntrusionSetCreation.js
    skipped 18 lines
    19 19  import ObjectMarkingField from '../../common/form/ObjectMarkingField';
    20 20  import MarkDownField from '../../../../components/MarkDownField';
    21 21  import ConfidenceField from '../../common/form/ConfidenceField';
    22  -import { insertNode } from '../../../../utils/Store';
     22 +import { insertNode } from '../../../../utils/store';
    23 23  import ExternalReferencesField from '../../common/form/ExternalReferencesField';
    24 24  import { fieldSpacingContainerStyle } from '../../../../utils/field';
    25 25   
    skipped 255 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/threats/intrusion_sets/IntrusionSetEditionOverview.js
    skipped 13 lines
    14 14  import ConfidenceField from '../../common/form/ConfidenceField';
    15 15  import CommitMessage from '../../common/form/CommitMessage';
    16 16  import { adaptFieldValue } from '../../../../utils/String';
    17  -import { convertCreatedBy, convertMarkings, convertStatus } from '../../../../utils/Edition';
     17 +import { convertCreatedBy, convertMarkings, convertStatus } from '../../../../utils/edition';
    18 18  import StatusField from '../../common/form/StatusField';
    19 19  import { fieldSpacingContainerStyle } from '../../../../utils/field';
    20 20   
    skipped 369 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/threats/threat_actors/ThreatActorCreation.js
    skipped 23 lines
    24 24  import MarkDownField from '../../../../components/MarkDownField';
    25 25  import SelectField from '../../../../components/SelectField';
    26 26  import ConfidenceField from '../../common/form/ConfidenceField';
    27  -import { insertNode } from '../../../../utils/Store';
     27 +import { insertNode } from '../../../../utils/store';
    28 28  import ExternalReferencesField from '../../common/form/ExternalReferencesField';
    29 29   
    30 30  const styles = (theme) => ({
    skipped 311 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/private/components/threats/threat_actors/ThreatActorEditionOverview.js
    skipped 20 lines
    21 21   convertCreatedBy,
    22 22   convertMarkings,
    23 23   convertStatus,
    24  -} from '../../../../utils/Edition';
     24 +} from '../../../../utils/edition';
    25 25   
    26 26  const threatActorMutationFieldPatch = graphql`
    27 27   mutation ThreatActorEditionOverviewFieldPatchMutation(
    skipped 425 lines
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/schema/relay.schema.graphql
    skipped 1462 lines
    1463 1463   
    1464 1464  type MarkingDefinitionConnection {
    1465 1465   pageInfo: PageInfo!
    1466  - edges: [MarkingDefinitionEdge]
     1466 + edges: [MarkingDefinitionEdge!]
    1467 1467  }
    1468 1468   
    1469 1469  type MarkingDefinitionEdge {
    skipped 3548 lines
    5018 5018   
    5019 5019  type StixCyberObservableConnection {
    5020 5020   pageInfo: PageInfo!
    5021  - edges: [StixCyberObservableEdge]
     5021 + edges: [StixCyberObservableEdge!]
    5022 5022  }
    5023 5023   
    5024 5024  type StixCyberObservableEdge {
    skipped 3499 lines
  • ■ ■ ■ ■
    opencti-platform/opencti-front/src/utils/Edition.js opencti-platform/opencti-front/src/utils/edition.js
    skipped 22 lines
    23 23  )(element);
    24 24   
    25 25  export const convertCreatedBy = (element) => (R.pathOr(null, ['createdBy', 'name'], element) === null
    26  - ? ''
     26 + ? undefined
    27 27   : {
    28 28   label: element?.createdBy?.name ?? null,
    29 29   value: element?.createdBy?.id ?? null,
    skipped 2 lines
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/utils/hooks/useForceUpdate.ts
    1  -import { useCallback, useState } from 'react';
    2  - 
    3  -const useForceUpdate = () => {
    4  - const [, setValue] = useState<object>({});
    5  - 
    6  - return useCallback((): void => {
    7  - setValue({});
    8  - }, []);
    9  -};
    10  - 
    11  -export default useForceUpdate;
    12  - 
  • ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/utils/hooks/useLocalStorage.ts
    skipped 10 lines
    11 11   sortBy?: string,
    12 12   orderAsc?: boolean,
    13 13   openExports?: boolean,
     14 + count?: number
    14 15  }
    15 16   
    16 17  export const localStorageToPaginationOptions = <U>({
    skipped 2 lines
    19 20   sortBy,
    20 21   orderAsc,
    21 22   ...props
    22  -}: LocalStorage & Omit<U, 'filters'>): unknown extends U ? PaginationOptions : U => ({
    23  - ...props,
     23 +}: LocalStorage & Omit<U, 'filters'>): unknown extends U ? PaginationOptions : U => {
     24 + // OpenExports and NumberOfElements are only display options, not query linked
     25 + const { openExports: _, numberOfElements: __, ...localOptions } = props;
     26 + return ({
     27 + ...localOptions,
    24 28   search: searchTerm,
    25 29   orderMode: orderAsc ? OrderMode.asc : OrderMode.desc,
    26 30   orderBy: sortBy,
    27 31   filters,
    28 32   }) as unknown extends U ? PaginationOptions : U;
     33 +};
    29 34   
    30 35  export type UseLocalStorage = [value: LocalStorage,
    31 36   setValue: Dispatch<SetStateAction<LocalStorage>>,
    skipped 95 lines
  • ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/utils/hooks/useQueryLoading.ts
    skipped 11 lines
    12 12   if (!equals(variables, varRef.current)) {
    13 13   varRef.current = variables;
    14 14   }
    15  - console.log('Variables', JSON.stringify(variables));
    16 15   // refetch when variables change
    17 16   useEffect(() => {
    18 17   loadQuery(variables);
    skipped 7 lines
  • ■ ■ ■ ■ ■
    opencti-platform/opencti-front/src/utils/Store.js opencti-platform/opencti-front/src/utils/store.js
    skipped 10 lines
    11 11  export const insertNode = (store, key, filters, rootField) => {
    12 12   // Build record ids
    13 13   const record = store.get(store.getRoot().getDataID());
    14  - const conn = ConnectionHandler.getConnection(record, key, filters);
     14 + 
     15 + // Connections cannot use count as a filter because we NEED to update the count when we push new elements
     16 + const params = { ...filters };
     17 + delete params.count;
     18 + 
     19 + const conn = ConnectionHandler.getConnection(record, key, params);
    15 20   if (conn) {
    16 21   // Build the payload to add
    17 22   const payload = store.getRootField(rootField);
    skipped 9 lines
    27 32   
    28 33  export const deleteNode = (store, key, filters, id) => {
    29 34   const record = store.get(store.getRoot().getDataID());
    30  - const conn = ConnectionHandler.getConnection(record, key, filters);
     35 + 
     36 + // Connections cannot use count as a filter because we NEED to update the count when we remove new elements
     37 + const params = { ...filters };
     38 + delete params.count;
     39 + 
     40 + const conn = ConnectionHandler.getConnection(record, key, params);
    31 41   if (conn) {
    32 42   ConnectionHandler.deleteNode(conn, id);
    33 43   } else {
    skipped 5 lines
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-graphql/config/schema/opencti.graphql
    skipped 1403 lines
    1404 1404  }
    1405 1405  type MarkingDefinitionConnection {
    1406 1406   pageInfo: PageInfo!
    1407  - edges: [MarkingDefinitionEdge]
     1407 + edges: [MarkingDefinitionEdge!]
    1408 1408  }
    1409 1409  type MarkingDefinitionEdge {
    1410 1410   cursor: String!
    skipped 4291 lines
    5702 5702  }
    5703 5703  type StixCyberObservableConnection {
    5704 5704   pageInfo: PageInfo!
    5705  - edges: [StixCyberObservableEdge]
     5705 + edges: [StixCyberObservableEdge!]
    5706 5706  }
    5707 5707  type StixCyberObservableEdge {
    5708 5708   cursor: String!
    skipped 5457 lines
  • ■ ■ ■ ■ ■ ■
    opencti-platform/opencti-graphql/src/generated/graphql.ts
    skipped 7418 lines
    7419 7419   
    7420 7420  export type MarkingDefinitionConnection = {
    7421 7421   __typename?: 'MarkingDefinitionConnection';
    7422  - edges?: Maybe<Array<Maybe<MarkingDefinitionEdge>>>;
     7422 + edges?: Maybe<Array<MarkingDefinitionEdge>>;
    7423 7423   pageInfo: PageInfo;
    7424 7424  };
    7425 7425   
    skipped 7453 lines
    14879 14879   
    14880 14880  export type StixCyberObservableConnection = {
    14881 14881   __typename?: 'StixCyberObservableConnection';
    14882  - edges?: Maybe<Array<Maybe<StixCyberObservableEdge>>>;
     14882 + edges?: Maybe<Array<StixCyberObservableEdge>>;
    14883 14883   pageInfo: PageInfo;
    14884 14884  };
    14885 14885   
    skipped 4558 lines
    19444 19444   StixCoreRelationshipsFiltering: StixCoreRelationshipsFiltering;
    19445 19445   StixCoreRelationshipsOrdering: StixCoreRelationshipsOrdering;
    19446 19446   StixCyberObservable: ResolversTypes['Artifact'] | ResolversTypes['AutonomousSystem'] | ResolversTypes['BankAccount'] | ResolversTypes['CryptocurrencyWallet'] | ResolversTypes['CryptographicKey'] | ResolversTypes['Directory'] | ResolversTypes['DomainName'] | ResolversTypes['EmailAddr'] | ResolversTypes['EmailMessage'] | ResolversTypes['EmailMimePartType'] | ResolversTypes['Hostname'] | ResolversTypes['IPv4Addr'] | ResolversTypes['IPv6Addr'] | ResolversTypes['MacAddr'] | ResolversTypes['MediaContent'] | ResolversTypes['Mutex'] | ResolversTypes['NetworkTraffic'] | ResolversTypes['PaymentCard'] | ResolversTypes['PhoneNumber'] | ResolversTypes['Process'] | ResolversTypes['Software'] | ResolversTypes['StixFile'] | ResolversTypes['Text'] | ResolversTypes['Url'] | ResolversTypes['UserAccount'] | ResolversTypes['UserAgent'] | ResolversTypes['WindowsRegistryKey'] | ResolversTypes['WindowsRegistryValueType'] | ResolversTypes['X509Certificate'];
    19447  - StixCyberObservableConnection: ResolverTypeWrapper<Omit<StixCyberObservableConnection, 'edges'> & { edges?: Maybe<Array<Maybe<ResolversTypes['StixCyberObservableEdge']>>> }>;
     19447 + StixCyberObservableConnection: ResolverTypeWrapper<Omit<StixCyberObservableConnection, 'edges'> & { edges?: Maybe<Array<ResolversTypes['StixCyberObservableEdge']>> }>;
    19448 19448   StixCyberObservableEdge: ResolverTypeWrapper<Omit<StixCyberObservableEdge, 'node'> & { node: ResolversTypes['StixCyberObservable'] }>;
    19449 19449   StixCyberObservableEditMutations: ResolverTypeWrapper<Omit<StixCyberObservableEditMutations, 'contextClean' | 'contextPatch' | 'exportAsk' | 'fieldPatch' | 'importPush' | 'promote' | 'relationDelete' | 'relationsAdd'> & { contextClean?: Maybe<ResolversTypes['StixCyberObservable']>, contextPatch?: Maybe<ResolversTypes['StixCyberObservable']>, exportAsk?: Maybe<Array<Maybe<ResolversTypes['File']>>>, fieldPatch?: Maybe<ResolversTypes['StixCyberObservable']>, importPush?: Maybe<ResolversTypes['File']>, promote?: Maybe<ResolversTypes['StixCyberObservable']>, relationDelete?: Maybe<ResolversTypes['StixCyberObservable']>, relationsAdd?: Maybe<ResolversTypes['StixCyberObservable']> }>;
    19450 19450   StixCyberObservableRelationship: ResolverTypeWrapper<Omit<StixCyberObservableRelationship, 'from' | 'groupings' | 'notes' | 'opinions' | 'reports' | 'to'> & { from?: Maybe<ResolversTypes['StixObjectOrStixRelationship']>, groupings?: Maybe<ResolversTypes['GroupingConnection']>, notes?: Maybe<ResolversTypes['NoteConnection']>, opinions?: Maybe<ResolversTypes['OpinionConnection']>, reports?: Maybe<ResolversTypes['ReportConnection']>, to?: Maybe<ResolversTypes['StixObjectOrStixRelationship']> }>;
    skipped 541 lines
    19992 19992   StixCoreRelationshipEditMutations: Omit<StixCoreRelationshipEditMutations, 'contextClean' | 'contextPatch' | 'fieldPatch' | 'relationDelete' | 'restrictionOrganizationAdd' | 'restrictionOrganizationDelete'> & { contextClean?: Maybe<ResolversParentTypes['StixCoreRelationship']>, contextPatch?: Maybe<ResolversParentTypes['StixCoreRelationship']>, fieldPatch?: Maybe<ResolversParentTypes['StixCoreRelationship']>, relationDelete?: Maybe<ResolversParentTypes['StixCoreRelationship']>, restrictionOrganizationAdd?: Maybe<ResolversParentTypes['StixCoreRelationship']>, restrictionOrganizationDelete?: Maybe<ResolversParentTypes['StixCoreRelationship']> };
    19993 19993   StixCoreRelationshipsFiltering: StixCoreRelationshipsFiltering;
    19994 19994   StixCyberObservable: ResolversParentTypes['Artifact'] | ResolversParentTypes['AutonomousSystem'] | ResolversParentTypes['BankAccount'] | ResolversParentTypes['CryptocurrencyWallet'] | ResolversParentTypes['CryptographicKey'] | ResolversParentTypes['Directory'] | ResolversParentTypes['DomainName'] | ResolversParentTypes['EmailAddr'] | ResolversParentTypes['EmailMessage'] | ResolversParentTypes['EmailMimePartType'] | ResolversParentTypes['Hostname'] | ResolversParentTypes['IPv4Addr'] | ResolversParentTypes['IPv6Addr'] | ResolversParentTypes['MacAddr'] | ResolversParentTypes['MediaContent'] | ResolversParentTypes['Mutex'] | ResolversParentTypes['NetworkTraffic'] | ResolversParentTypes['PaymentCard'] | ResolversParentTypes['PhoneNumber'] | ResolversParentTypes['Process'] | ResolversParentTypes['Software'] | ResolversParentTypes['StixFile'] | ResolversParentTypes['Text'] | ResolversParentTypes['Url'] | ResolversParentTypes['UserAccount'] | ResolversParentTypes['UserAgent'] | ResolversParentTypes['WindowsRegistryKey'] | ResolversParentTypes['WindowsRegistryValueType'] | ResolversParentTypes['X509Certificate'];
    19995  - StixCyberObservableConnection: Omit<StixCyberObservableConnection, 'edges'> & { edges?: Maybe<Array<Maybe<ResolversParentTypes['StixCyberObservableEdge']>>> };
     19995 + StixCyberObservableConnection: Omit<StixCyberObservableConnection, 'edges'> & { edges?: Maybe<Array<ResolversParentTypes['StixCyberObservableEdge']>> };
    19996 19996   StixCyberObservableEdge: Omit<StixCyberObservableEdge, 'node'> & { node: ResolversParentTypes['StixCyberObservable'] };
    19997 19997   StixCyberObservableEditMutations: Omit<StixCyberObservableEditMutations, 'contextClean' | 'contextPatch' | 'exportAsk' | 'fieldPatch' | 'importPush' | 'promote' | 'relationDelete' | 'relationsAdd'> & { contextClean?: Maybe<ResolversParentTypes['StixCyberObservable']>, contextPatch?: Maybe<ResolversParentTypes['StixCyberObservable']>, exportAsk?: Maybe<Array<Maybe<ResolversParentTypes['File']>>>, fieldPatch?: Maybe<ResolversParentTypes['StixCyberObservable']>, importPush?: Maybe<ResolversParentTypes['File']>, promote?: Maybe<ResolversParentTypes['StixCyberObservable']>, relationDelete?: Maybe<ResolversParentTypes['StixCyberObservable']>, relationsAdd?: Maybe<ResolversParentTypes['StixCyberObservable']> };
    19998 19998   StixCyberObservableRelationship: Omit<StixCyberObservableRelationship, 'from' | 'groupings' | 'notes' | 'opinions' | 'reports' | 'to'> & { from?: Maybe<ResolversParentTypes['StixObjectOrStixRelationship']>, groupings?: Maybe<ResolversParentTypes['GroupingConnection']>, notes?: Maybe<ResolversParentTypes['NoteConnection']>, opinions?: Maybe<ResolversParentTypes['OpinionConnection']>, reports?: Maybe<ResolversParentTypes['ReportConnection']>, to?: Maybe<ResolversParentTypes['StixObjectOrStixRelationship']> };
    skipped 2610 lines
    22609 22609  }>;
    22610 22610   
    22611 22611  export type MarkingDefinitionConnectionResolvers<ContextType = any, ParentType extends ResolversParentTypes['MarkingDefinitionConnection'] = ResolversParentTypes['MarkingDefinitionConnection']> = ResolversObject<{
    22612  - edges?: Resolver<Maybe<Array<Maybe<ResolversTypes['MarkingDefinitionEdge']>>>, ParentType, ContextType>;
     22612 + edges?: Resolver<Maybe<Array<ResolversTypes['MarkingDefinitionEdge']>>, ParentType, ContextType>;
    22613 22613   pageInfo?: Resolver<ResolversTypes['PageInfo'], ParentType, ContextType>;
    22614 22614   __isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
    22615 22615  }>;
    skipped 1859 lines
    24475 24475  }>;
    24476 24476   
    24477 24477  export type StixCyberObservableConnectionResolvers<ContextType = any, ParentType extends ResolversParentTypes['StixCyberObservableConnection'] = ResolversParentTypes['StixCyberObservableConnection']> = ResolversObject<{
    24478  - edges?: Resolver<Maybe<Array<Maybe<ResolversTypes['StixCyberObservableEdge']>>>, ParentType, ContextType>;
     24478 + edges?: Resolver<Maybe<Array<ResolversTypes['StixCyberObservableEdge']>>, ParentType, ContextType>;
    24479 24479   pageInfo?: Resolver<ResolversTypes['PageInfo'], ParentType, ContextType>;
    24480 24480   __isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
    24481 24481  }>;
    skipped 1746 lines
Please wait...
Page is in error, reload to recover