Skip to content

Commit c05183c

Browse files
authored
Merge pull request #44 from mapcomponents/Add-MultiTab 0.3
Add multi tab 0.3
2 parents 7aa091f + 2c917c7 commit c05183c

File tree

9 files changed

+164
-147
lines changed

9 files changed

+164
-147
lines changed

mc_meta.json

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -73,26 +73,29 @@
7373
"url": "https://mapcomponents.github.io/react-map-components-apps/powerplants/"
7474
}
7575
]
76-
},"MultiTab": {
77-
"name": "MultiTab",
78-
"title": "Multi-Tab Demo",
79-
"description": "This application is one way to split visual and information. You can open a table which contains all the information you can see on the map. Looking for an object but can't find it in one of the pages? Just click on it the programm will find it for you!",
80-
"i18n": {
81-
"de": {
82-
"title": "Multi-Tab Demo",
83-
"description": "Diese Anwendung ist eine Möglichkeit, visuelle Objekte und Informationen aufzuteilen. Sie können eine Tabelle öffnen, die alle Informationen, von den Objekten, die Sie auf der Karte sehen können, enthält. Suchen Sie ein Objekt, können es aber auf einer der Seiten nicht finden? Klicken Sie einfach auf das Objekt, das sie suchen. Das Programm findet es für Sie!"
84-
}
8576
},
86-
"tags": [],
87-
"category": "",
88-
"type": "application",
89-
"components": ["MlGeoJsonLayer"],
90-
"thumbnail": "https://mapcomponents.github.io/react-map-components-apps/assets/thumbnails/MultiTab.png",
91-
"demos": [
92-
{
93-
"name": "Demo",
94-
"url": "https://mapcomponents.github.io/react-map-components-apps/multi_tab/"
95-
}
96-
]
97-
}
77+
"MultiTab": {
78+
"name": "MultiTab",
79+
"title": "Multi-Tab Demo",
80+
"description": "This application combines graphical and text-based information of objects that are represented in a table and map: Open a table with all the information visible on the map. Looking for an object and can't find it? Just click on it - the program will show it to you!",
81+
"i18n": {
82+
"de": {
83+
"title": "Multi-Tab Demo",
84+
"description": "Diese Anwendung kombiniert grafische und textbasierte Informationen von Objekten, die in einer Tabelle und einer Karte dargestellt werden: Öffnen Sie eine Tabelle mit allen Informationen, die auf der Karte sichtbar sind. Sie suchen ein Objekt und können es nicht finden? Klicken Sie es einfach an - das Programm zeigt es Ihnen an!"
85+
}
86+
},
87+
"tags": [],
88+
"category": "",
89+
"type": "application",
90+
"components": [
91+
"MlGeoJsonLayer"
92+
],
93+
"thumbnail": "https://mapcomponents.github.io/react-map-components-apps/assets/thumbnails/MultiTab.png",
94+
"demos": [
95+
{
96+
"name": "Demo",
97+
"url": "https://mapcomponents.github.io/react-map-components-apps/multi_tab/"
98+
}
99+
]
100+
}
98101
}

multi_tab/src/App.tsx

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,43 @@
11
import "./App.css";
2-
import {MapLibreMap} from "@mapcomponents/react-maplibre";
2+
import {MapLibreMap, TopToolbar} from "@mapcomponents/react-maplibre";
33
import LayerManager from "./components/LayerManager.jsx";
44
import {Button} from "@mui/material";
5+
import {useState} from "react";
56

67
function App() {
8+
const [openSidebar, setOpenSidebar] = useState(true);
79

810
const openTable = () => {
911
const newUrl = `${window.location.href}#/table`;
1012
window.open(newUrl, "_blank", "popup");
1113
}
1214
return (
1315
<>
16+
<TopToolbar buttons={
17+
<>
18+
<Button
19+
sx={{
20+
color: openSidebar ? "#009EE0" : "white",
21+
backgroundColor: openSidebar ? "#fff" : '#009EE0',
22+
marginRight: {xs: '0px', sm: '10px'}
23+
}}
24+
variant={openSidebar ? 'outlined' : 'contained'}
25+
onClick={() => {
26+
setOpenSidebar(!openSidebar);
27+
}}
28+
>
29+
Sidebar
30+
</Button>
31+
32+
<Button
33+
sx={{
34+
background: '#009EE0'
35+
}}
36+
variant='contained'
37+
onClick={() => openTable()}
38+
>show table</Button>
39+
</>
40+
}/>
1441
<MapLibreMap
1542
options={{
1643
style: "https://wms.wheregroup.com/tileserver/style/osm-bright.json",
@@ -19,15 +46,7 @@ function App() {
1946
}}
2047
style={{position: "absolute", top: 0, bottom: 0, left: 0, right: 0}}
2148
/>
22-
<LayerManager/>
23-
<Button
24-
sx={{
25-
left: '93%'
26-
}}
27-
variant='contained'
28-
color="primary"
29-
onClick={() => openTable()}
30-
>show table</Button>
49+
<LayerManager setOpenSidebar={setOpenSidebar} openSidebar={openSidebar}/>
3150
</>
3251
);
3352
}

multi_tab/src/components/DataTableManager.jsx

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import {Box} from "@mui/material";
22
import React, {useContext, useEffect, useState} from "react";
3-
import TopToolBar from "./UI_Components/TopToolbar.tsx";
3+
import TopToolBar from "./UI_Components/TableToolbar.tsx";
44
import CreateTable from "./UI_Components/DataTable.jsx";
55
import {DataContext} from "../contexts/DataContext.tsx";
66

77
export default function DataTableManager() {
88
const data = useContext(DataContext);
99

1010
const [visibleIDs, setVisibleIDs] = useState([]);
11-
const [selected, setSelected] = useState(null);
11+
const [selected, setSelected] = useState();
1212
const [selectedLayer, setSelectedLayer] = useState("all");
1313
const [tableSplit, setTableSplit] = useState(false);
1414
/*const [showOnlyVisibleObjects, setShowOnlyVisibleObjects] = useState(true);*/
@@ -23,6 +23,18 @@ export default function DataTableManager() {
2323
break;
2424
case "selectedFromLayerManager":
2525
setSelected(message.selected);
26+
break;
27+
case"visibleLayers":
28+
setSelectedLayer(
29+
message.parksShown && message.restaurantsShown
30+
? 'all'
31+
: message.restaurantsShown
32+
? 'restaurant'
33+
: message.parksShown
34+
? 'park'
35+
: 'all'
36+
);
37+
2638
break;
2739
default:
2840
console.warn(`Unhandled message type: ${type}`);
@@ -38,10 +50,6 @@ export default function DataTableManager() {
3850
}, []);
3951

4052

41-
//sorts all Objects which is Layer codependent
42-
useEffect(() => {
43-
}, [visibleIDs, selectedLayer, data]);
44-
4553
if (!data) {
4654
return <div>Loading data...</div>;
4755
}

multi_tab/src/components/LayerManager.jsx

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {LayerList, Sidebar, useMap,} from "@mapcomponents/react-maplibre";
1+
import {LayerList, Sidebar, useMap, useMapState,} from "@mapcomponents/react-maplibre";
22
import ParkLayer from "./Layers/ParkLayer.tsx";
33
import {useContext, useEffect, useState} from "react";
44
import {sendMessageToServiceWorker} from "../js/sendMessageToSW";
@@ -48,7 +48,7 @@ const getSelectedFeature = (data, id) => {
4848
};
4949

5050

51-
export default function LayerManager() {
51+
export default function LayerManager(props) {
5252
const mapHook = useMap();
5353

5454
const [selected, setSelected] = useState();
@@ -57,6 +57,13 @@ export default function LayerManager() {
5757

5858
const data = useContext(DataContext);
5959

60+
const mapState = useMapState({
61+
watch:{
62+
layers: true
63+
},
64+
})
65+
66+
6067
useEffect(() => {
6168
if ('serviceWorker' in navigator) {
6269
const handleMessage = (event) => {
@@ -72,7 +79,7 @@ export default function LayerManager() {
7279
navigator.serviceWorker.removeEventListener('message', handleMessage);
7380
};
7481
}
75-
}, [setSelected]);
82+
}, []);
7683

7784
useEffect(() => {
7885
if (!mapHook.map || !selected) return;
@@ -122,11 +129,22 @@ export default function LayerManager() {
122129
};
123130
}, [mapHook.map]);
124131

132+
useEffect(() => {
133+
if (!mapHook.map) return;
134+
console.log("send")
135+
136+
sendMessageToServiceWorker({
137+
type: "visibleLayers",
138+
message: {
139+
parksShown: mapHook.map.getLayer('parks').visibility === "visible",
140+
restaurantsShown: mapHook.map.getLayer('restaurants').visibility === "visible",
141+
}
142+
})
143+
}, [mapState.layers]);
125144
return (
126145
<>
127-
<Sidebar open={true} name={"Layers"}>
146+
<Sidebar open={props.openSidebar} setOpen={props.setOpenSidebar} name={"Layers"} >
128147
<LayerList>
129-
{/* <RestaurantLayer /> */}
130148
<ParkLayer
131149
selected={selected}
132150
setSelected={setSelected}
@@ -138,8 +156,8 @@ export default function LayerManager() {
138156
setSrc={setSrc}
139157
/>
140158
</LayerList>
141-
{selectedFeature && <MlHighlightFeature features={[selectedFeature]} variant={"hell"} offset={1}/>}
142159
</Sidebar>
160+
{selectedFeature && <MlHighlightFeature features={[selectedFeature]} variant={"hell"} offset={1}/>}
143161
</>
144162
);
145163
}

multi_tab/src/components/Layers/ParkLayer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ interface ParkLayerProps {
88
setSrc: React.Dispatch<React.SetStateAction<string>>
99
}
1010

11-
// Function to initialize all parks to the map
11+
// Function to initialize all parks to the map if the data is fetched successfully
1212
export default function ParkLayer({
1313
setSelected,
1414
setSrc

multi_tab/src/components/Layers/RestaurantLayer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ interface RestaurantLayerProps {
88
setSrc: React.Dispatch<React.SetStateAction<string>>
99
}
1010

11-
// Function to initialize all restaurants to the map
11+
// Function to initialize all restaurants to the map if the data is fetched successfully
1212
export default function RestaurantLayer({
1313
setSelected,
1414
setSrc

multi_tab/src/components/UI_Components/DataTable.jsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,20 @@ import React, {useMemo} from "react";
22
import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material";
33
import {sendMessageToServiceWorker} from "../../js/sendMessageToSW.js";
44

5+
//Returns an Array of all objects which are visible on the map
56
const createObjectList = (data, visibleIDs, selectedLayer) => {
6-
console.log(data);
7-
console.log(visibleIDs);
8-
console.log(selectedLayer);
97
if (!data) return [];
108

119
return Object.values(data).flatMap(value =>
1210
value.features.filter(feature => {
1311
const isVisible = visibleIDs.length === 0 || visibleIDs.includes(feature.id);
14-
const isCorrectLayer = selectedLayer === "all" || feature.properties.amenity === selectedLayer;
12+
const isCorrectLayer = (selectedLayer === "all" || feature.properties.amenity === selectedLayer);
1513
return isVisible && isCorrectLayer;
1614
})
1715
);
1816
};
1917

18+
//Returns an array containing the properties as objects of the parameter list
2019
const createPropertiesList = (objectList) => {
2120
if (!objectList) return [];
2221
const propertiesList = [];
@@ -26,6 +25,7 @@ const createPropertiesList = (objectList) => {
2625
return propertiesList;
2726
};
2827

28+
//Returns an array containing all the keys from the properties (used in table to
2929
const createKeyList = (propertiesList) => {
3030
const keyFrequency = {};
3131
const minUsage = propertiesList.length < 4 ? 0 : 4;
@@ -53,7 +53,6 @@ const selecting = (id, src) => {
5353

5454
const DataTable = (props) => {
5555
const objectList = useMemo(() => createObjectList(props.data, props.visibleIDs, props.selectedLayer), [props.data, props.visibleIDs, props.selectedLayer]);
56-
console.log(objectList);
5756
const propertiesList = useMemo(() => createPropertiesList(objectList), [objectList]);
5857
const keyList = useMemo(() => createKeyList(propertiesList), [propertiesList]);
5958

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import * as React from 'react';
2+
import {useContext} from 'react';
3+
import {Button, MenuItem, Select, SelectChangeEvent} from "@mui/material";
4+
import {DataContext} from "../../contexts/DataContext";
5+
import {TopToolbar} from "@mapcomponents/react-maplibre";
6+
7+
export interface TopToolbarProps {
8+
children?: React.ReactNode;
9+
unmovableButtons?: React.ReactNode;
10+
buttons?: React.ReactNode;
11+
logo?: React.ReactNode;
12+
selectedLayer: string;
13+
setSelectedLayer: (layer: string) => void;
14+
tableSplit: boolean;
15+
setTableSplit: (split: boolean) => void;
16+
}
17+
18+
function TableToolbar(props: TopToolbarProps) {
19+
const data = useContext(DataContext);
20+
21+
const layers = data
22+
? Object.keys(data).map(layerName => layerName.replace(".json", ""))
23+
: [];
24+
25+
const handleLayerSelect = (event: SelectChangeEvent) => {
26+
props.setSelectedLayer(event.target.value as string);
27+
}
28+
29+
const handleTableSplit = () => {
30+
const newTableSplit = !props.tableSplit;
31+
props.setTableSplit(newTableSplit);
32+
}
33+
34+
return (
35+
<TopToolbar buttons={
36+
<>
37+
<Select
38+
variant={'outlined'}
39+
value={props.selectedLayer}
40+
onChange={handleLayerSelect}
41+
size={"small"}
42+
sx={{
43+
width: '122px',
44+
marginRight: {xs: '0px', sm: '10px'}
45+
}}
46+
>
47+
<MenuItem value={"all"}>all</MenuItem>
48+
{layers.map(layerName => (
49+
<MenuItem value={layerName} key={layerName}>{layerName}</MenuItem>
50+
))}
51+
</Select>
52+
<Button
53+
variant={'contained'}
54+
onClick={handleTableSplit}
55+
sx={{
56+
backgroundColor: '#009EE0'
57+
}}
58+
>
59+
{props.tableSplit ? ("merge table") : ("split table")}
60+
</Button>
61+
</>
62+
}/>
63+
64+
);
65+
}
66+
67+
export default TableToolbar;

0 commit comments

Comments
 (0)