Skip to content

Commit

Permalink
Add draw interaction (#1527)
Browse files Browse the repository at this point in the history
  • Loading branch information
tschumpr authored Sep 24, 2024
2 parents c44ba9b + 5707bce commit e4bef3d
Show file tree
Hide file tree
Showing 16 changed files with 624 additions and 223 deletions.
2 changes: 2 additions & 0 deletions src/client/public/locale/de/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"alls": "Alle",
"alteration": "Verwitterung",
"alternate_name": "Name",
"analyze": "Analysieren",
"appearance": "Erscheinungsbild",
"attachments": "Anhänge",
"backfill": "Verfüllung/Hinterfüllung",
Expand Down Expand Up @@ -116,6 +117,7 @@
"disclaimer_publish_title": "Disclaimer wird publiziert",
"done": "Ok",
"draft": "Entwurf",
"drawCoordinateBox": "Rahmen um Nord- und Ostkoordinaten zeichnen",
"drill_core_diameter": "Bohrkerndurchmesser [mm]",
"drill_diameter": "Bohrdurchmesser [mm]",
"drilling_end_date": "Datum Bohrende",
Expand Down
2 changes: 2 additions & 0 deletions src/client/public/locale/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"alls": "All",
"alteration": "Alteration",
"alternate_name": "Name",
"analyze": "Analyzing",
"appearance": "Appearance",
"attachments": "Attachments",
"backfill": "Sealing/Backfilling",
Expand Down Expand Up @@ -116,6 +117,7 @@
"disclaimer_publish_title": "Publish disclaimer",
"done": "Done",
"draft": "Draft",
"drawCoordinateBox": "Draw box around north & east coordinates",
"drill_core_diameter": "Core diameter [mm]",
"drill_diameter": "Borehole diameter [mm]",
"drilling_end_date": "Drilling date: end",
Expand Down
2 changes: 2 additions & 0 deletions src/client/public/locale/fr/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"alls": "Tous",
"alteration": "Altération",
"alternate_name": "Nom",
"analyze": "Analyser",
"appearance": "Mode de présentation",
"attachments": "Annexes",
"backfill": "Remplissage/Remblayage",
Expand Down Expand Up @@ -116,6 +117,7 @@
"disclaimer_publish_title": "La clause de non-responsabilité sera publiée",
"done": "OK",
"draft": "Ébauche",
"drawCoordinateBox": "Tracer un cadre autour des coordonnées nord et est",
"drill_core_diameter": "Diamètre de la carotte [mm]",
"drill_diameter": "Diamètre de forage [mm]",
"drilling_end_date": "Date de fin de forage",
Expand Down
2 changes: 2 additions & 0 deletions src/client/public/locale/it/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"alls": "Tutti",
"alteration": "Alterazione",
"alternate_name": "Nome",
"analyze": "Analisi in corso",
"appearance": "Aspetto",
"attachments": "Allegati",
"backfill": "Riempimento/Rinterro",
Expand Down Expand Up @@ -116,6 +117,7 @@
"disclaimer_publish_title": "Il disclaimer sarà pubblicato",
"done": "OK",
"draft": "Bozza",
"drawCoordinateBox": "Disegna un riquadro intorno alle coordinate nord ed est",
"drill_core_diameter": "Diametro della carota [mm]",
"drill_diameter": "Diametro perforazione [mm]",
"drilling_end_date": "Data fine della perforazione",
Expand Down
1 change: 1 addition & 0 deletions src/client/src/AppTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const theme = createTheme({
ai: {
background: "#46596B",
main: "#5B21B6",
mainTransparent: "rgba(91, 33, 182, 0.2)",
mainEnd: "#8B5CF6",
active: "#4F46E5",
activeEnd: "#E53940",
Expand Down
39 changes: 5 additions & 34 deletions src/client/src/components/alert/alertContext.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createContext, FC, PropsWithChildren, useEffect, useState } from "react";
import { AlertColor } from "@mui/material";
import { AlertContextInterface, AlertOptions } from "./alertInterfaces";
import { createContext, FC, PropsWithChildren } from "react";
import { AlertContextInterface } from "./alertInterfaces";
import { useAlertManager } from "./alertManager.tsx";

export const AlertContext = createContext<AlertContextInterface>({
alertIsOpen: false,
Expand All @@ -12,36 +12,7 @@ export const AlertContext = createContext<AlertContextInterface>({
});

export const AlertProvider: FC<PropsWithChildren> = ({ children }) => {
const [currentAlert, setCurrentAlert] = useState<AlertOptions>();
const [alerts, setAlerts] = useState<AlertOptions[]>([]);
const alertManager = useAlertManager();

const showAlert = (text: string, severity: AlertColor | undefined, allowAutoHide: boolean | undefined) => {
const newAlert = { text, severity: severity ?? "info", allowAutoHide: allowAutoHide ?? true };
setAlerts(prevAlerts => [...prevAlerts, newAlert]);
};

const closeAlert = () => {
setCurrentAlert(undefined);
};

useEffect(() => {
if (alerts.length > 0 && !currentAlert) {
setCurrentAlert(alerts[0]);
setAlerts(prevAlerts => prevAlerts.slice(1));
}
}, [alerts, currentAlert]);

return (
<AlertContext.Provider
value={{
alertIsOpen: currentAlert?.text != null,
text: currentAlert?.text,
severity: currentAlert?.severity,
autoHideDuration: currentAlert?.allowAutoHide === true ? 6000 : null,
showAlert,
closeAlert,
}}>
{children}
</AlertContext.Provider>
);
return <AlertContext.Provider value={alertManager}>{children}</AlertContext.Provider>;
};
33 changes: 33 additions & 0 deletions src/client/src/components/alert/alertManager.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useEffect, useState } from "react";
import { AlertColor } from "@mui/material";
import { AlertOptions } from "./alertInterfaces";

export const useAlertManager = () => {
const [currentAlert, setCurrentAlert] = useState<AlertOptions>();
const [alerts, setAlerts] = useState<AlertOptions[]>([]);

const showAlert = (text: string, severity: AlertColor | undefined, allowAutoHide?: boolean) => {
const newAlert = { text, severity: severity ?? "info", allowAutoHide: allowAutoHide ?? true };
setAlerts(prevAlerts => [...prevAlerts, newAlert]);
};

const closeAlert = () => {
setCurrentAlert(undefined);
};

useEffect(() => {
if (alerts.length > 0 && !currentAlert) {
setCurrentAlert(alerts[0]);
setAlerts(prevAlerts => prevAlerts.slice(1));
}
}, [alerts, currentAlert]);

return {
alertIsOpen: currentAlert?.text != null,
text: currentAlert?.text,
severity: currentAlert?.severity,
autoHideDuration: currentAlert?.allowAutoHide === true ? 6000 : null,
showAlert,
closeAlert,
};
};
4 changes: 3 additions & 1 deletion src/client/src/components/buttons/buttonSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ interface ButtonSelectProps {
transformOrigin?: { vertical: "top" | "center" | "bottom"; horizontal: "left" | "center" | "right" };
textAlign?: "left" | "right";
sx?: SxProps;
className?: string;
}

export const ButtonSelect: FC<ButtonSelectProps> = ({
Expand All @@ -35,6 +36,7 @@ export const ButtonSelect: FC<ButtonSelectProps> = ({
transformOrigin,
textAlign,
sx,
className,
}) => {
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement>();
const isOpen = Boolean(anchorEl);
Expand All @@ -55,7 +57,7 @@ export const ButtonSelect: FC<ButtonSelectProps> = ({
onClick={handleClick}
startIcon={startIcon}
endIcon={anchorEl ? <ChevronUp /> : <ChevronDown />}
className={isOpen ? "Mui-active" : ""}
className={`${isOpen ? "Mui-active" : ""} ${className || ""}`}
data-cy={`${fieldName}-button-select`}
sx={{ ...sx }}>
{selectedItem?.value}
Expand Down
1 change: 1 addition & 0 deletions src/client/src/mui.theme.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ declare module "@mui/material/styles" {
ai: {
background: string;
main: string;
mainTransparent: string;
mainEnd: string;
active: string;
activeEnd: string;
Expand Down
47 changes: 38 additions & 9 deletions src/client/src/pages/detail/form/location/coordinatesSegment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
} from "./coordinateSegmentInterfaces.js";
import { boundingBox, referenceSystems, webApilv03tolv95, webApilv95tolv03 } from "./coordinateSegmentConstants.js";
import { LabelingButton } from "../../../../components/buttons/labelingButton.tsx";
import { useLabelingContext } from "../../labeling/labelingInterfaces.js";
import { Coordinate, ExtractionState, useLabelingContext } from "../../labeling/labelingInterfaces.js";
import { FormSegmentBox } from "../../../../components/styledComponents.ts";
import { FormContainer, FormCoordinate, FormSelect } from "../../../../components/form/form";
import { Codelist } from "../../../../components/legacyComponents/domain/domainInterface.ts";
Expand All @@ -35,7 +35,7 @@ const CoordinatesSegment: React.FC<CoordinatesSegmentProps> = ({
editingEnabled,
}) => {
const { t, i18n } = useTranslation();
const { panelOpen, togglePanel } = useLabelingContext();
const { extractionObject, setExtractionObject } = useLabelingContext();

// --- State variables ---
const [currentReferenceSystem, setCurrentReferenceSystem] = useState<number>(borehole.data.spatial_reference_system);
Expand Down Expand Up @@ -222,7 +222,7 @@ const CoordinatesSegment: React.FC<CoordinatesSegmentProps> = ({

// Sync currentReferenceSystem with react-hook-form
useEffect(() => {
formMethods.setValue("spatial_reference_system", currentReferenceSystem);
formMethods.setValue("spatial_reference_system", currentReferenceSystem, { shouldValidate: true });
}, [currentReferenceSystem, formMethods]);

// reset form values when the borehole or map point changes.
Expand Down Expand Up @@ -281,6 +281,18 @@ const CoordinatesSegment: React.FC<CoordinatesSegmentProps> = ({
handleCoordinateTransformation,
]);

useEffect(() => {
if (extractionObject?.type === "coordinates" && extractionObject?.state === ExtractionState.success) {
const coordinate = extractionObject?.result?.value as Coordinate;
if (coordinate) {
setCurrentReferenceSystem(referenceSystems[coordinate.projection].code);
setValuesForReferenceSystem(coordinate.projection, coordinate.east.toString(), coordinate.north.toString());
}
}
}, [extractionObject, setValuesForReferenceSystem]);

const isCoordinateExtraction = extractionObject?.type === "coordinates";

// --- Event handlers --- /

// passed to the onChange handler of the location values. Checks bounding box before updating.
Expand Down Expand Up @@ -366,6 +378,20 @@ const CoordinatesSegment: React.FC<CoordinatesSegmentProps> = ({
setValuesForReferenceSystem(ReferenceSystemKey.LV95, "", "");
};

const startLabeling = () => {
const referenceSystemKey =
currentReferenceSystem === referenceSystems.LV95.code ? ReferenceSystemKey.LV95 : ReferenceSystemKey.LV03;
setExtractionObject({
type: "coordinates",
state: ExtractionState.start,
previousValue: {
east: formMethods.getValues(referenceSystems[referenceSystemKey].fieldName.X),
north: formMethods.getValues(referenceSystems[referenceSystemKey].fieldName.Y),
projection: referenceSystemKey,
},
});
};

return (
<>
<FormProvider {...formMethods}>
Expand All @@ -378,7 +404,10 @@ const CoordinatesSegment: React.FC<CoordinatesSegmentProps> = ({
action={
showLabeling &&
editingEnabled && (
<LabelingButton className={panelOpen ? "Mui-active" : ""} onClick={() => togglePanel()} />
<LabelingButton
className={extractionObject?.type === "coordinates" ? "Mui-active" : ""}
onClick={() => startLabeling()}
/>
)
}
/>
Expand All @@ -390,7 +419,7 @@ const CoordinatesSegment: React.FC<CoordinatesSegmentProps> = ({
label="spatial_reference_system"
selected={[currentReferenceSystem ?? referenceSystems.LV95.code]}
readonly={!editingEnabled}
className={panelOpen ? "ai" : ""}
className={isCoordinateExtraction ? "ai" : ""}
onUpdate={e => onReferenceSystemChange(e)}
values={Object.entries(referenceSystems).map(([, value]) => ({
key: value.code,
Expand All @@ -407,7 +436,7 @@ const CoordinatesSegment: React.FC<CoordinatesSegmentProps> = ({
onUpdate={onCoordinateChange}
disabled={currentReferenceSystem !== referenceSystems.LV95.code}
readonly={!editingEnabled}
className={panelOpen ? "ai" : ""}
className={isCoordinateExtraction ? "ai" : ""}
value={formMethods.getValues(referenceSystems.LV95.fieldName.X)}
/>
<FormCoordinate
Expand All @@ -418,7 +447,7 @@ const CoordinatesSegment: React.FC<CoordinatesSegmentProps> = ({
onUpdate={onCoordinateChange}
disabled={currentReferenceSystem !== referenceSystems.LV95.code}
readonly={!editingEnabled}
className={panelOpen ? "ai" : ""}
className={isCoordinateExtraction ? "ai" : ""}
value={formMethods.getValues(referenceSystems.LV95.fieldName.Y)}
/>
</FormContainer>
Expand All @@ -431,7 +460,7 @@ const CoordinatesSegment: React.FC<CoordinatesSegmentProps> = ({
onUpdate={onCoordinateChange}
disabled={currentReferenceSystem !== referenceSystems.LV03.code}
readonly={!editingEnabled}
className={panelOpen ? "ai" : ""}
className={isCoordinateExtraction ? "ai" : ""}
value={formMethods.getValues(referenceSystems.LV03.fieldName.X)}
/>
<FormCoordinate
Expand All @@ -442,7 +471,7 @@ const CoordinatesSegment: React.FC<CoordinatesSegmentProps> = ({
onUpdate={onCoordinateChange}
disabled={currentReferenceSystem !== referenceSystems.LV03.code}
readonly={!editingEnabled}
className={panelOpen ? "ai" : ""}
className={isCoordinateExtraction ? "ai" : ""}
value={formMethods.getValues(referenceSystems.LV03.fieldName.Y)}
/>
</FormContainer>
Expand Down
25 changes: 21 additions & 4 deletions src/client/src/pages/detail/labeling/labelingContext.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import { LabelingContextInterface, PanelPosition } from "./labelingInterfaces.tsx";
import { ExtractionObject, LabelingContextInterface, PanelPosition } from "./labelingInterfaces.tsx";
import { createContext, FC, PropsWithChildren, useCallback, useEffect, useLayoutEffect, useState } from "react";

export const LabelingContext = createContext<LabelingContextInterface>({
panelPosition: "right",
setPanelPosition: () => {},
panelOpen: false,
togglePanel: () => {},
extractionObject: undefined,
setExtractionObject: () => {},
});

export const LabelingProvider: FC<PropsWithChildren> = ({ children }) => {
const [panelPosition, setPanelPosition] = useState<PanelPosition>("right");
const [panelOpen, setPanelOpen] = useState(false);
const [extractionObject, setExtractionObject] = useState<ExtractionObject>();

const togglePanel = useCallback((isOpen?: boolean) => {
setPanelOpen(prevState => (isOpen !== undefined ? isOpen : !prevState));
}, []);

const panelPositionStorageName = "labelingPanelPosition";
useLayoutEffect(() => {
Expand All @@ -24,9 +31,17 @@ export const LabelingProvider: FC<PropsWithChildren> = ({ children }) => {
localStorage.setItem(panelPositionStorageName, panelPosition);
}, [panelPosition]);

const togglePanel = useCallback((isOpen?: boolean) => {
setPanelOpen(prevState => (isOpen !== undefined ? isOpen : !prevState));
}, []);
useEffect(() => {
if (extractionObject) {
togglePanel(true);
}
}, [extractionObject, togglePanel]);

useEffect(() => {
if (!panelOpen) {
setExtractionObject(undefined);
}
}, [panelOpen]);

return (
<LabelingContext.Provider
Expand All @@ -35,6 +50,8 @@ export const LabelingProvider: FC<PropsWithChildren> = ({ children }) => {
setPanelPosition,
panelOpen,
togglePanel,
extractionObject,
setExtractionObject,
}}>
{children}
</LabelingContext.Provider>
Expand Down
Loading

0 comments on commit e4bef3d

Please sign in to comment.