diff --git a/ISSUE_TEMPLATE b/ISSUE_TEMPLATE new file mode 100644 index 0000000..8190732 --- /dev/null +++ b/ISSUE_TEMPLATE @@ -0,0 +1,38 @@ +![](https://scontent.ford1-1.fna.fbcdn.net/v/t1.0-9/14717161_10154488333556101_5487997839680388224_n.png?oh=fd410a07763a52f126ae17433dc85340&oe=58A1F9EB) + +## Intro + + +## Requirements + + +## Project Background + + +For this series we are creating a Drone Service Platform (DSP) which consist of a marketplace where customers can request drone services for providers/operators. Examples of the services would be drone delivery, mapping, monitoring and many other tasks. In addition to delivering drone services we will also provide a level of traffic management. + + + + +## Other notable challenges in this series +* [Maps React and REST](https://www.topcoder.com/challenge-details/30055562) +* [React Map Mission Plan](http://www.topcoder.com/challenge-details/30055599/?type=develop&noncache=true) +* [Mission Plan fixes part 1](https://www.topcoder.com/challenge-details/30055665) +* [WEBAPI - Consumer to DSP API Product Catalog - swagger API design](http://www.topcoder.com/challenge-details/30055646) +* [Move Mission Planner to react frontend](https://www.topcoder.com/challenge-details/30055900) +* [Move Traffic Map to react frontend](https://www.topcoder.com/challenge-details/30055925) +* [No Fly Zone Polygons](https://www.topcoder.com/challenge-details/30055935) + + +# Links +[front end src: topcoderinc/dsp-frontend](http://github.com/topcoderinc/dsp-frontend) +[back end src: topcoderinc/dsp-server](http://github.com/topcoderinc/dsp-server) +[Live Heroku Dev Frontend: http://kb-dsp-server-dev.herokuapp.com/api/v1](http://kb-dsp-server-dev.herokuapp.com/api-docs/) + + +## Submission Guidelines +1. Ensure good test coverage on all modules +2. Upload documentation for how to run your submission +3. Upload all your source code as a zip for review +4. Winner will be required to submit a pull request with their winning code. +5. Please include a video with your submission. If you are not comfortable with spoken english feel free to annotate with text. diff --git a/README.md b/README.md index d0ff7c0..d9b75dd 100644 --- a/README.md +++ b/README.md @@ -6,23 +6,29 @@ Copy `envSample` as `.env`. Install node dependencies using `npm install` Run the development server using `npm run start` - # Local Configuration Variables You can edit them in `.env` file. # Heroku Deployment +Make sure your variables are defined in .env first. + +Install the heroku config plugin: +``` +heroku plugins:install heroku-config``` + ``` git init git add . git commit -m "react-create-app on Heroku" -# make sure commit all codes and usuaully you do not need to run above command if you are sure your codes in git repo is latest. -heroku create -b https://github.com/mars/create-react-app-buildpack.git +# make sure commit all codes and usually you do not need to run above command if you are sure your codes in git repo is latest. + +heroku create +heroku buildpacks:add heroku/nodejs +heroku buildpacks:add https://github.com/mars/create-react-app-buildpack.git + # set variables defined in .env -heroku config:set REACT_APP_API_BASE_PATH=base url -heroku config:set REACT_APP_SOCKET_URL=socket url -heroku config:set REACT_APP_AUTH0_CLIEND_ID=auth0 client id -heroku config:set REACT_APP_AUTH0_DOMAIN=auth0 domain -heroku config:set REACT_APP_GOOGLE_API_KEY=google api key +heroku config:push + git push heroku HEAD:master heroku open ``` @@ -31,5 +37,4 @@ You can use new configuration with below commands from [set-vars-on-heroku](http ``` heroku config:set REACT_APP_API_BASE_PATH=new base url git commit --allow-empty -m "Set REACT_APP_API_BASE_PATH config var" -git push heroku HEAD:master -``` +git push heroku HEAD:master``` diff --git a/app.json b/app.json new file mode 100644 index 0000000..33f6c94 --- /dev/null +++ b/app.json @@ -0,0 +1,39 @@ +{ + "name": "dsp-app", + "description": "Airbus DSP", + "scripts": { + }, + "env": { + "REACT_APP_API_BASE_PATH": { + "required": true + }, + "REACT_APP_AUTH0_CLIEND_ID": { + "required": true + }, + "REACT_APP_AUTH0_DOMAIN": { + "required": true + }, + "REACT_APP_GOOGLE_API_KEY": { + "required": true + }, + "REACT_APP_SOCKET_URL": { + "required": true + } + }, + "formation": { + "web": { + "quantity": 1 + } + }, + "addons": [ + "papertrail" + ], + "buildpacks": [ + { + "url": "heroku/nodejs" + }, + { + "url": "https://github.com/mars/create-react-app-buildpack.git" + } + ] +} diff --git a/src/api/Mission.js b/src/api/Mission.js index d162438..6b7c824 100644 --- a/src/api/Mission.js +++ b/src/api/Mission.js @@ -45,6 +45,7 @@ class MissionApi { plannedHomePosition: homePosition, missionItems: items, missionName: name, + status:'waiting', })}); } @@ -58,6 +59,7 @@ class MissionApi { plannedHomePosition: homePosition, missionItems: items, missionName: name, + status:'waiting', })}); } diff --git a/src/api/User.js b/src/api/User.js index 0a34e59..bbfaf92 100644 --- a/src/api/User.js +++ b/src/api/User.js @@ -23,7 +23,7 @@ class UserApi { } login(email, password) { - const url = `${this.basePath}/api/v1/users/auth`; + const url = `${this.basePath}/api/v1/login`; return reqwest({ url: url, method: 'post', type: 'json', contentType: 'application/json', @@ -34,19 +34,21 @@ class UserApi { } register(name, email, password) { - const url = `${this.basePath}/api/v1/users`; + const url = `${this.basePath}/api/v1/register`; return reqwest({ url: url, method: 'post', type: 'json', contentType: 'application/json', data: JSON.stringify({ - name: name, + firstName: name, + lastName: name, email: email, + phone: "1", password: password, })}); } registerSocialUser(name, email) { - const url = `${this.basePath}/api/v1/users/social`; + const url = `${this.basePath}/api/v1/login/social`; return reqwest({ url: url, method: 'post', type: 'json', contentType: 'application/json', diff --git a/src/components/maps/GoogleMap.js b/src/components/maps/GoogleMap.js index f490ea0..48a59c5 100644 --- a/src/components/maps/GoogleMap.js +++ b/src/components/maps/GoogleMap.js @@ -35,7 +35,7 @@ class GoogleMap extends Component { getMarkerConfig(drone) { const google = window.google; const config = { clickable: false, crossOnDrag: false, - cursor: 'pointer', position: new google.maps.LatLng(drone.lat, drone.lng) }; + cursor: 'pointer', position: new google.maps.LatLng(drone.currentLocation[0],drone.currentLocation[1]) }; switch (drone.status) { case 'in-motion': config.icon = 'http://maps.google.com/mapfiles/ms/icons/blue-dot.png'; @@ -90,7 +90,7 @@ class GoogleMap extends Component { }); // get a list of all the drones droneApi.getAll().then((drones) => { - _self.markers = drones.map((single) => { + _self.markers = drones.items.map((single) => { const marker = new google.maps.Marker(_self.getMarkerConfig(single)); // set the marker id, to identify a drone uniquely marker.set('id', single.id); @@ -110,7 +110,7 @@ class GoogleMap extends Component { // find a marker by id const marker = _.find(_self.markers, { id: data.id }); if (marker) { - marker.setPosition(new google.maps.LatLng(data.lat, data.lng)); + marker.setPosition(new google.maps.LatLng(data.currentLocation[0], data.currentLocation[1])); // repaint the cluster _self.markerCluster.repaint(); } diff --git a/src/components/mission/EditMissionPlanner.js b/src/components/mission/EditMissionPlanner.js index fe6a06f..3ae3c1a 100644 --- a/src/components/mission/EditMissionPlanner.js +++ b/src/components/mission/EditMissionPlanner.js @@ -61,7 +61,7 @@ class EditMissionPlanner extends Component { * @param {object} event the propogated event */ handleMapClick(event) { - this.addPoint(this, event.latLng, 0); + MapHelper.addPoint(this, event.latLng, 0); } componentWillReceiveProps(nextProps) { diff --git a/src/components/mission/InfoWindow.js b/src/components/mission/InfoWindow.js index e135f41..497465b 100644 --- a/src/components/mission/InfoWindow.js +++ b/src/components/mission/InfoWindow.js @@ -45,12 +45,14 @@ class InfoWindow extends Component { } getSelectedCommand() { - if (this.state.type === 'T') { - return 'Takeoff'; - } else if (this.state.type === 'W') { - return 'Waypoint'; - } else { - return ''; + if (this.state.command === 22) { + return `Takeoff (${this.state.command} / ${this.state.type} ) `; + } else if (this.state.command === 16) { + return `Waypoint (${this.state.command} / ${this.state.type} ) `; + } else if (this.state.command === 21) { + return `Land (${this.state.command} / ${this.state.type} ) `; + } else { + return `command: ${this.state.command} / type: ${this.state.type} `; } } @@ -198,6 +200,30 @@ class InfoWindow extends Component {
+ + + Lat/X: + + + + this.latitudeElement = latElem} + onChange={this.handlePointChange.bind(this, 'lat')} /> + + + + + + Lon/Y: + + + + this.longitudeElement = lngElem} + onChange={this.handlePointChange.bind(this, 'lng')} /> + + + Param1: diff --git a/src/components/mission/MissionPlannerList.js b/src/components/mission/MissionPlannerList.js index 69998a8..949e9a4 100644 --- a/src/components/mission/MissionPlannerList.js +++ b/src/components/mission/MissionPlannerList.js @@ -26,13 +26,13 @@ class MissionPlannerList extends Component { componentDidMount() { this.missionApi.getAll().then((missions) => { - this.setState({ missions: missions }); + this.setState({ missions: missions.items }); }); } refresh() { this.missionApi.getAll().then((missions) => { - this.setState({ missions: missions }); + this.setState({ missions: missions.items }); }); } diff --git a/src/components/mission/helpers/MapHelper.js b/src/components/mission/helpers/MapHelper.js index 51d54a6..a0bccc8 100644 --- a/src/components/mission/helpers/MapHelper.js +++ b/src/components/mission/helpers/MapHelper.js @@ -8,7 +8,7 @@ * @author TCSCODER * @version 1.0.0 */ - import circleGreen from '../../../i/circle_green.svg'; + import circleGreen from '../../../i/circle_cubs.svg'; /** * Clear all markers (waypoints) @@ -175,6 +175,30 @@ initPolyline(_self); } + function latLng2Point(latLng, map) { + const google = window.google; + var topRight = map.getProjection().fromLatLngToPoint(map.getBounds().getNorthEast()); + var bottomLeft = map.getProjection().fromLatLngToPoint(map.getBounds().getSouthWest()); + var scale = Math.pow(2, map.getZoom()); + var worldPoint = map.getProjection().fromLatLngToPoint(latLng); + return new google.maps.Point((worldPoint.x - bottomLeft.x) * scale, (worldPoint.y - topRight.y) * scale); +} + +function point2LatLng(point, map) { + const google = window.google; + var topRight = map.getProjection().fromLatLngToPoint(map.getBounds().getNorthEast()); + var bottomLeft = map.getProjection().fromLatLngToPoint(map.getBounds().getSouthWest()); + var scale = Math.pow(2, map.getZoom()); + var worldPoint = new google.maps.Point(point.x / scale + bottomLeft.x, point.y / scale + topRight.y); + return map.getProjection().fromPointToLatLng(worldPoint); +} + +function offsetLatLng(latLng, map){ + var point = latLng2Point(latLng, map); + point.y -= 10; + return point2LatLng(point, map); +} + /** * Draw Polyline on the map * @@ -184,8 +208,9 @@ const google = window.google; const locations = []; for (let i=1;i<_self.state.markers.length;i++) { - locations.push(_self.state.markers[i].getPosition()); + locations.push(offsetLatLng(_self.state.markers[i].getPosition(), _self.map)); } + if (_self.poly) _self.poly.setMap(null); _self.poly = new google.maps.Polyline({ path: locations, @@ -283,5 +308,8 @@ addPoint, deleteWaypoint, initPolyline, - getMarkerOpts + getMarkerOpts, + latLng2Point, + point2LatLng, + offsetLatLng }; diff --git a/src/i/circle_cubs.svg b/src/i/circle_cubs.svg new file mode 100644 index 0000000..45a32bf --- /dev/null +++ b/src/i/circle_cubs.svg @@ -0,0 +1,9 @@ + + + + Layer 1 + + + + + diff --git a/src/i/circle_green.svg b/src/i/circle_green.svg index 36d0af5..3a848f0 100644 --- a/src/i/circle_green.svg +++ b/src/i/circle_green.svg @@ -3,37 +3,8 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +