Skip to content

Commit

Permalink
Merge pull request #585 from kbss-cvut/fix/581-fix-creation-of-event-…
Browse files Browse the repository at this point in the history
…in-fault-tree

Fix/581 fix creation of event in fault tree
  • Loading branch information
kostobog authored Sep 5, 2024
2 parents bd0903a + a68e804 commit f622bd0
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 18 deletions.
32 changes: 24 additions & 8 deletions src/components/dialog/faultEvent/FaultEventCreation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const FaultEventCreation = ({
register,
} = useFormMethods;

const faultEvents = useReusableFaultEvents();
const faultEvents = disabled ? [] : useReusableFaultEvents();
const [newEvent, setNewEvent] = useState<string | null>(null);
const [selectedEvent, setSelectedEvent] = useState<FaultEvent | null>(null);
const [showCreateEvent, setShowCreateEvent] = useState(false);
Expand All @@ -49,18 +49,20 @@ const FaultEventCreation = ({
const gateTypeWatch = watch("gateType");

useEffect(() => {
reset();
if (selectedEvent) {
setValue("name", selectedEvent.name);
setValue("existingEvent", selectedEvent.iri ? selectedEvent : null);
setValue(
"existingEvent",
selectedEvent?.supertypes ? selectedEvent?.supertypes[0] : selectedEvent.iri ? selectedEvent : null,
);
if (existingEventSelected) {
setValue("eventType", selectedEvent.eventType);
}
if (isRootEvent || isCreatedEvent) {
setValue("eventType", EventType.INTERMEDIATE);
setValue("gateType", GateType.OR);
}
} else {
reset();
}
}, [isRootEvent, selectedEvent, setValue, existingEventSelected, isCreatedEvent, reset]);

Expand All @@ -83,12 +85,20 @@ const FaultEventCreation = ({

const handleEventSelect = (data: any) => {
setSelectedEvent(data);
setIsCreatedEvent(false);
if (!data) {
reset();
return;
}
setIsCreatedEvent(!data.iri);
};

function renderEventSelect() {
const eventVal = asArray(eventValue?.supertypes)?.[0] || eventValue;
const defaultValue = eventVal ? { name: eventVal.name, iri: eventVal.iri } : null;
const _eventVal = eventVal ? { name: eventVal.name, iri: eventVal.iri } : null;
if (_eventVal && !faultEvents.some((evt) => evt.iri === _eventVal.iri)) {
faultEvents.push(_eventVal);
updatedFHAEventTypes.push(_eventVal);
}
return (
<>
<Typography variant="subtitle1" gutterBottom>
Expand All @@ -97,8 +107,15 @@ const FaultEventCreation = ({

<ControlledAutocomplete
control={control}
name="event"
name="existingEvent"
options={isRootEvent ? faultEvents : updatedFHAEventTypes}
clearOnBlur={true}
newOption={(name) => {
return {
iri: null,
name: name,
};
}}
onChangeCallback={handleEventSelect}
onInputChangeCallback={handleFilterOptions}
onCreateEventClick={handleOnCreateEventClick}
Expand All @@ -107,7 +124,6 @@ const FaultEventCreation = ({
renderInput={(params) => (
<TextField {...params} label={t("newFtaModal.eventPlaceholder")} variant="outlined" {...register("name")} />
)}
defaultValue={defaultValue}
disabled={disabled}
/>

Expand Down
15 changes: 9 additions & 6 deletions src/components/dialog/faultEvent/FaultEventDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,30 @@ const FaultEventDialog = ({ open, eventIri, treeUri, onCreated, onClose }: Props

const [selectedSystem] = useSelectedSystemSummaries();
const useFormMethods = useForm({ resolver: yupResolver(faultEventSchema) });
const { handleSubmit, formState } = useFormMethods;
const { handleSubmit, formState, reset } = useFormMethods;
const { isSubmitting } = formState;

const handleClose = () => {
onClose();
reset();
};

const handleCreateEvent = async (values: any) => {
const requestEvent = eventFromHookFormValues(values);

faultEventService
.addEvent(eventIri, requestEvent)
.then((value) => {
onClose();
handleClose();
onCreated(value);
})
.catch((reason) => showSnackbar(reason, SnackbarType.ERROR));
};

return (
<div>
<Dialog open={open} onClose={onClose} aria-labelledby="form-dialog-title" maxWidth="md" fullWidth>
<DialogTitle id="form-dialog-title" onClose={onClose}>
Create Event
</DialogTitle>
<Dialog open={open} onClose={handleClose} aria-labelledby="form-dialog-title" maxWidth="md" fullWidth>
<DialogTitle id="form-dialog-title">Create Event</DialogTitle>
<DialogContent dividers>
<ReusableFaultEventsProvider treeUri={treeUri} systemUri={selectedSystem?.iri}>
<FaultEventCreation useFormMethods={useFormMethods} isRootEvent={false} />
Expand Down
63 changes: 59 additions & 4 deletions src/components/materialui/ControlledAutocomplete.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React, { useState } from "react";
import { Controller } from "react-hook-form";
import { Autocomplete, Grid, Link, Typography } from "@mui/material";
import { Autocomplete, createFilterOptions, Grid, Link, Tooltip, Typography } from "@mui/material";
import { simplifyReferences } from "@utils/utils";
import { useTranslation } from "react-i18next";
import { AddCircle } from "@mui/icons-material";

interface Props {
name: string;
options: any[];
newOption?: (string) => any;
getOptionKey: (any) => string;
getOptionLabel: (any) => string;
renderInput;
Expand Down Expand Up @@ -48,6 +50,7 @@ const ControlledAutocomplete = ({
options = [],
name,
renderInput,
newOption = null,
getOptionKey,
getOptionLabel,
control,
Expand All @@ -64,6 +67,7 @@ const ControlledAutocomplete = ({
// TODO - refactor use SafeAutocomplete instead of the implementation here
const [_options, _defaultValue, getOptionValue] = prepareOptions(useSafeOptions, options, defaultValue);
const [menuOpen, setMenuOpen] = useState(false);
const [newOptionValue, setNewOptionValue] = useState(null);
const { t } = useTranslation();

const handleOnClick = (e) => {
Expand All @@ -86,28 +90,79 @@ const ControlledAutocomplete = ({
);
};

const defaultFilter = createFilterOptions();
const newOptionFilter = (options, state) => {
const filtered = defaultFilter(options, state);
const { inputValue } = state;
const isExisting = filtered.some((option) => inputValue === getOptionLabel(option));
if (inputValue !== "" && !isExisting) {
const inputOption = newOption(inputValue);
inputOption.newOption = true;
filtered.splice(0, 0, inputOption);
}
return filtered;
};

const renderNewOption = (params, option) => {
const { key, ...optionProps } = params;

return (
<li key={key} {...optionProps}>
<Grid container alignItems="center" justifyContent="space-between">
<Grid item>{getOptionLabel(option)}</Grid>
<Grid item>
{option?.newOption && (
<Tooltip title={t("newFtaModal.createEvent")}>
<AddCircle style={{ color: "green" }} />
</Tooltip>
)}
</Grid>
</Grid>
</li>
);
};

const getNewOptionLabel = (option) => {
// Value selected with enter, right from the input
if (typeof option === "string") {
return option;
}

// Regular option
return getOptionLabel(option);
};

return (
<Controller
render={({ field: { onChange, onBlur, value, ref }, ...props }) => (
<Autocomplete
fullWidth
options={_options}
getOptionKey={getOptionKey}
getOptionLabel={getOptionLabel}
renderOption={renderOption}
getOptionLabel={newOption ? getNewOptionLabel : getOptionLabel}
renderOption={renderNewOption}
renderInput={renderInput}
clearOnBlur={clearOnBlur}
freeSolo
onChange={(e, data) => {
let _data = getOptionValue(data);
if (!data || data.newOption) setNewOptionValue(data);
onChangeCallback(_data);
onChange(data);
}}
filterOptions={newOption ? newOptionFilter : defaultFilter}
onBlur={onBlur}
value={value}
value={newOptionValue ? newOptionValue : value}
ref={ref}
onInputChange={(e, inputValue) => {
if (!inputValue) onChangeCallback(null);
onInputChangeCallback(inputValue);
}}
isOptionEqualToValue={
getOptionKey
? (option, value) => value && (value?.newOption || getOptionKey(option) === getOptionKey(value))
: null
}
open={menuOpen}
onClose={() => setMenuOpen(false)}
onOpen={() => setMenuOpen(true)}
Expand Down

0 comments on commit f622bd0

Please sign in to comment.