Skip to content

Commit

Permalink
first draft of a public shared link view
Browse files Browse the repository at this point in the history
* API method to create a new time-limited shared link
* API method for retrieving the current location given a shared link token
* map view that refreshes the current location every 5 seconds
  • Loading branch information
aaronpk committed May 12, 2019
1 parent 917cc9c commit 6a0eb89
Show file tree
Hide file tree
Showing 10 changed files with 227 additions and 4 deletions.
27 changes: 27 additions & 0 deletions compass/app/Http/Controllers/Api.php
Expand Up @@ -412,4 +412,31 @@ public static function geocode($params) {
}
}

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);
}

}
48 changes: 48 additions & 0 deletions compass/app/Http/Controllers/Share.php
@@ -0,0 +1,48 @@
<?php

namespace App\Http\Controllers;

use Laravel\Lumen\Routing\Controller as BaseController;
use Illuminate\Http\Request;
use DB;

class Share extends BaseController
{

private function _databaseFromToken($token) {
$share = DB::table('shares')
->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');
}

}
4 changes: 4 additions & 0 deletions compass/app/Http/routes.php
Expand Up @@ -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');
Expand All @@ -22,3 +25,4 @@
$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');
33 changes: 33 additions & 0 deletions compass/database/migrations/2019_05_12_123107_shares.php
@@ -0,0 +1,33 @@
<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class Shares extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('shares', function (Blueprint $table) {
$table->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');
}
}
4 changes: 0 additions & 4 deletions compass/public/assets/map.js
Expand Up @@ -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);
Expand Down
12 changes: 12 additions & 0 deletions 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;
}
60 changes: 60 additions & 0 deletions 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 &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
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])
}
25 changes: 25 additions & 0 deletions compass/resources/views/layouts/share.blade.php
@@ -0,0 +1,25 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Compass</title>
<link rel="stylesheet" href="/assets/semantic/semantic.min.css">
<link rel="stylesheet" href="/assets/font-awesome-4.4.0/css/font-awesome.min.css">
<link rel="stylesheet" href="/assets/styles.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="/assets/jquery-1.11.3.min.js"></script>
<link rel="stylesheet" href="/assets/leaflet-0.7.3/leaflet.css" />
<link rel="stylesheet" href="/assets/share-map.css">
</head>
<body>

@yield('content')

<script src="/assets/leaflet-0.7.3/leaflet.js"></script>
<script src="/assets/leaflet-0.7.3/esri-leaflet.js"></script>
<script src="/assets/semantic/semantic.min.js"></script>
<script src="/assets/semantic/components/dropdown.min.js"></script>
<script src="/assets/extensions.js"></script>
<script src="/assets/share.js"></script>
</body>
</html>
9 changes: 9 additions & 0 deletions compass/resources/views/share-expired.blade.php
@@ -0,0 +1,9 @@
@extends('layouts.master')

@section('content')

<div style="text-align: center; margin-top: 3em;">
This shared link has expired.
</div>

@endsection
9 changes: 9 additions & 0 deletions compass/resources/views/share.blade.php
@@ -0,0 +1,9 @@
@extends('layouts.share')

@section('content')

<div id="map"></div>

<input type="hidden" id="share_token" value="{{ $share_token }}">

@endsection

0 comments on commit 6a0eb89

Please sign in to comment.