Browse Source

adds calendar view and query API

pull/5/head
Aaron Parecki 6 years ago
parent
commit
edec00bae2
5 changed files with 183 additions and 26 deletions
  1. +53
    -4
      compass/app/Http/Controllers/Api.php
  2. +24
    -0
      compass/public/assets/map.css
  3. +23
    -22
      compass/public/assets/map.js
  4. +31
    -0
      compass/resources/views/map.blade.php
  5. +52
    -0
      compass/resources/views/partials/calendar.blade.php

+ 53
- 4
compass/app/Http/Controllers/Api.php View File

@ -7,13 +7,60 @@ use Illuminate\Http\Request;
use DB;
use Quartz;
use Log;
use DateTime;
use DateTime, DateTimeZone;
class Api extends BaseController
{
public function query(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('read_token','=',$token)->first();
if(!$db)
return response(json_encode(['error' => 'invalid token']))->header('Content-Type', 'application/json');
$qz = new Quartz\DB(env('STORAGE_DIR').$db->name, 'r');
if($date=$request->input('date')) {
if($request->input('tz')) {
$tz = $request->input('tz');
} else {
$tz = 'America/Los_Angeles';
}
$start = DateTime::createFromFormat('Y-m-d H:i:s', $date.' 00:00:00', new DateTimeZone($tz));
$end = DateTime::createFromFormat('Y-m-d H:i:s', $date.' 23:59:59', new DateTimeZone($tz));
} else {
return response(json_encode(['error' => 'no date provided']))->header('Content-Type', 'application/json');
}
$results = $qz->queryRange($start, $end);
$locations = [];
foreach($results as $id=>$record) {
$record->date->format('U.u');
$locations[] = $record->data;
}
if($request->input('format') == 'linestring') {
$response = array(
'type' => 'LineString',
'coordinates' => array()
);
foreach($locations as $loc) {
$response['coordinates'][] = $loc->geometry->coordinates;
}
} else {
$response = [
'locations' => $locations
];
}
return response(json_encode($response))->header('Content-Type', 'application/json');
}
public function input(Request $request) {
@ -26,13 +73,15 @@ class Api extends BaseController
return response(json_encode(['error' => 'invalid token']))->header('Content-Type', 'application/json');
if(!is_array($request->input('locations')))
return response(json_encode(['error' => 'invalid input', 'error_description' => 'parameter "locations" must be an array of location data with a "timestamp" property']))->header('Content-Type', 'application/json');
return response(json_encode(['error' => 'invalid input', 'error_description' => 'parameter "locations" must be an array of GeoJSON data with a "timestamp" property']))->header('Content-Type', 'application/json');
$qz = new Quartz\DB(env('STORAGE_DIR').$db->name, 'w');
foreach($request->input('locations') as $loc) {
$date = DateTime::createFromFormat('U', $loc['timestamp']);
$line = $qz->add($date, $loc);
if(array_key_exists('properties', $loc) && array_key_exists('timestamp', $loc['properties'])) {
$date = DateTime::createFromFormat('U', $loc['properties']['timestamp']);
$line = $qz->add($date, $loc);
}
}
return response(json_encode(['result' => 'ok']))->header('Content-Type', 'application/json');

+ 24
- 0
compass/public/assets/map.css View File

@ -7,8 +7,32 @@ html, body, #map {
margin-left: 26px;
}
#calendar {
z-index: 100;
width: 200px;
height: calc(100% - 40px);
position: absolute;
top: 10px;
right: 10px;
border: 3px #888 solid;
background: white;
font-size: 14px;
line-height: 20px;
}
#calendar #controls {
position: absolute;
top: 0;
padding: 3px;
background: white;
}
#calendar .scroll {
overflow: scroll;
height: calc(100%);
}
table.calendar {
width: 100%;
margin-bottom: 10px;
}
.calendar th, .calendar td {
text-align: center;

+ 23
- 22
compass/public/assets/map.js View File

@ -51,32 +51,33 @@ jQuery(function($){
var db_name = $("#database").data("name");
var db_token = $("#database").data("token");
$.get("/api/query?date="+$(this).data('date')+"&tz=America/Los_Angeles&token="+db_token, function(data){
visible_data.push(data);
visible_layers.push(L.geoJson(data, {
style: geojsonLineOptions
}).addTo(map));
// If the new layer is completely outside the current view, zoom the map to fit all layers
var layer = visible_layers[visible_layers.length - 1];
var is_outside = false;
if(!map.getBounds().intersects(layer.getBounds())) {
is_outside = true;
}
$.get("/api/query?format=linestring&date="+$(this).data('date')+"&tz=America/Los_Angeles&token="+db_token, function(data){
if(data.coordinates && data.coordinates.length > 0) {
visible_data.push(data);
visible_layers.push(L.geoJson(data, {
style: geojsonLineOptions
}).addTo(map));
// If the new layer is completely outside the current view, zoom the map to fit all layers
var layer = visible_layers[visible_layers.length - 1];
var is_outside = false;
if(!map.getBounds().intersects(layer.getBounds())) {
is_outside = true;
}
if(is_outside) {
var full_bounds;
for(var i in visible_layers) {
layer = visible_layers[i];
if(full_bounds) {
full_bounds.extend(layer.getBounds());
} else {
full_bounds = layer.getBounds();
if(is_outside) {
var full_bounds;
for(var i in visible_layers) {
layer = visible_layers[i];
if(full_bounds) {
full_bounds.extend(layer.getBounds());
} else {
full_bounds = layer.getBounds();
}
}
map.fitBounds(full_bounds);
}
map.fitBounds(full_bounds);
}
});
return false;

+ 31
- 0
compass/resources/views/map.blade.php View File

@ -4,8 +4,39 @@
<div class="corner-logo"><a href="/"><img src="/assets/compass.svg" height="40"/></a></div>
<div id="calendar">
<div class="scroll">
<?php
$days = array_fill(1,31,['#']);
$start = new DateTime('2008-05-30T00:00:00-0800');
$end = new DateTime();
$end->setTimeZone(new DateTimeZone('America/Los_Angeles'));
$i = clone $start;
while((int)$i->format('Y') <= (int)$end->format('Y') && (int)$i->format('M') <= (int)$end->format('M')) {
?>
@include('partials/calendar', [
'year' => $i->format('Y'),
'month' => $i->format('m'),
'days' => $days,
'day_name_length' => 3,
'month_href' => null,
'first_day' => 1,
'pn' => []
])
<?php
$i = $i->add(new DateInterval('P1M'));
}
?>
</div>
</div>
<div id="map"></div>
<div id="database" data-name="{{ $database->name }}" data-token="{{ $database->read_token }}"></div>
<script>
jQuery(function($){
$(".calendar a[data-date='{{ date('Y-m-d') }}']").focus().click();
});
</script>
@endsection

+ 52
- 0
compass/resources/views/partials/calendar.blade.php View File

@ -0,0 +1,52 @@
<!--
# Adapted from
# PHP Calendar (version 2.3), written by Keith Devens
# http://keithdevens.com/software/php_calendar
# see example at http://keithdevens.com/weblog
# License: http://keithdevens.com/software/license
-->
<?php
$first_of_month = gmmktime(0,0,0,$month,1,$year);
#remember that mktime will automatically correct if invalid dates are entered
# for instance, mktime(0,0,0,12,32,1997) will be the date for Jan 1, 1998
# this provides a built in "rounding" feature to generate_calendar()
$day_names = array(); #generate all the day names according to the current locale
for($n=0,$t=(3+$first_day)*86400; $n<7; $n++,$t+=86400) #January 4, 1970 was a Sunday
$day_names[$n] = ucfirst(gmstrftime('%A',$t)); #%A means full textual day name
list($month, $year, $month_name, $weekday) = explode(',',gmstrftime('%m,%Y,%B,%w',$first_of_month));
$weekday = ($weekday + 7 - $first_day) % 7; #adjust for $first_day
$title = htmlentities(ucfirst($month_name)).'&nbsp;'.$year; #note that some locales don't capitalize month and day names
#Begin calendar. Uses a real <caption>. See http://diveintomark.org/archives/2002/07/03
@list($p, $pl) = each($pn); @list($n, $nl) = each($pn); #previous and next links, if applicable
if($p) $p = '<span class="calendar-prev">'.($pl ? '<a href="'.htmlspecialchars($pl).'">'.$p.'</a>' : $p).'</span>&nbsp;';
if($n) $n = '&nbsp;<span class="calendar-next">'.($nl ? '<a href="'.htmlspecialchars($nl).'">'.$n.'</a>' : $n).'</span>';
$calendar = '<table class="calendar">'."\n".
'<caption class="calendar-month">'.$p.($month_href ? '<a href="'.htmlspecialchars($month_href).'">'.$title.'</a>' : $title).$n."</caption>\n<tr>";
if($day_name_length){ #if the day names should be shown ($day_name_length > 0)
#if day_name_length is >3, the full name of the day will be printed
foreach($day_names as $d)
$calendar .= '<th abbr="'.htmlentities($d).'">'.htmlentities($day_name_length < 4 ? substr($d,0,$day_name_length) : $d).'</th>';
$calendar .= "</tr>\n<tr>";
}
if($weekday > 0) $calendar .= '<td colspan="'.$weekday.'">&nbsp;</td>'; #initial 'empty' days
for($day=1,$days_in_month=gmdate('t',$first_of_month); $day<=$days_in_month; $day++,$weekday++){
if($weekday == 7){
$weekday = 0; #start a new week
$calendar .= "</tr>\n<tr>";
}
if(isset($days[$day]) and is_array($days[$day])){
@list($link, $classes, $content) = $days[$day];
if(is_null($content)) $content = $day;
$calendar .= '<td'.($classes ? ' class="'.htmlspecialchars($classes).'">' : '>').
($link ? '<a href="'.htmlspecialchars($link).'" data-date="'.sprintf('%4d-%02d-%02d',$year,$month,$day).'">'.$content.'</a>' : $content).'</td>';
}
else $calendar .= "<td>$day</td>";
}
if($weekday != 7) $calendar .= '<td colspan="'.(7-$weekday).'">&nbsp;</td>'; #remaining "empty" days
echo $calendar."</tr>\n</table>\n";

Loading…
Cancel
Save