Fixes for API and live map

This commit is contained in:
Nabeel Shahzad
2018-05-02 15:14:18 -05:00
parent 9183e0b2aa
commit 5dff563c75
18 changed files with 1971 additions and 377 deletions
+1 -1
View File
@@ -48,7 +48,7 @@ class DevInstall extends Command
# #
$this->info('Importing sample data'); $this->info('Importing sample data');
\Artisan::call('phpvms:import', [ \Artisan::call('phpvms:yaml-import', [
'files' => ['app/Database/seeds/sample.yml'], 'files' => ['app/Database/seeds/sample.yml'],
]); ]);
+4
View File
@@ -2,6 +2,7 @@
namespace App\Http\Resources; namespace App\Http\Resources;
use App\Models\Enums\PirepStatus;
use App\Support\Units\Distance; use App\Support\Units\Distance;
use App\Support\Units\Fuel; use App\Support\Units\Fuel;
use Illuminate\Http\Resources\Json\Resource; use Illuminate\Http\Resources\Json\Resource;
@@ -40,9 +41,12 @@ class Pirep extends Resource
if($this->block_off_time) if($this->block_off_time)
$pirep['block_off_time'] = $this->block_off_time->toIso8601ZuluString(); $pirep['block_off_time'] = $this->block_off_time->toIso8601ZuluString();
$pirep['status_text'] = PirepStatus::label($this->status);
$pirep['airline'] = new Airline($this->airline); $pirep['airline'] = new Airline($this->airline);
$pirep['dpt_airport'] = new Airport($this->dpt_airport); $pirep['dpt_airport'] = new Airport($this->dpt_airport);
$pirep['arr_airport'] = new Airport($this->arr_airport); $pirep['arr_airport'] = new Airport($this->arr_airport);
$pirep['position'] = new Acars($this->position); $pirep['position'] = new Acars($this->position);
$pirep['comments'] = PirepComment::collection($this->comments); $pirep['comments'] = PirepComment::collection($this->comments);
$pirep['user'] = [ $pirep['user'] = [
+7 -1
View File
@@ -34,8 +34,14 @@ class GeoJson
*/ */
public function addPoint($lat, $lon, array $attrs) public function addPoint($lat, $lon, array $attrs)
{ {
$point = [$lon, $lat];
$this->line_coords[] = [$lon, $lat]; $this->line_coords[] = [$lon, $lat];
$this->point_coords[] = new Feature(new Point([$lon, $lat]), $attrs);
if(array_key_exists('alt', $attrs)) {
$point[] = $attrs['alt'];
}
$this->point_coords[] = new Feature(new Point($point), $attrs);
++$this->counter; ++$this->counter;
} }
+14
View File
@@ -43,6 +43,7 @@ use PhpUnitsOfMeasure\Exception\NonStringUnitName;
* @property Carbon created_at * @property Carbon created_at
* @property Carbon updated_at * @property Carbon updated_at
* @property bool state * @property bool state
* @property Acars position
* @package App\Models * @package App\Models
*/ */
class Pirep extends Model class Pirep extends Model
@@ -177,6 +178,19 @@ class Pirep extends Model
return null; return null;
} }
/**
* Return the block on time
* @return Carbon
*/
public function getSubmittedAtAttribute()
{
if (array_key_exists('submitted_at', $this->attributes)) {
return new Carbon($this->attributes['submitted_at']);
}
return null;
}
/** /**
* Return a new Length unit so conversions can be made * Return a new Length unit so conversions can be made
* @return int|Distance * @return int|Distance
+1 -1
View File
@@ -5,6 +5,7 @@
*/ */
Route::group([], function () { Route::group([], function () {
Route::get('acars', 'AcarsController@index'); Route::get('acars', 'AcarsController@index');
Route::get('pireps/{pirep_id}', 'PirepController@get');
Route::get('pireps/{pirep_id}/acars/geojson', 'PirepController@acars_geojson'); Route::get('pireps/{pirep_id}/acars/geojson', 'PirepController@acars_geojson');
Route::get('news', 'NewsController@index'); Route::get('news', 'NewsController@index');
@@ -32,7 +33,6 @@ Route::group(['middleware' => ['api.auth']], function () {
Route::get('flights/{id}', 'FlightController@get'); Route::get('flights/{id}', 'FlightController@get');
Route::get('flights/{id}/route', 'FlightController@route'); Route::get('flights/{id}/route', 'FlightController@route');
Route::get('pireps/{pirep_id}', 'PirepController@get');
Route::put('pireps/{pirep_id}', 'PirepController@update'); Route::put('pireps/{pirep_id}', 'PirepController@update');
/* /*
+8 -3
View File
@@ -190,12 +190,17 @@ class GeoService extends Service
foreach ($pirep->acars as $point) { foreach ($pirep->acars as $point) {
$route->addPoint($point->lat, $point->lon, [ $route->addPoint($point->lat, $point->lon, [
'pirep_id' => $pirep->id, 'pirep_id' => $pirep->id,
'name' => $point->altitude, 'name' => '',
'popup' => $counter.'<br />GS: '.$point->gs.'<br />Alt: '.$point->altitude, 'alt' => $point->altitude,
'popup' => 'GS: '.$point->gs.'<br />Alt: '.$point->altitude,
]); ]);
} }
return [ return [
'position' => [
'lat' => $pirep->position->lat,
'lon' => $pirep->position->lon,
],
'line' => $route->getLine(), 'line' => $route->getLine(),
'points' => $route->getPoints() 'points' => $route->getPoints()
]; ];
@@ -225,7 +230,7 @@ class GeoService extends Service
'gs' => $point->gs, 'gs' => $point->gs,
'alt' => $point->altitude, 'alt' => $point->altitude,
'heading' => $point->heading ?: 0, 'heading' => $point->heading ?: 0,
'popup' => $pirep->ident.'<br />GS: '.$point->gs.'<br />Alt: '.$point->altitude, //'popup' => $pirep->ident.'<br />GS: '.$point->gs.'<br />Alt: '.$point->altitude,
]); ]);
} }
+4 -4
View File
@@ -2,12 +2,12 @@
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "yarn run development", "dev": "yarn run development",
"development": "NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch-poll": "yarn run watch -- --watch-poll", "watch-poll": "yarn run watch -- --watch-poll",
"hot": "NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"prod": "yarns run production", "prod": "yarns run production",
"production": "NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
}, },
"dependencies": { "dependencies": {
"Leaflet.Geodesic": "git+https://git@github.com/henrythasler/Leaflet.Geodesic.git", "Leaflet.Geodesic": "git+https://git@github.com/henrythasler/Leaflet.Geodesic.git",
+240
View File
@@ -10838,6 +10838,246 @@ button.close {
.select2-container--classic.select2-container--open .select2-dropdown { .select2-container--classic.select2-container--open .select2-dropdown {
border-color: #5897fb; } border-color: #5897fb; }
@charset "UTF-8";
/*!
* Pikaday
* Copyright © 2014 David Bushell | BSD & MIT license | http://dbushell.com/
*/
.pika-single {
z-index: 9999;
display: block;
position: relative;
color: #333;
background: #fff;
border: 1px solid #ccc;
border-bottom-color: #bbb;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
/*
clear child float (pika-lendar), using the famous micro clearfix hack
http://nicolasgallagher.com/micro-clearfix-hack/
*/
.pika-single:before,
.pika-single:after {
content: " ";
display: table;
}
.pika-single:after { clear: both }
.pika-single { *zoom: 1 }
.pika-single.is-hidden {
display: none;
}
.pika-single.is-bound {
position: absolute;
box-shadow: 0 5px 15px -5px rgba(0,0,0,.5);
}
.pika-lendar {
float: left;
width: 240px;
margin: 8px;
}
.pika-title {
position: relative;
text-align: center;
}
.pika-label {
display: inline-block;
*display: inline;
position: relative;
z-index: 9999;
overflow: hidden;
margin: 0;
padding: 5px 3px;
font-size: 14px;
line-height: 20px;
font-weight: bold;
background-color: #fff;
}
.pika-title select {
cursor: pointer;
position: absolute;
z-index: 9998;
margin: 0;
left: 0;
top: 5px;
filter: alpha(opacity=0);
opacity: 0;
}
.pika-prev,
.pika-next {
display: block;
cursor: pointer;
position: relative;
outline: none;
border: 0;
padding: 0;
width: 20px;
height: 30px;
/* hide text using text-indent trick, using width value (it's enough) */
text-indent: 20px;
white-space: nowrap;
overflow: hidden;
background-color: transparent;
background-position: center center;
background-repeat: no-repeat;
background-size: 75% 75%;
opacity: .5;
*position: absolute;
*top: 0;
}
.pika-prev:hover,
.pika-next:hover {
opacity: 1;
}
.pika-prev,
.is-rtl .pika-next {
float: left;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAUklEQVR42u3VMQoAIBADQf8Pgj+OD9hG2CtONJB2ymQkKe0HbwAP0xucDiQWARITIDEBEnMgMQ8S8+AqBIl6kKgHiXqQqAeJepBo/z38J/U0uAHlaBkBl9I4GwAAAABJRU5ErkJggg==');
*left: 0;
}
.pika-next,
.is-rtl .pika-prev {
float: right;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAU0lEQVR42u3VOwoAMAgE0dwfAnNjU26bYkBCFGwfiL9VVWoO+BJ4Gf3gtsEKKoFBNTCoCAYVwaAiGNQGMUHMkjGbgjk2mIONuXo0nC8XnCf1JXgArVIZAQh5TKYAAAAASUVORK5CYII=');
*right: 0;
}
.pika-prev.is-disabled,
.pika-next.is-disabled {
cursor: default;
opacity: .2;
}
.pika-select {
display: inline-block;
*display: inline;
}
.pika-table {
width: 100%;
border-collapse: collapse;
border-spacing: 0;
border: 0;
}
.pika-table th,
.pika-table td {
width: 14.285714285714286%;
padding: 0;
}
.pika-table th {
color: #999;
font-size: 12px;
line-height: 25px;
font-weight: bold;
text-align: center;
}
.pika-button {
cursor: pointer;
display: block;
box-sizing: border-box;
-moz-box-sizing: border-box;
outline: none;
border: 0;
margin: 0;
width: 100%;
padding: 5px;
color: #666;
font-size: 12px;
line-height: 15px;
text-align: right;
background: #f5f5f5;
}
.pika-week {
font-size: 11px;
color: #999;
}
.is-today .pika-button {
color: #33aaff;
font-weight: bold;
}
.is-selected .pika-button,
.has-event .pika-button {
color: #fff;
font-weight: bold;
background: #33aaff;
box-shadow: inset 0 1px 3px #178fe5;
border-radius: 3px;
}
.has-event .pika-button {
background: #005da9;
box-shadow: inset 0 1px 3px #0076c9;
}
.is-disabled .pika-button,
.is-inrange .pika-button {
background: #D5E9F7;
}
.is-startrange .pika-button {
color: #fff;
background: #6CB31D;
box-shadow: none;
border-radius: 3px;
}
.is-endrange .pika-button {
color: #fff;
background: #33aaff;
box-shadow: none;
border-radius: 3px;
}
.is-disabled .pika-button {
pointer-events: none;
cursor: default;
color: #999;
opacity: .3;
}
.is-outside-current-month .pika-button {
color: #999;
opacity: .3;
}
.is-selection-disabled {
pointer-events: none;
cursor: default;
}
.pika-button:hover,
.pika-row.pick-whole-week:hover .pika-button {
color: #fff;
background: #ff8000;
box-shadow: none;
border-radius: 3px;
}
/* styling for abbr */
.pika-table abbr {
border-bottom: none;
cursor: help;
}
/*! X-editable - v1.5.1 /*! X-editable - v1.5.1
* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery * In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
* http://github.com/vitalets/x-editable * http://github.com/vitalets/x-editable
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -281,14 +281,14 @@ eval("// shim for using process in browser\nvar process = module.exports = {};\n
/***/ "./resources/js/bootstrap.js": /***/ "./resources/js/bootstrap.js":
/***/ (function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
eval("/**\n * Bootstrap any Javascript libraries required\n */\n\nwindow.axios = __webpack_require__(\"./node_modules/axios/index.js\");\n\n/**\n * Container for phpVMS specific functions\n */\nwindow.phpvms = {};\n\n/**\n * Configure Axios with both the csrf token and the API key\n */\n\nvar base_url = document.head.querySelector('meta[name=\"base-url\"]');\nif (base_url) {\n window.axios.default.baseURL = base_url;\n}\n\nwindow.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';\nvar token = document.head.querySelector('meta[name=\"csrf-token\"]');\n\nif (token) {\n window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;\n /*window.jquery.ajaxSetup({\n 'X-CSRF-TOKEN': token.content\n })*/\n} else {\n console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');\n}\n\nvar api_key = document.head.querySelector('meta[name=\"api-key\"]');\nif (api_key) {\n window.axios.defaults.headers.common['x-api-key'] = api_key.content;\n window.PHPVMS_USER_API_KEY = api_key.content;\n} else {\n window.PHPVMS_USER_API_KEY = false;\n console.error('API Key not found!');\n}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvYm9vdHN0cmFwLmpzPzBlNTgiXSwibmFtZXMiOlsid2luZG93IiwiYXhpb3MiLCJyZXF1aXJlIiwicGhwdm1zIiwiYmFzZV91cmwiLCJkb2N1bWVudCIsImhlYWQiLCJxdWVyeVNlbGVjdG9yIiwiZGVmYXVsdCIsImJhc2VVUkwiLCJkZWZhdWx0cyIsImhlYWRlcnMiLCJjb21tb24iLCJ0b2tlbiIsImNvbnRlbnQiLCJjb25zb2xlIiwiZXJyb3IiLCJhcGlfa2V5IiwiUEhQVk1TX1VTRVJfQVBJX0tFWSJdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7QUFJQUEsT0FBT0MsS0FBUCxHQUFlLG1CQUFBQyxDQUFRLCtCQUFSLENBQWY7O0FBRUE7OztBQUdBRixPQUFPRyxNQUFQLEdBQWdCLEVBQWhCOztBQUVBOzs7O0FBSUEsSUFBTUMsV0FBV0MsU0FBU0MsSUFBVCxDQUFjQyxhQUFkLENBQTRCLHVCQUE1QixDQUFqQjtBQUNBLElBQUdILFFBQUgsRUFBYTtBQUNYSixTQUFPQyxLQUFQLENBQWFPLE9BQWIsQ0FBcUJDLE9BQXJCLEdBQStCTCxRQUEvQjtBQUNEOztBQUVESixPQUFPQyxLQUFQLENBQWFTLFFBQWIsQ0FBc0JDLE9BQXRCLENBQThCQyxNQUE5QixDQUFxQyxrQkFBckMsSUFBMkQsZ0JBQTNEO0FBQ0EsSUFBTUMsUUFBUVIsU0FBU0MsSUFBVCxDQUFjQyxhQUFkLENBQTRCLHlCQUE1QixDQUFkOztBQUVBLElBQUlNLEtBQUosRUFBVztBQUNUYixTQUFPQyxLQUFQLENBQWFTLFFBQWIsQ0FBc0JDLE9BQXRCLENBQThCQyxNQUE5QixDQUFxQyxjQUFyQyxJQUF1REMsTUFBTUMsT0FBN0Q7QUFDQTs7O0FBR0QsQ0FMRCxNQUtPO0FBQ0xDLFVBQVFDLEtBQVIsQ0FBYyx1RUFBZDtBQUNEOztBQUVELElBQU1DLFVBQVVaLFNBQVNDLElBQVQsQ0FBY0MsYUFBZCxDQUE0QixzQkFBNUIsQ0FBaEI7QUFDQSxJQUFJVSxPQUFKLEVBQWE7QUFDWGpCLFNBQU9DLEtBQVAsQ0FBYVMsUUFBYixDQUFzQkMsT0FBdEIsQ0FBOEJDLE1BQTlCLENBQXFDLFdBQXJDLElBQW9ESyxRQUFRSCxPQUE1RDtBQUNBZCxTQUFPa0IsbUJBQVAsR0FBNkJELFFBQVFILE9BQXJDO0FBQ0QsQ0FIRCxNQUdPO0FBQ0xkLFNBQU9rQixtQkFBUCxHQUE2QixLQUE3QjtBQUNBSCxVQUFRQyxLQUFSLENBQWMsb0JBQWQ7QUFDRCIsImZpbGUiOiIuL3Jlc291cmNlcy9qcy9ib290c3RyYXAuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEJvb3RzdHJhcCBhbnkgSmF2YXNjcmlwdCBsaWJyYXJpZXMgcmVxdWlyZWRcbiAqL1xuXG53aW5kb3cuYXhpb3MgPSByZXF1aXJlKCdheGlvcycpO1xuXG4vKipcbiAqIENvbnRhaW5lciBmb3IgcGhwVk1TIHNwZWNpZmljIGZ1bmN0aW9uc1xuICovXG53aW5kb3cucGhwdm1zID0ge307XG5cbi8qKlxuICogQ29uZmlndXJlIEF4aW9zIHdpdGggYm90aCB0aGUgY3NyZiB0b2tlbiBhbmQgdGhlIEFQSSBrZXlcbiAqL1xuXG5jb25zdCBiYXNlX3VybCA9IGRvY3VtZW50LmhlYWQucXVlcnlTZWxlY3RvcignbWV0YVtuYW1lPVwiYmFzZS11cmxcIl0nKTtcbmlmKGJhc2VfdXJsKSB7XG4gIHdpbmRvdy5heGlvcy5kZWZhdWx0LmJhc2VVUkwgPSBiYXNlX3VybDtcbn1cblxud2luZG93LmF4aW9zLmRlZmF1bHRzLmhlYWRlcnMuY29tbW9uWydYLVJlcXVlc3RlZC1XaXRoJ10gPSAnWE1MSHR0cFJlcXVlc3QnO1xuY29uc3QgdG9rZW4gPSBkb2N1bWVudC5oZWFkLnF1ZXJ5U2VsZWN0b3IoJ21ldGFbbmFtZT1cImNzcmYtdG9rZW5cIl0nKTtcblxuaWYgKHRva2VuKSB7XG4gIHdpbmRvdy5heGlvcy5kZWZhdWx0cy5oZWFkZXJzLmNvbW1vblsnWC1DU1JGLVRPS0VOJ10gPSB0b2tlbi5jb250ZW50XG4gIC8qd2luZG93LmpxdWVyeS5hamF4U2V0dXAoe1xuICAgICdYLUNTUkYtVE9LRU4nOiB0b2tlbi5jb250ZW50XG4gIH0pKi9cbn0gZWxzZSB7XG4gIGNvbnNvbGUuZXJyb3IoJ0NTUkYgdG9rZW4gbm90IGZvdW5kOiBodHRwczovL2xhcmF2ZWwuY29tL2RvY3MvY3NyZiNjc3JmLXgtY3NyZi10b2tlbicpXG59XG5cbmNvbnN0IGFwaV9rZXkgPSBkb2N1bWVudC5oZWFkLnF1ZXJ5U2VsZWN0b3IoJ21ldGFbbmFtZT1cImFwaS1rZXlcIl0nKTtcbmlmIChhcGlfa2V5KSB7XG4gIHdpbmRvdy5heGlvcy5kZWZhdWx0cy5oZWFkZXJzLmNvbW1vblsneC1hcGkta2V5J10gPSBhcGlfa2V5LmNvbnRlbnQ7XG4gIHdpbmRvdy5QSFBWTVNfVVNFUl9BUElfS0VZID0gYXBpX2tleS5jb250ZW50XG59IGVsc2Uge1xuICB3aW5kb3cuUEhQVk1TX1VTRVJfQVBJX0tFWSA9IGZhbHNlO1xuICBjb25zb2xlLmVycm9yKCdBUEkgS2V5IG5vdCBmb3VuZCEnKVxufVxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vcmVzb3VyY2VzL2pzL2Jvb3RzdHJhcC5qcyJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./resources/js/bootstrap.js\n"); eval("/**\r\n * Bootstrap any Javascript libraries required\r\n */\n\nwindow.axios = __webpack_require__(\"./node_modules/axios/index.js\");\n\n/**\r\n * Container for phpVMS specific functions\r\n */\nwindow.phpvms = {};\n\n/**\r\n * Configure Axios with both the csrf token and the API key\r\n */\n\nvar base_url = document.head.querySelector('meta[name=\"base-url\"]');\nif (base_url) {\n window.axios.default.baseURL = base_url;\n}\n\nwindow.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';\nvar token = document.head.querySelector('meta[name=\"csrf-token\"]');\n\nif (token) {\n window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;\n /*window.jquery.ajaxSetup({\r\n 'X-CSRF-TOKEN': token.content\r\n })*/\n} else {\n console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');\n}\n\nvar api_key = document.head.querySelector('meta[name=\"api-key\"]');\nif (api_key) {\n window.axios.defaults.headers.common['x-api-key'] = api_key.content;\n window.PHPVMS_USER_API_KEY = api_key.content;\n} else {\n window.PHPVMS_USER_API_KEY = false;\n console.error('API Key not found!');\n}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvYm9vdHN0cmFwLmpzPzBlNTgiXSwibmFtZXMiOlsid2luZG93IiwiYXhpb3MiLCJyZXF1aXJlIiwicGhwdm1zIiwiYmFzZV91cmwiLCJkb2N1bWVudCIsImhlYWQiLCJxdWVyeVNlbGVjdG9yIiwiZGVmYXVsdCIsImJhc2VVUkwiLCJkZWZhdWx0cyIsImhlYWRlcnMiLCJjb21tb24iLCJ0b2tlbiIsImNvbnRlbnQiLCJjb25zb2xlIiwiZXJyb3IiLCJhcGlfa2V5IiwiUEhQVk1TX1VTRVJfQVBJX0tFWSJdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7QUFJQUEsT0FBT0MsS0FBUCxHQUFlLG1CQUFBQyxDQUFRLCtCQUFSLENBQWY7O0FBRUE7OztBQUdBRixPQUFPRyxNQUFQLEdBQWdCLEVBQWhCOztBQUVBOzs7O0FBSUEsSUFBTUMsV0FBV0MsU0FBU0MsSUFBVCxDQUFjQyxhQUFkLENBQTRCLHVCQUE1QixDQUFqQjtBQUNBLElBQUdILFFBQUgsRUFBYTtBQUNYSixTQUFPQyxLQUFQLENBQWFPLE9BQWIsQ0FBcUJDLE9BQXJCLEdBQStCTCxRQUEvQjtBQUNEOztBQUVESixPQUFPQyxLQUFQLENBQWFTLFFBQWIsQ0FBc0JDLE9BQXRCLENBQThCQyxNQUE5QixDQUFxQyxrQkFBckMsSUFBMkQsZ0JBQTNEO0FBQ0EsSUFBTUMsUUFBUVIsU0FBU0MsSUFBVCxDQUFjQyxhQUFkLENBQTRCLHlCQUE1QixDQUFkOztBQUVBLElBQUlNLEtBQUosRUFBVztBQUNUYixTQUFPQyxLQUFQLENBQWFTLFFBQWIsQ0FBc0JDLE9BQXRCLENBQThCQyxNQUE5QixDQUFxQyxjQUFyQyxJQUF1REMsTUFBTUMsT0FBN0Q7QUFDQTs7O0FBR0QsQ0FMRCxNQUtPO0FBQ0xDLFVBQVFDLEtBQVIsQ0FBYyx1RUFBZDtBQUNEOztBQUVELElBQU1DLFVBQVVaLFNBQVNDLElBQVQsQ0FBY0MsYUFBZCxDQUE0QixzQkFBNUIsQ0FBaEI7QUFDQSxJQUFJVSxPQUFKLEVBQWE7QUFDWGpCLFNBQU9DLEtBQVAsQ0FBYVMsUUFBYixDQUFzQkMsT0FBdEIsQ0FBOEJDLE1BQTlCLENBQXFDLFdBQXJDLElBQW9ESyxRQUFRSCxPQUE1RDtBQUNBZCxTQUFPa0IsbUJBQVAsR0FBNkJELFFBQVFILE9BQXJDO0FBQ0QsQ0FIRCxNQUdPO0FBQ0xkLFNBQU9rQixtQkFBUCxHQUE2QixLQUE3QjtBQUNBSCxVQUFRQyxLQUFSLENBQWMsb0JBQWQ7QUFDRCIsImZpbGUiOiIuL3Jlc291cmNlcy9qcy9ib290c3RyYXAuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcclxuICogQm9vdHN0cmFwIGFueSBKYXZhc2NyaXB0IGxpYnJhcmllcyByZXF1aXJlZFxyXG4gKi9cclxuXHJcbndpbmRvdy5heGlvcyA9IHJlcXVpcmUoJ2F4aW9zJyk7XHJcblxyXG4vKipcclxuICogQ29udGFpbmVyIGZvciBwaHBWTVMgc3BlY2lmaWMgZnVuY3Rpb25zXHJcbiAqL1xyXG53aW5kb3cucGhwdm1zID0ge307XHJcblxyXG4vKipcclxuICogQ29uZmlndXJlIEF4aW9zIHdpdGggYm90aCB0aGUgY3NyZiB0b2tlbiBhbmQgdGhlIEFQSSBrZXlcclxuICovXHJcblxyXG5jb25zdCBiYXNlX3VybCA9IGRvY3VtZW50LmhlYWQucXVlcnlTZWxlY3RvcignbWV0YVtuYW1lPVwiYmFzZS11cmxcIl0nKTtcclxuaWYoYmFzZV91cmwpIHtcclxuICB3aW5kb3cuYXhpb3MuZGVmYXVsdC5iYXNlVVJMID0gYmFzZV91cmw7XHJcbn1cclxuXHJcbndpbmRvdy5heGlvcy5kZWZhdWx0cy5oZWFkZXJzLmNvbW1vblsnWC1SZXF1ZXN0ZWQtV2l0aCddID0gJ1hNTEh0dHBSZXF1ZXN0JztcclxuY29uc3QgdG9rZW4gPSBkb2N1bWVudC5oZWFkLnF1ZXJ5U2VsZWN0b3IoJ21ldGFbbmFtZT1cImNzcmYtdG9rZW5cIl0nKTtcclxuXHJcbmlmICh0b2tlbikge1xyXG4gIHdpbmRvdy5heGlvcy5kZWZhdWx0cy5oZWFkZXJzLmNvbW1vblsnWC1DU1JGLVRPS0VOJ10gPSB0b2tlbi5jb250ZW50XHJcbiAgLyp3aW5kb3cuanF1ZXJ5LmFqYXhTZXR1cCh7XHJcbiAgICAnWC1DU1JGLVRPS0VOJzogdG9rZW4uY29udGVudFxyXG4gIH0pKi9cclxufSBlbHNlIHtcclxuICBjb25zb2xlLmVycm9yKCdDU1JGIHRva2VuIG5vdCBmb3VuZDogaHR0cHM6Ly9sYXJhdmVsLmNvbS9kb2NzL2NzcmYjY3NyZi14LWNzcmYtdG9rZW4nKVxyXG59XHJcblxyXG5jb25zdCBhcGlfa2V5ID0gZG9jdW1lbnQuaGVhZC5xdWVyeVNlbGVjdG9yKCdtZXRhW25hbWU9XCJhcGkta2V5XCJdJyk7XHJcbmlmIChhcGlfa2V5KSB7XHJcbiAgd2luZG93LmF4aW9zLmRlZmF1bHRzLmhlYWRlcnMuY29tbW9uWyd4LWFwaS1rZXknXSA9IGFwaV9rZXkuY29udGVudDtcclxuICB3aW5kb3cuUEhQVk1TX1VTRVJfQVBJX0tFWSA9IGFwaV9rZXkuY29udGVudFxyXG59IGVsc2Uge1xyXG4gIHdpbmRvdy5QSFBWTVNfVVNFUl9BUElfS0VZID0gZmFsc2U7XHJcbiAgY29uc29sZS5lcnJvcignQVBJIEtleSBub3QgZm91bmQhJylcclxufVxyXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9yZXNvdXJjZXMvanMvYm9vdHN0cmFwLmpzIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./resources/js/bootstrap.js\n");
/***/ }), /***/ }),
/***/ "./resources/js/installer/app.js": /***/ "./resources/js/installer/app.js":
/***/ (function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
eval("/**\n * Admin stuff needed\n */\n\n__webpack_require__(\"./resources/js/bootstrap.js\");//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvaW5zdGFsbGVyL2FwcC5qcz8wNTdjIl0sIm5hbWVzIjpbInJlcXVpcmUiXSwibWFwcGluZ3MiOiJBQUFBOzs7O0FBSUEsbUJBQUFBLENBQVEsNkJBQVIiLCJmaWxlIjoiLi9yZXNvdXJjZXMvanMvaW5zdGFsbGVyL2FwcC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQWRtaW4gc3R1ZmYgbmVlZGVkXG4gKi9cblxucmVxdWlyZSgnLi8uLi9ib290c3RyYXAnKTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3Jlc291cmNlcy9qcy9pbnN0YWxsZXIvYXBwLmpzIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./resources/js/installer/app.js\n"); eval("/**\r\n * Admin stuff needed\r\n */\n\n__webpack_require__(\"./resources/js/bootstrap.js\");//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvaW5zdGFsbGVyL2FwcC5qcz8wNTdjIl0sIm5hbWVzIjpbInJlcXVpcmUiXSwibWFwcGluZ3MiOiJBQUFBOzs7O0FBSUEsbUJBQUFBLENBQVEsNkJBQVIiLCJmaWxlIjoiLi9yZXNvdXJjZXMvanMvaW5zdGFsbGVyL2FwcC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxyXG4gKiBBZG1pbiBzdHVmZiBuZWVkZWRcclxuICovXHJcblxyXG5yZXF1aXJlKCcuLy4uL2Jvb3RzdHJhcCcpO1xyXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9yZXNvdXJjZXMvanMvaW5zdGFsbGVyL2FwcC5qcyJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./resources/js/installer/app.js\n");
/***/ }), /***/ }),
+8 -8
View File
@@ -1,20 +1,20 @@
{ {
"/assets/frontend/js/app.js": "/assets/frontend/js/app.js?id=cd886ba18357a1c96ec0", "/assets/frontend/js/app.js": "/assets/frontend/js/app.js?id=df652ba09d3074d46cd0",
"/assets/frontend/css/now-ui-kit.css": "/assets/frontend/css/now-ui-kit.css?id=b0a0f05b94a4486db4f2", "/assets/frontend/css/now-ui-kit.css": "/assets/frontend/css/now-ui-kit.css?id=70c0f73b28bc686d7791",
"/assets/admin/css/vendor.min.css": "/assets/admin/css/vendor.min.css?id=cc80aec3cf1646f83d8d", "/assets/admin/css/vendor.min.css": "/assets/admin/css/vendor.min.css?id=42f138d32d03b309dec7",
"/assets/admin/js/app.js": "/assets/admin/js/app.js?id=559d5e8e5d6ecc64a3af", "/assets/admin/js/app.js": "/assets/admin/js/app.js?id=cf0b6af9aeb25fe3fbcd",
"/assets/installer/js/app.js": "/assets/installer/js/app.js?id=c65781eda730445d666e", "/assets/installer/js/app.js": "/assets/installer/js/app.js?id=27b9f2ce0b268e658f01",
"/assets/fonts/glyphicons-halflings-regular.woff2": "/assets/fonts/glyphicons-halflings-regular.woff2?id=b5b5055c6d812c0f9f0d", "/assets/fonts/glyphicons-halflings-regular.woff2": "/assets/fonts/glyphicons-halflings-regular.woff2?id=b5b5055c6d812c0f9f0d",
"/assets/admin/fonts/glyphicons-halflings-regular.woff2": "/assets/admin/fonts/glyphicons-halflings-regular.woff2?id=b5b5055c6d812c0f9f0d", "/assets/admin/fonts/glyphicons-halflings-regular.woff2": "/assets/admin/fonts/glyphicons-halflings-regular.woff2?id=b5b5055c6d812c0f9f0d",
"/assets/admin/img/clear.png": "/assets/admin/img/clear.png?id=0e92f4c3efc6988a3c96", "/assets/admin/img/clear.png": "/assets/admin/img/clear.png?id=0e92f4c3efc6988a3c96",
"/assets/admin/img/loading.gif": "/assets/admin/img/loading.gif?id=90a4b76b4f11558691f6", "/assets/admin/img/loading.gif": "/assets/admin/img/loading.gif?id=90a4b76b4f11558691f6",
"/assets/global/js/jquery.js": "/assets/global/js/jquery.js?id=6a07da9fae934baf3f74", "/assets/global/js/jquery.js": "/assets/global/js/jquery.js?id=6a07da9fae934baf3f74",
"/assets/admin/css/vendor.css": "/assets/admin/css/vendor.css?id=d4c03403265f42272050", "/assets/admin/css/vendor.css": "/assets/admin/css/vendor.css?id=f139af0f666d5cefde4d",
"/assets/admin/js/vendor.js": "/assets/admin/js/vendor.js?id=aa7db4bedfe23409f625", "/assets/admin/js/vendor.js": "/assets/admin/js/vendor.js?id=5130233c88c71fc60135",
"/assets/admin/css/blue.png": "/assets/admin/css/blue.png?id=753a3c0dec86d3a38d9c", "/assets/admin/css/blue.png": "/assets/admin/css/blue.png?id=753a3c0dec86d3a38d9c",
"/assets/admin/css/blue@2x.png": "/assets/admin/css/blue@2x.png?id=97da23d47b838cbd4bef", "/assets/admin/css/blue@2x.png": "/assets/admin/css/blue@2x.png?id=97da23d47b838cbd4bef",
"/assets/global/js/vendor.js": "/assets/global/js/vendor.js?id=6436d215691e8f38eb12", "/assets/global/js/vendor.js": "/assets/global/js/vendor.js?id=6436d215691e8f38eb12",
"/assets/global/css/vendor.css": "/assets/global/css/vendor.css?id=115d5c4f2370ae94a962", "/assets/global/css/vendor.css": "/assets/global/css/vendor.css?id=115d5c4f2370ae94a962",
"/assets/installer/css/vendor.css": "/assets/installer/css/vendor.css?id=cd76d2d9611b9a13d644", "/assets/installer/css/vendor.css": "/assets/installer/css/vendor.css?id=344796a10af1741dc754",
"/assets/installer/js/vendor.js": "/assets/installer/js/vendor.js?id=01249af00bd2c1267e15" "/assets/installer/js/vendor.js": "/assets/installer/js/vendor.js?id=01249af00bd2c1267e15"
} }
-1
View File
@@ -1,4 +1,3 @@
const leaflet = require('leaflet'); const leaflet = require('leaflet');
export default (opts) => { export default (opts) => {
+87 -31
View File
@@ -1,4 +1,3 @@
const leaflet = require('leaflet'); const leaflet = require('leaflet');
import draw_base_map from './base_map' import draw_base_map from './base_map'
@@ -13,10 +12,11 @@ export default (opts) => {
opts = Object.assign({ opts = Object.assign({
update_uri: '/api/acars', update_uri: '/api/acars',
pirep_uri: '/api/pireps/{id}/acars', pirep_uri: '/api/pireps/{id}',
positions: null, positions: null,
render_elem: 'map', render_elem: 'map',
aircraft_icon: '/assets/img/acars/aircraft.png', aircraft_icon: '/assets/img/acars/aircraft.png',
units: 'nmi',
}, opts); }, opts);
const map = draw_base_map(opts); const map = draw_base_map(opts);
@@ -24,12 +24,13 @@ export default (opts) => {
iconUrl: opts.aircraft_icon, iconUrl: opts.aircraft_icon,
iconSize: [42, 42], iconSize: [42, 42],
iconAnchor: [21, 21], iconAnchor: [21, 21],
}) });
let layerFlights = null let pannedToCenter = false;
let layerSelFlight = null let layerFlights = null;
let layerSelFlightFeature = null let layerSelFlight = null;
let layerSelFlightLayer = null let layerSelFlightFeature = null;
let layerSelFlightLayer = null;
/** /**
* When a flight is clicked on, show the path, etc for that flight * When a flight is clicked on, show the path, etc for that flight
@@ -38,17 +39,25 @@ export default (opts) => {
*/ */
const onFlightClick = (feature, layer) => { const onFlightClick = (feature, layer) => {
const uri = opts.pirep_uri.replace('{id}', feature.properties.pirep_id) const pirep_uri = opts.pirep_uri.replace('{id}', feature.properties.pirep_id);
const geojson_uri = opts.pirep_uri.replace('{id}', feature.properties.pirep_id) + "/acars/geojson";
const flight_route = $.ajax({ const pirep_info = $.ajax({
url: uri, url: pirep_uri,
dataType: 'json', dataType: 'json',
error: console.log error: console.log
}) });
const flight_route = $.ajax({
url: geojson_uri,
dataType: 'json',
error: console.log
});
// Load up the PIREP info
$.when(flight_route).done((routeJson) => { $.when(flight_route).done((routeJson) => {
if (layerSelFlight !== null) { if (layerSelFlight !== null) {
map.removeLayer(layerSelFlight) map.removeLayer(layerSelFlight);
} }
layerSelFlight = leaflet.geodesic([], { layerSelFlight = leaflet.geodesic([], {
@@ -56,19 +65,66 @@ export default (opts) => {
opacity: 0.9, opacity: 0.9,
color: ACTUAL_ROUTE_COLOR, color: ACTUAL_ROUTE_COLOR,
wrap: false, wrap: false,
}).addTo(map) }).addTo(map);
layerSelFlight.geoJson(routeJson.line) layerSelFlight.geoJson(routeJson.line);
layerSelFlightFeature = feature;
layerSelFlightLayer = layer;
layerSelFlightFeature = feature // Center on it, but only do it once, in case the map is moved
layerSelFlightLayer = layer if(!pannedToCenter) {
//map.fitBounds(layerSelFlight.getBounds()); map.panTo({lat: routeJson.position.lat, lng: routeJson.position.lon});
}) pannedToCenter = true;
} }
});
//
// When the PIREP info is done loading, show the bottom bar
//
$.when(pirep_info).done(pirep => { pirep = pirep.data;
let dist, planned_dist;
if(opts.units === 'nmi') {
dist = pirep.distance.nmi;
planned_dist = pirep.planned_distance.nmi;
} else if(opts.units === 'mi') {
dist = pirep.distance.mi;
planned_dist = pirep.planned_distance.mi;
} else if(opts.units === 'km') {
dist = pirep.distance.km;
planned_dist = pirep.planned_distance.km;
}
// Parse flight time
const hours = Math.floor(pirep.flight_time / 60);
const mins = pirep.flight_time % 60;
$('#map_flight_id').text(pirep.airline.icao + pirep.flight_number);
$('#map_flight_info').text(
pirep.dpt_airport.name + ' (' + pirep.dpt_airport.icao + ') to ' +
pirep.arr_airport.name + ' (' + pirep.arr_airport.icao + ')'
);
$('#map_flight_stats_middle').html(
'Status: <strong>' + pirep.status_text + '</strong><br />' +
'Flight Time: <strong>' + hours + 'h ' + mins + 'm</strong><br />' +
'Distance: <strong>' + dist + '</strong> / ' + planned_dist + opts.units + '<br />'
);
// Show flight stat info
$('#map_flight_stats_right').html(
'Ground Speed: <strong>' + pirep.position.gs + '</strong><br />' +
'Altitude: <strong>' + pirep.position.altitude + '</strong><br />' +
'Heading: <strong>' + pirep.position.heading + '</strong>'
);
$('#map-info-bar').show();
});
};
const updateMap = () => { const updateMap = () => {
console.log('reloading flights from acars...') console.log('reloading flights from acars...');
/** /**
* AJAX UPDATE * AJAX UPDATE
@@ -78,7 +134,7 @@ export default (opts) => {
url: opts.update_uri, url: opts.update_uri,
dataType: 'json', dataType: 'json',
error: console.log error: console.log
}) });
$.when(flights).done(function (flightGeoJson) { $.when(flights).done(function (flightGeoJson) {
@@ -88,19 +144,18 @@ export default (opts) => {
layerFlights = leaflet.geoJSON(flightGeoJson, { layerFlights = leaflet.geoJSON(flightGeoJson, {
onEachFeature: (feature, layer) => { onEachFeature: (feature, layer) => {
layer.on({ layer.on({
click: (e) => { click: (e) => {
pannedToCenter = false;
onFlightClick(feature, layer) onFlightClick(feature, layer)
} }
}) });
let popup_html = '' let popup_html = '';
if (feature.properties && feature.properties.popup) { if (feature.properties && (feature.properties.popup !== '' && feature.properties.popup !== undefined)) {
popup_html += feature.properties.popup popup_html += feature.properties.popup;
layer.bindPopup(popup_html);
} }
layer.bindPopup(popup_html)
}, },
pointToLayer: function (feature, latlon) { pointToLayer: function (feature, latlon) {
return leaflet.marker(latlon, { return leaflet.marker(latlon, {
@@ -108,16 +163,17 @@ export default (opts) => {
rotationAngle: feature.properties.heading rotationAngle: feature.properties.heading
}) })
} }
}) });
layerFlights.addTo(map) layerFlights.addTo(map);
// Reload the clicked-flight information
if (layerSelFlight !== null) { if (layerSelFlight !== null) {
onFlightClick(layerSelFlightFeature, layerSelFlightLayer) onFlightClick(layerSelFlightFeature, layerSelFlightLayer)
} }
}) })
} };
updateMap() updateMap();
setInterval(updateMap, 10000) setInterval(updateMap, 10000)
}; };
@@ -1,7 +1,30 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<div class="box-body"> <div class="box-body">
<div id="map" style="width: {{ $config['width'] }}; height: {{ $config['height'] }}"></div>
<div id="map" style="width: {{ $config['width'] }}; height: {{ $config['height'] }}">
<div id="map-info-bar"
style="display: none;
position: absolute;
bottom: 0;
padding: 20px;
height: 100px;
z-index: 9999;
background-color:rgba(232, 232, 232, 0.9);
width: {{ $config['width'] }};">
<div style="float: left; margin-right: 30px; width: 50%;">
<h3 style="margin: 0" id="map_flight_id"></h3>
<p id="map_flight_info"></p>
</div>
<div style="float: left; margin-right: 30px;">
<p id="map_flight_stats_middle"></p>
</div>
<div style="float: left;">
<p id="map_flight_stats_right"></p>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -33,8 +56,9 @@
<script> <script>
phpvms.map.render_live_map({ phpvms.map.render_live_map({
'update_uri': '{!! url('/api/acars') !!}', 'update_uri': '{!! url('/api/acars') !!}',
'pirep_uri': '{!! url('/api/pireps/{id}/acars/geojson') !!}', 'pirep_uri': '{!! url('/api/pireps/{id}') !!}',
'aircraft_icon': '{!! public_asset('/assets/img/acars/aircraft.png') !!}', 'aircraft_icon': '{!! public_asset('/assets/img/acars/aircraft.png') !!}',
'units': '{{ setting('units.distance') }}',
}); });
</script> </script>
@endsection @endsection