Unverified Commit e9ca9345 authored by amystamile's avatar amystamile Committed by GitHub
Browse files

Merge pull request #22 from amystamile/limits

Adds Footprint Display Slider and Moved Pagination
parents 16ead9db 9c820f6f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ export default function App() {
          <ArrowLeftIcon/>
        </div>
          <div className={sortBarStyle}>
            <SearchAndFilterInput />
            <SearchAndFilterInput target={targetPlanet}/>
            {/* instead of styled surrounding div: { showSortBar ? <SearchAndFilterInput /> : null } 
                ^ simpler but might break things if another part of the program is looking for it and it's not there? */}
          </div> 
+63 −6
Original line number Diff line number Diff line
import React from "react";
import React, {useEffect} from "react";
// Apply and Clear Buttons
import ButtonGroup from "@material-ui/core/ButtonGroup";
import Button from "@material-ui/core/Button";
@@ -21,6 +21,10 @@ import InputLabel from '@mui/material/InputLabel';
import FormControl from '@mui/material/FormControl';
import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward';
import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward';
import Slider from '@mui/material/Slider';
import Pagination from '@mui/material/Pagination';

import { getMaxNumberPages, setCurrentPage, getCurrentPage, getNumberMatched } from "../../js/ApiJsonCollection";


/**
@@ -80,7 +84,7 @@ const useStyles = makeStyles(theme => ({
 * <SearchAndFilterInput />
 *
 */
export default function SearchAndFilterInput() {
export default function SearchAndFilterInput(props) {

  // import stylesheet from above
  const classes = useStyles();
@@ -99,6 +103,9 @@ export default function SearchAndFilterInput() {
  const [dateCheckVal, setDateCheckVal] = React.useState(false);
  const [dateFromVal, setDateFromVal] = React.useState(null);
  const [dateToVal, setDateToVal] = React.useState(null);
  const [maxPages, setMaxPages] = React.useState(0);
  const [maxNumberFootprints, setMaxNumberFootprints] = React.useState(0);
  const [limitVal, setLimitVal] = React.useState(0);

  // Clear all values
  const handleClear = (event) => {
@@ -110,6 +117,9 @@ export default function SearchAndFilterInput() {
    setDateCheckVal(false);
    setDateFromVal(null);
    setDateToVal(null);
    setLimitVal(10);
    setMaxPages(getMaxNumberPages);
    setMaxNumberFootprints(getNumberMatched);
    //// Uncomment to close details on clear
    // keywordDetails.current.open = false;
    // dateDetails.current.open = false;
@@ -156,6 +166,29 @@ export default function SearchAndFilterInput() {
    setDateCheckVal(true);
  }

  // limit
  const handleLimitChange = (event, value) => {
    setLimitVal(value);
    setTimeout(() => {
      setMaxPages(getMaxNumberPages);
    }, 1000);
  }

  // resets pagination and limit when switching targets
  useEffect(() => {
    setTimeout(() => {
      setMaxNumberFootprints(getNumberMatched);
      setLimitVal(10);
      setMaxPages(getMaxNumberPages);
    }, 1000);
  }, [props.target]);

  // Pagination
  const handlePageChange = (event, value) => {
    setCurrentPage(value);
  };


  /* Control IDs for reference:
  applyButton
  clearButton
@@ -176,7 +209,6 @@ export default function SearchAndFilterInput() {
          <div className="panelSection panelHeader">
            Sort and Filter
          </div>
          
          <div className="panelSection">
            <ButtonGroup>
              <Button id="applyButton" variant="contained" startIcon={<FilterAltIcon />} className={classes.button}>
@@ -294,6 +326,31 @@ export default function SearchAndFilterInput() {
              </div>
            </details>
            </div>
            <div className="panelSectionHeader">
              <div className="panelItem">
                <div className="panelSectionTitle">Number of Displayed Footprints</div>
                  <Slider
                    id="valueSlider"
                    size="small"
                    valueLabelDisplay="auto"
                    onChange={handleLimitChange}
                    value={limitVal}
                    max={maxNumberFootprints}
                    defaultValue={10}
                  />
              </div>
            </div>
            <div className="panelSectionHeader">
              <div className="panelItem">
                <div className="panelSectionTitle">Showing {limitVal} of {maxNumberFootprints} Footprints</div>
                  <Pagination
                    id="pagination"
                    count={maxPages}
                    size="small"
                    onChange={handlePageChange}
                  />
              </div>
            </div>
        </div>
    </div>
  );
+59 −1
Original line number Diff line number Diff line
var _maxNumberPages = 0;
var _currentPage = 1;
var _numberMatched = 0;

function callAPI() {
  return fetch(
    "https://stac.astrogeology.usgs.gov/api/collections"
@@ -44,4 +48,58 @@ function getItemCollection(name, queryString) {
  });
}

export { getItemCollection };
 No newline at end of file
/**
 * @function setNumberMatched
 * @description Sets the value of the return number of footprints
 */
function setNumberMatched(matched) {
  _numberMatched = matched;
  let sliderElement = document.getElementById('valueSlider');
  let limitVal = sliderElement.lastChild.firstChild.value;
    if (limitVal != 0 && matched != 0){
      setMaxNumberPages(Math.floor(matched/limitVal));
    }
}

/**
 * @function getNumberMatched
 * @description Gets the value of the return number of footprints
 */
function getNumberMatched() {
  return _numberMatched
}

/**
 * @function setMaxNumberPages
 * @description Sets the value of the max number of pages possible
 */
function setMaxNumberPages(pages) {
  _maxNumberPages = pages;
}

/**
 * @function getMaxNumberPages
 * @description Gets the value of the max number of pages possible
 */
function getMaxNumberPages() {
  return _maxNumberPages;
}

/**
 * @function setCurrentPage
 * @description Sets the value of the current page
 */
function setCurrentPage(page) {
  _currentPage = page;
}

/**
 * @function getMaxNumberPages
 * @description Gets the value of the max number of pages possible
 */
function getCurrentPage() {
  return _currentPage;
}


export { getItemCollection, getMaxNumberPages, setCurrentPage, getCurrentPage, setNumberMatched, getNumberMatched, setMaxNumberPages };
+53 −8
Original line number Diff line number Diff line
import L from "leaflet";
import "leaflet-draw";
import Wkt from "wicket";
import {getCurrentPage} from "./ApiJsonCollection";

/**
 * @class AstroDrawControl
 * @aka L.Control.AstroDrawControl
@@ -79,6 +81,12 @@ export default L.Control.AstroDrawControl = L.Control.Draw.extend({
    );
    L.DomEvent.on(L.DomUtil.get("clearButton"), "click", this.clearMap, this);

    this.valueSlider = L.DomUtil.get("valueSlider")
    L.DomEvent.on(this.valueSlider, "click", this.applyLimit, this);

    this.pagination = L.DomUtil.get("pagination")
    L.DomEvent.on(this.pagination, "click", this.applyPage, this);

    map.on("draw:created", this.shapesToWKT, this);

    // map.on("projChange", this.reprojectFeature, this);
@@ -109,9 +117,49 @@ export default L.Control.AstroDrawControl = L.Control.Draw.extend({

  clearMap: function() {
    this._map._footprintControl.remove();
    this._map._geoLayer.clearLayers();
    for(let i = 0; i < this._map._geoLayers.length; i++){
      this._map._geoLayers[i].clearLayers();
    }
  },


  applyLimit: function() {
    this._map._footprintControl.remove();

    for(let i = 0; i < this._map._geoLayers.length; i++){
      this._map._geoLayers[i].clearLayers();
    }
    let currentPage = getCurrentPage();

    let sliderElement = L.DomUtil.get("valueSlider");
    let limitVal = sliderElement.lastChild.firstChild.value;

    let queryString = "?page=" + currentPage;
    queryString += "&limit=" + limitVal;

    this._map.loadFootprintLayer(this._map._target, queryString);
  },



  applyPage: function() {
    this._map._footprintControl.remove();

    for(let i = 0; i < this._map._geoLayers.length; i++){
      this._map._geoLayers[i].clearLayers();
    }
    let currentPage = getCurrentPage();

    let sliderElement = L.DomUtil.get("valueSlider");
    let limitVal = sliderElement.lastChild.firstChild.value;

    let queryString = "?page=" + currentPage;
    queryString += "&limit=" + limitVal;

    this._map.loadFootprintLayer(this._map._target, queryString);
  },


  /**
   * @function shapesToFootprint
   * @description Is called when a user draws a shape using the on map drawing features.
@@ -139,9 +187,6 @@ export default L.Control.AstroDrawControl = L.Control.Draw.extend({
      bboxCoordArr[1][0],
      bboxCoordArr[1][1]
    ];
    this._map._footprintControl.remove();
    this._map._geoLayer.clearLayers();
    this._map.removeControl(this._map._htmllegend);
    let queryString = "bbox=" + "[" + bboxArr + "]";
    return queryString;
  },
@@ -184,7 +229,6 @@ export default L.Control.AstroDrawControl = L.Control.Draw.extend({
    }

    if (L.DomUtil.get("areaCheckBox").checked == true) {
      console.log("area");
      let bboxValue = this.shapesToFootprint(this.wktTextBox.value);
      filterOptions.push(bboxValue);
    }
@@ -200,9 +244,10 @@ export default L.Control.AstroDrawControl = L.Control.Draw.extend({
    }
    // re render map
    this._map._footprintControl.remove();
    this._map._geoLayer.clearLayers();
    this._map.removeControl(this._map._htmllegend);
    this._map.loadFootprintLayer(this._map._name, queryString);
    for(let i = 0; i < this._map._geoLayers.length; i++){
      this._map._geoLayers[i].clearLayers();
    }
    this._map.loadFootprintLayer(this._map._target, queryString);
  },

  /**
+17 −74
Original line number Diff line number Diff line
@@ -2,10 +2,8 @@ import L from "leaflet";
import "proj4leaflet";
import AstroProj from "./AstroProj";
import LayerCollection from "./LayerCollection";
import { getItemCollection, url } from "./ApiJsonCollection";
import { getItemCollection, setNumberMatched, setMaxNumberPages, getCurrentPage, setCurrentPage } from "./ApiJsonCollection";
import { MY_JSON_MAPS } from "./layers";
import "leaflet-html-legend";
import React from "react";

/**
 * @class AstroMap
@@ -47,10 +45,8 @@ export default L.Map.AstroMap = L.Map.extend({
    };
    this._footprintCollection = {};
    this._footprintControl = null;
    this._geoLayer = null;
    this._name = null;
    this._geoLayers = [];
    this._htmllegend = null;
    this._currentPage = 1;

    // Set by layer collection or baselayerchange event
    this._currentLayer = null;
@@ -98,7 +94,8 @@ export default L.Map.AstroMap = L.Map.extend({
    L.Map.prototype.initialize.call(this, this._mapDiv, this.options);
    this.loadLayerCollection("cylindrical");

    this.loadFootprintLayer(target, "?page=" + this._currentPage);
    setCurrentPage(1);
    this.loadFootprintLayer(target, "?page=1");

    // Listen to baselayerchange event so that we can set the current layer being
    // viewed by the map.
@@ -125,6 +122,7 @@ export default L.Map.AstroMap = L.Map.extend({
    this.layers[name].addTo(this);
  },


  /**
   * @function AstroMap.prototype.loadFootprintLayer
   * @description Adds the ApiJsonCollection with the requested name.
@@ -133,84 +131,29 @@ export default L.Map.AstroMap = L.Map.extend({
   *
   * @param {String} queryString - Filter for deisered footprints ie: ?page=1
   *
   * @param {Boolean} loadFootprintLegend - Boolean value used to bypass adding
   *                                        the FootprintLegend
   */
  loadFootprintLayer: function(name, queryString, loadFootprintLegend = true) {
  loadFootprintLayer: function(name, queryString) {
    var matched = 0;
    
    getItemCollection(name, queryString).then(result => {
      if (result != undefined) {
        this._name = name;
        this._geoLayer = L.geoJSON()
        this._geoLayers = new Array(result.length);
        for (let i = 0; i < result.length; i++) {
          this._geoLayers[i] = L.geoJSON()
            .on('click', function(e){
              console.log(e);
            }).addTo(this);
        this._footprintCollection["Footprints"] = this._geoLayer;
        for (let i = 0; i < result.length; i++) {
          matched += result[i].numberMatched;
          for (let j = 0; j < result[i].features.length; j++) {
            this._geoLayer.addData(result[i].features[j]);
            this._footprintCollection[result[i].features[j].collection] = this._geoLayers[i];
            this._geoLayers[i].addData(result[i].features[j]);
          }
        }

        this._footprintControl = L.control
          .layers(null, this._footprintCollection)
          .addTo(this);

        if (loadFootprintLegend) {
          this.addFootprintLegend(name);
        }
      }
    });
  },

  /**
   * @function AstroMap.prototype.addFootprintLegend
   * @description Adds legend for each footprint layer
   *
   * @param {String} name - Name of the projection
   *
   */
  addFootprintLegend: function(name) {
    var self = this;

    var legend = L.control.htmllegend({
      legends: [
        {
          name: "Footprints",
          layer: this._geoLayer,
          elements: [
            {
              html: `<div class="pagination">
                      <a id=footprint_left>&laquo;</a>
                      <a id=footprint_pageNumber>${self._currentPage}</a>
                      <a id=footprint_right>&raquo;</a>
                    </div>`
            }
          ]
        }
      ]
    });
    this._htmllegend = legend;
    this.addControl(legend);

    $("#footprint_right").click(function() {
      self._currentPage += 1;
      self._footprintControl.remove();
      self._geoLayer.clearLayers();
      self.removeControl(legend);
      let queryString = "?page=" + self._currentPage;
      self.loadFootprintLayer(name, queryString);
    });

    $("#footprint_left").click(function() {
      self._currentPage -= 1;
      if (this._currentPage > 0) {
        self._footprintControl.remove();
        self._geoLayer.clearLayers();
        self.removeControl(legend);
        let queryString = "?page=" + self._currentPage;
        self.loadFootprintLayer(name, queryString);
      }
      // should add some error message here eventually
      setNumberMatched(matched);
    });
  },

Loading