From b897de35ede7b027a895360a94c4a33bd1d6766d Mon Sep 17 00:00:00 2001
From: esikkala <esko.ikkala@aalto.fi>
Date: Fri, 9 Nov 2018 09:26:52 -0800
Subject: [PATCH] Add tabs for subviews

---
 src/client/components/LeafletMap.js      |  66 ++-----------
 src/client/components/Main.js            |   2 +-
 src/client/components/Manuscripts.js     |  47 ++++++---
 src/client/components/ResultTable.js     | 121 ++++++++++-------------
 src/client/components/ResultTableHead.js |   7 +-
 src/client/components/TopBar.js          |   2 +-
 src/client/components/ViewTabs.js        |  58 +++++++++++
 src/client/containers/MapApp.js          |  44 +--------
 src/client/index.html                    |   6 +-
 webpack.client.common.js                 |   1 +
 webpack.client.dev.js                    |   5 +-
 11 files changed, 172 insertions(+), 187 deletions(-)
 create mode 100644 src/client/components/ViewTabs.js

diff --git a/src/client/components/LeafletMap.js b/src/client/components/LeafletMap.js
index a3d36267..781ec553 100644
--- a/src/client/components/LeafletMap.js
+++ b/src/client/components/LeafletMap.js
@@ -2,7 +2,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import L from 'leaflet';
 import { has, orderBy } from 'lodash';
-import LeafletSidebar from './LeafletSidebar';
+// import LeafletSidebar from './LeafletSidebar';
 
 import 'leaflet-sidebar-v2/js/leaflet-sidebar.min.js';
 import 'leaflet-sidebar-v2/css/leaflet-sidebar.min.css';
@@ -46,6 +46,7 @@ const style = {
 class LeafletMap extends React.Component {
 
   componentDidMount() {
+    console.log('mounted')
     //this.props.fetchManuscripts();
     this.props.fetchPlaces('creationPlaces');
 
@@ -76,6 +77,7 @@ class LeafletMap extends React.Component {
     this.bouncingMarkerObj = null;
     this.popupMarkerObj = null;
 
+
     if (this.props.mapMode === 'cluster') {
       this.updateMarkersAndCluster(this.props.results);
     } else {
@@ -121,34 +123,7 @@ class LeafletMap extends React.Component {
 
   }
 
-  componentDidUpdate({ results, place, mapMode, geoJSONKey, bouncingMarkerKey, openPopupMarkerKey }) {
-    if (this.props.bouncingMarker === '' && this.bouncingMarkerObj !== null) {
-      this.leafletMap.removeLayer(this.bouncingMarkerObj);
-    }
-
-    if (this.props.bouncingMarkerKey !== bouncingMarkerKey) {
-      if (this.props.mapMode === 'cluster') {
-        const m = this.markers[this.props.bouncingMarker];
-        const latlng = m.getLatLng();
-        // create a new marker so that the temporary popup can be left open
-        this.bouncingMarkerObj = L.marker(latlng);
-        this.bouncingMarkerObj.addTo(this.leafletMap).bounce(1);
-      } else {
-        this.markers[this.props.bouncingMarker].bounce(1);
-      }
-    }
-
-    if (this.props.openPopupMarkerKey !== openPopupMarkerKey) {
-      if (this.props.mapMode === 'cluster') {
-        if (this.popupMarkerObj !== null) {
-          this.leafletMap.removeLayer(this.popupMarkerObj);
-        }
-        this.popupMarkerObj = this.markers[this.props.popupMarker];
-        this.popupMarkerObj.addTo(this.leafletMap).openPopup();
-      } else {
-        this.markers[this.props.popupMarker].openPopup();
-      }
-    }
+  componentDidUpdate({ results, mapMode }) {
 
     // check if results data or mapMode have changed
     if (this.props.results !== results || this.props.mapMode !== mapMode) {
@@ -158,27 +133,6 @@ class LeafletMap extends React.Component {
         this.updateMarkers(this.props.results);
       }
     }
-
-    if (this.props.place !== place) {
-      this.markers[this.props.place.id.replace('http://ldf.fi/mmm/place/', '')]
-        .bindPopup(this.createPopUpContent(this.props.place), {
-          maxHeight: 300,
-          maxWidth: 400,
-          minWidth: 400,
-        //closeButton: false,
-        })
-        .openPopup();
-    }
-
-    // check if geoJSON has updated
-    if (this.props.geoJSONKey !== geoJSONKey) {
-      this.props.geoJSON.map(obj => {
-        const layer = L.geoJSON(obj.geoJSON, {
-          onEachFeature: this.onEachFeature
-        });
-        this.layerControl.addOverlay(layer, obj.layerID);
-      });
-    }
   }
 
   updateMarkers(results) {
@@ -301,7 +255,7 @@ class LeafletMap extends React.Component {
 
   render() {
     return (
-      <div className="leaflet-container">
+      <div className="leaflet-outer-container">
         {/*<LeafletSidebar />*/}
         <div id="map" style={style} />
       </div>
@@ -314,15 +268,7 @@ LeafletMap.propTypes = {
   fetchPlace: PropTypes.func.isRequired,
   fetchManuscripts: PropTypes.func.isRequired,
   results: PropTypes.array.isRequired,
-  place: PropTypes.object.isRequired,
-  mapMode: PropTypes.string.isRequired,
-  geoJSON: PropTypes.array,
-  geoJSONKey: PropTypes.number.isRequired,
-  getGeoJSON: PropTypes.func.isRequired,
-  bouncingMarker: PropTypes.string.isRequired,
-  popupMarker: PropTypes.string.isRequired,
-  bouncingMarkerKey: PropTypes.number.isRequired,
-  openPopupMarkerKey: PropTypes.number.isRequired,
+  mapMode: PropTypes.string.isRequired
 };
 
 export default LeafletMap;
diff --git a/src/client/components/Main.js b/src/client/components/Main.js
index 252d8f91..cb3e15f3 100644
--- a/src/client/components/Main.js
+++ b/src/client/components/Main.js
@@ -38,7 +38,7 @@ const styles = theme => ({
     maxWidth: 340,
   },
   media: {
-    height: 110,
+    height: 100,
   },
 });
 
diff --git a/src/client/components/Manuscripts.js b/src/client/components/Manuscripts.js
index 86ce7517..442d4921 100644
--- a/src/client/components/Manuscripts.js
+++ b/src/client/components/Manuscripts.js
@@ -1,20 +1,42 @@
 import React from 'react';
 import PropTypes from 'prop-types';
+import { Route, Switch } from 'react-router-dom';
+import ViewTabs from './ViewTabs';
 import ResultTable from './ResultTable';
+import LeafletMap from './LeafletMap';
 
 let Manuscripts = props => {
-
   return (
-    <ResultTable
-      rows={props.search.manuscripts}
-      facet={props.facet}
-      fetchManuscripts={props.fetchManuscripts}
-      fetchingManuscripts={props.search.fetchingManuscripts}
-      fetchFacet={props.fetchFacet}
-      results={props.search.results}
-      fetchResults={props.fetchResults}
-      page={props.search.page}
-    />
+    <React.Fragment>
+      <ViewTabs />
+      <Switch>
+        <Route
+          path={props.match.url + '/table'}
+          render={() =>
+            <ResultTable
+              rows={props.search.manuscripts}
+              facet={props.facet}
+              fetchManuscripts={props.fetchManuscripts}
+              fetchingManuscripts={props.search.fetchingManuscripts}
+              fetchFacet={props.fetchFacet}
+              results={props.search.results}
+              fetchResults={props.fetchResults}
+              page={props.search.page}
+            />}
+        />
+        <Route
+          path={props.match.url + '/creation_places'}
+          render={() =>
+            <LeafletMap
+              fetchPlaces={props.fetchPlaces}
+              fetchPlace={props.fetchPlace}
+              fetchManuscripts={props.fetchManuscripts}
+              results={props.search.places}
+              mapMode='cluster'
+            />}
+        />
+      </Switch>
+    </React.Fragment>
   );
 };
 
@@ -26,7 +48,8 @@ Manuscripts.propTypes = {
   fetchPlaces: PropTypes.func.isRequired,
   fetchPlace:  PropTypes.func.isRequired,
   fetchFacet: PropTypes.func.isRequired,
-  fetchResults: PropTypes.func.isRequired
+  fetchResults: PropTypes.func.isRequired,
+  match: PropTypes.object.isRequired
 };
 
 export default Manuscripts;
diff --git a/src/client/components/ResultTable.js b/src/client/components/ResultTable.js
index f230a8ba..19006337 100644
--- a/src/client/components/ResultTable.js
+++ b/src/client/components/ResultTable.js
@@ -12,19 +12,12 @@ import purple from '@material-ui/core/colors/purple';
 import ResultTableHead from './ResultTableHead';
 import { has, orderBy } from 'lodash';
 
-const styles = () => ({
-  root: {
-    width: '100%',
-    height: '100%',
-    //marginTop: theme.spacing.unit * 3,
-    overflowX: 'auto',
-
-  },
+const styles = (theme) => ({
   table: {
+    marginTop: 72,
     minWidth: 700,
-  },
-  tableWrapper: {
-    overflow: 'auto',
+    overflowX: 'auto',
+    backgroundColor: theme.palette.background.paper
   },
   paginationRow: {
     borderBottom: '1px solid lightgrey'
@@ -43,6 +36,7 @@ const styles = () => ({
     paddingTop: 15
   },
   progressContainer: {
+    width: '100%',
     height: '100%',
     display: 'flex',
     alignItems: 'center',
@@ -212,70 +206,61 @@ class ResultTable extends React.Component {
 
   render() {
     const { classes, rows } = this.props;
-    let table = '';
     if (this.props.fetchingManuscripts   ) {
-      table = (
-        <div className={classes.progressContainer}>
+      return (
+        <Paper className={classes.progressContainer}>
           <Typography className={classes.progressTitle} variant="h4" color='primary'>Fetching manuscript data</Typography>
           <CircularProgress style={{ color: purple[500] }} thickness={5} />
-        </div>
+        </Paper>
       );
     } else {
-      table = (
-        <div className={classes.tableWrapper}>
-          <Table className={classes.table}>
-            <ResultTableHead
-              fetchFacet={this.props.fetchFacet}
-              fetchManuscripts={this.props.fetchManuscripts}
-              facet={this.props.facet}
-              results={this.props.results}
-              page={this.props.page}
-            />
-            <TableBody>
-              {rows.map(row => {
-                return (
-                  <TableRow key={row.id}>
-                    <TableCell component="th" scope="row" >
-                      {this.idRenderer(row)}
-                    </TableCell>
-                    <TableCell className={classes.withFilter} >
-                      {this.stringListRenderer(row.prefLabel)}
-                    </TableCell>
-                    <TableCell className={classes.withFilter}>
-                      {this.objectListRenderer(row.author, true)}
-                    </TableCell>
-                    <TableCell className={classes.withFilter}>
-                      {this.objectListRenderer(row.creationPlace, true)}
-                    </TableCell>
-                    <TableCell className={classes.withFilter}>
-                      {this.objectListRenderer(row.timespan)}
-                    </TableCell>
-                    <TableCell className={classes.withFilter}>
-                      {this.stringListRenderer(row.language)}
-                    </TableCell>
-                    {/*<TableCell className={classes.withFilter}>
-                        {this.stringListRenderer(row.material)}
-                      </TableCell>*/}
-                    <TableCell className={classes.withFilter}>
-                      {this.transactionRenderer(row.acquisition)}
-                    </TableCell>
-                    <TableCell className={classes.withFilter}>
-                      {this.ownerRenderer(row.owner)}
-                    </TableCell>
-                  </TableRow>
-                );
-              })}
-            </TableBody>
-          </Table>
-        </div>
+      return (
+        <Table className={classes.table}>
+          <ResultTableHead
+            fetchFacet={this.props.fetchFacet}
+            fetchManuscripts={this.props.fetchManuscripts}
+            facet={this.props.facet}
+            results={this.props.results}
+            page={this.props.page}
+          />
+          <TableBody>
+            {rows.map(row => {
+              return (
+                <TableRow key={row.id}>
+                  <TableCell component="th" scope="row" >
+                    {this.idRenderer(row)}
+                  </TableCell>
+                  <TableCell className={classes.withFilter} >
+                    {this.stringListRenderer(row.prefLabel)}
+                  </TableCell>
+                  <TableCell className={classes.withFilter}>
+                    {this.objectListRenderer(row.author, true)}
+                  </TableCell>
+                  <TableCell className={classes.withFilter}>
+                    {this.objectListRenderer(row.creationPlace, true)}
+                  </TableCell>
+                  <TableCell className={classes.withFilter}>
+                    {this.objectListRenderer(row.timespan)}
+                  </TableCell>
+                  <TableCell className={classes.withFilter}>
+                    {this.stringListRenderer(row.language)}
+                  </TableCell>
+                  {/*<TableCell className={classes.withFilter}>
+                          {this.stringListRenderer(row.material)}
+                        </TableCell>*/}
+                  <TableCell className={classes.withFilter}>
+                    {this.transactionRenderer(row.acquisition)}
+                  </TableCell>
+                  <TableCell className={classes.withFilter}>
+                    {this.ownerRenderer(row.owner)}
+                  </TableCell>
+                </TableRow>
+              );
+            })}
+          </TableBody>
+        </Table>
       );
     }
-
-    return (
-      <Paper className={classes.root}>
-        {table}
-      </Paper>
-    );
   }
 }
 
diff --git a/src/client/components/ResultTableHead.js b/src/client/components/ResultTableHead.js
index c899d45b..fd45ae53 100644
--- a/src/client/components/ResultTableHead.js
+++ b/src/client/components/ResultTableHead.js
@@ -14,6 +14,10 @@ import ResultTablePaginationActions from './ResultTablePaginationActions';
 const styles = () => ({
   paginationRow: {
     borderBottom: '1px solid lightgrey'
+  },
+  paginationRoot: {
+    display: 'flex',
+    justifyContent: 'flex-start'
   }
 });
 
@@ -75,7 +79,7 @@ class ResultTableHead extends React.Component {
   };
 
   handleChangePage = (event, page) => {
-    console.log(page)
+    // console.log(page)
     this.props.fetchManuscripts(page);
   };
 
@@ -115,6 +119,7 @@ class ResultTableHead extends React.Component {
             onChangePage={this.handleChangePage}
             onChangeRowsPerPage={this.handleChangeRowsPerPage}
             ActionsComponent={ResultTablePaginationActions}
+            classes={{root: classes.paginationRoot}}
           />
         </TableRow>
         <TableRow>
diff --git a/src/client/components/TopBar.js b/src/client/components/TopBar.js
index cbb774e6..36cb627b 100644
--- a/src/client/components/TopBar.js
+++ b/src/client/components/TopBar.js
@@ -172,7 +172,7 @@ class TopBar extends React.Component {
 
     const ManuscriptLink = props =>
       <NavLink
-        to="/manuscripts"
+        to="/manuscripts/table"
         className={classes.appBarButton}
         activeClassName={classes.appBarButtonActive}
         {...props}
diff --git a/src/client/components/ViewTabs.js b/src/client/components/ViewTabs.js
new file mode 100644
index 00000000..e2eace35
--- /dev/null
+++ b/src/client/components/ViewTabs.js
@@ -0,0 +1,58 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import Paper from '@material-ui/core/Paper';
+import { withStyles } from '@material-ui/core/styles';
+import Tabs from '@material-ui/core/Tabs';
+import Tab from '@material-ui/core/Tab';
+import CalendarViewDayIcon from '@material-ui/icons/CalendarViewDay';
+import AddLocationIcon from '@material-ui/icons/AddLocation';
+import RedoIcon from '@material-ui/icons/Redo';
+import PieChartIcon from '@material-ui/icons/PieChart';
+import { Link } from 'react-router-dom';
+
+
+const styles = {
+  root: {
+    width: 'calc(100% - 8px)',
+    position: 'absolute',
+    top: 64,
+    //backgroundColor: 'rgb(238, 238, 238)',
+  },
+};
+
+class ViewTabs extends React.Component {
+  state = {
+    value: 0,
+  };
+
+  handleChange = (event, value) => {
+    this.setState({ value });
+  };
+
+  render() {
+    const { classes } = this.props;
+
+    return (
+      <Paper square className={classes.root}>
+        <Tabs
+          value={this.state.value}
+          onChange={this.handleChange}
+          fullWidth
+          indicatorColor="secondary"
+          textColor="secondary"
+        >
+          <Tab icon={<CalendarViewDayIcon />} label="table" component={Link} to="/manuscripts/table" />
+          <Tab icon={<AddLocationIcon />} label="creation places" component={Link} to="/manuscripts/creation_places" />
+          <Tab icon={<RedoIcon />} label="migrations" />
+          <Tab icon={<PieChartIcon />} label="statistics" />
+        </Tabs>
+      </Paper>
+    );
+  }
+}
+
+ViewTabs.propTypes = {
+  classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(ViewTabs);
diff --git a/src/client/containers/MapApp.js b/src/client/containers/MapApp.js
index f077cdde..16a5e9eb 100644
--- a/src/client/containers/MapApp.js
+++ b/src/client/containers/MapApp.js
@@ -54,46 +54,6 @@ const styles = theme => ({
     borderLeft: '4px solid' + theme.palette.primary.main,
     backgroundColor: 'rgb(238, 238, 238)'
   },
-  // resultTable: {
-  //   width: 1024,
-  //   height: 'calc(100% - 5px)',
-  //   borderRight: '4px solid' + theme.palette.primary.main,
-  //
-  // },
-  // resultTableOneColumn: {
-  //   width: '100%',
-  //   height: 'calc(100% - 5px)',
-  //   overflow: 'auto'
-  // },
-  // rightColumn: {
-  //   height: '100%',
-  //   width: 'calc(100% - 1024px)',
-  // },
-  // map: {
-  //   width: '100%',
-  //   height: '50%',
-  //   borderBottom: '4px solid' + theme.palette.primary.main,
-  // },
-  // fullMap: {
-  //   width: '100%',
-  //   height: '100%',
-  // },
-  // statistics: {
-  //   width: '100%',
-  //   height: '50%',
-  // },
-  // statisticsOneColumn: {
-  //   width: '100%',
-  //   height: '100%',
-  // },
-  // progress: {
-  //   display: 'flex',
-  //   alignItems: 'center',
-  //   justifyContent: 'center',
-  // },
-  // progressTitle: {
-  //   marginRight: 15
-  // },
   footer: {
     position: 'absolute',
     borderTop: '4px solid' + theme.palette.primary.main,
@@ -151,6 +111,7 @@ let MapApp = (props) => {
                   fetchPlace={props.fetchPlace}
                   fetchFacet={props.fetchFacet}
                   fetchResults={props.fetchResults}
+                  match={props.match}
                 />}
             />
           </Switch>
@@ -198,7 +159,8 @@ MapApp.propTypes = {
   fetchPlaces: PropTypes.func.isRequired,
   fetchPlace:  PropTypes.func.isRequired,
   fetchFacet: PropTypes.func.isRequired,
-  fetchResults: PropTypes.func.isRequired
+  fetchResults: PropTypes.func.isRequired,
+  match: PropTypes.object.isRequired
 };
 
 export default compose(
diff --git a/src/client/index.html b/src/client/index.html
index 5fb22df7..b750d60f 100644
--- a/src/client/index.html
+++ b/src/client/index.html
@@ -21,8 +21,10 @@
     #root, #app {
       height: 100%;
     }
-    .leaflet-container {
-      height: 100%;
+    .leaflet-outer-container {
+      height: cacl(100% - 72px);
+      width: 100%;
+      margin-top: 72px
     }
     a, a:visited, a:hover, a:active {
       color: blue;
diff --git a/webpack.client.common.js b/webpack.client.common.js
index ba4ef89c..70ff3ea3 100644
--- a/webpack.client.common.js
+++ b/webpack.client.common.js
@@ -26,6 +26,7 @@ module.exports = {
   output: {
     filename: '[name].bundle.js',
     path: path.resolve(__dirname, outputDirectory),
+    publicPath: '/'
   },
   module: {
     rules: [
diff --git a/webpack.client.dev.js b/webpack.client.dev.js
index 11d9dbfb..819680a2 100644
--- a/webpack.client.dev.js
+++ b/webpack.client.dev.js
@@ -1,5 +1,6 @@
 const merge = require('webpack-merge');
 const common = require('./webpack.client.common.js');
+const path = require('path');
 
 module.exports = merge(common, {
   mode: 'development',
@@ -8,6 +9,8 @@ module.exports = merge(common, {
     hot: true,
     port: 8080,
     open: true,
-    historyApiFallback: true
+    historyApiFallback: true,
+    publicPath: '/',
+    contentBase: path.join(__dirname, 'dist/public')
   }
 });
-- 
GitLab