Skip to content

Commit

Permalink
Add spatial extent to admin mandate grid (#230)
Browse files Browse the repository at this point in the history
  • Loading branch information
tschumpr authored Jul 17, 2024
2 parents f3b980c + 49b97c9 commit aa024a1
Show file tree
Hide file tree
Showing 15 changed files with 348 additions and 34 deletions.
21 changes: 19 additions & 2 deletions src/Geopilot.Api/Controllers/MandateController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public async Task<IActionResult> Create(MandateDto mandateDto)
try
{
if (mandateDto == null)
return BadRequest();
return BadRequest();

var mandate = await TransformToMandate(mandateDto);

Expand Down Expand Up @@ -165,12 +165,29 @@ private async Task<Mandate> TransformToMandate(MandateDto mandateDto)
{
var organisations = await context.Organisations.Where(o => mandateDto.Organisations.Contains(o.Id)).ToListAsync();
var deliveries = await context.Deliveries.Where(d => mandateDto.Deliveries.Contains(d.Id)).ToListAsync();
Geometry spatialExtent;
if (mandateDto.SpatialExtent.Count != 2)
{
spatialExtent = Geometry.DefaultFactory.CreatePolygon();
}
else
{
spatialExtent = Geometry.DefaultFactory.CreatePolygon(new Coordinate[]
{
new (mandateDto.SpatialExtent[0].X, mandateDto.SpatialExtent[0].Y),
new (mandateDto.SpatialExtent[0].X, mandateDto.SpatialExtent[1].Y),
new (mandateDto.SpatialExtent[1].X, mandateDto.SpatialExtent[1].Y),
new (mandateDto.SpatialExtent[1].X, mandateDto.SpatialExtent[0].Y),
new (mandateDto.SpatialExtent[0].X, mandateDto.SpatialExtent[0].Y),
});
}

return new Mandate
{
Id = mandateDto.Id,
Name = mandateDto.Name,
FileTypes = mandateDto.FileTypes.ToArray(),
SpatialExtent = Geometry.DefaultFactory.CreatePolygon(),
SpatialExtent = spatialExtent,
Organisations = organisations,
Deliveries = deliveries,
};
Expand Down
26 changes: 22 additions & 4 deletions src/Geopilot.Api/DTOs/MandateDto.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,30 @@ public class MandateDto
/// </summary>
public static MandateDto FromMandate(Mandate mandate)
{
var wkt = mandate.SpatialExtent.AsText();
var spatialExtent = new List<CoordinateDto>();
if (mandate.SpatialExtent.Coordinates.Length == 5)
switch (mandate.SpatialExtent.Coordinates.Length)
{
spatialExtent.Add(CoordinateDto.FromCoordinate(mandate.SpatialExtent.Coordinates[0]));
spatialExtent.Add(CoordinateDto.FromCoordinate(mandate.SpatialExtent.Coordinates[2]));
case 0:
break;
case 5:
double minX = mandate.SpatialExtent.Coordinates[0].X;
double minY = mandate.SpatialExtent.Coordinates[0].Y;
double maxX = mandate.SpatialExtent.Coordinates[0].X;
double maxY = mandate.SpatialExtent.Coordinates[0].Y;

foreach (var coord in mandate.SpatialExtent.Coordinates)
{
minX = Math.Min(minX, coord.X);
minY = Math.Min(minY, coord.Y);
maxX = Math.Max(maxX, coord.X);
maxY = Math.Max(maxY, coord.Y);
}

spatialExtent.Add(new CoordinateDto { X = minX, Y = minY });
spatialExtent.Add(new CoordinateDto { X = maxX, Y = maxY });
break;
default:
throw new InvalidOperationException($"Unsupported number of coordinates. Spatial extent must be a rectangle.");
}

return new MandateDto
Expand Down
6 changes: 6 additions & 0 deletions src/Geopilot.Frontend/public/locale/de/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,14 @@
"id": "ID",
"impressum": "Impressum",
"info": "Info",
"latitude": "Breite",
"licenses": "Lizenzen",
"licenseInformation": "Lizenzinformationen",
"loggedInAs": "Angemeldet als {{name}}",
"logIn": "Anmelden",
"logInForDelivery": "Anmelden um Lieferung zu erstellen",
"logOut": "Abmelden",
"longitude": "Länge",
"mandate": "Mandat",
"mandateDisconnectMessage": "Das Mandat wird von allen Organisationen getrennt. Diese Aktion kann nicht rückgängig gemacht werden.",
"mandateDisconnectTitle": "Möchten Sie das Mandat wirklich inaktiv setzen?",
Expand All @@ -60,7 +62,11 @@
"organisationsLoadingError": "Beim Laden der Organisationen ist ein Fehler aufgetreten: {{error}}",
"predecessor": "Vorgänger",
"privacyPolicy": "Datenschutz",
"reset": "Aktuelle Änderungen zurücksetzen",
"save": "Speichern",
"spatialExtent": "Räumliche Ausdehnung",
"spatialExtentIncompleteMessage": "Es müssen entweder alle Felder leer oder alle abgefüllt sein. Möchten Sie die aktuellen Änderungen zurücksetzen?",
"spatialExtentIncompleteTitle": "Ungültige räumliche Ausdehnung",
"stacBrowser": "STAC Browser",
"termsOfUse": "Nutzungsbestimmungen",
"termsOfUseAccpetance": "Ich akzeptiere die <button>Nutzungsbestimmungen</button>.",
Expand Down
6 changes: 6 additions & 0 deletions src/Geopilot.Frontend/public/locale/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,14 @@
"id": "ID",
"impressum": "Imprint",
"info": "Info",
"latitude": "Latitude",
"licenses": "Licenses",
"licenseInformation": "License Information",
"loggedInAs": "Logged in as {{name}}",
"logIn": "Log In",
"logInForDelivery": "Log in to create delivery",
"logOut": "Log Out",
"longitude": "Longitude",
"mandate": "Mandate",
"mandateDisconnectMessage": "This will remove all connections to organisations and cannot be undone.",
"mandateDisconnectTitle": "Do you really want to disconnect the mandate?",
Expand All @@ -60,7 +62,11 @@
"organisationsLoadingError": "An error occurred while loading the organisations: {{error}}",
"predecessor": "Predecessor",
"privacyPolicy": "Privacy policy",
"reset": "Reset current changes",
"save": "Save",
"spatialExtent": "Spatial extent",
"spatialExtentIncompleteMessage": "All fields must either be empty or filled in. Would you like to reset the current changes?",
"spatialExtentIncompleteTitle": "Invalid spatial extent",
"stacBrowser": "STAC Browser",
"termsOfUse": "Terms of use",
"termsOfUseAccpetance": "I accept the <button>terms of use</button>.",
Expand Down
6 changes: 6 additions & 0 deletions src/Geopilot.Frontend/public/locale/fr/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,14 @@
"id": "ID",
"impressum": "Mentions légales",
"info": "Info",
"latitude": "Latitude",
"licenses": "Licences",
"licenseInformation": "Informations sur la licence",
"loggedInAs": "Connecté en tant que {{name}}",
"logIn": "Se connecter",
"logInForDelivery": "Connectez-vous pour créer une livraison",
"logOut": "Se déconnecter",
"longitude": "Longitude",
"mandate": "Mandat",
"mandateDisconnectMessage": "Cette opération supprime toutes les connexions avec les organisations et ne peut être annulée.",
"mandateDisconnectTitle": "Voulez-vous vraiment déconnecter le mandat?",
Expand All @@ -60,7 +62,11 @@
"organisationsLoadingError": "Une erreur s'est produite lors du chargement des organisations: {{error}}",
"predecessor": "Prédécesseur",
"privacyPolicy": "Politique de confidentialité",
"reset": "Réinitialiser les modifications en cours",
"save": "Sauver",
"spatialExtent": "Étendue spatiale",
"spatialExtentIncompleteMessage": "Tous les champs doivent être soit vides, soit tous remplis. Vous souhaitez réinitialiser les modifications en cours?",
"spatialExtentIncompleteTitle": "Étendue spatiale non valide",
"stacBrowser": "Navigateur STAC",
"termsOfUse": "Conditions d'utilisation",
"termsOfUseAccpetance": "J'accepte les <button>conditions d'utilisation</button>.",
Expand Down
6 changes: 6 additions & 0 deletions src/Geopilot.Frontend/public/locale/it/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,14 @@
"id": "ID",
"impressum": "Impressum",
"info": "Informazioni",
"latitude": "Latitudine",
"licenses": "Licenze",
"licenseInformation": "Informazioni sulla licenza",
"loggedInAs": "Accesso effettuato come {{name}}",
"logIn": "Accedi",
"logInForDelivery": "Accedi per creare una consegna",
"logOut": "Esci",
"longitude": "Longitudine",
"mandate": "Mandato",
"mandateDisconnectMessage": "Questa operazione rimuove tutti i collegamenti alle organizzazioni e non può essere annullata.",
"mandateDisconnectTitle": "Volete davvero scollegare il mandato?",
Expand All @@ -60,7 +62,11 @@
"organisationsLoadingError": "Si è verificato un errore durante il caricamento delle organizzazioni: {{error}}",
"predecessor": "Predecessore",
"privacyPolicy": "Informativa sulla privacy",
"reset": "Ripristino delle modifiche correnti",
"save": "Salvare",
"spatialExtent": "Misura spaziale",
"spatialExtentIncompleteMessage": "Tutti i campi devono essere vuoti o compilati. Volete ripristinare le modifiche correnti?",
"spatialExtentIncompleteTitle": "Misura spaziale non valida",
"stacBrowser": "Browser STAC",
"termsOfUse": "Termini di utilizzo",
"termsOfUseAccpetance": "Accetto i <button>Termini di utilizzo</button>.",
Expand Down
4 changes: 2 additions & 2 deletions src/Geopilot.Frontend/src/AppInterfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ export interface ErrorResponse {
}

export interface Coordinate {
x: number;
y: number;
x: number | null;
y: number | null;
}

export interface Mandate {
Expand Down
11 changes: 11 additions & 0 deletions src/Geopilot.Frontend/src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -538,3 +538,14 @@ footer {
.alert p {
margin-bottom: 0;
}

.spatial-extent-popover {
padding: 20px;
}

.spatial-extent-coordinate-row {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 20px;
}
33 changes: 27 additions & 6 deletions src/Geopilot.Frontend/src/components/adminGrid/AdminGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,19 @@ import {
GridRowModes,
GridRowModesModel,
} from "@mui/x-data-grid";
import { Tooltip } from "@mui/material";
import SaveOutlinedIcon from "@mui/icons-material/SaveOutlined";
import CancelOutlinedIcon from "@mui/icons-material/CancelOutlined";
import EditOutlinedIcon from "@mui/icons-material/EditOutlined";
import LinkOffIcon from "@mui/icons-material/LinkOff";
import { useTranslation } from "react-i18next";
import { AdminGridProps, DataRow } from "./AdminGridInterfaces.ts";
import { AdminGridProps, DataRow, GridColDef } from "./AdminGridInterfaces.ts";
import {
GridColDef,
GridMultiSelectColDef,
IsGridMultiSelectColDef,
TransformToMultiSelectColumn,
} from "../dataGrid/DataGridMultiSelectColumn.tsx";
import { IsGridSpatialExtentColDef, TransformToSpatialExtentColumn } from "../dataGrid/DataGridSpatialExtentColumn.tsx";

export const AdminGrid: FC<AdminGridProps> = ({ addLabel, data, columns, onSave, onDisconnect }) => {
const { t } = useTranslation();
Expand Down Expand Up @@ -56,14 +57,22 @@ export const AdminGrid: FC<AdminGridProps> = ({ addLabel, data, columns, onSave,
return [
<GridActionsCellItem
key="save"
icon={<SaveOutlinedIcon />}
icon={
<Tooltip title={t("save")}>
<SaveOutlinedIcon />
</Tooltip>
}
label={t("save")}
onClick={handleSaveClick(id)}
color="inherit"
/>,
<GridActionsCellItem
key="cancel"
icon={<CancelOutlinedIcon />}
icon={
<Tooltip title={t("cancel")}>
<CancelOutlinedIcon />
</Tooltip>
}
label={t("cancel")}
onClick={handleCancelClick(id)}
color="inherit"
Expand All @@ -74,15 +83,23 @@ export const AdminGrid: FC<AdminGridProps> = ({ addLabel, data, columns, onSave,
return [
<GridActionsCellItem
key="edit"
icon={<EditOutlinedIcon />}
icon={
<Tooltip title={t("edit")}>
<EditOutlinedIcon />
</Tooltip>
}
label={t("edit")}
onClick={handleEditClick(id)}
color="inherit"
disabled={editingRow !== undefined}
/>,
<GridActionsCellItem
key="disconnect"
icon={<LinkOffIcon />}
icon={
<Tooltip title={t("disconnect")}>
<LinkOffIcon />
</Tooltip>
}
label={t("disconnect")}
onClick={handleDisconnectClick(id)}
color="error"
Expand All @@ -95,6 +112,9 @@ export const AdminGrid: FC<AdminGridProps> = ({ addLabel, data, columns, onSave,
if (IsGridMultiSelectColDef(column)) {
TransformToMultiSelectColumn(column as GridMultiSelectColDef);
}
if (IsGridSpatialExtentColDef(column)) {
TransformToSpatialExtentColumn(column);
}
});
const adminGridColumns: GridColDef[] = columns.concat(actionColumn);

Expand All @@ -112,6 +132,7 @@ export const AdminGrid: FC<AdminGridProps> = ({ addLabel, data, columns, onSave,
[defaultRow.id]: { mode: GridRowModes.Edit, fieldToFocus: columns[0].field },
}));
}
// eslint-disable-next-line
}, [rows]);

const handleEditClick = (id: GridRowId) => () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { GridColDef } from "../dataGrid/DataGridMultiSelectColumn.tsx";
import { GridMultiSelectColDef } from "../dataGrid/DataGridMultiSelectColumn.tsx";
import { GridActionsColDef, GridSingleSelectColDef, GridValidRowModel } from "@mui/x-data-grid";
import { GridBaseColDef } from "@mui/x-data-grid/internals";

export interface AdminGridProps {
addLabel?: string;
Expand All @@ -12,3 +14,10 @@ export interface DataRow {
// eslint-disable-next-line
[key: string]: any;
}

// eslint-disable-next-line
export type GridColDef<R extends GridValidRowModel = any, V = any, F = V> =
| GridBaseColDef<R, V, F>
| GridActionsColDef<R, V, F>
| GridSingleSelectColDef<R, V, F>
| GridMultiSelectColDef<R, V, F>;
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import {
GridActionsColDef,
GridRenderEditCellParams,
GridSingleSelectColDef,
GridValidRowModel,
useGridApiContext,
} from "@mui/x-data-grid";
import { GridRenderEditCellParams, GridValidRowModel, useGridApiContext } from "@mui/x-data-grid";
import { FormControl, InputLabel, MenuItem, Select, SelectChangeEvent } from "@mui/material";
import { ReactNode } from "react";
import { GridBaseColDef } from "@mui/x-data-grid/internals";
import { DataRow } from "../adminGrid/AdminGridInterfaces.ts";
import { DataRow, GridColDef } from "../adminGrid/AdminGridInterfaces.ts";

// eslint-disable-next-line
export interface GridMultiSelectColDef<R extends GridValidRowModel = any, V = any, F = V>
Expand All @@ -19,13 +13,6 @@ export interface GridMultiSelectColDef<R extends GridValidRowModel = any, V = an
getOptionValue: (value: DataRow | string) => string | number;
}

// eslint-disable-next-line
export type GridColDef<R extends GridValidRowModel = any, V = any, F = V> =
| GridBaseColDef<R, V, F>
| GridActionsColDef<R, V, F>
| GridSingleSelectColDef<R, V, F>
| GridMultiSelectColDef<R, V, F>;

export const IsGridMultiSelectColDef = (columnDef: GridColDef) =>
columnDef.type === "custom" && "valueOptions" in columnDef;

Expand Down
Loading

0 comments on commit aa024a1

Please sign in to comment.