Skip to content

Commit

Permalink
[frontend] Fix marking definition handling in workbench (#4698)
Browse files Browse the repository at this point in the history
  • Loading branch information
SamuelHassine committed Oct 20, 2023
1 parent 88ebeb3 commit 91cdfa8
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,34 +29,38 @@ const useStyles = makeStyles(() => ({
}));

export const objectMarkingFieldAllowedMarkingsQuery = graphql`
query ObjectMarkingFieldAllowedMarkingsQuery {
me {
allowed_marking {
id
entity_type
standard_id
definition_type
definition
x_opencti_color
x_opencti_order
}
}
query ObjectMarkingFieldAllowedMarkingsQuery {
me {
allowed_marking {
id
entity_type
standard_id
definition_type
definition
x_opencti_color
x_opencti_order
}
}
}
`;

interface ObjectMarkingFieldProps {
name: string;
style?: React.CSSProperties;
onChange?: (name: string, values: Option[], operation?: string | undefined) => void;
onChange?: (
name: string,
values: Option[],
operation?: string | undefined,
) => void;
helpertext?: unknown;
disabled?: boolean;
label?: string;
setFieldValue?: (name: string, values: Option[]) => void
setFieldValue?: (name: string, values: Option[]) => void;
}

interface OptionValues {
currentValues: Option[],
valueToReplace: Option
currentValues: Option[];
valueToReplace: Option;
}

const ObjectMarkingField: FunctionComponent<ObjectMarkingFieldProps> = ({
Expand All @@ -70,17 +74,19 @@ const ObjectMarkingField: FunctionComponent<ObjectMarkingFieldProps> = ({
}) => {
const classes = useStyles();
const { t } = useFormatter();
const [newMarking, setNewMarking] = useState<Option[] | OptionValues | undefined>(undefined);
const [newMarking, setNewMarking] = useState<
Option[] | OptionValues | undefined
>(undefined);
const [operation, setOperation] = useState<string | undefined>(undefined);

const { me } = useAuth();
const allowedMarkingDefinitions = me.allowed_marking?.map(convertMarking) ?? [];

const optionSorted = allowedMarkingDefinitions.sort((a, b) => {
if (a.definition_type === b.definition_type) {
return (a.x_opencti_order < b.x_opencti_order ? -1 : 1);
return a.x_opencti_order < b.x_opencti_order ? -1 : 1;
}
return (a.definition_type < b.definition_type ? -1 : 1);
return a.definition_type < b.definition_type ? -1 : 1;
});
const handleClose = () => {
setNewMarking(undefined);
Expand All @@ -100,7 +106,11 @@ const ObjectMarkingField: FunctionComponent<ObjectMarkingFieldProps> = ({
if (operation === 'replace') {
const { currentValues, valueToReplace } = newMarking as OptionValues;
const markingAdded = currentValues[currentValues.length - 1];
const markingsReplace = currentValues.filter((marking) => marking.definition_type !== valueToReplace.definition_type).concat([markingAdded]);
const markingsReplace = currentValues
.filter(
(marking) => marking.definition_type !== valueToReplace.definition_type,
)
.concat([markingAdded]);

onChange?.(name, markingsReplace as Option[], operation);
setOperation(undefined);
Expand All @@ -112,10 +122,16 @@ const ObjectMarkingField: FunctionComponent<ObjectMarkingFieldProps> = ({
};
const handleOnChange = (n: string, values: Option[]) => {
const valueAdded = values[values.length - 1];
const valueToReplace = values.find((marking) => marking.definition_type === valueAdded.definition_type && marking.x_opencti_order !== valueAdded.x_opencti_order);
const valueToReplace = values.find(
(marking) => marking.definition_type === valueAdded.definition_type
&& marking.x_opencti_order !== valueAdded.x_opencti_order,
);

if (valueToReplace) {
if ((valueToReplace.x_opencti_order ?? 0) > (valueAdded.x_opencti_order ?? 0)) {
if (
(valueToReplace.x_opencti_order ?? 0)
> (valueAdded.x_opencti_order ?? 0)
) {
setOperation('replace');
setNewMarking({ currentValues: values, valueToReplace });
} else {
Expand All @@ -126,57 +142,55 @@ const ObjectMarkingField: FunctionComponent<ObjectMarkingFieldProps> = ({
};

const renderOption: RenderOption = (props, option) => (
<li {...props}>
<div className={classes.icon} style={{ color: option.color }}>
<ItemIcon type="Marking-Definition" color={option.color}/>
</div>
<div className={classes.text}>{option.label}</div>
</li>
<li {...props}>
<div className={classes.icon} style={{ color: option.color }}>
<ItemIcon type="Marking-Definition" color={option.color} />
</div>
<div className={classes.text}>{option.label}</div>
</li>
);

return (
<>
<Field
component={AutocompleteField}
style={style}
name={name}
multiple={true}
disabled={disabled}
textfieldprops={{
variant: 'standard',
label: label ?? t('Markings'),
helperText: helpertext,
}}
noOptionsText={t('No available options')}
options={optionSorted}
onChange={typeof onChange === 'function' ? handleOnChange : null}
renderOption={renderOption}
/>
<Dialog
PaperProps={{ elevation: 1 }}
open={!!newMarking}
keepMounted={true}
TransitionComponent={Transition}
onClose={handleClose}
>
<DialogContent>
<DialogContentText>
{t('You are about to change the marking with another rank.')}
</DialogContentText>
<DialogContentText>
{t('Are you sure you want to make the change?')}
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleCancellation}>
{t('Cancel')}
</Button>
<Button color="secondary" onClick={submitUpdate}>
{t('Replace')}
</Button>
</DialogActions>
</Dialog>
</>
<>
<Field
component={AutocompleteField}
style={style}
name={name}
multiple={true}
disabled={disabled}
textfieldprops={{
variant: 'standard',
label: label ?? t('Markings'),
helperText: helpertext,
}}
noOptionsText={t('No available options')}
options={optionSorted}
onChange={typeof onChange === 'function' ? handleOnChange : null}
renderOption={renderOption}
/>
<Dialog
PaperProps={{ elevation: 1 }}
open={!!newMarking}
keepMounted={true}
TransitionComponent={Transition}
onClose={handleClose}
>
<DialogContent>
<DialogContentText>
{t('You are about to change the marking with another rank.')}
</DialogContentText>
<DialogContentText>
{t('Are you sure you want to make the change?')}
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleCancellation}>{t('Cancel')}</Button>
<Button color="secondary" onClick={submitUpdate}>
{t('Replace')}
</Button>
</DialogActions>
</Dialog>
</>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export interface Option {
color?: string;
[key: string]: ReactNode;
type?: string;
standard_id?: string;
}

interface RelationFieldProps {
Expand Down
18 changes: 13 additions & 5 deletions opencti-platform/opencti-front/src/utils/edition.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export const convertMarking = (element) => ({
color: element.x_opencti_color,
definition_type: element.definition_type,
x_opencti_order: element.x_opencti_order,
entity: {
...element,
},
});

export const convertMarkings = (element) => (element?.objectMarking?.edges ?? []).map((n) => convertMarking(n.node));
Expand All @@ -27,7 +30,10 @@ export const convertTriggers = (element) => (element?.triggers ?? []).map((n) =>
value: n.id,
}));

export const convertAuthorizedMembers = (element) => (element?.authorized_members ?? []).map(({ id, name }) => ({ value: id, label: name }));
export const convertAuthorizedMembers = (element) => (element?.authorized_members ?? []).map(({ id, name }) => ({
value: id,
label: name,
}));

export const convertAssignees = (element) => (element?.objectAssignee?.edges ?? []).map((n) => ({
label: n.node.name,
Expand Down Expand Up @@ -59,7 +65,9 @@ export const convertExternalReferences = (element) => (element?.externalReferenc

export const convertImagesToCarousel = (element) => {
const images = element.images.edges ?? [];
const carouselImages = images ? images.filter(({ node }) => node?.metaData.inCarousel === true) : [];
const carouselImages = images
? images.filter(({ node }) => node?.metaData.inCarousel === true)
: [];
return carouselImages.map((file) => ({
tooltipTitle: file.node.metaData.description,
imageSrc: getFileUri(file.node.id),
Expand All @@ -84,7 +92,7 @@ export const convertUser = (element, field = 'user') => (isEmptyField(element?.[
type: element[field].entity_type,
});

export const convertNotifiers = (element) => (element?.notifiers?.map(({ id, name }) => ({ value: id, label: name })));
export const convertNotifiers = (element) => element?.notifiers?.map(({ id, name }) => ({ value: id, label: name }));

export const filterEventTypesOptions = [
{ value: 'create', label: 'Creation' },
Expand All @@ -97,6 +105,6 @@ export const instanceEventTypesOptions = [
{ value: 'delete', label: 'Deletion' },
];

export const convertEventTypes = (element) => (element?.event_types?.map((event_type) => {
export const convertEventTypes = (element) => element?.event_types?.map((event_type) => {
return filterEventTypesOptions.find((o) => o.value === event_type);
}));
});

0 comments on commit 91cdfa8

Please sign in to comment.