Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Anlegen einer Subsite mit dem Titel des entsprechenden Gruppennamens #17

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
54dbc3d
- added: initial commit
THS-LMIS Nov 25, 2024
0d6f013
- removed: unnecessary code
THS-LMIS Nov 25, 2024
9ea2aa0
- added: hello world page
THS-LMIS Nov 25, 2024
4dbefd6
- added: dev dependency for @babel/plugin-proposal-private-property-i…
THS-LMIS Nov 25, 2024
750e2e4
- added: Docker
THS-LMIS Nov 25, 2024
8eebdf2
Create continuous_integration.yml
THS-LMIS Nov 26, 2024
9ea66ea
Create publish-dev-docker-image.yml
THS-LMIS Nov 26, 2024
fc258f9
Create release.yml
THS-LMIS Nov 26, 2024
92d7205
- moved: Dockerfile in .github folder
THS-LMIS Nov 26, 2024
537f6b8
- added: Router package
THS-LMIS Nov 27, 2024
ab2dc77
- added: Router functionality
THS-LMIS Nov 27, 2024
7b2a331
- fixed: dockerfile & README.md
THS-LMIS Nov 27, 2024
aeeca97
Update continuous_integration.yml
THS-LMIS Nov 27, 2024
70cadc5
Rename dockerfile to Dockerfile
THS-LMIS Nov 27, 2024
7f58342
Update publish-dev-docker-image.yml
THS-LMIS Nov 27, 2024
be0d788
Delete .github/workflows/release.yml
THS-LMIS Nov 27, 2024
af9a5d3
- fixed: pr comments
THS-LMIS Nov 27, 2024
1380179
Merge branch '1-aufsetzen-der-infrastruktur' into 7-konzeption-der-se…
THS-LMIS Nov 27, 2024
9fed1c7
- fixed: spelling in README.md
THS-LMIS Nov 27, 2024
d829844
- added: Header, Footer, Impressum
THS-LMIS Nov 27, 2024
ebffdf5
- added: breadcrumb navigation
THS-LMIS Nov 28, 2024
9cf724e
- added: placeholder flex container on homepage
THS-LMIS Nov 28, 2024
7b914a7
- added: OpenLayers module & OpenLayers map
THS-LMIS Nov 28, 2024
02a8bc1
- removed: unnecessary web server in Dockerfile
THS-LMIS Dec 2, 2024
812b279
- added: vector layer with example points
THS-LMIS Dec 4, 2024
7929be8
- added: axios module
THS-LMIS Dec 4, 2024
1f21cd4
WIP
THS-LMIS Dec 4, 2024
2edffbd
Merge branch 'refs/heads/main' into 2-hinzufügen-von-funktionalitäten…
Dec 5, 2024
cb4e35f
Merge branch 'main' into 2-hinzufügen-von-funktionalitäten-der-karten…
Dec 6, 2024
86e6bf9
- removed: index.html
Dec 6, 2024
5f0956d
- added: proxy server for development
Dec 6, 2024
85cea4d
- added: Agvolution and Sentek sensors to map
THS-LMIS Dec 9, 2024
15ed32a
- added: untested agri crop polygon import
THS-LMIS Dec 9, 2024
5091fee
- added: key properties to nav link elements
THS-LMIS Dec 11, 2024
61e6d91
- changed: interface properties to the actual name to make it work
THS-LMIS Dec 11, 2024
35e23a7
- changed: injection of fiware server url with environment variable
THS-LMIS Dec 11, 2024
1d26649
- added: docker environment variable
THS-LMIS Dec 11, 2024
cd68b5f
- changed: tsconfig.json
THS-LMIS Dec 11, 2024
3a8d519
- added: Bootstrap
THS-LMIS Dec 12, 2024
3f9d9d7
- added: single selection group with example data
THS-LMIS Dec 12, 2024
85ed3ec
- added: single selection group with api import
THS-LMIS Dec 12, 2024
925c4f4
- changed: Dockerfile & README.md
THS-LMIS Dec 12, 2024
fb59ef4
- changed: group label
THS-LMIS Dec 13, 2024
d41fd95
- added: group selection handling
THS-LMIS Dec 13, 2024
cfe207e
- changed: state selectedGroup from string to TenantGroup
THS-LMIS Dec 13, 2024
ba8b24d
WIP
Dec 13, 2024
1042778
WIP
THS-LMIS Dec 16, 2024
5c435c4
WIP
THS-LMIS Dec 16, 2024
3bde5cf
WIP
THS-LMIS Dec 16, 2024
d1b9ec6
WIP
THS-LMIS Dec 16, 2024
e2b1282
- added: filtering of agri crops and sensors by selecting a group
THS-LMIS Dec 18, 2024
31b3722
- added: reset to global map, if no agri crops are selectable
THS-LMIS Dec 18, 2024
19be1ad
Merge branch 'main' into 9-erstellung-der-gruppenlogik
THS-LMIS Dec 18, 2024
e36ef60
- added: new route for group page
THS-LMIS Dec 18, 2024
e72131c
- added: single selection for group contents
THS-LMIS Dec 19, 2024
2bd511a
Merge branch 'main' into 4-anlegen-einer-subsite-mit-dem-titel-des-en…
THS-LMIS Dec 19, 2024
d1e98fe
- fixed: breadcrumb element group without link
THS-LMIS Dec 19, 2024
c634798
- added: highlighting of sensor when selected
THS-LMIS Dec 19, 2024
06825f8
- added: highlighting of sensor when selected
THS-LMIS Dec 19, 2024
ccf2e20
- added: agri crops to group contents
THS-LMIS Dec 19, 2024
2ef9bfa
- fixed: map zoomed automatically when selecting agri crop group content
THS-LMIS Dec 19, 2024
bc7b368
- improved: responsiveness
THS-LMIS Dec 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions app/components/Breadcrumbs.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@
background-color: #41485A;
display: flex;
padding: 10px min(4vh, 2vw);
@media only screen and (max-height: 767px) {
padding-bottom: 5px;
padding-top: 5px;
}
a {
color: white;
font-size: large;
@media only screen and (max-height: 767px) {
font-size: medium;
}
text-decoration: none;
}
a + a:before {
Expand All @@ -15,4 +22,7 @@
a.active {
font-weight: bold;
}
a.disabled {
pointer-events: none;
}
}
21 changes: 19 additions & 2 deletions app/components/Breadcrumbs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,25 @@ import {NavLink, useLocation} from 'react-router';
import styles from './Breadcrumbs.module.css';

const routeLabels: { [key: string]: string } = {
group: 'Gruppe',
impressum: 'Impressum'
};

const routeWithoutLink: string[] = [
'group'
];

function calculateNavLinkClassNames(isActive: boolean, disabled: boolean) {
const classNames: string[] = [];
if (isActive) {
classNames.push(styles.active);
}
if (disabled) {
classNames.push(styles.disabled);
}
return classNames.join(' ');
}

function Breadcrumbs() {
const location = useLocation();
const pathnames = location.pathname.split('/').filter((x) => x);
Expand All @@ -20,9 +36,10 @@ function Breadcrumbs() {
{pathnames.map((pathname, index) => {
const to = `/${pathnames.slice(0, index + 1).join('/')}`;
const label: string = routeLabels[pathname] || pathname;
const disabled = routeWithoutLink.includes(pathname);
return <NavLink
to={to}
className={({ isActive }) => (isActive ? styles.active : undefined)}
to={disabled ? '#' : to}
className={({ isActive }) => calculateNavLinkClassNames(isActive, disabled)}
key={pathname}
>
{decodeURIComponent(label)}
Expand Down
4 changes: 4 additions & 0 deletions app/components/Footer.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
gap: 40px;
list-style: none;
padding: 20px min(4vh, 2vw);
@media only screen and (max-height: 767px) {
padding-bottom: 10px;
padding-top: 10px;
}
a {
color: white;
font-size: x-large;
Expand Down
5 changes: 5 additions & 0 deletions app/components/Header.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@
padding: 20px min(4vh, 2vw);
text-align: center;
text-decoration: none;
@media only screen and (max-height: 767px) {
font-size: xx-large;
padding-bottom: 10px;
padding-top: 10px;
}
}
48 changes: 40 additions & 8 deletions app/components/OpenLayers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import React, {useEffect, useRef} from 'react';

import {Feature, Map, View} from 'ol';
import {Coordinate} from 'ol/coordinate';
import {Extent} from "ol/extent";
import {Extent} from 'ol/extent';
import {Point, Polygon} from 'ol/geom';
import TileLayer from 'ol/layer/Tile';
import VectorLayer from "ol/layer/Vector";
import {fromLonLat} from 'ol/proj';
import {OSM} from 'ol/source';
import VectorSource from 'ol/source/Vector';
import {Fill, Stroke, Style} from 'ol/style';
import CircleStyle from 'ol/style/Circle';

import 'ol/ol.css';
import styles from './OpenLayers.module.css';
Expand All @@ -36,7 +37,9 @@ function createPointVectorLayer(name: string, source: VectorSource<Feature<Point
interface Props {
id: string,
agriCrops: AgriCrop[],
selectedAgriCrop?: AgriCrop|undefined,
selectedGroup: TenantGroup|undefined,
selectedSensor?: Sensor|undefined,
sensors: Sensor[]
}

Expand All @@ -52,7 +55,7 @@ function fitMap(mapView: View | undefined, extent: Extent | undefined) {
}
}

function OpenLayers({ agriCrops, id, selectedGroup, sensors }: Props) {
function OpenLayers({ agriCrops, id, selectedAgriCrop, selectedGroup, selectedSensor, sensors }: Props) {

const mapRef = useRef<Map | undefined>(undefined);

Expand All @@ -70,7 +73,7 @@ function OpenLayers({ agriCrops, id, selectedGroup, sensors }: Props) {
let pointVectorLayer = createPointVectorLayer(pointVectorLayerName, pointVectorSource);
let polygonVectorLayer = createPolygonVectorLayer(polygonVectorLayerName, polygonVectorSource);

const style = new Style({
const normalPolygonStyle = new Style({
fill: new Fill({
color: 'rgba(0, 128, 255, 0.4)',
}),
Expand All @@ -80,6 +83,29 @@ function OpenLayers({ agriCrops, id, selectedGroup, sensors }: Props) {
}),
});

const highlightPolygonStyle = new Style({
fill: new Fill({
color: 'rgba(255, 0, 0, 0.4)',
}),
stroke: new Stroke({
color: 'red',
width: 2,
}),
});

const highlightPointStyle = new Style({
image: new CircleStyle({
fill: new Fill({
color: 'rgba(255, 0, 0, 0.4)'
}),
stroke: new Stroke({
color: 'red',
width: 1
}),
radius: 5
})
});

function updateAgriCrops () {
const map = mapRef.current;
if (!map || agriCrops.length === 0) return;
Expand All @@ -93,7 +119,7 @@ function OpenLayers({ agriCrops, id, selectedGroup, sensors }: Props) {
lonLatCoordinates.push(fromLonLat(coordinate));
});
const polygonFeature = new Feature({ geometry: new Polygon([lonLatCoordinates]) });
polygonFeature.setStyle(style);
polygonFeature.setStyle(agriCrop.id === selectedAgriCrop?.id ? highlightPolygonStyle : normalPolygonStyle);
features.push(polygonFeature);
});
polygonVectorSource.clear();
Expand All @@ -105,7 +131,9 @@ function OpenLayers({ agriCrops, id, selectedGroup, sensors }: Props) {
}
polygonVectorLayer = createPolygonVectorLayer(polygonVectorLayerName, polygonVectorSource);
map.addLayer(polygonVectorLayer);
fitMap(map.getView(), polygonVectorSource.getExtent());
if (!selectedAgriCrop && !selectedSensor) {
fitMap(map.getView(), polygonVectorSource.getExtent());
}
}

function updateSensors() {
Expand All @@ -116,7 +144,11 @@ function OpenLayers({ agriCrops, id, selectedGroup, sensors }: Props) {
return !selectedGroup || sensor.customGroup === selectedGroup.groupId;
});
_sensors.forEach((sensor: Sensor) => {
features.push(new Feature({ geometry: new Point(fromLonLat(sensor.coordinates)) }));
const pointFeature = new Feature({ geometry: new Point(fromLonLat(sensor.coordinates)) });
if (sensor.id === selectedSensor?.id) {
pointFeature.setStyle(highlightPointStyle);
}
features.push(pointFeature);
});
pointVectorSource.clear();
pointVectorSource.addFeatures(features);
Expand Down Expand Up @@ -148,13 +180,13 @@ function OpenLayers({ agriCrops, id, selectedGroup, sensors }: Props) {
if (mapRef.current && agriCrops.length > 0) {
updateAgriCrops();
}
}, [agriCrops, selectedGroup]);
}, [agriCrops, selectedGroup, selectedAgriCrop]);

useEffect(() => {
if (mapRef.current && sensors.length > 0) {
updateSensors();
}
}, [sensors, selectedGroup]);
}, [sensors, selectedGroup, selectedSensor]);

return <div id={id} className={styles.map}></div>;
}
Expand Down
57 changes: 57 additions & 0 deletions app/components/SingleSelectionGroupContents.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React, {ChangeEventHandler, MouseEventHandler} from 'react';
import {Button, Form} from 'react-bootstrap';
import {NavLink} from 'react-router';

import AgriCrop from '../models/AgriCrop';
import Sensor from '../models/Sensor';

import styles from './SingleSelectionGroups.module.css';

interface Props {
agriCrops: AgriCrop[],
handleChange: ChangeEventHandler,
handleReset: MouseEventHandler,
selectedAgriCrop: AgriCrop | undefined,
selectedSensor: Sensor | undefined,
sensors: Sensor[]
}

function SingleSelectionGroupContents({ agriCrops, handleChange, handleReset, selectedAgriCrop, selectedSensor, sensors }: Props) {
return <>
<h4>Übersicht der Gruppeninhalte:</h4>
<Form id="group_contents">
{sensors.map((sensor) => (
<Form.Check
className={styles.groups}
type="radio"
id={sensor.id}
key={sensor.id}
label={sensor.id}
value={sensor.id}
name="group_contents"
checked={selectedSensor?.id === sensor.id}
onChange={handleChange}
/>
))}
{agriCrops.map((agriCrops) => (
<Form.Check
className={styles.groups}
type="radio"
id={agriCrops.id}
key={agriCrops.id}
label={agriCrops.id}
value={agriCrops.id}
name="group_contents"
checked={selectedAgriCrop?.id === agriCrops.id}
onChange={handleChange}
/>
))}
<NavLink className="btn btn-secondary mt-5" to="/">Zurück</NavLink>
<Button className="ms-5 mt-5" variant="secondary" onClick={handleReset} disabled={!selectedSensor && !selectedAgriCrop}>
Auswahl aufheben
</Button>
</Form>
</>;
}

export default SingleSelectionGroupContents;
13 changes: 9 additions & 4 deletions app/components/SingleSelectionGroups.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import styles from './SingleSelectionGroups.module.css';

import React from 'react';
import React, {ChangeEventHandler, MouseEventHandler} from 'react';
import {Button, Form} from 'react-bootstrap';
import {NavLink} from 'react-router';

import TenantGroup from '../models/TenantGroup';

interface Props {
groups: TenantGroup[],
handleChange: any,
handleReset: any,
handleChange: ChangeEventHandler,
handleReset: MouseEventHandler,
selectedGroup: TenantGroup|undefined
}

Expand All @@ -31,9 +32,13 @@ function SingleSelectionGroups({ handleChange, handleReset, groups, selectedGrou
onChange={handleChange}
/>
))}
<Button className="mt-5" variant="secondary" onClick={handleReset}>
<Button className="mt-5" variant="secondary" onClick={handleReset} disabled={!selectedGroup}>
Auswahl aufheben
</Button>
<NavLink className={`btn btn-secondary ms-5 mt-5 ${selectedGroup ? '' : 'disabled'}`}
to={selectedGroup ? '/group/' + selectedGroup.name : '#'}>
Weiter
</NavLink>
</Form>
</>
);
Expand Down
1 change: 1 addition & 0 deletions app/models/Sensor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {Coordinate} from 'ol/coordinate';
export default interface Sensor {
id: string,
type: string,
name: string,
customGroup: string,
coordinates: Coordinate
}
3 changes: 2 additions & 1 deletion app/models/SensorResponse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ export default interface SensorResponse {
id: string,
type: string,
customGroup: string,
location: SingleLocationResponse | null
location: SingleLocationResponse | null,
name: string
}
3 changes: 2 additions & 1 deletion app/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ import {index, route, RouteConfig} from '@react-router/dev/routes';

export default [
index('./routes/Home.tsx'),
route('impressum', './routes/Impressum.tsx')
route('impressum', './routes/Impressum.tsx'),
route('group/:groupName', './routes/Group.tsx')
] satisfies RouteConfig;
Loading
Loading