diff --git a/compass/app/Http/Controllers/Api.php b/compass/app/Http/Controllers/Api.php index e49b98e..6036795 100644 --- a/compass/app/Http/Controllers/Api.php +++ b/compass/app/Http/Controllers/Api.php @@ -412,4 +412,31 @@ class Api extends BaseController } } + public function share(Request $request) { + $token = $request->input('token'); + if(!$token) + return response(json_encode(['error' => 'no token provided']))->header('Content-Type', 'application/json'); + + $db = DB::table('databases')->where('write_token','=',$token)->first(); + if(!$db) + return response(json_encode(['error' => 'invalid token']))->header('Content-Type', 'application/json'); + + $expires_at = time() + $request->input('duration'); + $share_token = str_random(15); + + $share_id = DB::table('shares')->insertGetId([ + 'database_id' => $db->id, + 'created_at' => date('Y-m-d H:i:s'), + 'expires_at' => date('Y-m-d H:i:s', $expires_at), + 'token' => $share_token, + ]); + + $share_url = env('BASE_URL').'s/'.$share_token; + + return response(json_encode([ + 'url' => $share_url + ]), 201)->header('Content-Type', 'application/json') + ->header('Location', $share_url); + } + } diff --git a/compass/app/Http/Controllers/Share.php b/compass/app/Http/Controllers/Share.php new file mode 100644 index 0000000..a8b613d --- /dev/null +++ b/compass/app/Http/Controllers/Share.php @@ -0,0 +1,48 @@ +where('token', $token) + ->where('expires_at', '>', time()) + ->first(); + + if(!$share) return false; + + $database = DB::table('databases')->where('id', $share->database_id)->first(); + + return $database; + } + + public function view(Request $request, $token) { + $database = $this->_databaseFromToken($token); + + if(!$database) { + return view('share-expired'); + } + + return view('share', [ + 'database' => $database, + 'share_token' => $token, + ]); + } + + public function current_location(Request $request) { + $database = $this->_databaseFromToken($request->input('token')); + + $response = [ + 'data' => json_decode($database->last_location), + ]; + + return response(json_encode($response))->header('Content-Type', 'application/json'); + } + +} diff --git a/compass/app/Http/routes.php b/compass/app/Http/routes.php index f3053d9..c5ee012 100644 --- a/compass/app/Http/routes.php +++ b/compass/app/Http/routes.php @@ -2,6 +2,9 @@ $app->get('/', 'Controller@index'); +$app->get('/s/{token:[A-Za-z0-9]+}', 'Share@view'); +$app->get('/share/current.json', 'Share@current_location'); + $app->post('/auth/start', 'IndieAuth@start'); $app->get('/auth/callback', 'IndieAuth@callback'); $app->get('/auth/github', 'IndieAuth@github'); @@ -22,3 +25,4 @@ $app->get('/api/find-from-localtime', 'LocalTime@find'); $app->get('/api/input', 'Api@account'); $app->post('/api/input', 'Api@input'); $app->post('/api/trip-complete', 'Api@trip_complete'); +$app->post('/api/share', 'Api@share'); diff --git a/compass/database/migrations/2019_05_12_123107_shares.php b/compass/database/migrations/2019_05_12_123107_shares.php new file mode 100644 index 0000000..64c37bd --- /dev/null +++ b/compass/database/migrations/2019_05_12_123107_shares.php @@ -0,0 +1,33 @@ +increments('id'); + $table->unsignedInteger('database_id'); + $table->datetime('expires_at')->nullable(); + $table->string('token', 30); + $table->datetime('created_at'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('shares'); + } +} diff --git a/compass/public/assets/map.js b/compass/public/assets/map.js index 469e17d..76d4d3c 100644 --- a/compass/public/assets/map.js +++ b/compass/public/assets/map.js @@ -32,10 +32,6 @@ var startMarker; var endMarker; var timers = []; -function pointFromGeoJSON(geo) { - return L.latLng(geo[1], geo[0]) -} - function resetAnimation() { if(animatedMarker) { map.removeLayer(animatedMarker); diff --git a/compass/public/assets/share-map.css b/compass/public/assets/share-map.css new file mode 100644 index 0000000..adec8f0 --- /dev/null +++ b/compass/public/assets/share-map.css @@ -0,0 +1,12 @@ +html, body { + height: 100%; +} +#map { + height: 100%; +} + +/* Move the map zoom controls away from the Compass logo */ +.leaflet-top .leaflet-control-zoom { + margin-top: 60px; + margin-left: 26px; +} diff --git a/compass/public/assets/share.js b/compass/public/assets/share.js new file mode 100644 index 0000000..e4383d8 --- /dev/null +++ b/compass/public/assets/share.js @@ -0,0 +1,60 @@ +var map = L.map('map', { zoomControl: false }).setView([45.516, -122.660], 14, null, null, 24); + +L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', { + attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox', + maxZoom: 18, + id: 'mapbox.streets', + accessToken: 'pk.eyJ1IjoiYWFyb25wayIsImEiOiI1T0tpNjdzIn0.OQjXyI3xSt8Dj8na3l90Sg' +}).addTo(map); + +new L.Control.Zoom({ position: 'topleft' }).addTo(map); + +var geojsonLineOptions = { + color: "#0033ff", + weight: 4, + opacity: 0.5 +}; + +var startIcon = L.icon({ + iconUrl: '/assets/map-pin-start.png', + iconSize: [18,28], + iconAnchor: [9,28] +}); + +// Load the current location and show on the map + +var currentLocationMarker; + +function getCurrentLocation() { + $.getJSON("/share/current.json?token="+$("#share_token").val(), function(data){ + if(data.data) { + moveMarkerToPosition(data.data); + map.setView(currentLocationMarker.getLatLng()); + } + setTimeout(getCurrentLocation, 5000); + }); +} + +getCurrentLocation(); + + + + + + +function moveMarkerToPosition(feature) { + if(feature && feature.geometry) { + var coord = pointFromGeoJSON(feature.geometry.coordinates); + if(coord) { + if(!currentLocationMarker) { + currentLocationMarker = L.marker(coord).addTo(map); + } else { + currentLocationMarker.setLatLng(coord); + } + } + } +} + +function pointFromGeoJSON(geo) { + return L.latLng(geo[1], geo[0]) +} diff --git a/compass/resources/views/layouts/share.blade.php b/compass/resources/views/layouts/share.blade.php new file mode 100644 index 0000000..bbbabf8 --- /dev/null +++ b/compass/resources/views/layouts/share.blade.php @@ -0,0 +1,25 @@ + + +
+ +