Skip to content

Commit

Permalink
bring in ui polish with latest code + add interactions between map an…
Browse files Browse the repository at this point in the history
…d table (#132)

* bring in ui polish with latest code

* give selected layer color

* refactor logic to handle incoming data from different places; renamed a component and some related variables for clarity

* edit code comments
  • Loading branch information
smcalilly authored Mar 9, 2022
1 parent 7e20e97 commit 9d63fcd
Show file tree
Hide file tree
Showing 26 changed files with 373 additions and 159 deletions.
6 changes: 5 additions & 1 deletion asset_dashboard/static/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,9 @@ input[type="checkbox"] {
}

.map-container {
height: 650px;
height: 85vh;
}

.map-thumbnail {
height: 40vh;
}
Binary file modified asset_dashboard/static/images/favicon-16x16.png
100755 → 100644
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified asset_dashboard/static/images/favicon-32x32.png
100755 → 100644
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified asset_dashboard/static/images/favicon.ico
100755 → 100644
Binary file not shown.
Binary file added asset_dashboard/static/images/fpdcc-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion asset_dashboard/static/js/PortfolioPlanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ class PortfolioPlanner extends React.Component {
<CSVLink
data={this.state.portfolio.projects}
filename={`CIP-${this.getDate()}`}
className='btn btn-primary mx-auto'
className='btn btn-info mx-auto'
>
Export as CSV
</CSVLink>
Expand Down
8 changes: 4 additions & 4 deletions asset_dashboard/static/js/components/BaseTable.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react'
import { useTable, usePagination, useSortBy } from 'react-table'

const BaseTable = ({ rows = [], columns, getTrProps = props => props, rowClassNames, sizeOfPage=15, pageSizeIncrements=[15, 30, 45] }) => {
const BaseTable = ({ rows = [], columns, getTrProps = props => props, rowClassNames, cellClassNames, sizeOfPage=15, pageSizeIncrements=[15, 30, 45] }) => {

const data = React.useMemo(
() => rows.map((row) => {
Expand Down Expand Up @@ -50,7 +50,7 @@ const BaseTable = ({ rows = [], columns, getTrProps = props => props, rowClassNa
key={i} className={rowClassNames ? `${rowClassNames} cursor-pointer` : 'cursor-pointer'}>
{row.cells.map(cell => {
return (
<td {...cell.getCellProps()} className='text-center'>
<td {...cell.getCellProps()} className={`${cellClassNames && cellClassNames} text-center`}>
{cell.render('Cell')}
</td>
)
Expand All @@ -64,9 +64,9 @@ const BaseTable = ({ rows = [], columns, getTrProps = props => props, rowClassNa

<div className="row container" aria-label="Pagination for all potential projects.">
<div className="d-flex col align-items-center ml-2">
<small className="text-muted">Pages {pageIndex + 1} of {pageOptions.length > 0 ? pageOptions.length : 1 }</small>
<small className="text-muted mb-3">Pages {pageIndex + 1} of {pageOptions.length > 0 ? pageOptions.length : 1 }</small>
</div>
<ul className="pagination col d-flex align-items-center mb-0">
<ul className="pagination col d-flex align-items-center justify-content-center">
<li className="page-item">
<button onClick={() => gotoPage(0)} disabled={!canPreviousPage} className="btn btn-light btn-sm">
{'<<'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ import clip from 'turf-clip'
import * as turf from '@turf/turf'
import EditControl from './EditControl'

export default function MapClipper({ geoJson, onClipped }) {
/*
Allows the selection of multiple geometries at once. Also clips
LineStrings based on the bounds of the drawn geometry area.
*/
export default function GeometrySelector({ geoJson, onGeometriesSelected }) {
const [drawnGeometries, setDrawnGeometries] = useState(null)

useEffect(() => {
if (drawnGeometries) {
clipGeometries(drawnGeometries)
selectGeometries(drawnGeometries)
}
}, [drawnGeometries])

Expand Down Expand Up @@ -60,7 +64,8 @@ export default function MapClipper({ geoJson, onClipped }) {
intersect with the drawnGeometries.
A LineString would be a trail that can be clipped.
The remaining types would be like a building or structure, etc
that should be treated as an entire entity and not clipped. */
that should be treated as an entire entity and not clipped, but entirely selected.
*/
function separateGeometryTypes() {
const lineStringFeatureTypes = []
const allOtherFeatureTypes = []
Expand Down Expand Up @@ -103,7 +108,7 @@ export default function MapClipper({ geoJson, onClipped }) {
return []
}

function clipGeometries(geometries) {
function selectGeometries(geometries) {
const [lineStringFeatureCollection, allOtherTypesFeatureCollection] = separateGeometryTypes()

const bounds = turf.featureCollection(Object.values(geometries))
Expand All @@ -115,11 +120,11 @@ export default function MapClipper({ geoJson, onClipped }) {
const finalFeatureCollection = turf.featureCollection(intersectingFeatures.concat(clippedFeatures))

if (finalFeatureCollection.features.length > 0) {
onClipped(finalFeatureCollection)
onGeometriesSelected(finalFeatureCollection)
} else {
// No features exist, which means they were deleted.
// Send back null so that the caller has no clipped geometries.
onClipped(null)
// Send back null so that the caller has no geometries.
onGeometriesSelected(null)
}
}

Expand Down
24 changes: 24 additions & 0 deletions asset_dashboard/static/js/components/map_utils/ShowPopup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React, { useEffect } from 'react'
import { useMap } from 'react-leaflet'

export default function ShowPopup({ geojson }) {
const map = useMap()

useEffect(() => {
map.eachLayer((layer) => {
if (layer.feature == geojson) {
layer.openPopup()

// Make the layer appear selected.
layer.setStyle({
fillColor: '#3388ff',
fillOpacity: '0.2',
color: '#3388ff',
weight: '4'
})
}
})
}, [geojson])

return null
}
36 changes: 36 additions & 0 deletions asset_dashboard/static/js/components/map_utils/bindPopup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react'
import ReactDOMServer from 'react-dom/server'

function Popup({ feature }) {
const properties = feature.properties
return (
<>
{properties &&
<div>
<h6>Asset Info</h6>
<ul className='list-group list-group-flush'>
<li className='list-group-item'>
<strong>ID:</strong> {properties.asset_id ? properties.asset_id : properties.identifier }
</li>
<li className='list-group-item'>
<strong>Name:</strong> {properties.asset_name ? properties.asset_name : properties.name }
</li>
{properties.asset_type
&& <li className='list-group-item'>
<strong>Asset Type:</strong> {properties.asset_type}
</li>
}
</ul>
</div>
}
</>
)
}

export default function bindPopup(feature, layer, autoShow=false) {
const popupContent = ReactDOMServer.renderToString(
<Popup feature={feature} />
)

layer.bindPopup(popupContent)
}
54 changes: 39 additions & 15 deletions asset_dashboard/static/js/components/maps/ListAssetsMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import BaseMap from './BaseMap'
import { GeoJSON } from 'react-leaflet'
import zoomToExistingGeometries from '../map_utils/zoomToExistingGeometries'
import circleMarker from '../map_utils/circleMarker'
import ReactTable from '../BaseTable'
import existingAssetsColumns from '../table_utils/existingAssetsColumns'
import bindPopup from '../map_utils/bindPopup'

function ListAssetsMap(props) {

Expand All @@ -13,21 +16,42 @@ function ListAssetsMap(props) {
}

return (
<div className='map-container'>
<BaseMap
center={[41.8781, -87.6298]}
zoom={11}
whenCreated={onMapCreated}>
{
props?.assets &&
<GeoJSON
data={props.assets}
style={{color: 'green'}}
pointToLayer={circleMarker}
/>
}
</BaseMap>
</div>
<>
{
props?.assets &&
<div className=''>
<div className='row'>
<div className='col-4 m-3'>
<div className="d-flex align-items-center justify-content-between m-2">
<h3>Phase Assets</h3>
<a href={`${window.location.href}assets`} class="text-info lead">Edit Assets ></a>
</div>
<div className='map-thumbnail'>
<BaseMap
center={[41.8781, -87.6298]}
zoom={11}
whenCreated={onMapCreated}>
<GeoJSON
data={props.assets}
style={{color: 'green'}}
pointToLayer={circleMarker}
onEachFeature={bindPopup}
/>
</BaseMap>
</div>
</div>
<div className='col m-3'>
<ReactTable
rows={props.assets.features}
columns={React.useMemo(() => existingAssetsColumns(), [])}
pageSizeIncrements={[10]}
sizeOfPage={10}
/>
</div>
</div>
</div>
}
</>
)
}

Expand Down
Loading

0 comments on commit 9d63fcd

Please sign in to comment.