diff options
| author | Kumar Damani <kumar.damani@mail.utoronto.ca> | 2019-04-23 18:36:36 +0000 |
|---|---|---|
| committer | Kumar Damani <kumar.damani@mail.utoronto.ca> | 2019-04-23 18:36:36 +0000 |
| commit | 0380ba5ea5c134f3b7c79efae4daa1034d405daf (patch) | |
| tree | 63c8b95e5b88738c7562b2c22766f7c90f01778e | |
| parent | 8808175e3aa8ffc4022e58c9f926abfd28ce62c4 (diff) | |
| parent | 8135fe42bfa36df72c427e8d567aad2182e14372 (diff) | |
Merge branch 'master' into qa
| -rw-r--r-- | mobile/.expo/packager-info.json | 12 | ||||
| -rw-r--r-- | mobile/App.js | 13 | ||||
| -rw-r--r-- | mobile/components/FormPage.js | 20 | ||||
| -rw-r--r-- | mobile/screens/GreetingPage.js (renamed from mobile/components/GreetingPage.js) | 0 | ||||
| -rw-r--r-- | mobile/screens/HomeScreen.js | 188 | ||||
| -rw-r--r-- | mobile/screens/LinksScreen.js | 27 | ||||
| -rw-r--r-- | mobile/screens/MapPage.js | 154 | ||||
| -rw-r--r-- | mobile/screens/SettingsScreen.js | 14 | ||||
| -rw-r--r-- | web/app.js | 20 | ||||
| -rw-r--r-- | web/models/mockpoints.js | 34 | ||||
| -rw-r--r-- | web/models/points.js | 58 | ||||
| -rw-r--r-- | web/public/javascripts/map.js | 369 | ||||
| -rw-r--r-- | web/routes/index.js | 120 |
13 files changed, 391 insertions, 638 deletions
diff --git a/mobile/.expo/packager-info.json b/mobile/.expo/packager-info.json index 7391ba7..606e044 100644 --- a/mobile/.expo/packager-info.json +++ b/mobile/.expo/packager-info.json @@ -1,9 +1,9 @@ { "devToolsPort": 19002, - "expoServerPort": null, - "packagerPort": null, - "packagerPid": null, - "expoServerNgrokUrl": null, - "packagerNgrokUrl": null, - "ngrokPid": null + "expoServerPort": 19000, + "packagerPort": 19001, + "packagerPid": 29021, + "expoServerNgrokUrl": "https://h6-m98.csc301dreamteam.mobile.exp.direct", + "packagerNgrokUrl": "https://packager.h6-m98.csc301dreamteam.mobile.exp.direct", + "ngrokPid": 29069 }
\ No newline at end of file diff --git a/mobile/App.js b/mobile/App.js index 703c6eb..a1f3bc4 100644 --- a/mobile/App.js +++ b/mobile/App.js @@ -3,15 +3,20 @@ import { Text, View, Alert, StyleSheet, Button, AppRegistry, Navigator, Touchabl import { Ionicons } from '@expo/vector-icons'; import { createStackNavigator, createAppContainer } from 'react-navigation'; -import GreetingPage from './components/GreetingPage'; +import GreetingPage from './screens/GreetingPage'; import FormPage from './screens/Form1'; import MapPage from './screens/MapPage'; -const RootStack = createStackNavigator( {GreetingPage: GreetingPage, FormPage: FormPage, MapPage: MapPage}, - {headerMode: 'none'}) +const RootStack = createStackNavigator( + { + GreetingPage: GreetingPage, + FormPage: FormPage, + MapPage: MapPage + }, + { headerMode: 'none' } +) const App = createAppContainer(RootStack) export default App; - diff --git a/mobile/components/FormPage.js b/mobile/components/FormPage.js deleted file mode 100644 index 9ea3dce..0000000 --- a/mobile/components/FormPage.js +++ /dev/null @@ -1,20 +0,0 @@ -import React, { Component } from 'react'; -import { Text, View, Alert, StyleSheet, Button, AppRegistry, Navigator, TouchableHighlight} from 'react-native'; -import { Ionicons } from '@expo/vector-icons'; -import { createStackNavigator, createAppContainer } from 'react-navigation'; - -export default class FormPage extends Component { - render() { - return ( - <View marginTop = {50}> - <Text> - Put the form stuff here - </Text> - <Button - onPress={() => this.props.navigation.navigate('GreetingPage')} - title='Go Back' - /> - </View> - ); - } -} diff --git a/mobile/components/GreetingPage.js b/mobile/screens/GreetingPage.js index 18c202f..18c202f 100644 --- a/mobile/components/GreetingPage.js +++ b/mobile/screens/GreetingPage.js diff --git a/mobile/screens/HomeScreen.js b/mobile/screens/HomeScreen.js deleted file mode 100644 index 0d3548e..0000000 --- a/mobile/screens/HomeScreen.js +++ /dev/null @@ -1,188 +0,0 @@ -import React from 'react'; -import { - Image, - Platform, - ScrollView, - StyleSheet, - Text, - TouchableOpacity, - View, -} from 'react-native'; -import { WebBrowser } from 'expo'; - -import { MonoText } from '../components/StyledText'; - -export default class HomeScreen extends React.Component { - static navigationOptions = { - header: null, - }; - - render() { - return ( - <View style={styles.container}> - <ScrollView style={styles.container} contentContainerStyle={styles.contentContainer}> - <View style={styles.welcomeContainer}> - <Image - source={ - __DEV__ - ? require('../assets/images/robot-dev.png') - : require('../assets/images/robot-prod.png') - } - style={styles.welcomeImage} - /> - </View> - - <View style={styles.getStartedContainer}> - {this._maybeRenderDevelopmentModeWarning()} - - <Text style={styles.getStartedText}>Get started by opening</Text> - - <View style={[styles.codeHighlightContainer, styles.homeScreenFilename]}> - <MonoText style={styles.codeHighlightText}>screens/HomeScreen.js</MonoText> - </View> - - <Text style={styles.getStartedText}> - Change this text and your app will automatically reload. - </Text> - </View> - - <View style={styles.helpContainer}> - <TouchableOpacity onPress={this._handleHelpPress} style={styles.helpLink}> - <Text style={styles.helpLinkText}>Help, it didn’t automatically reload!</Text> - </TouchableOpacity> - </View> - </ScrollView> - - <View style={styles.tabBarInfoContainer}> - <Text style={styles.tabBarInfoText}>This is a tab bar. You can edit it in:</Text> - - <View style={[styles.codeHighlightContainer, styles.navigationFilename]}> - <MonoText style={styles.codeHighlightText}>navigation/MainTabNavigator.js</MonoText> - </View> - </View> - </View> - ); - } - - _maybeRenderDevelopmentModeWarning() { - if (__DEV__) { - const learnMoreButton = ( - <Text onPress={this._handleLearnMorePress} style={styles.helpLinkText}> - Learn more - </Text> - ); - - return ( - <Text style={styles.developmentModeText}> - Development mode is enabled, your app will be slower but you can use useful development - tools. {learnMoreButton} - </Text> - ); - } else { - return ( - <Text style={styles.developmentModeText}> - You are not in development mode, your app will run at full speed. - </Text> - ); - } - } - - _handleLearnMorePress = () => { - WebBrowser.openBrowserAsync('https://docs.expo.io/versions/latest/guides/development-mode'); - }; - - _handleHelpPress = () => { - WebBrowser.openBrowserAsync( - 'https://docs.expo.io/versions/latest/guides/up-and-running.html#can-t-see-your-changes' - ); - }; -} - -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: '#fff', - }, - developmentModeText: { - marginBottom: 20, - color: 'rgba(0,0,0,0.4)', - fontSize: 14, - lineHeight: 19, - textAlign: 'center', - }, - contentContainer: { - paddingTop: 30, - }, - welcomeContainer: { - alignItems: 'center', - marginTop: 10, - marginBottom: 20, - }, - welcomeImage: { - width: 100, - height: 80, - resizeMode: 'contain', - marginTop: 3, - marginLeft: -10, - }, - getStartedContainer: { - alignItems: 'center', - marginHorizontal: 50, - }, - homeScreenFilename: { - marginVertical: 7, - }, - codeHighlightText: { - color: 'rgba(96,100,109, 0.8)', - }, - codeHighlightContainer: { - backgroundColor: 'rgba(0,0,0,0.05)', - borderRadius: 3, - paddingHorizontal: 4, - }, - getStartedText: { - fontSize: 17, - color: 'rgba(96,100,109, 1)', - lineHeight: 24, - textAlign: 'center', - }, - tabBarInfoContainer: { - position: 'absolute', - bottom: 0, - left: 0, - right: 0, - ...Platform.select({ - ios: { - shadowColor: 'black', - shadowOffset: { height: -3 }, - shadowOpacity: 0.1, - shadowRadius: 3, - }, - android: { - elevation: 20, - }, - }), - alignItems: 'center', - backgroundColor: '#fbfbfb', - paddingVertical: 20, - }, - tabBarInfoText: { - fontSize: 17, - color: 'rgba(96,100,109, 1)', - textAlign: 'center', - }, - navigationFilename: { - marginTop: 5, - }, - helpContainer: { - marginTop: 15, - alignItems: 'center', - }, - helpLink: { - paddingVertical: 15, - }, - helpLinkText: { - fontSize: 14, - color: '#2e78b7', - }, -}); diff --git a/mobile/screens/LinksScreen.js b/mobile/screens/LinksScreen.js deleted file mode 100644 index 7bb4a62..0000000 --- a/mobile/screens/LinksScreen.js +++ /dev/null @@ -1,27 +0,0 @@ -import React from 'react'; -import { ScrollView, StyleSheet } from 'react-native'; -import { ExpoLinksView } from '@expo/samples'; - -export default class LinksScreen extends React.Component { - static navigationOptions = { - title: 'Links', - }; - - render() { - return ( - <ScrollView style={styles.container}> - {/* Go ahead and delete ExpoLinksView and replace it with your - * content, we just wanted to provide you with some helpful links */} - <ExpoLinksView /> - </ScrollView> - ); - } -} - -const styles = StyleSheet.create({ - container: { - flex: 1, - paddingTop: 15, - backgroundColor: '#fff', - }, -}); diff --git a/mobile/screens/MapPage.js b/mobile/screens/MapPage.js index f8e2a79..7cdb873 100644 --- a/mobile/screens/MapPage.js +++ b/mobile/screens/MapPage.js @@ -14,86 +14,84 @@ import {MapView} from 'expo'; export default class Form1 extends Component { - constructor(props) { - super(props); - this.state = { - initial_region_coordinates: [-79.3832, 43.6532], - markers: [], - canProceed: false, - } - } - - addMarker(e) { - this.setState( - { markers : [{ latlng: e.nativeEvent.coordinate}], canProceed: true} - ); - } - deleteMarker() { - this.setState( - { markers : [], canProceed: false} - ); - } - moveToFormPage = () => { - if(this.state.canProceed === false) { - alert("Please press on the map to drop a pin"); - return; - } - this.props.navigation.navigate('FormPage', - {coordinates : [ - this.state.markers[0].latlng.longitude, - this.state.markers[0].latlng.latitude] - }); - }; - moveToGreetingPage = () => { - this.props.navigation.navigate('GreetingPage'); - } + constructor(props) { + super(props); + this.state = { + initial_region_coordinates: [-79.3832, 43.6532], + markers: [], + canProceed: false, + } + } + addMarker(e) { + this.setState( + { markers : [{ latlng: e.nativeEvent.coordinate}], canProceed: true} + ); + } + deleteMarker() { + this.setState( + { markers : [], canProceed: false} + ); + } + moveToFormPage = () => { + if(this.state.canProceed === false) { + alert("Please press on the map to drop a pin"); + return; + } + this.props.navigation.navigate('FormPage', + {coordinates : [ + this.state.markers[0].latlng.longitude, + this.state.markers[0].latlng.latitude] + }); + }; + moveToGreetingPage = () => { + this.props.navigation.navigate('GreetingPage'); + } - render() { - return ( - <View style={{flex:1,}}> - <View style={{flex:3}}> - <MapView - style={{ flex: 1 }} - initialRegion={{ - latitude: this.state.initial_region_coordinates[1], - longitude: this.state.initial_region_coordinates[0], - latitudeDelta: 0.0922, - longitudeDelta: 0.0421, - }} - onPress={this.addMarker.bind(this)} - > + render() { + return ( + <View style={{flex:1,}}> + <View style={{flex:3}}> + <MapView + style={{ flex: 1 }} + initialRegion={{ + latitude: this.state.initial_region_coordinates[1], + longitude: this.state.initial_region_coordinates[0], + latitudeDelta: 0.0922, + longitudeDelta: 0.0421, + }} + onPress={this.addMarker.bind(this)} + > - { - this.state.markers.map((marker, i) => (<MapView.Marker key={i} coordinate={marker.latlng} - onPress={(e) => {e.stopPropagation(); this.deleteMarker(i)}} />)) - } - </MapView> - </View> + { + this.state.markers.map((marker, i) => (<MapView.Marker key={i} coordinate={marker.latlng} + onPress={(e) => {e.stopPropagation(); this.deleteMarker(i)}} />)) + } + </MapView> + </View> - <TouchableHighlight - style={styles.first_button_container} - onPress={() => { this.moveToFormPage() }}> - <Text style={styles.proceed_title}> - Proceed - </Text> - </TouchableHighlight> - <TouchableHighlight - style={styles.second_button_container} - onPress={() => { this.moveToGreetingPage() }}> - <Text style={styles.proceed_title}> - Back - </Text> - </TouchableHighlight> - </View> - ); + <TouchableHighlight + style={styles.first_button_container} + onPress={() => { this.moveToFormPage() }}> + <Text style={styles.proceed_title}> + Proceed + </Text> + </TouchableHighlight> + <TouchableHighlight + style={styles.second_button_container} + onPress={() => { this.moveToGreetingPage() }}> + <Text style={styles.proceed_title}> + Back + </Text> + </TouchableHighlight> + </View> + ); } - } const styles = StyleSheet.create( { - first_button_container: { - width: '100%', - flex: 1, - position: 'absolute', + first_button_container: { + width: '100%', + flex: 1, + position: 'absolute', bottom:60, backgroundColor: '#c0392b', flexDirection: 'row', @@ -101,9 +99,9 @@ const styles = StyleSheet.create( { alignItems: 'stretch' }, second_button_container: { - width: '100%', - flex: 1, - position: 'absolute', + width: '100%', + flex: 1, + position: 'absolute', bottom:0, backgroundColor: '#535c68', flexDirection: 'row', @@ -118,4 +116,4 @@ const styles = StyleSheet.create( { opacity: 0.9, fontSize: 20 } -})
\ No newline at end of file +}) diff --git a/mobile/screens/SettingsScreen.js b/mobile/screens/SettingsScreen.js deleted file mode 100644 index 6957dcb..0000000 --- a/mobile/screens/SettingsScreen.js +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react'; -import { ExpoConfigView } from '@expo/samples'; - -export default class SettingsScreen extends React.Component { - static navigationOptions = { - title: 'app.json', - }; - - render() { - /* Go ahead and delete ExpoConfigView and replace it with your - * content, we just wanted to give you a quick view of your config */ - return <ExpoConfigView />; - } -} @@ -24,21 +24,21 @@ app.use(require('./routes/sse')); var env = process.env.NODE_ENV || 'development'; var uri; if (env === 'development') { - uri = 'mongodb://localhost:27017/helpthehome' + uri = 'mongodb://localhost:27017/helpthehome' } else { - // for qa and production set it on heroku config vars - uri = process.env.MONGODB_URI + // for qa and production set it on heroku config vars + uri = process.env.MONGODB_URI } // Mongoose connection to MongoDB mongoose.connect(uri, { useNewUrlParser: true }, function (error) { - if (error) { - console.log(error); - console.log("App was not able to connect to the mongo server!"); - console.log("... double check that the mongo server is running locally"); - } else { - console.log(`connected to ${uri}`); - } + if (error) { + console.log(error); + console.log("App was not able to connect to the mongo server!"); + console.log("... double check that the mongo server is running locally"); + } else { + console.log(`connected to ${uri}`); + } }); app.use('/', indexRouter); diff --git a/web/models/mockpoints.js b/web/models/mockpoints.js index 51bd422..05e9f18 100644 --- a/web/models/mockpoints.js +++ b/web/models/mockpoints.js @@ -3,15 +3,15 @@ var mongoose = require('mongoose'); // Mongoose Schema definition var Schema = mongoose.Schema; var dumbJsonSchema = new Schema({ - type: String, - coordinates: Array, - gender: String, - age: String, - race: String, - longhair: Boolean, - longbeard: Boolean, - extra: String, - status: String + type: String, + coordinates: Array, + gender: String, + age: String, + race: String, + longhair: Boolean, + longbeard: Boolean, + extra: String, + status: String }); // Mongoose Model definition @@ -20,16 +20,16 @@ var dumbJson = mongoose.model('dumbJstring', dumbJsonSchema, 'dumbpointscollecti // this function gets ALL the points from the db // returns the entire document without modifications exports.get_points = function(callback) { - dumbJson.find({}).exec(function(err, docs) { - if (err) callback(err, null); - callback(null, docs); - }); + dumbJson.find({}).exec(function(err, docs) { + if (err) callback(err, null); + callback(null, docs); + }); } // this function stores A user report into the db exports.save_request = function(data, callback) { - dumbJson.create(data, function(err, result) { - if (err) callback(err, null); - callback(null, result); - }); + dumbJson.create(data, function(err, result) { + if (err) callback(err, null); + callback(null, result); + }); } diff --git a/web/models/points.js b/web/models/points.js index e8c181e..d506900 100644 --- a/web/models/points.js +++ b/web/models/points.js @@ -3,15 +3,15 @@ var mongoose = require('mongoose'); // Mongoose Schema definition var Schema = mongoose.Schema; var JsonSchema = new Schema({ - type: String, - coordinates: Array, - gender: String, - age: String, - race: String, - longhair: Boolean, - longbeard: Boolean, - extra: String, - status: String + type: String, + coordinates: Array, + gender: String, + age: String, + race: String, + longhair: Boolean, + longbeard: Boolean, + extra: String, + status: String }); // Mongoose Model definition @@ -20,34 +20,34 @@ var Json = mongoose.model('Jstring', JsonSchema, 'pointscollection'); // this function gets ALL the points from the db // returns the entire document without modifications exports.get_points = function(callback) { - Json.find({}).exec(function(err, docs) { - if (err) callback(err, null); - callback(null, docs); - }); + Json.find({}).exec(function(err, docs) { + if (err) callback(err, null); + callback(null, docs); + }); } exports.get_all_active_points = function(callback) { - var activeStatusTypes = ["new", "pending"]; - Json.find({ status: { $in: activeStatusTypes } }).exec(function(err, docs) { - if (err) callback(err, null); - callback(null, docs); - }); + var activeStatusTypes = ["new", "pending"]; + Json.find({ status: { $in: activeStatusTypes } }).exec(function(err, docs) { + if (err) callback(err, null); + callback(null, docs); + }); } // this function stores A user report into the db exports.save_request = function(data, callback) { - Json.create(data, function(err, result) { - if (err) callback(err, null); - callback(null, result); - }); + Json.create(data, function(err, result) { + if (err) callback(err, null); + callback(null, result); + }); } exports.update_point_status = function(id, newStatus, callback) { - Json.findByIdAndUpdate(id, {status: newStatus}, {new: true}, - function(err, result) { - if (err) callback(err, null); - // result contains the updated point document - callback(null, result); - } - ); + Json.findByIdAndUpdate(id, {status: newStatus}, {new: true}, + function(err, result) { + if (err) callback(err, null); + // result contains the updated point document + callback(null, result); + } + ); } diff --git a/web/public/javascripts/map.js b/web/public/javascripts/map.js index a3d2fb3..5ee9219 100644 --- a/web/public/javascripts/map.js +++ b/web/public/javascripts/map.js @@ -5,198 +5,197 @@ let currPoint; const Races = { - "White" : "European or White", - "eAsian" : "East Asian", - "sAsian" : "South Asian", - "Black" : "Black or African American", - "Aboriginal": "Aboriginal", - "Other" : "Other", + "White" : "European or White", + "eAsian" : "East Asian", + "sAsian" : "South Asian", + "Black" : "Black or African American", + "Aboriginal": "Aboriginal", + "Other" : "Other", }; const PendingIcon = new L.Icon({ - iconAnchor: [ 12, 41 ], - iconUrl: "../images/orange-icon.png", - iconSize: [ 25, 41 ], - popupAnchor: [ 1, -34 ], - shadowSize: [ 41, 41 ], - shadowUrl: "../images/marker-shadow.png", - tooltipAnchor: [ 16, -28 ] + iconAnchor: [ 12, 41 ], + iconUrl: "../images/orange-icon.png", + iconSize: [ 25, 41 ], + popupAnchor: [ 1, -34 ], + shadowSize: [ 41, 41 ], + shadowUrl: "../images/marker-shadow.png", + tooltipAnchor: [ 16, -28 ] }); function plotPointsOnMap(points) { - L.geoJson(points, { - pointToLayer: function (feature, latlng) { - //return L.circleMarker(latlng); - latlngbounds.extend(latlng); - if (feature.status === "pending") { - return L.marker(latlng, {icon: PendingIcon}); - } - return L.marker(latlng); - } - }).on('click', showDetails).addTo(map); - - // rezoom the map so that all the markers fit in the view, add 20% padding so - // that marker dont cut off - console.log(latlngbounds) - map.fitBounds(latlngbounds.pad(0.20)); + L.geoJson(points, { + pointToLayer: function (feature, latlng) { + //return L.circleMarker(latlng); + latlngbounds.extend(latlng); + if (feature.status === "pending") { + return L.marker(latlng, {icon: PendingIcon}); + } + return L.marker(latlng); + } + }).on('click', showDetails).addTo(map); + + // rezoom the map so that all the markers fit in the view, add 20% padding so + // that marker dont cut off + map.fitBounds(latlngbounds.pad(0.20)); } // show details about point // e is the event info function showDetails(e) { - if(currPoint !== undefined) { - if (currPoint.feature.geometry.status === "new") { - currPoint._icon.src = '../images/blue-icon.png'; - } - else if (currPoint.feature.geometry.status === "pending") { - currPoint._icon.src = '../images/orange-icon.png'; - } - } - - // layer.feature.geometry gives you access to all the fields - let layer = e.layer; - currPoint = layer; - - if (currPoint.feature.geometry.status === "new") { - currPoint._icon.src = '../images/blue-icon-focused.png'; - } - else if (currPoint.feature.geometry.status === "pending") { - currPoint._icon.src = '../images/orange-icon-focused.png'; - } - - const pointBounds = [currPoint.getLatLng()]; - map.fitBounds(pointBounds); - - let sideBar = document.getElementById('sidebar'); - - if (getComputedStyle(sideBar).visibility === 'hidden') { - sideBar.style.visibility = 'visible'; - } - - // remove the previous report text - let report = document.getElementById('report'); - let prevUserInputs = report.getElementsByClassName('user-input'); - for (let i=0; i < prevUserInputs.length; i++) { - prevUserInputs[i].innerHTML = ""; - } - - // put gender of the person - let genderTextSpan = document.getElementById('report-gender'); - genderTextSpan.className = 'user-input'; - let genderText = document.createTextNode(layer.feature.geometry['gender']); - genderTextSpan.appendChild(genderText); - - // put age range of person - let ageRangeTextSpan = document.getElementById('report-age-range'); - ageRangeTextSpan.className = 'user-input'; - let ageRangeText = document.createTextNode( - " ~ " + layer.feature.geometry['age'] + " years"); - ageRangeTextSpan.appendChild(ageRangeText); - - // put race of person - let raceTextSpan = document.getElementById('report-race'); - raceTextSpan.className = 'user-input'; - let raceText = document.createTextNode( - Races[layer.feature.geometry['race']] - ); - raceTextSpan.appendChild(raceText); - - // put other attributes - let otherAttrTextSpan = document.getElementById('report-other'); - otherAttrTextSpan.className = 'user-input'; - otherAttrTextSpan.innerHTML = - "Long hair? " + (layer.feature.geometry['longhair'] ? "Yes" : "No") + - "<br>" + - "Long beard? " + (layer.feature.geometry['longbeard'] ? "Yes" : "No"); - - // put extra info - let extraTextSpan = document.getElementById('report-distinctive'); - extraTextSpan.className = 'user-input'; - let extraText = document.createTextNode(layer.feature.geometry['extra']); - extraTextSpan.appendChild(extraText); - - let pendingBtn = document.getElementById('pending-btn'); - pendingBtn.addEventListener('click', markAsPending); - - let completedBtn = document.getElementById('completed-btn'); - completedBtn.addEventListener('click', markAsCompleted); - - let closeBtn = document.getElementById('close-btn'); - closeBtn.addEventListener('click', closeDetails); + if(currPoint !== undefined) { + if (currPoint.feature.geometry.status === "new") { + currPoint._icon.src = '../images/blue-icon.png'; + } + else if (currPoint.feature.geometry.status === "pending") { + currPoint._icon.src = '../images/orange-icon.png'; + } + } + + // layer.feature.geometry gives you access to all the fields + let layer = e.layer; + currPoint = layer; + + if (currPoint.feature.geometry.status === "new") { + currPoint._icon.src = '../images/blue-icon-focused.png'; + } + else if (currPoint.feature.geometry.status === "pending") { + currPoint._icon.src = '../images/orange-icon-focused.png'; + } + + const pointBounds = [currPoint.getLatLng()]; + map.fitBounds(pointBounds); + + let sideBar = document.getElementById('sidebar'); + + if (getComputedStyle(sideBar).visibility === 'hidden') { + sideBar.style.visibility = 'visible'; + } + + // remove the previous report text + let report = document.getElementById('report'); + let prevUserInputs = report.getElementsByClassName('user-input'); + for (let i=0; i < prevUserInputs.length; i++) { + prevUserInputs[i].innerHTML = ""; + } + + // put gender of the person + let genderTextSpan = document.getElementById('report-gender'); + genderTextSpan.className = 'user-input'; + let genderText = document.createTextNode(layer.feature.geometry['gender']); + genderTextSpan.appendChild(genderText); + + // put age range of person + let ageRangeTextSpan = document.getElementById('report-age-range'); + ageRangeTextSpan.className = 'user-input'; + let ageRangeText = document.createTextNode( + " ~ " + layer.feature.geometry['age'] + " years"); + ageRangeTextSpan.appendChild(ageRangeText); + + // put race of person + let raceTextSpan = document.getElementById('report-race'); + raceTextSpan.className = 'user-input'; + let raceText = document.createTextNode( + Races[layer.feature.geometry['race']] + ); + raceTextSpan.appendChild(raceText); + + // put other attributes + let otherAttrTextSpan = document.getElementById('report-other'); + otherAttrTextSpan.className = 'user-input'; + otherAttrTextSpan.innerHTML = + "Long hair? " + (layer.feature.geometry['longhair'] ? "Yes" : "No") + + "<br>" + + "Long beard? " + (layer.feature.geometry['longbeard'] ? "Yes" : "No"); + + // put extra info + let extraTextSpan = document.getElementById('report-distinctive'); + extraTextSpan.className = 'user-input'; + let extraText = document.createTextNode(layer.feature.geometry['extra']); + extraTextSpan.appendChild(extraText); + + let pendingBtn = document.getElementById('pending-btn'); + pendingBtn.addEventListener('click', markAsPending); + + let completedBtn = document.getElementById('completed-btn'); + completedBtn.addEventListener('click', markAsCompleted); + + let closeBtn = document.getElementById('close-btn'); + closeBtn.addEventListener('click', closeDetails); } function markAsPending(e) { - let currPointDetails = currPoint.feature.geometry; - let currPointId = currPointDetails._id; - if (currPointDetails.status === "pending") return; - - currPoint._icon.src = '../images/orange-icon-focused.png'; - currPointDetails.status = "pending"; - - updatePointStatusInDb(currPointId, "pending") - .then(function(responseJson) { - alert("Your change has been saved."); - currPoint._icon.src = '../images/orange-icon-focused.png'; - }) - .catch(function(error) { - alert(error); - }); + let currPointDetails = currPoint.feature.geometry; + let currPointId = currPointDetails._id; + if (currPointDetails.status === "pending") return; + + currPoint._icon.src = '../images/orange-icon-focused.png'; + currPointDetails.status = "pending"; + + updatePointStatusInDb(currPointId, "pending") + .then(function(responseJson) { + alert("Your change has been saved."); + currPoint._icon.src = '../images/orange-icon-focused.png'; + }) + .catch(function(error) { + alert(error); + }); } function markAsCompleted(e) { - let currPointDetails = currPoint.feature.geometry; - let currPointId = currPointDetails._id; - if (currPointDetails.status === "complete") return; - - updatePointStatusInDb(currPointId, "complete") - .then(function(responseJson) { - alert("Your change has been saved."); - map.removeLayer(currPoint); - currPoint = undefined; - }) - .catch(function(error) { - alert(error); - }); - closeDetails(); + let currPointDetails = currPoint.feature.geometry; + let currPointId = currPointDetails._id; + if (currPointDetails.status === "complete") return; + + updatePointStatusInDb(currPointId, "complete") + .then(function(responseJson) { + alert("Your change has been saved."); + map.removeLayer(currPoint); + currPoint = undefined; + }) + .catch(function(error) { + alert(error); + }); + closeDetails(); } function closeDetails(e) { - let details = document.getElementById('sidebar') - details.style.visibility = 'hidden'; - - if (currPoint.feature.geometry.status === "pending") { - currPoint._icon.src = '../images/orange-icon.png'; - } - else if (currPoint.feature.geometry.status === "new") { - currPoint._icon.src = '../images/blue-icon.png'; - } - map.fitBounds(latlngbounds.pad(0.20)); + let details = document.getElementById('sidebar') + details.style.visibility = 'hidden'; + + if (currPoint.feature.geometry.status === "pending") { + currPoint._icon.src = '../images/orange-icon.png'; + } + else if (currPoint.feature.geometry.status === "new") { + currPoint._icon.src = '../images/blue-icon.png'; + } + map.fitBounds(latlngbounds.pad(0.20)); } // returns a Promise object function updatePointStatusInDb(pointId, pointStatus) { - return fetch('/savestatus/' + pointStatus, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({id: pointId}), - }) - .then(function(response) { - if (response.ok) { - return response.json(); - } - throw new Error("We were unable to save your changes."); - }); + return fetch('/savestatus/' + pointStatus, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({id: pointId}), + }) + .then(function(response) { + if (response.ok) { + return response.json(); + } + throw new Error("We were unable to save your changes."); + }); } // different basemap L.tileLayer('https://stamen-tiles-{s}.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}{r}.{ext}', { - attribution: 'Map tiles by <a href="http://stamen.com">Stamen Design</a>, <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a> — Map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors', - subdomains: 'abcd', - minZoom: 0, - maxZoom: 18, - ext: 'png' + attribution: 'Map tiles by <a href="http://stamen.com">Stamen Design</a>, <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a> — Map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors', + subdomains: 'abcd', + minZoom: 0, + maxZoom: 18, + ext: 'png' }).addTo(map); // keep track of the boundary of the markers so that we can update the @@ -204,29 +203,29 @@ L.tileLayer('https://stamen-tiles-{s}.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}{r} var latlngbounds = new L.latLngBounds(); if (points.length) { - plotPointsOnMap(points); + plotPointsOnMap(points); } // setup live updates if (window.EventSource) { - var source = new EventSource('/stream'); - - source.addEventListener('message', function(e) { - var data = JSON.parse(e.data); - if (data.coordinates) { - points.push(data); - plotPointsOnMap(data); - } - }, false) - - source.addEventListener('open', function(e) { - console.log("Connection was opened") - }, false) - - source.addEventListener('error', function(e) { - if (e.readyState == EventSource.CLOSED) { - console.log("Connection was closed") - } - }, false) + var source = new EventSource('/stream'); + + source.addEventListener('message', function(e) { + var data = JSON.parse(e.data); + if (data.coordinates) { + points.push(data); + plotPointsOnMap(data); + } + }, false) + + source.addEventListener('open', function(e) { + console.log("Connection was opened") + }, false) + + source.addEventListener('error', function(e) { + if (e.readyState == EventSource.CLOSED) { + console.log("Connection was closed") + } + }, false) } else { - console.log("sse not supported."); + console.log("sse not supported."); } diff --git a/web/routes/index.js b/web/routes/index.js index 05df4d4..24fa334 100644 --- a/web/routes/index.js +++ b/web/routes/index.js @@ -11,82 +11,82 @@ const glookup = new GeoJsonGeometriesLookup(torontoNeighbourhoords); /* GET home page. */ router.get('/', function(req, res, next) { - // for now just redirect to /map - //res.redirect('/map'); - res.render('index'); + // for now just redirect to /map + //res.redirect('/map'); + res.render('index'); }); /* GET Map page. */ router.get('/map', function(req,res) { - Points.get_all_active_points(function(err, points){ - res.render('map', { - lat : 43.665234, - lng : -79.383370, - points: points - }); - }); + Points.get_all_active_points(function(err, points){ + res.render('map', { + lat : 43.665234, + lng : -79.383370, + points: points + }); + }); }); router.post('/mobilerequest', function(req, res) { - var point = req.body; + var point = req.body; - if (!point.coordinates.length) { - var errMssg = "Coordinates field must not be empty in a request."; - return res.status(422).send({ error: errMssg }); - } + if (!point.coordinates.length) { + var errMssg = "Coordinates field must not be empty in a request."; + return res.status(422).send({ error: errMssg }); + } - if (!glookup.hasContainers(point)) { - var errMssg = "Sorry, we currently only support locations strictly within the City of Toronto."; - return res.status(422).send({ error: errMssg }); - } + if (!glookup.hasContainers(point)) { + var errMssg = "Sorry, we currently only support locations strictly within the City of Toronto."; + return res.status(422).send({ error: errMssg }); + } - // here we are guaranteed to have a valid point in Toronto - Points.save_request(point, function(err, result) { - if (err) { - console.log(`err inserting mobile request into db: ${err}`); - res.status(500).send({ error: "Sorry, something failed on our end." }); - } else { - // send event to all connections - for(var i = 0; i < connections.length; i++) { - connections[i].sseSend(result); - } - console.log(result); - res.status(201).send({'status': 'success'}); - } - }); + // here we are guaranteed to have a valid point in Toronto + Points.save_request(point, function(err, result) { + if (err) { + console.log(`err inserting mobile request into db: ${err}`); + res.status(500).send({ error: "Sorry, something failed on our end." }); + } else { + // send event to all connections + for(var i = 0; i < connections.length; i++) { + connections[i].sseSend(result); + } + console.log(result); + res.status(201).send({'status': 'success'}); + } + }); }); router.post('/savestatus/:status', function(req, res) { - var data = req.body; - var pointId = data.id; - var setStatus = req.params.status; - if ( - setStatus !== "new" && - setStatus !== "pending" && - setStatus !== "complete" - ) { - console.log("Invalid status supplied."); - return res.status(422).send({error: "Error: Status must be one of 'new', 'pending', or 'complete'"}); - } + var data = req.body; + var pointId = data.id; + var setStatus = req.params.status; + if ( + setStatus !== "new" && + setStatus !== "pending" && + setStatus !== "complete" + ) { + console.log("Invalid status supplied."); + return res.status(422).send({error: "Error: Status must be one of 'new', 'pending', or 'complete'"}); + } - // here we are guaranteed to be able to do the query - Points.update_point_status(pointId, setStatus, function(err, result) { - if (err) { - console.log(`err updating point status in db: ${err}`); - res.status(500).send({ error: "Oops. Something went wrong on our end." }); - } else { - console.log(result); - res.status(200).send({'status': 'success'}); - } - }); + // here we are guaranteed to be able to do the query + Points.update_point_status(pointId, setStatus, function(err, result) { + if (err) { + console.log(`err updating point status in db: ${err}`); + res.status(500).send({ error: "Oops. Something went wrong on our end." }); + } else { + console.log(result); + res.status(200).send({'status': 'success'}); + } + }); }); router.get('/stream', function(req, res){ - // set up server side event (communication line between front end and server) - res.sseSetup(); - // send an event to the front end to open the connection - res.sseSend('ok'); - // push connection to connection array - connections.push(res); + // set up server side event (communication line between front end and server) + res.sseSetup(); + // send an event to the front end to open the connection + res.sseSend('ok'); + // push connection to connection array + connections.push(res); }); module.exports = router; |
