diff --git a/smppir-checkin-portal/src/Pages/MainPage.js b/smppir-checkin-portal/src/Pages/MainPage.js index 7b446f1b8a4c0f61d03f13213979adff51041aa4..8966616f2a5e05fc6d5774190022fd0b333fed83 100644 --- a/smppir-checkin-portal/src/Pages/MainPage.js +++ b/smppir-checkin-portal/src/Pages/MainPage.js @@ -1,26 +1,196 @@ import React, { Component } from 'react'; import './Styles/MainPage.css'; import BarraBrasil from '../Components/BarraBrasil' -import { Row, Col, Preloader, NavItem } from 'react-materialize' import AppFooter from '../Components/AppFooter' +import { Card, Row, Col, Button, Icon, Input, NavItem, Preloader } from 'react-materialize' import NavigationBar from '../Components/NavigationBar' +import IterativeCollapsible from '../Components/IterativeCollapsible' +import MapComponent from '../Components/MapComponent' +import {URL} from '../env' +import DataFrame from 'dataframe-js'; +import axios from 'axios'; class MainPage extends Component { + constructor(props) { + super(props); + this.state={ + 'redirect':false, + 'credentials': {}, + 'geolocationsDF': undefined, //it's a dataframe + 'locationsDF': undefined, //it's a dataframe + 'categoriesDF': undefined, //it's a dataframe + 'latLng': [], + 'originalLocation':[], + 'centerLocation': undefined, + 'zoom': undefined, + 'dataset':'1' + } + this.outerCollapsibleItems = this.outerCollapsibleItems.bind(this) + this.zoomInMap = this.zoomInMap.bind(this) + this.selectDataset = this.selectDataset.bind(this) + this.resetMap = this.resetMap.bind(this) + } + componentWillMount(){ + axios.get(`${URL}geolocations`).then((resp) => { + axios.get(`${URL}categories`).then((resp2) => { + let response = resp.data.result + let response2 = resp2.data.result + let df = new DataFrame(response) + let df2 = new DataFrame(response2) + let latLng = df.select('latitude', 'longitude','geolocation_name').toCollection() + this.setState({geolocationsDF: df, locationsDF: df, categoriesDF: df2, latLng: latLng, originalLocation: [-14.424429, -49.265382]}) + }) + }) + } + render() { + let items = this.outerCollapsibleItems() return ( <div> <BarraBrasil /> <NavigationBar button={<NavItem id={'login-btn'} href='/login'>Login</NavItem>}/> - <Row> - <Col id='map' s={4}> - <Preloader size='big'/> + <Row style={{marginTop:15}} > + <Col s={12}> + <Card> + <h1> Tela de bem-vindos - Escrever alguma coisa aqui depois</h1> + </Card> </Col> - </Row> - <h1> Colocar mapa </h1> + + <Col s={12} m={5}> + <Card> + <Row id='map-filters'> + <Row> + <Col s={12} m={6}> + <Input s={12} type='select' label="Fonte de dados" defaultValue='1' onChange={this.selectDataset}> + <option value='1'>Todas</option> + <option value='2'>Portal</option> + <option value='3'>Mobile</option> + </Input> + </Col> + <div className='right'> + <div id='resetMapZoom' className='tooltip'> + <Button floating id={'changeMapModeButton'} type='submit' onClick={this.resetMap}><Icon>zoom_out_map</Icon></Button> + <span className="tooltiptext">Voltar o mapa para posição original</span> + </div> + </div> + </Row> + + </Row> + </Card> + <Card id={'Map-locations-main-page'}> + { + items ? + <IterativeCollapsible + id="outerMapCollapsible" + classes="category-list" + items={ + items + } + /> + : + '' + } + </Card> + </Col> + <Col s={12} m={7}> + <Card id='mapCard' className='white' textClassName='black-text'> + <MapComponent + readOnly={true} + markers={this.state.latLng} + zoom={this.state.zoom} + centerLocation={this.state.centerLocation} + /> + </Card> + </Col> + </Row> + + <AppFooter/> </div> ); } + + resetMap(){ + let originalPosition = {'position': this.state.originalLocation, 'zoom': 4} + this.setState({'centerLocation': originalPosition.position, 'zoom': originalPosition.zoom}) + } + selectDataset(e){ + this.setState({dataset: e.target.value}, () => { + let df = this.state.geolocationsDF + let dataset = this.state.dataset + switch(dataset){ + case '1': + df = this.state.locationsDF; + break; + case '2': + df = df.filter(row => row.get('user_id') !== null); + break; + case '3': + df = this.state.locationsDF.filter(row => row.get('user_id') === null); + break; + default: + break; + } + let latLng = df.select('latitude', 'longitude','geolocation_name').toCollection() + this.setState({geolocationsDF: df, latLng:latLng}) + }) + } + outerCollapsibleItems(){ + if(this.state.categoriesDF){ + let names = this.state.categoriesDF.select('id','category_name').toArray() + let geolocations = this.state.geolocationsDF.toCollection() + let classes = 'GreengAnchor Custom-padding-list' + let content = {} + let returnArray = [] + let names_len = names.length + + //Initialize 'content' as an object of arrays + for(let i = 0; i < names.length; i++){ + content[names[i][0]] = [] + } + + for(let i = 0; i < geolocations.length; i++){ + content[geolocations[i].category_id].push(geolocations[i]) + } + + for(let i = 0; i < names_len; i++){ + let aux = this.innerCollapsibleItems(content, names[i]) + returnArray.push({name: names[i], classes: classes, content: <IterativeCollapsible + id="innerMapCollapsible" + classes="location-list" + items={aux} + />}) + } + return returnArray + } + } + innerCollapsibleItems(content, key){ + let items = [] + let received_array = Object.values(content[key[0]]) + for(let i = 0; i < received_array.length; i++){ + items.push({classes: 'OrangeAnchor Custom-padding-list', name: received_array[i].geolocation_name, content: + <div className={'insideCollapsibleLocation'}> + <Row> + <Col s={12} m={9}> + <p><b>Local: </b>{received_array[i].geolocation_name}</p> + <p><b>Latitude: </b>{received_array[i].latitude}</p> + <p><b>Longitude: </b>{received_array[i].longitude}</p> + </Col> + <div className='right'> + <div className='tooltip'> + <Button id={'locateInMap'} floating onClick={() => this.zoomInMap(received_array[i].latitude, received_array[i].longitude)} ><Icon>my_location</Icon></Button> + <span className="tooltiptext">Visualizar no mapa</span> + </div> + </div> + </Row> + </div> + }) + } + return (items) + } + zoomInMap(lat, lng){ + this.setState({zoom:25, centerLocation:[lat,lng]}) + } } export default MainPage; \ No newline at end of file diff --git a/smppir-checkin-portal/src/Pages/Map.js b/smppir-checkin-portal/src/Pages/Map.js index a0d8ba8c9b55f99420b9a2da8d81db0d3c7393d9..2eddeab14bb85193449d34bdf78543e94ff89c67 100644 --- a/smppir-checkin-portal/src/Pages/Map.js +++ b/smppir-checkin-portal/src/Pages/Map.js @@ -63,74 +63,74 @@ class Map extends Component { <MenuItem>Mapa</MenuItem> </Breadcrumb> <Row> - <Col s={12} m={5}> - <Card> - <Row id='map-filters'> - <Row> - <Col m={6}> - <Input s={12} type='select' label="Fonte de dados" defaultValue='1' onChange={this.selectDataset}> - <option value='1'>Todas</option> - <option value='2'>Portal</option> - <option value='3'>Mobile</option> - </Input> - </Col> - <Col m={1} offset={'m4'}> - <div className='tooltip'> - <Button floating id={'changeMapModeButton'} type='submit' onClick={this.changeMode} alt='Alterar para modo de inserção' ><Icon>edit</Icon></Button> - <span class="tooltiptext">Alterar para modo de inserção</span> - </div> - </Col> - <Col m={1}> - <div className='tooltip'> - <Button floating id={'changeMapModeButton'} type='submit' onClick={this.resetMap}><Icon>zoom_out_map</Icon></Button> - <span class="tooltiptext">Voltar o mapa para posição original</span> - </div> - </Col> - </Row> + <Col s={12} m={5}> + <Card> <Row id='map-filters'> - <p id={'map-status'} - style={ this.state.insertLocation ? {backgroundColor:'rgb(22, 60, 122)', color:'white'} : {backgroundColor:'orange', color:'white'} }> - <b>{this.state.insertLocation ? 'Em modo de inserção' : 'Em modo de leitura'}</b> - </p> + <Row> + <Col s={12} m={6}> + <Input s={12} type='select' label="Fonte de dados" defaultValue='1' onChange={this.selectDataset}> + <option value='1'>Todas</option> + <option value='2'>Portal</option> + <option value='3'>Mobile</option> + </Input> + </Col> + <div className='right'> + <div className='tooltip'> + <Button floating id={'changeMapModeButton'} type='submit' onClick={this.changeMode} alt='Alterar modo' ><Icon>edit</Icon></Button> + <span className="tooltiptext">Alterar para modo de inserção</span> + </div> + + + <div id='resetMapZoom' className='tooltip'> + <Button floating id={'changeMapModeButton'} type='submit' onClick={this.resetMap}><Icon>zoom_out_map</Icon></Button> + <span className="tooltiptext">Voltar o mapa para posição original</span> + </div> + </div> + </Row> + <Row id='map-filters'> + <p id={'map-status'} + style={ this.state.insertLocation ? {backgroundColor:'rgb(22, 60, 122)', color:'white'} : {backgroundColor:'orange', color:'white'} }> + <b>{this.state.insertLocation ? 'Em modo de inserção' : 'Em modo de leitura'}</b> + </p> + </Row> </Row> - </Row> - </Card> - <Card id={'Map-locations'}> - { - items ? - <IterativeCollapsible - id="outerMapCollapsible" - classes="category-list" - items={ - items - } - /> - : - '' - } - </Card> - </Col> - <Col s={12} m={7}> - <Card className='white' textClassName='black-text'> - { - !this.state.insertLocation ? - <MapComponent - readOnly={true} - markers={this.state.latLng} - zoom={this.state.zoom} - centerLocation={this.state.centerLocation} - /> - : - <MapComponent - readOnly={true} - markers={this.state.latLng} - zoom={this.state.zoom} - centerLocation={this.state.centerLocation} - /> - } - - </Card> - </Col> + </Card> + <Card id={'Map-locations'}> + { + items ? + <IterativeCollapsible + id="outerMapCollapsible" + classes="category-list" + items={ + items + } + /> + : + '' + } + </Card> + </Col> + <Col s={12} m={7}> + <Card id='mapCard' className='white' textClassName='black-text'> + { + !this.state.insertLocation ? + <MapComponent + readOnly={true} + markers={this.state.latLng} + zoom={this.state.zoom} + centerLocation={this.state.centerLocation} + /> + : + <MapComponent + readOnly={true} + markers={this.state.latLng} + zoom={this.state.zoom} + centerLocation={this.state.centerLocation} + /> + } + + </Card> + </Col> </Row> <AppFooter/> </div> @@ -158,7 +158,8 @@ class Map extends Component { default: break; } - this.setState({geolocationsDF: df}) + let latLng = df.select('latitude', 'longitude','geolocation_name').toCollection() + this.setState({geolocationsDF: df, latLng:latLng}) }) } changeMode(){ @@ -201,13 +202,19 @@ class Map extends Component { for(let i = 0; i < received_array.length; i++){ items.push({classes: 'OrangeAnchor Custom-padding-list', name: received_array[i].geolocation_name, content: <div className={'insideCollapsibleLocation'}> - <p><b>Local: </b>{received_array[i].geolocation_name}</p> - <p><b>Latitude: </b>{received_array[i].latitude}</p> - <p><b>Longitude: </b>{received_array[i].longitude}</p> - <div className='tooltip'> - <Button floating onClick={() => this.zoomInMap(received_array[i].latitude, received_array[i].longitude)} ><Icon>my_location</Icon></Button> - <span class="tooltiptext">Visualizar no mapa</span> - </div> + <Row> + <Col s={12} m={9}> + <p><b>Local: </b>{received_array[i].geolocation_name}</p> + <p><b>Latitude: </b>{received_array[i].latitude}</p> + <p><b>Longitude: </b>{received_array[i].longitude}</p> + </Col> + <div className='right'> + <div className='tooltip'> + <Button id={'locateInMap'} floating onClick={() => this.zoomInMap(received_array[i].latitude, received_array[i].longitude)} ><Icon>my_location</Icon></Button> + <span className="tooltiptext">Visualizar no mapa</span> + </div> + </div> + </Row> </div> }) } diff --git a/smppir-checkin-portal/src/Pages/Styles/MainPage.css b/smppir-checkin-portal/src/Pages/Styles/MainPage.css index c6a4954f409d2d1991d2db3255b82c0e806f929a..67d260fa38841dab1ffbb17da6c8c661730719c9 100644 --- a/smppir-checkin-portal/src/Pages/Styles/MainPage.css +++ b/smppir-checkin-portal/src/Pages/Styles/MainPage.css @@ -15,4 +15,10 @@ #map{ margin-left: 50%; +} + +#Map-locations-main-page{ + max-height: 589px; + overflow-y: scroll; + /* height: 600px; */ } \ No newline at end of file diff --git a/smppir-checkin-portal/src/Pages/Styles/Map.css b/smppir-checkin-portal/src/Pages/Styles/Map.css index 4d568c088cd91bd7ba55542ff21055faf4c56939..45b6fdae2cfcecdbf2a6851d272edaf20ee05c98 100644 --- a/smppir-checkin-portal/src/Pages/Styles/Map.css +++ b/smppir-checkin-portal/src/Pages/Styles/Map.css @@ -42,7 +42,15 @@ margin-left: 5px; margin-right: 5px; } - +#mapCard > .card-content{ + padding: 0; +} +#resetMapZoom{ + margin-left: 8px +} +#locateInMap{ + margin-top: 8px; +} @@ -58,14 +66,17 @@ color: #fff; text-align: center; border-radius: 2px; - padding: 5px 0; + padding: 10px 5px; position: absolute; - z-index: 1; + z-index: 1005; bottom: 85%; - left: 50%; + left: 15%; margin-left: -60px; opacity: 0; transition: opacity 0.3s; + + -webkit-box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.2); + box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.2); } .tooltip .tooltiptext::after { @@ -75,8 +86,7 @@ left: 50%; margin-left: -5px; border-color: #555 transparent transparent transparent; - -webkit-box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.2); - box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.2); + } .tooltip:hover .tooltiptext { diff --git a/smppir-checkin-portal/src/Pages/Welcome.js b/smppir-checkin-portal/src/Pages/Welcome.js index 8e64fc41e6ee63bbd0a2283813686537cdb86d60..76ff8887715f1272e62708ddebf9dad38f2efe12 100644 --- a/smppir-checkin-portal/src/Pages/Welcome.js +++ b/smppir-checkin-portal/src/Pages/Welcome.js @@ -43,7 +43,7 @@ class Welcome extends Component { <Card> <p>Bem-vindo <b>{this.state.currentUser.name}</b>, o que faremos agora?</p> <Row> - <List items={ADMIN_FEATURES}/> + <List items={ADMIN_FEATURES} credentials={this.state.credentials} currentUser={this.props.currentUser}/> </Row> </Card> </Col> diff --git a/smppir-checkin-portal/src/env.js b/smppir-checkin-portal/src/env.js index aabae849ab3a8be63cba15495ad3e245afb44f52..104edb63c1c619674d471c8bc69c85f2f80dbe85 100644 --- a/smppir-checkin-portal/src/env.js +++ b/smppir-checkin-portal/src/env.js @@ -4,7 +4,7 @@ export const ADMIN_FEATURES = [ {'value':'Gerenciar Usuários', 'active': false}, {'value':'Gerenciar Categorias', 'active': false}, {'value':'Gerenciar Localizações', 'active': false}, - {'value':'Visualizar Mapa', 'active': false} + {'value':'Visualizar Mapa', 'active': false, 'href':'/map'} ] export default function downloadNominatimURL(query, format='json'){ var baseURL = 'https://nominatim.openstreetmap.org/search?';