Commit caed283f authored by amarcic's avatar amarcic
Browse files

Merge branch 'master' of...

Merge branch 'master' of https://gitlab.cceh.uni-koeln.de/spp-2143-learning-through-connecting/ltc_website
parents ec0e4e12 44859380
......@@ -3,5 +3,15 @@
"current language": "Deutsch",
"EntangledAfrica1": "Entangled Africa",
"EntangledAfrica2": "Innerafrikanische Beziehungen zwischen Regenwald und Mittelmeer, ca. 6.000 - 500 Jahre vor heute",
"Map": "Karte"
"Filters": "Filter",
"Map": "Karte",
"Search results": "Suchergebnisse",
"Image contents": "Bildinhalte",
"Data sources": "Herkunft der Daten",
"Timeline": "Zeitstrahl",
"Temporal distribution": "Zeitliche Verteilung",
"Turn on/off marker clustering": "Gruppieren von Markern",
"Resize map to show all markers": "Kartenausschnitt für aktuelle Marker anpassen"
}
\ No newline at end of file
......@@ -3,9 +3,9 @@ import { useTranslation } from 'react-i18next';
import { latLngBounds } from 'leaflet';
import { useQuery } from "@apollo/react-hooks";
import {
CollapsedFilters, DataSources, Filters, Histogram, ImageContents, OurMap, Timeline, OurTimeline, ResultsTable, ShowNext
CollapsedFilters, DashboardTile, DataSources, Filters, Histogram, ImageContents, Layout, OurMap, Timeline, OurTimeline, ResultsTable, ShowNext
} from "..";
import { Grid, LinearProgress } from "@material-ui/core";
import { LinearProgress } from "@material-ui/core";
// Queries
import {
byRegion as GET_SITES_BY_REGION, searchArchaeoSites as GET_ARCHAEOLOGICAL_SITES,
......@@ -41,7 +41,8 @@ const initialInput = {
timelineSort: "period",
highlightedTimelineObject: undefined,
areaA: 1,
areaB: 0
areaB: 0,
bigTileArea: ""
};
......@@ -176,22 +177,6 @@ export const AppContent = () => {
dispatch({type: "UPDATE_INPUT", payload: {field: "selectedMarker", value: index}});
}
const extendMapBounds = () => {
let markers;
if(mapDataContext.entity) markers = mapDataContext.entity;
else if(mapDataObjects.entitiesMultiFilter) markers = mapDataObjects.entitiesMultiFilter;
else if(mapDataSitesByRegion.sitesByRegion) markers = mapDataSitesByRegion.sitesByRegion;
else if(mapDataArchaeoSites.archaeologicalSites) markers = mapDataArchaeoSites.archaeologicalSites;
const newMapBounds = latLngBounds();
markers.map( (item) => {
if (item && item.coordinates) return newMapBounds.extend(item.coordinates.split(", ").reverse());
else if (item && item.spatial) return item.spatial.map( (nestedItem) =>
nestedItem &&
newMapBounds.extend(nestedItem.coordinates.split(", ").reverse()));
});
dispatch({type: "UPDATE_INPUT", payload: {field: "mapBounds", value: newMapBounds}});
}
useEffect( () => {
if(dataContext && input.mode === "objects" && input.showRelatedObjects) {
......@@ -266,50 +251,46 @@ export const AppContent = () => {
// query result not empty
&& mapDataSitesByRegion && mapDataSitesByRegion.sitesByRegion;
const getMapData = () => {
let mapData;
return (
<Grid container spacing={2} className={classes.gridBody}>
{/*GRID: Filters*/}
<Grid className={classes.gridFullHeightItem} item container direction="row" xs={2}>
{input.mapControlsExpanded
? <Filters
chronOntologyTerms={chronOntologyTerms}
reducer={[input, dispatch]}
input={input}
regions={regions}
/>
: (/*summary of active filters when control panel is closed*/
<CollapsedFilters
reducer={[input, dispatch]}
/>
)
}
</Grid>
{/*GRID: Map*/}
{<Grid className={classes.gridFullHeightItem} item xs={4} container>
<OurMap
extendMapBounds={extendMapBounds}
handleRelatedObjects={handleRelatedObjects}
mapDataObjects={mapDataObjects}
mapDataContext={mapDataContext}
mapDataArchaeoSites={mapDataArchaeoSites}
mapDataSitesByRegion={mapDataSitesByRegion}
reducer={[input, dispatch]}
renderingConditionObjects={renderingConditionObjects}
renderingConditionRelatedObjects={renderingConditionRelatedObjects}
renderingConditionSites={renderingConditionSites}
renderingConditionSitesByRegion={renderingConditionSitesByRegion}
/>
</Grid>}
if(renderingConditionObjects) mapData = mapDataObjects?.entitiesMultiFilter;
else if(renderingConditionRelatedObjects) mapData = {original: mapDataContext?.entity?.spatial, related: mapDataContext?.entity?.related};
else if(renderingConditionSites) mapData = mapDataArchaeoSites?.archaeologicalSites;
else if(renderingConditionSitesByRegion) mapData = mapDataSitesByRegion?.sitesByRegion;
return mapData;
}
{/*GRID: Container for results list and timeline*/}
{<Grid className={classes.gridFullHeightItem} item xs={6} container direction="row" spacing={2}>
const getMapDataType = () => {
let type = null;
let handler = false;
{/*GRID: Results list, image contents, data sources*/}
{<Grid className={classes.gridHalfHeightItem} item xs={12} container direction="row">
{input.areaA===0
&& <ResultsTable
if(renderingConditionObjects) handler = true;
else if(renderingConditionRelatedObjects) {
type = "related";
handler = true;
}
return {type: type, handler: handler};
}
const setWidth = () => window.innerWidth
const setOneTwelfthWidth = () => setWidth() / 12
window.addEventListener('resize', setOneTwelfthWidth)
const renderAreaA = () => {
const area = "areaA";
return(
<DashboardTile
reducer={[input, dispatch]}
area={area}
content={
input[area]===0 && <ResultsTable
handleRelatedObjects={handleRelatedObjects}
mapDataObjects={mapDataObjects}
mapDataContext={mapDataContext}
......@@ -321,44 +302,131 @@ export const AppContent = () => {
renderingConditionSites={renderingConditionSites}
renderingConditionSitesByRegion={renderingConditionSitesByRegion}
openPopup={openPopup}
/>}
{input.areaA===1
&& <ImageContents
/>
|| input[area]===1 && <ImageContents
contents={dataObjects
&& [dataObjects?.entitiesMultiFilter?.map(entity => entity?.categoryOfDepicted),
dataObjects?.entitiesMultiFilter?.map(entity => entity?.materialOfDepicted)]}
/>}
{input.areaA===2
&& <DataSources/>}
/>
|| input[area]===2 && <DataSources/>
}
showNext={
<ShowNext
area={"areaA"}
area={area}
labels={["Results table", "Image contents", "Data sources"]}
reducer={[input, dispatch]}
/>
</Grid>}
}
/>
)
}
const renderAreaB = () => {
const area = "areaB";
{/*GRID: Timeline, histogram*/}
{<Grid className={classes.gridHalfHeightItem} item xs={12} container direction="row" alignItems="stretch">
{input.areaB===0 && <Timeline
return(
<DashboardTile
reducer={[input, dispatch]}
area={area}
content={
input[area]===0 && <Timeline
reducer={[input, dispatch]}
timelineObjectsData={dataObjects?.entitiesMultiFilter.flatMap(timelineAdapter)}
/>}
{input.areaB===1 && <Histogram
/>
|| input[area]===1 && <Histogram
timelineData={dataObjects?.entitiesMultiFilter.map(timelineMapper)}
/>}
/>
}
showNext={
<ShowNext
area={"areaB"}
area={area}
labels={["Timeline", "Histogram"]}
reducer={[input, dispatch]}
/>
</Grid>}
</Grid>}
{/*GRID: Loading indicator*/}
<Grid item xs={12}>
{(loadingContext || loadingObjects || loadingArchaeoSites || loadingSitesByRegion) &&
<LinearProgress/>}
</Grid>
</Grid>
);
}
}
/>
)
}
const renderAreaC = () => {
const area = "areaC";
return(
<DashboardTile
reducer={[input, dispatch]}
area={area}
content={
<OurMap
handleRelatedObjects={handleRelatedObjects}
data={getMapData()}
dataType={getMapDataType()}
reducer={[input, dispatch]}
/>
}
/>
)
}
return (
/* Layout schema:
F = filters, M = map, A = area A, B = area B; two rows = 100% height, four columns = 100 % width
Size md/lg:
default: | big M: | big A: | big B: | with expanded filters: (?)
------------------------------------------------------------------------------------------------------
F | F | F | F | F F F F
M M A A | M M M M | A A A A | B B B B | ...
M M B B | M M M M | A A A A | B B B B |
| A A B B | M M B B | M M A A |
| | M M | M M |
Size xs:
default: (?) | with expanded filters: (?)
--------------------------------------------
F . . . | F F F F
M M M M | F F F F
M M M M | M M M M
A A A A | M M M M
A A A A | A A A A
B B B B | A A A A
B B B B | B B B B
| B B B B
*/
<Layout
menu={input.mapControlsExpanded
? <Filters
chronOntologyTerms={chronOntologyTerms}
reducer={[input, dispatch]}
input={input}
regions={regions}
/>
: (
<CollapsedFilters
reducer={[input, dispatch]}
/>
)
}
bigTile={
(input.bigTileArea === "areaA" && renderAreaA())
|| (input.bigTileArea === "areaB" && renderAreaB())
|| (input.bigTileArea === "areaC" && renderAreaC())
}
leftOrTopTile={
input.bigTileArea !== "areaC" && renderAreaC()
}
topRightOrMiddleTile={
input.bigTileArea !== "areaA"
? renderAreaA()
: renderAreaB()
}
bottomRightOrBottomTile={
input.bigTileArea !== "areaA" && input.bigTileArea !== "areaB" && renderAreaB()
}
loadingIndicator={
(loadingContext || loadingObjects || loadingArchaeoSites || loadingSitesByRegion)
&& <LinearProgress/>
}
rightTileIsMovedToBottomInstead={input.bigTileArea === "areaC" ? "true" : false}
/>
)
};
......@@ -7,6 +7,7 @@ query searchObjects($searchTerm: String, $catalogIds: [Int], $bbox: [String], $p
identifier
name
coordinates
polygon
}
dating
datingSpan
......@@ -44,6 +45,7 @@ query searchObjectContext($arachneId: ID!) {
identifier
name
coordinates
polygon
}
dating
datingSpan
......@@ -77,6 +79,7 @@ query searchArchaeoSites($searchTerm: String, $bbox: [String]) {
identifier
name
coordinates
polygon
types
locatedIn {
identifier
......@@ -90,6 +93,7 @@ query byRegion($searchTerm: String, $idOfRegion: ID!) {
identifier
name
coordinates
polygon
types
locatedIn {
identifier
......@@ -103,6 +107,7 @@ query searchArchaeoSiteContext($searchTerm: String, $bbox: [String]) {
identifier
name
coordinates
polygon
types
locatedIn {
identifier
......
......@@ -15,7 +15,7 @@ export const CollapsedFilters = (props) => {
return (
<Card className={classes.card}>
<Grid className={classes.gridHead} item>
<Grid className={classes.dashboardTileHeader} item>
<Button
onClick={() => {
dispatch({type: "TOGGLE_STATE", payload: {toggledField: "mapControlsExpanded"}})
......@@ -24,39 +24,35 @@ export const CollapsedFilters = (props) => {
<h3 className={classes.h3}>{t('Filters')}</h3>
{input.mapControlsExpanded ? <ExpandLessIcon/> : <ExpandMoreIcon/>}
</Button>
</Grid>
<Grid className={classes.gridContent} item container direction="column" spacing={2}>
<Grid item container direction="column" spacing={2}>
{/*Chip for mode*/}
<Chip label={input.mode === "archaeoSites"
? "Archaeological Sites"
: "Objects"}
/>
{/*Chip for for string query*/}
{input.searchStr !== ""
&& <Chip variant="outlined" label={`Search term: ${input.searchStr}`}/>}
{/*Chip for filter by period*/}
{input.chronOntologyTerm !== null
&& <Chip variant="outlined" label={`Chronontology term: ${input.chronOntologyTerm}`}/>}
{/*Chip for filter by region*/}
{input.sitesMode === "region" && input.regionTitle !== null
&& <Chip variant="outlined"
label={`Region: ${input.regionTitle}`}
/>}
{/*Chip for filter by coordinates*/}
{(/-?\d{1,2}\.\d+,-?\d{1,3}\.\d+/.test(input.boundingBoxCorner1) && (/-?\d{1,2}\.\d+,-?\d{1,3}\.\d+/.test(input.boundingBoxCorner2)))
&& <Chip variant="outlined"
label={`Bounding box: [${input.boundingBoxCorner1}], [${input.boundingBoxCorner2}]`}/>}
{/*Chip for filter by catalogs*/}
{input.checkedCatalogLabels.length !== 0
&& <Chip variant="outlined" label={`Catalog: ${input.checkedCatalogLabels}`}/>}
</Grid>
{/*Chip for mode*/}
<Chip label={input.mode === "archaeoSites"
? "Archaeological Sites"
: "Objects"}
/>
{/*Chip for for string query*/}
{input.searchStr !== ""
&& <Chip variant="outlined" label={`Search term: ${input.searchStr}`}/>}
{/*Chip for filter by period*/}
{input.chronOntologyTerm !== null
&& <Chip variant="outlined" label={`Chronontology term: ${input.chronOntologyTerm}`}/>}
{/*Chip for filter by region*/}
{input.sitesMode === "region" && input.regionTitle !== null
&& <Chip variant="outlined"
label={`Region: ${input.regionTitle}`}
/>}
{/*Chip for filter by coordinates*/}
{(/-?\d{1,2}\.\d+,-?\d{1,3}\.\d+/.test(input.boundingBoxCorner1) && (/-?\d{1,2}\.\d+,-?\d{1,3}\.\d+/.test(input.boundingBoxCorner2)))
&& <Chip variant="outlined"
label={`Bounding box: [${input.boundingBoxCorner1}], [${input.boundingBoxCorner2}]`}/>}
{/*Chip for filter by catalogs*/}
{input.checkedCatalogLabels.length !== 0
&& <Chip variant="outlined" label={`Catalog: ${input.checkedCatalogLabels}`}/>}
</Grid>
</Card>
)
......
......@@ -6,7 +6,8 @@ export const CreateMarkers = (props) => {
const { data, selectedMarker, handleRelatedObjects, showRelatedObjects } = props;
return data && data.map((item, index) => {
if(!data) return null;
else return data && data.map((item, index) => {
if (item && item.coordinates) {
return (
item &&
......
import React from "react";
import { Card, IconButton } from "@material-ui/core";
import ZoomOutIcon from "@material-ui/icons/ZoomOut";
import ZoomInIcon from "@material-ui/icons/ZoomIn";
import { useStyles } from "../../styles";
export const DashboardTile = (props) => {
const [input, dispatch] = props.reducer;
const {area, content, showNext} = props;
const classes = useStyles();
return (
<>
<Card className={showNext ? classes.cardOfTileWithShowNext : classes.cardOfTileWithoutShowNext}>
<IconButton
onClick={() => dispatch({type: "UPDATE_INPUT", payload: {field: "bigTileArea", value: input.bigTileArea === area ? "" : area}})}
style={{backgroundColor: "rgba(171,134,97,0.18)"/*, position: "relative", left: "20px", top: "70px"*/}}
>
{input.bigTileArea === area
? <ZoomOutIcon/>
: <ZoomInIcon/>
}
</IconButton>
{content}
</Card>
{showNext}
</>
);
}
\ No newline at end of file
import React from "react";
import { useTranslation } from "react-i18next";
import { useStyles } from "../../styles";
import { Card, Grid, List, ListItem } from "@material-ui/core";
import { Grid, List, ListItem } from "@material-ui/core";
export const DataSources = () => {
const { t, i18n } = useTranslation();
......@@ -9,13 +9,13 @@ export const DataSources = () => {
const classes = useStyles();
return (
<Card className={classes.card}>
<Grid className={classes.gridHead} item container direction="row" spacing={2}>
<>
<Grid className={classes.dashboardTileHeader} item container direction="row" spacing={2}>
<Grid item>
<h3 className={classes.h3}>{t('Data sources')}</h3>
</Grid>
</Grid>
<Grid className={classes.gridContent} item container direction="column" spacing={2}>
<Grid className={classes.dashboardTileContent} item container direction="column" spacing={2}>
<Grid item>
Here could be a list maybe...
<List>
......@@ -25,6 +25,6 @@ export const DataSources = () => {
</List>
</Grid>
</Grid>
</Card>
</>
)
};
......@@ -33,7 +33,7 @@ export const Filters = (props) => {
return (
<Card className={classes.card}>
<Grid className={classes.gridHead} item>
<Grid className={classes.dashboardTileHeader} item>
<Button
onClick={() => {
dispatch({type: "TOGGLE_STATE", payload: {toggledField: "mapControlsExpanded"}})
......@@ -43,10 +43,10 @@ export const Filters = (props) => {
{input.mapControlsExpanded ? <ExpandLessIcon/> : <ExpandMoreIcon/>}
</Button>
</Grid>
{<Grid className={classes.gridContent} item container direction="column" spacing={2}>
<Grid item container direction="column" spacing={2}>
{<Grid className={classes.dashboardTileContent} item container direction="column" spacing={2}>
<Grid item container direction="row" spacing={2}>
{/*radio buttons for selecting mode*/
<Grid item xs={12}>
<Grid item>
<FormGroup>
<FormLabel component="legend">Search mode</FormLabel>
<RadioGroup
......@@ -66,7 +66,7 @@ export const Filters = (props) => {
</Grid>}
{/*input field for string query*/
<Grid item xs={12}>
<Grid item>
<FormGroup>
<FormLabel component="legend">Filter by search term</FormLabel>
<TextField
......@@ -94,7 +94,7 @@ export const Filters = (props) => {
</Grid>}
{/*dropdown for filter by period; only active in object search mode*/
!input.showArchaeoSites && <Grid item xs={12}>
!input.showArchaeoSites && <Grid item>
<FormGroup>
<FormLabel component="legend" disabled={input.showArchaeoSites}>Filter by time</FormLabel>
<Autocomplete
......@@ -115,7 +115,7 @@ export const Filters = (props) => {
</Grid>}
{/*dropdown for filter by region; only active in site search mode*/
input.showArchaeoSites && <Grid item xs={12}>
input.showArchaeoSites && <Grid item>
<FormGroup>
<FormLabel component="legend">Filter by region</FormLabel>
<Autocomplete
......@@ -144,7 +144,7 @@ export const Filters = (props) => {
</Grid>}
{/*switch and input fields for filter by coordinates*/
<Grid item xs={12}>
<Grid item>
<FormGroup>
<FormLabel>Filter by coordinates (bounding box)
<Tooltip title="Activate the switch to select a bounding box directly on the map. Click the map in two places to select first the north-east corner, then the south-west corner." arrow placement="right-start">
......@@ -229,7 +229,7 @@ export const Filters = (props) => {
</Grid>}
{/*checkboxes for filter by catalogs; only active in object search mode*/
!input.showArchaeoSites && <Grid item xs={12}>
!input.showArchaeoSites && <Grid item>
<FormGroup>
<FormLabel component="legend" disabled={input.showArchaeoSites}>Filter by catalogs</FormLabel>
{input.catalogIdsList && input.catalogIdsList.map(project => {
......
import React, {useEffect, useRef, useState} from "react";
import { Card, Grid } from "@material-ui/core";
import { Grid } from "@material-ui/core";
import { useTranslation } from "react-i18next";
import { useStyles } from "../../styles";
import {select, scaleBand, axisBottom, axisLeft, scaleLinear, max} from "d3";
......@@ -110,13 +110,13 @@ export const Histogram = (props) => {
}, [binnedData])
return (
<Card className={classes.card}>
<Grid className={classes.gridHead} item container direction="row" spacing={2}>
<>
<Grid className={classes.dashboardTileHeader} item container direction="row" spacing={2}>
<Grid item>
<h3 className={classes.h3}>{t('Temporal distribution')}</h3>
</Grid>
</Grid>