Removed deprecated (now obsolete) projects and updated readme's.
|
@ -19,5 +19,8 @@ This repository contains samples applications demonstrating the power of MariaDB
|
|||
## [Places](https://github.com/mariadb-corporation/dev-example-places)
|
||||
**Places** is a web application that, backed by the power of MariaDB connectors and [MariaDB platform](https://mariadb.com/products/mariadb-platform/), allows you to record all of your favorite locations!
|
||||
|
||||
## [TODO](https://github.com/mariadb-corporation/dev-example-todo)
|
||||
**TODO** is a web application that that introduces you to the power, performance and simplicity of [MariaDB](https://mariadb.com/products/). Through the use of simple task management you'll learn how to interact with MariaDB databases and perform simple CRUD operations!
|
||||
|
||||
## Support and Contribution <a name="support-contribution"></a>
|
||||
If you have any questions, comments, or would like to contribute to this or future projects like this please reach out to us directly at developers@mariadb.com or on [Twitter](https://twitter.com/mariadb).
|
||||
|
|
|
@ -3,366 +3,3 @@
|
|||
|
||||
This application is no longer being maintained here. It has been moved to [**this repository**](https://github.com/mariadb-corporation/dev-example-bookings).
|
||||
|
||||
|
||||
# Bookings
|
||||
|
||||
**Bookings** is a web application written in [React.js](https://reactjs.org) and [Node.js](https://nodejs.org) that, backed by the power of the [MariaDB Node.js Connector](https://github.com/MariaDB/mariadb-connector-nodejs) and the [MariaDB X4 Platform](https://mariadb.com/resources/blog/deploying-mariadb-platform-x4/#smart), unleashes the power of [smart transactions](https://mariadb.com/resources/blog/introducing-mariadb-platform-x4-smart-transactions-and-cloud-native-storage/) on hundreds of millions of records with sub-second query performance without having to add any indexes!
|
||||
|
||||
<p align="center" spacing="10">
|
||||
<kbd>
|
||||
<img src="media/demo.gif" />
|
||||
</kbd>
|
||||
</p>
|
||||
|
||||
The following will walk you through the steps for getting this application up and running (locally) within minutes! This application is completely open source. Please feel free to use it and the source code as you see fit.
|
||||
|
||||
# Table of Contents
|
||||
1. [Environment and Compatibility](#compatibility)
|
||||
2. [Getting started with MariaDB and Hybrid Transactional-Analytical Processing](#overview)
|
||||
1. [The Basics](#intro-mariadb)
|
||||
2. [Deploying MariaDB HTAP](#installation)
|
||||
3. [Clone repo](#clone-repo)
|
||||
3. [Retrieving flight data](#retrieve-data)
|
||||
4. [Create the schema](#create-schema)
|
||||
5. [Load airport, airline, and flight data](#load-data)
|
||||
6. [Setting up replication](#replication)
|
||||
3. [Requirements to run the app](#requirements)
|
||||
4. [Getting started with the app](#getting-started)
|
||||
1. [Grab the code](#grab-code)
|
||||
2. [Build the code](#build-code)
|
||||
3. [Run the app](#run-app)
|
||||
4. [Adding app data](#create-data)
|
||||
5. [Smart Transactions](#smart-transactions)
|
||||
6. [Cross-Engine Queries](#cross-engine-queries)
|
||||
7. [Support and Contribution](#support-contribution)
|
||||
8. [License](#license)
|
||||
|
||||
## Environment and Compatibility <a name="compatibility"></a>
|
||||
|
||||
This sample was created using the following techologies:
|
||||
|
||||
* [MariaDB X4 HTAP (v10.4)](https://github.com/mariadb-corporation/mariadb-columnstore-htap)
|
||||
* [React.js (v.16.12.0)](https://github.com/facebook/react/blob/master/CHANGELOG.md#16120-november-14-2019)
|
||||
* [Node.js (v.12.x)](https://nodejs.org/docs/latest-v12.x/api/index.html)
|
||||
* [NPM (v.6.11.3)](https://docs.npmjs.com/)
|
||||
|
||||
This sample was tested on macOS v.10.14.6.
|
||||
|
||||
## Overview <a name="overview"></a>
|
||||
|
||||
### Introduction to MariaDB <a name="intro-mariadb"></a>
|
||||
|
||||
[MariaDB platform](https://mariadb.com/products/mariadb-platform/) unifies [transactional](https://mariadb.com/products/mariadb-platform-transactional/) and [analytical](https://mariadb.com/products/mariadb-platform-analytical/) information so applications can leverage powerful, real-time analytics in order to provide data-driven customers with more information, actionable insight and greater value.
|
||||
|
||||
<p align="center">
|
||||
<kbd>
|
||||
<img src="media/platform.png" />
|
||||
</kbd>
|
||||
</p>
|
||||
|
||||
### Deploying MariaDB Hybrid Transactional-Analytical Processing (HTAP) <a name="installation"></a>
|
||||
|
||||
MariaDB Platform supports [Hybrid Transactional-Analytical Processing (HTAP)](https://mariadb.com/docs/deploy/htap/) through a combination of MariaDB Enterprise Server, MariaDB ColumnStore, and MariaDB MaxScale.
|
||||
|
||||
Here's a simple architecture diagram of MariaDB X4 Platform.
|
||||
|
||||
<p align="center" spacing="10">
|
||||
<kbd>
|
||||
<img src="media/x4.png" style="height: 300px;" />
|
||||
</kbd>
|
||||
</p>
|
||||
|
||||
For this application we'll be targeting a single instance of MariaDB HTAP, and instructions for setting such an environment can be found here:
|
||||
|
||||
https://github.com/mariadb-corporation/mariadb-columnstore-htap
|
||||
|
||||
Once you have created your HTAP instance you will be able to create the schemas and load the data. If you have elected to use the method above you simply need to use
|
||||
|
||||
```
|
||||
$ vagrant ssh node1
|
||||
```
|
||||
|
||||
to access the database instance.
|
||||
|
||||
**Note:** You can also find more details on how to *manually* deploy MariaDB X4 [here](https://mariadb.com/docs/deploy/htap/).
|
||||
|
||||
### Clone repo <a name="clone-repo"></a>
|
||||
|
||||
Next `git clone` this repository to the machine that contains your database instance, and then proceed to the following steps for retrieving flight data, creating schemas, and loading airports/airlines/flight data.
|
||||
|
||||
### Retrieving flight data <a name="retrieve-data"></a>
|
||||
|
||||
This application uses flight record data provided by the [Bureau of Transportation](https://www.bts.gov/).
|
||||
|
||||
The following script will retrieve the data set by year and month creating CSV data files under the data directory. By default the script will retrieve data for all months from 1990 to 2020. The script can be edited to retrieve smaller or larger data ranges as needed:
|
||||
|
||||
```
|
||||
$ ./get_flight_data.sh
|
||||
|
||||
2018-011
|
||||
% Total % Received % Xferd Average Speed Time Time Time Current
|
||||
Dload Upload Total Spent Left Speed
|
||||
100 654 100 183 100 471 12 33 0:00:15 0:00:14 0:00:01 0
|
||||
100 14.9M 100 14.9M 0 0 415k 0 0:00:36 0:00:36 --:--:-- 736k
|
||||
Archive: data.zip
|
||||
inflating: 544122566_.csv
|
||||
2018-02
|
||||
```
|
||||
|
||||
**Note:** The script makes use of curl and unzip which may need to be installed if not already present on your Linux OS.
|
||||
|
||||
### Create the schema <a name="create-schema"></a>
|
||||
|
||||
The following script will create (and drop if it already exists) the flights database:
|
||||
|
||||
```
|
||||
$ ./create_schemas.sh
|
||||
```
|
||||
|
||||
This includes the following 6 tables within the schema `innodb_schema`:
|
||||
|
||||
* airlines
|
||||
* airports
|
||||
* flights
|
||||
* tickets
|
||||
* trips
|
||||
|
||||
This also includes the following table within the schema `columnstore_schema`:
|
||||
|
||||
* flights
|
||||
|
||||
### Loading Flights data into ColumnStore <a name="load-data"></a>
|
||||
|
||||
The airlines and airports table can be populated from the airlines.csv and airports.csv files in the schema directory. Use the following script to do this:
|
||||
|
||||
```
|
||||
$ ./load_airports_airlines.sh
|
||||
```
|
||||
|
||||
The flights table is populated using a script which will load each CSV file from the data directory into the flights table:
|
||||
|
||||
```
|
||||
$ ./load_flight_data.sh
|
||||
```
|
||||
|
||||
### Setting up HTAP Replication <a name="htap-replication"></a>
|
||||
|
||||
Using MariaDB Replication, MariaDB Enterprise Server replicates writes from InnoDB tables to the MariaDB ColumnStore tables, ensuring that the application can perform analytical processing on current data. Combining MariaDB Replication with MariaDB MaxScale configured as a Binlog Server, MariaDB Enterprise Server can host InnoDB and ColumnStore on the same Server.
|
||||
|
||||
This application uses replication on a single table called `flights`, which exists `innodb_schema` and `columnstore_schema`. In order to set up replication add the following to `/etc/maxscale.cnf` for your HTAP instance.
|
||||
|
||||
```
|
||||
[replication-filter]
|
||||
type = filter
|
||||
module = binlogfilter
|
||||
match = /[.]flights/
|
||||
rewrite_src = innodb
|
||||
rewrite_dest = columnstore
|
||||
```
|
||||
|
||||
For more information on configuring MariaDB HTAP please review the official [Enterprise Documentation](https://mariadb.com/docs/deploy/htap/#maxscale-configuration).
|
||||
|
||||
## Requirements to run the app <a name="requirements"></a>
|
||||
|
||||
This project assumes you have familiarity with building web applications using [ReactJS](https://reactjs.org) and [NodeJS](https://nodejs.org) technologies.
|
||||
|
||||
The following is required to run this application:
|
||||
|
||||
1. [Download and install MariaDB HTAP](#installation).
|
||||
2. [Download and install NodeJS](https://nodejs.org/en/download/).
|
||||
3. git (Optional) - this is required if you would prefer to pull the source code from GitHub repo.
|
||||
- Create a [free github account](https://github.com/) if you don’t already have one
|
||||
- git can be downloaded from git-scm.org
|
||||
|
||||
## Getting started with the app <a name="getting-started"></a>
|
||||
|
||||
### Grab the code <a name="grab-code"></a>
|
||||
|
||||
Download this code directly or use [git](http://www.git-scm.org) (through CLI or a client) to retrieve the code.
|
||||
|
||||
### Configure the code <a name="configure-code"></a>
|
||||
|
||||
Configure the MariaDB connection by [adding an .env file to the Node.js project](https://github.com/mariadb-corporation/mariadb-connector-nodejs/blob/master/documentation/promise-api.md#security-consideration).
|
||||
|
||||
Example implementation:
|
||||
|
||||
```
|
||||
DB_HOST=<host_address>
|
||||
DB_PORT=<port_number>
|
||||
DB_USER=<username>
|
||||
DB_PASS=<password>
|
||||
DB_NAME=<database>
|
||||
```
|
||||
|
||||
The environmental variables from `.env` are used within the [db.js](src/db.js) for the MariaDB Node.js Connector configuration pool settings:
|
||||
|
||||
```javascript
|
||||
var mariadb = require('mariadb');
|
||||
require('dotenv').config();
|
||||
|
||||
const pool = mariadb.createPool({
|
||||
host: process.env.DB_HOST,
|
||||
user: process.env.DB_USER,
|
||||
password: process.env.DB_PASS,
|
||||
port: process.env.DB_PORT,
|
||||
multipleStatements: true,
|
||||
connectionLimit: 5
|
||||
});
|
||||
```
|
||||
|
||||
### Build the code <a name="build-code"></a>
|
||||
|
||||
Once you have retrieved a copy of the code you're ready to build and run the project! However, before running the code it's important to point out that the application uses several Node Packages.
|
||||
|
||||
Executing the CLI command
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
within
|
||||
|
||||
* [src](src): the Node.js project
|
||||
* [client](src/client): the React.js project
|
||||
|
||||
folders will target the the relative `package.json` file and [install all dependencies](https://docs.npmjs.com/downloading-and-installing-packages-locally).
|
||||
|
||||
### Run the app <a name="run-app"></a>
|
||||
|
||||
Once you've pulled down the code and have verified that all of the required Node packages are installed you're ready to run the application! It's as easy as 1,2,3.
|
||||
|
||||
1. Using a command line interface (CLI) navigate to the `src` directory.
|
||||
|
||||
<p align="center">
|
||||
<kbd>
|
||||
<img src="media/cli_root.png" />
|
||||
</kbd>
|
||||
</p>
|
||||
|
||||
2. Run the command:
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
<p align="center">
|
||||
<kbd>
|
||||
<img src="media/npm_start.png" />
|
||||
</kbd>
|
||||
</p>
|
||||
|
||||
3. Open a browser window and navigate to http://localhost:3000.
|
||||
|
||||
<p align="center">
|
||||
<kbd>
|
||||
<img src="media/get_started.png" />
|
||||
</kbd>
|
||||
</p>
|
||||
|
||||
### Adding app data <a name="create-data"></a>
|
||||
|
||||
**Upcoming flight data**
|
||||
|
||||
Upon running the application you will notice that searching for flights and viewin upcoming trips yields no results. This is because there currently no transactional flights, tickets, or trips data. Because this application is merely meant for demonstration purposes only you will need to provide *relevant* data within the following:
|
||||
|
||||
* innodb_schema.flights
|
||||
* innodb_schema.tickets
|
||||
* innodb_schema.trips
|
||||
|
||||
The following are sample datasets for:
|
||||
|
||||
An upcoming flight (option) from LAX to ORD on February 5th, 2020.
|
||||
|
||||
```sql
|
||||
INSERT INTO `flights` (`year`, `month`, `day`, `day_of_week`, `fl_date`, `carrier`, `tail_num`, `fl_num`, `origin`, `dest`, `crs_dep_time`, `dep_time`, `dep_delay`, `taxi_out`, `wheels_off`, `wheels_on`, `taxi_in`, `crs_arr_time`, `arr_time`, `arr_delay`, `cancelled`, `cancellation_code`, `diverted`, `crs_elapsed_time`, `actual_elapsed_time`, `air_time`, `distance`, `carrier_delay`, `weather_delay`, `nas_delay`, `security_delay`, `late_aircraft_delay`) VALUES (2020, 2, 5, 5, '2020-02-05', 'DL', NULL, 1280, 'LAX', 'ORD', '0600', '0600', NULL, NULL, NULL, NULL, NULL, '0913', '0913', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
INSERT INTO `tickets` (`id`, `fl_date`, `fl_num`, `carrier`, `origin`, `dest`, `price`) VALUES (1, '2020-02-05', 1280, 'DL', 'LAX', 'ORD', 240.00);
|
||||
```
|
||||
|
||||
An upcoming trip from ORD to LAX on February 6th, 2020.
|
||||
|
||||
```sql
|
||||
INSERT INTO `flights` (`year`, `month`, `day`, `day_of_week`, `fl_date`, `carrier`, `tail_num`, `fl_num`, `origin`, `dest`, `crs_dep_time`, `dep_time`, `dep_delay`, `taxi_out`, `wheels_off`, `wheels_on`, `taxi_in`, `crs_arr_time`, `arr_time`, `arr_delay`, `cancelled`, `cancellation_code`, `diverted`, `crs_elapsed_time`, `actual_elapsed_time`, `air_time`, `distance`, `carrier_delay`, `weather_delay`, `nas_delay`, `security_delay`, `late_aircraft_delay`) VALUES (2020, 2, 6, 2, '2020-02-06', 'DL', NULL, 1170, 'ORD', 'LAX', '1420', '1420', NULL, NULL, NULL, NULL, NULL, '1730', '1730', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
INSERT INTO `tickets` (`id`, `fl_date`, `fl_num`, `carrier`, `origin`, `dest`, `price`) VALUES (2, '2020-02-06', 1170, 'DL', 'ORD', 'LAX', 276.00);
|
||||
|
||||
INSERT INTO `trips` (`id`, `ticket_id`) VALUES (1, 2);
|
||||
```
|
||||
|
||||
**Weather forecast data**
|
||||
|
||||
You also have the option of hard-coding your weather forecast information or integrating a Weather Forecast API of your choice. Currently the data is hard-coded, but can facilitate either approach.
|
||||
|
||||
Check out [tripRoutes.js](https://github.com/mariadb-corporation/Developer-Examples/blob/master/Bookings/src/routes/tripsRoutes.js#L105-L122) to learn more.
|
||||
|
||||
```js
|
||||
var forecasts = {
|
||||
"ORD_2020-02-06": {
|
||||
description: "Snow",
|
||||
icon: "snow",
|
||||
temp_low: "28°F",
|
||||
temp_high: "29°F",
|
||||
precip_probability: 0.6,
|
||||
wind_speed: 15
|
||||
},
|
||||
"LAX_2020-02-08": {
|
||||
description: "Clear",
|
||||
icon: "clear-day",
|
||||
temp_low: "56°F",
|
||||
temp_high: "65°F",
|
||||
precip_probability: 0,
|
||||
wind_speed: 5
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Smart Transactions <a name="smart-transactions"></a>
|
||||
|
||||
At this point you're probably wondering, what are smart transactions?
|
||||
|
||||
At their core, smart transactions are the standard transactions that databases have been performing for decades – ultimately powering the online interactions we’ve become accustomed to. The difference with modern applications is the use of real-time analytics before, during and/or after these transactions.
|
||||
|
||||
**Pre-transaction**
|
||||
|
||||
This application uses real-time analytics before a flight is booked. Each flight ticket option contains information calculated from the historical records (average delay, average duration, flight score, etc.) within the `flights` table.
|
||||
|
||||
<p align="center">
|
||||
<kbd>
|
||||
<img src="media/flight_1.png" />
|
||||
</kbd>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<kbd>
|
||||
<img src="media/flight_2.png" />
|
||||
</kbd>
|
||||
</p>
|
||||
|
||||
**Post-transaction**
|
||||
|
||||
This application also uses real-time analytics after a flight has been booked, and a trip has been created.
|
||||
|
||||
<p align="center">
|
||||
<kbd>
|
||||
<img src="media/trip_1.png" />
|
||||
</kbd>
|
||||
</p>
|
||||
|
||||
## Cross-Engine Queries <a name="cross-engine-queries"></a>
|
||||
|
||||
This application uses cross-engine queries to maximize the potentials of the MariaDB X4 Platform. Cross-engine querying is the ability to access, via MaxScale, both the transactional and analytics data within a single query.
|
||||
|
||||
<p align="center">
|
||||
<kbd>
|
||||
<img src="media/cross_engine.png" />
|
||||
</kbd>
|
||||
</p>
|
||||
|
||||
## Support and Contribution <a name="support-contribution"></a>
|
||||
|
||||
Thanks so much for taking a look at the Bookings app! As this is a very simple example, there's plenty of potential for customization. Please feel free to submit PR's to the project to include your modifications!
|
||||
|
||||
If you have any questions, comments, or would like to contribute to this or future projects like this please reach out to us directly at developers@mariadb.com or on [Twitter](https://twitter.com/mariadb).
|
||||
|
||||
## License <a name="license"></a>
|
||||
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg?style=plastic)](https://opensource.org/licenses/Apache-2.0)
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
target_year=$1
|
||||
source_year=$2
|
||||
month=$3
|
||||
|
||||
MariaDB="mariadb -h10.10.10.11 -udba -pDemo_password1 innodb_schema -e"
|
||||
|
||||
${MariaDB} "INSERT INTO innodb_schema.flights (year,month,day,fl_date,carrier,fl_num,origin,dest,dep_time,arr_time,distance) SELECT $target_year,month,day,(concat($target_year,'-',month,'-',day)),carrier,fl_num,origin,dest,dep_time,arr_time,distance from columnstore_schema.flights where (year=$source_year and month=$month);"
|
||||
|
||||
${MariaDB} "DELETE FROM innodb_schema.tickets;"
|
||||
|
||||
${MariaDB} "INSERT INTO innodb_schema.tickets (fl_date,fl_num,carrier,origin,dest,price) SELECT fl_date,fl_num,carrier,origin,dest,distance*((FLOOR(RAND()*(75-55+1))+55)/100) FROM innodb_schema.flights;"
|
||||
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
SCHEMA_DIR=$(readlink -f ./schema)
|
||||
|
||||
# create innodbtables: airports, airlines
|
||||
/usr/bin/mysql -udba -pDemo_password1 -h10.10.10.10 -vvv < $SCHEMA_DIR/idb_schema.sql
|
||||
# create columnstore table: flights
|
||||
/usr/bin/mysql -udba -pDemo_password1 -h10.10.10.10 -vvv < $SCHEMA_DIR/cs_schema.sql
|
|
@ -1,19 +0,0 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# This script will remotely invoke the bureau of transportation statistics web form to retrieve data by month:
|
||||
# https://www.transtats.bts.gov/DL_SelectFields.asp?Table_ID=236&DB_Short_Name=On-Time
|
||||
# for the specific columns listed in the SQL and utilized by the sample schema.
|
||||
mkdir -p data
|
||||
for y in {1990..2020}; do
|
||||
for m in {1..12}; do
|
||||
yyyymm="$y-$(printf %02d $m)"
|
||||
echo "$yyyymm"
|
||||
curl -L -o data.zip -d "sqlstr=+SELECT+YEAR%2CMONTH%2CDAY_OF_MONTH%2CDAY_OF_WEEK%2CFL_DATE%2CCARRIER%2CTAIL_NUM%2CFL_NUM%2CORIGIN%2CDEST%2CCRS_DEP_TIME%2CDEP_TIME%2CDEP_DELAY%2CTAXI_OUT%2CWHEELS_OFF%2CWHEELS_ON%2CTAXI_IN%2CCRS_ARR_TIME%2CARR_TIME%2CARR_DELAY%2CCANCELLED%2CCANCELLATION_CODE%2CDIVERTED%2CCRS_ELAPSED_TIME%2CACTUAL_ELAPSED_TIME%2CAIR_TIME%2CDISTANCE%2CCARRIER_DELAY%2CWEATHER_DELAY%2CNAS_DELAY%2CSECURITY_DELAY%2CLATE_AIRCRAFT_DELAY+FROM++T_ONTIME+WHERE+Month+%3D$m+AND+YEAR%3D$y" https://www.transtats.bts.gov/DownLoad_Table.asp?Table_ID=236
|
||||
rm -f *.csv
|
||||
unzip data.zip
|
||||
rm -f data.zip
|
||||
mv *.csv $yyyymm.csv
|
||||
tail -n +2 $yyyymm.csv > data/$yyyymm.csv
|
||||
rm -f $yyyymm.csv
|
||||
done
|
||||
done
|
|
@ -1,8 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
SCHEMA_DIR=$(readlink -f ./schema)
|
||||
|
||||
# use the csv's to load data into the airports and airlines tables
|
||||
#/usr/bin/mysql --defaults-file=/etc/my.cnf -u root -vvv < $SCHEMA_DIR/idb_load_data.sql
|
||||
/usr/bin/mysql -udba -pDemo_password1 -h10.10.10.10 -e "LOAD DATA INFILE '${SCHEMA_DIR}/airports.csv' INTO TABLE innodb_schema.airports FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n';"
|
||||
/usr/bin/mysql -udba -pDemo_password1 -h10.10.10.10 -e "LOAD DATA INFILE '${SCHEMA_DIR}/airlines.csv' INTO TABLE innodb_schema.airlines FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n';"
|
|
@ -1,15 +0,0 @@
|
|||
#!/bin/bash
|
||||
# check for argument, if so use as wildcard for file load match, otherwise load everything
|
||||
DATA_DIR=$(readlink -f ./data)
|
||||
filematch="*"
|
||||
if [ $# -eq 1 ]
|
||||
then
|
||||
filematch="*$1*"
|
||||
fi
|
||||
# load the specified files under the data directory with the file pattern match
|
||||
# here we use cpimport mode 2 to force processing at each PM node which has
|
||||
# the advantage of this being runnable as a regular user with a root installation.
|
||||
for f in $DATA_DIR/$filematch.csv; do
|
||||
echo $f
|
||||
/usr/bin/cpimport -m2 -s ',' -E '"' columnstore_schema flights -l $f
|
||||
done
|
Przed Szerokość: | Wysokość: | Rozmiar: 156 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 91 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 622 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 82 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 107 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 249 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 739 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 1.2 MiB |
Przed Szerokość: | Wysokość: | Rozmiar: 211 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 30 KiB |
|
@ -1,17 +0,0 @@
|
|||
UA,United Air Lines Inc.
|
||||
AA,American Airlines Inc.
|
||||
US,US Airways Inc.
|
||||
F9,Frontier Airlines Inc.
|
||||
B6,JetBlue Airways
|
||||
OO,Skywest Airlines Inc.
|
||||
AS,Alaska Airlines Inc.
|
||||
NK,Spirit Air Lines
|
||||
WN,Southwest Airlines Co.
|
||||
DL,Delta Air Lines Inc.
|
||||
EV,ExpressJet
|
||||
HA,Hawaiian Airlines Inc.
|
||||
MQ,American Eagle Airlines Inc.
|
||||
VX,Virgin America
|
||||
9E,Endeavor Air
|
||||
FL,AirTran Airways Inc.
|
||||
YV,Mesa Airlines Inc
|
|
|
@ -1,342 +0,0 @@
|
|||
ABE,Lehigh Valley International Airport,Allentown,PA,USA,40.65236,-75.44040
|
||||
ABI,Abilene Regional Airport,Abilene,TX,USA,32.41132,-99.68190
|
||||
ABQ,Albuquerque International Sunport,Albuquerque,NM,USA,35.04022,-106.60919
|
||||
ABR,Aberdeen Regional Airport,Aberdeen,SD,USA,45.44906,-98.42183
|
||||
ABY,Southwest Georgia Regional Airport,Albany,GA,USA,31.53552,-84.19447
|
||||
ACK,Nantucket Memorial Airport,Nantucket,MA,USA,41.25305,-70.06018
|
||||
ACT,Waco Regional Airport,Waco,TX,USA,31.61129,-97.23052
|
||||
ACV,Arcata Airport,Arcata/Eureka,CA,USA,40.97812,-124.10862
|
||||
ACY,Atlantic City International Airport,Atlantic City,NJ,USA,39.45758,-74.57717
|
||||
ADK,Adak Airport,Adak,AK,USA,51.87796,-176.64603
|
||||
ADQ,Kodiak Airport,Kodiak,AK,USA,57.74997,-152.49386
|
||||
AEX,Alexandria International Airport,Alexandria,LA,USA,31.32737,-92.54856
|
||||
AGS,Augusta Regional Airport (Bush Field),Augusta,GA,USA,33.36996,-81.96450
|
||||
AKN,King Salmon Airport,King Salmon,AK,USA,58.67680,-156.64922
|
||||
ALB,Albany International Airport,Albany,NY,USA,42.74812,-73.80298
|
||||
ALO,Waterloo Regional Airport,Waterloo,IA,USA,42.55708,-92.40034
|
||||
AMA,Rick Husband Amarillo International Airport,Amarillo,TX,USA,35.21937,-101.70593
|
||||
ANC,Ted Stevens Anchorage International Airport,Anchorage,AK,USA,61.17432,-149.99619
|
||||
APN,Alpena County Regional Airport,Alpena,MI,USA,45.07807,-83.56029
|
||||
ASE,Aspen-Pitkin County Airport,Aspen,CO,USA,39.22316,-106.86885
|
||||
ATL,Hartsfield-Jackson Atlanta International Airport,Atlanta,GA,USA,33.64044,-84.42694
|
||||
ATW,Appleton International Airport,Appleton,WI,USA,44.25741,-88.51948
|
||||
AUS,Austin-Bergstrom International Airport,Austin,TX,USA,30.19453,-97.66987
|
||||
AVL,Asheville Regional Airport,Asheville,NC,USA,35.43619,-82.54181
|
||||
AVP,Wilkes-Barre/Scranton International Airport,Wilkes-Barre/Scranton,PA,USA,41.33815,-75.72427
|
||||
AZO,Kalamazoo/Battle Creek International Airport,Kalamazoo,MI,USA,42.23488,-85.55206
|
||||
BDL,Bradley International Airport,Windsor Locks,CT,USA,41.93887,-72.68323
|
||||
BET,Bethel Airport,Bethel,AK,USA,60.77978,-161.83800
|
||||
BFL,Meadows Field,Bakersfield,CA,USA,35.43360,-119.05677
|
||||
BGM,Greater Binghamton Airport,Binghamton,NY,USA,42.20848,-75.97961
|
||||
BGR,Bangor International Airport,Bangor,ME,USA,44.80744,-68.82814
|
||||
BHM,Birmingham-Shuttlesworth International Airport,Birmingham,AL,USA,33.56294,-86.75355
|
||||
BIL,Billings Logan International Airport,Billings,MT,USA,45.80766,-108.54286
|
||||
BIS,Bismarck Municipal Airport,Bismarck,ND,USA,46.77411,-100.74672
|
||||
BJI,Bemidji Regional Airport,Bemidji,MN,USA,47.50942,-94.93372
|
||||
BLI,Bellingham International Airport,Bellingham,WA,USA,48.79275,-122.53753
|
||||
BMI,Central Illinois Regional Airport at Bloomington-Normal,Bloomington,IL,USA,40.47799,-88.91595
|
||||
BNA,Nashville International Airport,Nashville,TN,USA,36.12448,-86.67818
|
||||
BOI,Boise Airport (Boise Air Terminal),Boise,ID,USA,43.56444,-116.22278
|
||||
BOS,Gen. Edward Lawrence Logan International Airport,Boston,MA,USA,42.36435,-71.00518
|
||||
BPT,Jack Brooks Regional Airport (Southeast Texas Regional),Beaumont/Port Arthur,TX,USA,29.95083,-94.02069
|
||||
BQK,Brunswick Golden Isles Airport,Brunswick,GA,USA,31.25903,-81.46631
|
||||
BQN,Rafael Hernández Airport,Aguadilla,PR,USA,18.49486,-67.12944
|
||||
BRD,Brainerd Lakes Regional Airport,Brainerd,MN,USA,46.39786,-94.13723
|
||||
BRO,Brownsville/South Padre Island International Airport,Brownsville,TX,USA,25.90683,-97.42586
|
||||
BRW,Wiley Post-Will Rogers Memorial Airport,Barrow,AK,USA,71.28545,-156.76600
|
||||
BTM,Bert Mooney Airport,Butte,MT,USA,45.95480,-112.49746
|
||||
BTR,Baton Rouge Metropolitan Airport,Baton Rouge,LA,USA,30.53316,-91.14963
|
||||
BTV,Burlington International Airport,Burlington,VT,USA,44.47300,-73.15031
|
||||
BUF,Buffalo Niagara International Airport,Buffalo,NY,USA,42.94052,-78.73217
|
||||
BUR,Bob Hope Airport (Hollywood Burbank Airport),Burbank,CA,USA,34.20062,-118.35850
|
||||
BWI,Baltimore-Washington International Airport,Baltimore,MD,USA,39.17540,-76.66820
|
||||
BZN,Bozeman Yellowstone International Airport (Gallatin Field Airport),Bozeman,MT,USA,45.77690,-111.15301
|
||||
CAE,Columbia Metropolitan Airport,Columbia,SC,USA,33.93884,-81.11954
|
||||
CAK,Akron-Canton Regional Airport,Akron,OH,USA,40.91631,-81.44247
|
||||
CDC,Cedar City Regional Airport,Cedar City,UT,USA,37.70097,-113.09858
|
||||
CDV,Merle K. (Mudhole) Smith Airport,Cordova,AK,USA,60.49183,-145.47765
|
||||
CEC,Del Norte County Airport (Jack McNamara Field),Crescent City,CA,USA,41.78016,-124.23653
|
||||
CHA,Chattanooga Metropolitan Airport (Lovell Field),Chattanooga,TN,USA,35.03527,-85.20379
|
||||
CHO,Charlottesville-Albemarle Airport,Charlottesville,VA,USA,38.13864,-78.45286
|
||||
CHS,Charleston International Airport/Charleston AFB,Charleston,SC,USA,32.89865,-80.04051
|
||||
CID,The Eastern Iowa Airport,Cedar Rapids,IA,USA,41.88459,-91.71087
|
||||
CIU,Chippewa County International Airport,Sault Ste. Marie,MI,USA,46.25075,-84.47239
|
||||
CLD,McClellan-Palomar Airport,San Diego,CA,USA,33.12723,-117.27873
|
||||
CLE,Cleveland Hopkins International Airport,Cleveland,OH,USA,41.41089,-81.84940
|
||||
CLL,Easterwood Airport,College Station,TX,USA,30.58859,-96.36382
|
||||
CLT,Charlotte Douglas International Airport,Charlotte,NC,USA,35.21401,-80.94313
|
||||
CMH,Port Columbus International Airport,Columbus,OH,USA,39.99799,-82.89188
|
||||
CMI,University of Illinois - Willard Airport,Champaign/Urbana,IL,USA,40.03925,-88.27806
|
||||
CMX,Houghton County Memorial Airport,Hancock,MI,USA,47.16842,-88.48906
|
||||
CNY,Canyonlands Field,Moab,UT,USA,38.75496,-109.75484
|
||||
COD,Yellowstone Regional Airport,Cody,WY,USA,44.52019,-109.02380
|
||||
COS,City of Colorado Springs Municipal Airport,Colorado Springs,CO,USA,38.80581,-104.70025
|
||||
COU,Columbia Regional Airport,Columbia,MO,USA,38.81809,-92.21963
|
||||
CPR,Natrona County International Airport,Casper,WY,USA,42.90836,-106.46447
|
||||
CRP,Corpus Christi International Airport,Corpus Christi,TX,USA,27.77036,-97.50122
|
||||
CRW,Yeager Airport,Charleston,WV,USA,38.37315,-81.59319
|
||||
CSG,Columbus Metropolitan Airport,Columbus,GA,USA,32.51633,-84.93886
|
||||
CVG,Cincinnati/Northern Kentucky International Airport,Covington,KY,USA,39.04614,-84.66217
|
||||
CWA,Central Wisconsin Airport,Mosinee,WI,USA,44.77762,-89.66678
|
||||
DAB,Daytona Beach International Airport,Daytona Beach,FL,USA,29.17992,-81.05806
|
||||
DAL,Dallas Love Field,Dallas,TX,USA,32.84711,-96.85177
|
||||
DAY,James M. Cox Dayton International Airport,Dayton,OH,USA,39.90238,-84.21938
|
||||
DBQ,Dubuque Regional Airport,Dubuque,IA,USA,42.40296,-90.70917
|
||||
DCA,Ronald Reagan Washington National Airport,Arlington,VA,USA,38.85208,-77.03772
|
||||
DEN,Denver International Airport,Denver,CO,USA,39.85841,-104.66700
|
||||
DFW,Dallas/Fort Worth International Airport,Dallas-Fort Worth,TX,USA,32.89595,-97.03720
|
||||
DHN,Dothan Regional Airport,Dothan,AL,USA,31.32134,-85.44963
|
||||
DIK,Dickinson Theodore Roosevelt Regional Airport,Dickinson,ND,USA,46.79739,-102.80195
|
||||
DLG,Dillingham Airport,Dillingham,AK,USA,59.04541,-158.50334
|
||||
DLH,Duluth International Airport,Duluth,MN,USA,46.84209,-92.19365
|
||||
DRO,Durango-La Plata County Airport,Durango,CO,USA,37.15152,-107.75377
|
||||
DSM,Des Moines International Airport,Des Moines,IA,USA,41.53493,-93.66068
|
||||
DTW,Detroit Metropolitan Airport,Detroit,MI,USA,42.21206,-83.34884
|
||||
DVL,Devils Lake Regional Airport,Devils Lake,ND,USA,48.11425,-98.90878
|
||||
EAU,Chippewa Valley Regional Airport,Eau Claire,WI,USA,44.86526,-91.48507
|
||||
ECP,Northwest Florida Beaches International Airport,Panama City,FL,USA,,
|
||||
EGE,Eagle County Regional Airport,Eagle,CO,USA,39.64257,-106.91770
|
||||
EKO,Elko Regional Airport,Elko,NV,USA,40.82493,-115.79170
|
||||
ELM,Elmira/Corning Regional Airport,Elmira,NY,USA,42.15991,-76.89144
|
||||
ELP,El Paso International Airport,El Paso,TX,USA,31.80667,-106.37781
|
||||
ERI,Erie International Airport,Erie,PA,USA,42.08202,-80.17622
|
||||
ESC,Delta County Airport,Escanaba,MI,USA,45.72267,-87.09373
|
||||
EUG,Eugene Airport (Mahlon Sweet Field),Eugene,OR,USA,44.12326,-123.21869
|
||||
EVV,Evansville Regional Airport,Evansville,IN,USA,38.03799,-87.53063
|
||||
EWN,Coastal Carolina Regional Airport (Craven County Regional),New Bern,NC,USA,35.07297,-77.04294
|
||||
EWR,Newark Liberty International Airport,Newark,NJ,USA,40.69250,-74.16866
|
||||
EYW,Key West International Airport,Key West,FL,USA,24.55611,-81.75956
|
||||
FAI,Fairbanks International Airport,Fairbanks,AK,USA,64.81368,-147.85967
|
||||
FAR,Hector International Airport,Fargo,ND,USA,46.91935,-96.81499
|
||||
FAT,Fresno Yosemite International Airport,Fresno,CA,USA,36.77619,-119.71814
|
||||
FAY,Fayetteville Regional Airport,Fayetteville,NC,USA,34.99147,-78.88000
|
||||
FCA,Glacier Park International Airport,Kalispell,MT,USA,48.31140,-114.25507
|
||||
FLG,Flagstaff Pulliam Airport,Flagstaff,AZ,USA,35.13845,-111.67122
|
||||
FLL,Fort Lauderdale-Hollywood International Airport,Ft. Lauderdale,FL,USA,26.07258,-80.15275
|
||||
FNT,Bishop International Airport,Flint,MI,USA,42.96550,-83.74346
|
||||
FSD,Sioux Falls Regional Airport,Sioux Falls,SD,USA,43.58135,-96.74170
|
||||
FSM,Fort Smith Regional Airport,Fort Smith,AR,USA,35.33659,-94.36744
|
||||
FWA,Fort Wayne International Airport,Fort Wayne,IN,USA,40.97847,-85.19515
|
||||
GCC,Gillette-Campbell County Airport,Gillette,WY,USA,44.34890,-105.53936
|
||||
GCK,Garden City Regional Airport,Garden City,KS,USA,37.92752,-100.72441
|
||||
GEG,Spokane International Airport,Spokane,WA,USA,47.61986,-117.53384
|
||||
GFK,Grand Forks International Airport,Grand Forks,ND,USA,47.94926,-97.17611
|
||||
GGG,East Texas Regional Airport,Longview,TX,USA,32.38486,-94.71171
|
||||
GJT,Grand Junction Regional Airport (Walker Field),Grand Junction,CO,USA,39.12241,-108.52673
|
||||
GNV,Gainesville Regional Airport,Gainesville,FL,USA,29.69006,-82.27178
|
||||
GPT,Gulfport-Biloxi International Airport,Gulfport-Biloxi,MS,USA,30.40728,-89.07009
|
||||
GRB,Green Bay-Austin Straubel International Airport,Green Bay,WI,USA,44.48507,-88.12959
|
||||
GRI,Central Nebraska Regional Airport,Grand Island,NE,USA,40.96747,-98.30861
|
||||
GRK,Killeen-Fort Hood Regional Airport,Killeen,TX,USA,31.06490,-97.82780
|
||||
GRR,Gerald R. Ford International Airport,Grand Rapids,MI,USA,42.88082,-85.52277
|
||||
GSO,Piedmont Triad International Airport,Greensboro,NC,USA,36.09775,-79.93730
|
||||
GSP,Greenville-Spartanburg International Airport,Greer,SC,USA,34.89567,-82.21886
|
||||
GST,Gustavus Airport,Gustavus,AK,USA,58.42438,-135.70738
|
||||
GTF,Great Falls International Airport,Great Falls,MT,USA,47.48200,-111.37069
|
||||
GTR,Golden Triangle Regional Airport,Columbus-Starkville-West Point,MS,USA,33.45033,-88.59137
|
||||
GUC,Gunnison-Crested Butte Regional Airport,Gunnison,CO,USA,38.53396,-106.93318
|
||||
GUM,Guam International Airport,Agana,GU,USA,13.48345,-144.79598
|
||||
HDN,Yampa Valley Airport (Yampa Valley Regional),Hayden,CO,USA,40.48118,-107.21766
|
||||
HIB,Range Regional Airport (Chisholm-Hibbing Airport),Hibbing,MN,USA,47.38660,-92.83899
|
||||
HLN,Helena Regional Airport,Helena,MT,USA,46.60682,-111.98275
|
||||
HNL,Honolulu International Airport,Honolulu,HI,USA,21.31869,-157.92241
|
||||
HOB,Lea County Regional Airport,Hobbs,NM,USA,32.68753,-103.21703
|
||||
HOU,William P. Hobby Airport,Houston,TX,USA,29.64542,-95.27889
|
||||
HPN,Westchester County Airport,White Plains,NY,USA,41.06696,-73.70757
|
||||
HRL,Valley International Airport,Harlingen,TX,USA,26.22851,-97.65439
|
||||
HSV,Huntsville International Airport,Huntsville,AL,USA,34.64045,-86.77311
|
||||
HYA,Barnstable Municipal Airport,Hyannis,MA,USA,41.66934,-70.28036
|
||||
HYS,Hays Regional Airport,Hays,KS,USA,38.84494,-99.27403
|
||||
IAD,Washington Dulles International Airport,Chantilly,VA,USA,38.94453,-77.45581
|
||||
IAG,Niagara Falls International Airport,Niagara Falls,NY,USA,43.10726,-78.94538
|
||||
IAH,George Bush Intercontinental Airport,Houston,TX,USA,29.98047,-95.33972
|
||||
ICT,Wichita Dwight D. Eisenhower National Airport (Wichita Mid-Continent Airport),Wichita,KS,USA,37.64996,-97.43305
|
||||
IDA,Idaho Falls Regional Airport,Idaho Falls,ID,USA,43.51456,-112.07017
|
||||
ILG,Wilmington Airport,Wilmington,DE,USA,39.67872,-75.60653
|
||||
ILM,Wilmington International Airport,Wilmington,NC,USA,34.27061,-77.90256
|
||||
IMT,Ford Airport,Iron Mountain/Kingsford,MI,USA,45.81835,-88.11454
|
||||
IND,Indianapolis International Airport,Indianapolis,IN,USA,39.71733,-86.29438
|
||||
INL,Falls International Airport,International Falls,MN,USA,48.56619,-93.40307
|
||||
ISN,Sloulin Field International Airport,Williston,ND,USA,48.17794,-103.64235
|
||||
ISP,Long Island MacArthur Airport,Islip,NY,USA,40.79524,-73.10021
|
||||
ITH,Ithaca Tompkins Regional Airport,Ithaca,NY,USA,42.49103,-76.45844
|
||||
ITO,Hilo International Airport,Hilo,HI,USA,19.72026,-155.04847
|
||||
JAC,Jackson Hole Airport,Jackson,WY,USA,43.60732,-110.73774
|
||||
JAN,Jackson-Evers International Airport,Jackson,MS,USA,32.31117,-90.07589
|
||||
JAX,Jacksonville International Airport,Jacksonville,FL,USA,30.49406,-81.68786
|
||||
JFK,John F. Kennedy International Airport (New York International Airport),New York,NY,USA,40.63975,-73.77893
|
||||
JLN,Joplin Regional Airport,Joplin,MO,USA,37.15181,-94.49827
|
||||
JMS,Jamestown Regional Airport,Jamestown,ND,USA,46.92972,-98.67820
|
||||
JNU,Juneau International Airport,Juneau,AK,USA,58.35496,-134.57628
|
||||
KOA,Kona International Airport at Keahole,Kailua/Kona,HI,USA,19.73877,-156.04563
|
||||
KTN,Ketchikan International Airport,Ketchikan,AK,USA,55.35557,-131.71374
|
||||
LAN,Capital Region International Airport ( Lansing Capital City),Lansing,MI,USA,42.77870,-84.58736
|
||||
LAR,Laramie Regional Airport,Laramie,WY,USA,41.31205,-105.67499
|
||||
LAS,McCarran International Airport,Las Vegas,NV,USA,36.08036,-115.15233
|
||||
LAW,Lawton-Fort Sill Regional Airport,Lawton,OK,USA,34.56771,-98.41664
|
||||
LAX,Los Angeles International Airport,Los Angeles,CA,USA,33.94254,-118.40807
|
||||
LBB,Lubbock Preston Smith International Airport,Lubbock,TX,USA,33.66364,-101.82278
|
||||
LBE,Arnold Palmer Regional Airport,Latrobe,PA,USA,40.27594,-79.40480
|
||||
LCH,Lake Charles Regional Airport,Lake Charles,LA,USA,30.12610,-93.22340
|
||||
LEX,Blue Grass Airport,Lexington,KY,USA,38.03697,-84.60539
|
||||
LFT,Lafayette Regional Airport,Lafayette,LA,USA,30.20528,-91.98766
|
||||
LGA,LaGuardia Airport (Marine Air Terminal),New York,NY,USA,40.77724,-73.87261
|
||||
LGB,Long Beach Airport (Daugherty Field),Long Beach,CA,USA,33.81772,-118.15161
|
||||
LIH,Lihue Airport,Lihue,HI,USA,21.97598,-159.33896
|
||||
LIT,Bill and Hillary Clinton National Airport (Adams Field),Little Rock,AR,USA,34.72940,-92.22425
|
||||
LNK,Lincoln Airport (Lincoln Municipal),Lincoln,NE,USA,40.85097,-96.75925
|
||||
LRD,Laredo International Airport,Laredo,TX,USA,27.54374,-99.46154
|
||||
LSE,La Crosse Regional Airport,La Crosse,WI,USA,43.87938,-91.25654
|
||||
LWS,Lewiston-Nez Perce County Airport,Lewiston,ID,USA,46.37450,-117.01539
|
||||
MAF,Midland International Airport,Midland,TX,USA,31.94253,-102.20191
|
||||
MBS,MBS International Airport,Saginaw,MI,USA,43.53291,-84.07965
|
||||
MCI,Kansas City International Airport,Kansas City,MO,USA,39.29761,-94.71391
|
||||
MCO,Orlando International Airport,Orlando,FL,USA,28.42889,-81.31603
|
||||
MDT,Harrisburg International Airport,Harrisburg,PA,USA,40.19350,-76.76340
|
||||
MDW,Chicago Midway International Airport,Chicago,IL,USA,41.78598,-87.75242
|
||||
MEI,Meridian Regional Airport,Meridian,MS,USA,32.33313,-88.75121
|
||||
MEM,Memphis International Airport,Memphis,TN,USA,35.04242,-89.97667
|
||||
MFE,McAllen-Miller International Airport (McAllen Miller International),McAllen,TX,USA,26.17583,-98.23861
|
||||
MFR,Rogue Valley International Airport,Medford,OR,USA,42.37423,-122.87350
|
||||
MGM,Montgomery Regional Airport,Montgomery,AL,USA,32.30064,-86.39398
|
||||
MHK,Manhattan Regional Airport,Manhattan,KS,USA,39.14097,-96.67083
|
||||
MHT,Manchester-Boston Regional Airport,Manchester,NH,USA,42.93452,-71.43706
|
||||
MIA,Miami International Airport,Miami,FL,USA,25.79325,-80.29056
|
||||
MKE,General Mitchell International Airport,Milwaukee,WI,USA,42.94722,-87.89658
|
||||
MKG,Muskegon County Airport,Muskegon,MI,USA,43.16949,-86.23822
|
||||
MLB,Melbourne International Airport,Melbourne,FL,USA,28.10275,-80.64581
|
||||
MLI,Quad City International Airport,Moline,IL,USA,41.44853,-90.50754
|
||||
MLU,Monroe Regional Airport,Monroe,LA,USA,32.51087,-92.03769
|
||||
MMH,Mammoth Yosemite Airport,Mammoth Lakes,CA,USA,37.62405,-118.83777
|
||||
MOB,Mobile Regional Airport,Mobile,AL,USA,30.69142,-88.24283
|
||||
MOT,Minot International Airport,Minot,ND,USA,48.25938,-101.28033
|
||||
MQT,Sawyer International Airport,Marquette,MI,USA,46.35364,-87.39536
|
||||
MRY,Monterey Regional Airport (Monterey Peninsula Airport),Monterey,CA,USA,36.58698,-121.84295
|
||||
MSN,Dane County Regional Airport,Madison,WI,USA,43.13986,-89.33751
|
||||
MSO,Missoula International Airport,Missoula,MT,USA,46.91631,-114.09056
|
||||
MSP,Minneapolis-Saint Paul International Airport,Minneapolis,MN,USA,44.88055,-93.21692
|
||||
MSY,Louis Armstrong New Orleans International Airport,New Orleans,LA,USA,29.99339,-90.25803
|
||||
MTJ,Montrose Regional Airport,Montrose,CO,USA,38.50887,-107.89383
|
||||
MVY,Martha's Vineyard Airport,Marthas Vineyard,MA,USA,41.39303,-70.61433
|
||||
MYR,Myrtle Beach International Airport,Myrtle Beach,SC,USA,33.67975,-78.92833
|
||||
OAJ,Albert J. Ellis Airport,Jacksonville,NC,USA,34.82916,-77.61214
|
||||
OAK,Oakland International Airport,Oakland,CA,USA,37.72129,-122.22072
|
||||
OGG,Kahului Airport,Kahului,HI,USA,20.89865,-156.43046
|
||||
OKC,Will Rogers World Airport,Oklahoma City,OK,USA,35.39309,-97.60073
|
||||
OMA,Eppley Airfield,Omaha,NE,USA,41.30252,-95.89417
|
||||
OME,Nome Airport,Nome,AK,USA,64.51220,-165.44525
|
||||
ONT,Ontario International Airport,Ontario,CA,USA,34.05600,-117.60119
|
||||
ORD,Chicago O'Hare International Airport,Chicago,IL,USA,41.97960,-87.90446
|
||||
ORF,Norfolk International Airport,Norfolk,VA,USA,36.89461,-76.20122
|
||||
ORH,Worcester Regional Airport,Worcester,MA,USA,42.26734,-71.87571
|
||||
OTH,Southwest Oregon Regional Airport (North Bend Municipal),North Bend,OR,USA,43.41714,-124.24603
|
||||
OTZ,Ralph Wien Memorial Airport,Kotzebue,AK,USA,66.88468,-162.59855
|
||||
PAH,Barkley Regional Airport,Paducah,KY,USA,37.06083,-88.77375
|
||||
PBG,Plattsburgh International Airport,Plattsburgh,NY,USA,,
|
||||
PBI,Palm Beach International Airport,West Palm Beach,FL,USA,26.68316,-80.09559
|
||||
PDX,Portland International Airport,Portland,OR,USA,45.58872,-122.59750
|
||||
PHF,Newport News/Williamsburg International Airport,Newport News,VA,USA,37.13190,-76.49299
|
||||
PHL,Philadelphia International Airport,Philadelphia,PA,USA,39.87195,-75.24114
|
||||
PHX,Phoenix Sky Harbor International Airport,Phoenix,AZ,USA,33.43417,-112.00806
|
||||
PIA,General Wayne A. Downing Peoria International Airport,Peoria,IL,USA,40.66424,-89.69331
|
||||
PIB,Hattiesburg-Laurel Regional Airport,Hattiesburg-Laurel,MS,USA,31.46715,-89.33706
|
||||
PIH,Pocatello Regional Airport,Pocatello,ID,USA,42.91131,-112.59586
|
||||
PIT,Pittsburgh International Airport,Pittsburgh,PA,USA,40.49147,-80.23287
|
||||
PLN,Pellston Regional Airport of Emmet County,Pellston,MI,USA,45.57093,-84.79672
|
||||
PNS,Pensacola International Airport (Pensacola Gulf Coast Regional Airport),Pensacola,FL,USA,30.47331,-87.18744
|
||||
PPG,Pago Pago International Airport (Tafuna Airport),Pago Pago,AS,USA,14.33102,-170.71053
|
||||
PSC,Tri-Cities Airport,Pasco,WA,USA,46.26468,-119.11903
|
||||
PSE,Mercedita Airport,Ponce,PR,USA,18.00830,-66.56301
|
||||
PSG,Petersburg James A. Johnson Airport,Petersburg,AK,USA,56.80165,-132.94528
|
||||
PSP,Palm Springs International Airport,Palm Springs,CA,USA,33.82922,-116.50625
|
||||
PUB,Pueblo Memorial Airport,Pueblo,CO,USA,38.28909,-104.49657
|
||||
PVD,Theodore Francis Green State Airport,Providence,RI,USA,41.72400,-71.42822
|
||||
PWM,Portland International Jetport,Portland,ME,USA,43.64617,-70.30875
|
||||
RAP,Rapid City Regional Airport,Rapid City,SD,USA,44.04532,-103.05737
|
||||
RDD,Redding Municipal Airport,Redding,CA,USA,40.50898,-122.29340
|
||||
RDM,Redmond Municipal Airport (Roberts Field),Redmond,OR,USA,44.25407,-121.14996
|
||||
RDU,Raleigh-Durham International Airport,Raleigh,NC,USA,35.87764,-78.78747
|
||||
RHI,Rhinelander-Oneida County Airport,Rhinelander,WI,USA,45.63119,-89.46745
|
||||
RIC,Richmond International Airport,Richmond,VA,USA,37.50517,-77.31967
|
||||
RKS,Rock Springs-Sweetwater County Airport,Rock Springs,WY,USA,41.59422,-109.06519
|
||||
RNO,Reno/Tahoe International Airport,Reno,NV,USA,39.49858,-119.76806
|
||||
ROA,Roanoke Regional Airport (Woodrum Field),Roanoke,VA,USA,37.32547,-79.97543
|
||||
ROC,Greater Rochester International Airport,Rochester,NY,USA,43.11887,-77.67238
|
||||
ROW,Roswell International Air Center,Roswell,NM,USA,33.30156,-104.53056
|
||||
RST,Rochester International Airport,Rochester,MN,USA,43.90883,-92.49799
|
||||
RSW,Southwest Florida International Airport,Ft. Myers,FL,USA,26.53617,-81.75517
|
||||
SAF,Santa Fe Municipal Airport,Santa Fe,NM,USA,35.61678,-106.08814
|
||||
SAN,San Diego International Airport (Lindbergh Field),San Diego,CA,USA,32.73356,-117.18966
|
||||
SAT,San Antonio International Airport,San Antonio,TX,USA,29.53369,-98.46978
|
||||
SAV,Savannah/Hilton Head International Airport,Savannah,GA,USA,32.12758,-81.20214
|
||||
SBA,Santa Barbara Municipal Airport (Santa Barbara Airport),Santa Barbara,CA,USA,34.42621,-119.84037
|
||||
SBN,South Bend International Airport (South Bend Regional),South Bend,IN,USA,41.70895,-86.31847
|
||||
SBP,San Luis Obispo County Regional Airport (McChesney Field),San Luis Obispo,CA,USA,35.23706,-120.64239
|
||||
SCC,Deadhorse Airport (Prudhoe Bay Airport),Deadhorse,AK,USA,70.19476,-148.46516
|
||||
SCE,University Park Airport,State College,PA,USA,40.85121,-77.84630
|
||||
SDF,Louisville International Airport (Standiford Field),Louisville,KY,USA,38.17439,-85.73600
|
||||
SEA,Seattle-Tacoma International Airport,Seattle,WA,USA,47.44898,-122.30931
|
||||
SFO,San Francisco International Airport,San Francisco,CA,USA,37.61900,-122.37484
|
||||
SGF,Springfield-Branson National Airport,Springfield,MO,USA,37.24433,-93.38686
|
||||
SGU,St. George Regional Airport,St George,UT,USA,37.09058,-113.59306
|
||||
SHV,Shreveport Regional Airport,Shreveport,LA,USA,32.44663,-93.82560
|
||||
SIT,Sitka Rocky Gutierrez Airport,Sitka,AK,USA,57.04714,-135.36160
|
||||
SJC,Norman Y. Mineta San José International Airport,San Jose,CA,USA,37.36186,-121.92901
|
||||
SJT,San Angelo Regional Airport (Mathis Field),San Angelo,TX,USA,31.35775,-100.49631
|
||||
SJU,Luis Muñoz Marín International Airport,San Juan,PR,USA,18.43942,-66.00183
|
||||
SLC,Salt Lake City International Airport,Salt Lake City,UT,USA,40.78839,-111.97777
|
||||
SMF,Sacramento International Airport,Sacramento,CA,USA,38.69542,-121.59077
|
||||
SMX,Santa Maria Public Airport (Capt G. Allan Hancock Field),Santa Maria,CA,USA,34.89925,-120.45758
|
||||
SNA,John Wayne Airport (Orange County Airport),Santa Ana,CA,USA,33.67566,-117.86822
|
||||
SPI,Abraham Lincoln Capital Airport,Springfield,IL,USA,39.84395,-89.67762
|
||||
SPS,Wichita Falls Municipal Airport/Sheppard AFB,Wichita Falls,TX,USA,33.98880,-98.49189
|
||||
SRQ,Sarasota-Bradenton International Airport,Sarasota,FL,USA,27.39533,-82.55411
|
||||
STC,St. Cloud Regional Airport,St Cloud,MN,USA,45.54532,-94.05834
|
||||
STL,St. Louis International Airport at Lambert Field,St Louis,MO,USA,38.74769,-90.35999
|
||||
STT,Cyril E. King Airport,Charlotte Amalie,VI,USA,18.33731,-64.97336
|
||||
STX,Henry E. Rohlsen Airport,Christiansted,VI,USA,17.70189,-64.79856
|
||||
SUN,Friedman Memorial Airport,Hailey,ID,USA,43.50484,-114.29659
|
||||
SUX,Sioux Gateway Airport,Sioux City,IA,USA,42.40260,-96.38437
|
||||
SWF,Stewart International Airport,Newburgh,NY,USA,41.50409,-74.10484
|
||||
SYR,Syracuse Hancock International Airport,Syracuse,NY,USA,43.11119,-76.10631
|
||||
TLH,Tallahassee International Airport,Tallahassee,FL,USA,30.39653,-84.35033
|
||||
TOL,Toledo Express Airport,Toledo,OH,USA,41.58681,-83.80783
|
||||
TPA,Tampa International Airport,Tampa,FL,USA,27.97547,-82.53325
|
||||
TRI,Tri-Cities Regional Airport,Bristol,TN,USA,36.47521,-82.40742
|
||||
TTN,Trenton Mercer Airport,Trenton,NJ,USA,40.27669,-74.81347
|
||||
TUL,Tulsa International Airport,Tulsa,OK,USA,36.19837,-95.88824
|
||||
TUS,Tucson International Airport,Tucson,AZ,USA,32.11608,-110.94103
|
||||
TVC,Cherry Capital Airport,Traverse City,MI,USA,44.74144,-85.58224
|
||||
TWF,Magic Valley Regional Airport (Joslin Field),Twin Falls,ID,USA,42.48180,-114.48774
|
||||
TXK,Texarkana Regional Airport (Webb Field),Texarkana,AR,USA,33.45371,-93.99102
|
||||
TYR,Tyler Pounds Regional Airport,Tyler,TX,USA,32.35414,-95.40239
|
||||
TYS,McGhee Tyson Airport,Knoxville,TN,USA,35.81249,-83.99286
|
||||
UST,Northeast Florida Regional Airport (St. Augustine Airport),St. Augustine,FL,USA,,
|
||||
VEL,Valdez Airport,Vernal,UT,USA,40.44090,-109.50992
|
||||
VLD,Valdosta Regional Airport,Valdosta,GA,USA,30.78250,-83.27672
|
||||
VPS,Destin-Fort Walton Beach Airport/Eglin AFB,Valparaiso,FL,USA,30.48325,-86.52540
|
||||
WRG,Wrangell Airport,Wrangell,AK,USA,56.48433,-132.36982
|
||||
WYS,Westerly State Airport,West Yellowstone,MT,USA,44.68840,-111.11764
|
||||
XNA,Northwest Arkansas Regional Airport,Fayetteville/Springdale/Rogers,AR,USA,36.28187,-94.30681
|
||||
YAK,Yakutat Airport,Yakutat,AK,USA,59.50336,-139.66023
|
||||
YUM,Yuma International Airport,Yuma,AZ,USA,32.65658,-114.60597
|
||||
ART,Watertown International Airport,Dexter,NY,USA,43.99190,-76.02169
|
||||
AZA,Phoenix-Mesa-Gateway Airport,Mesa,AZ,USA,33.30780029,-111.6549988
|
||||
BFF,Western Neb. Rgnl/William B. Heilig Airport,Scottsbluff,NE,USA,41.87400,-103.59600
|
||||
BKG,Branson,Hollister,MO,USA,36.53199,-93.20055
|
||||
CIC,Chico Municipal Airport,Chico,CA,USA,39.79539,-121.85800
|
||||
CYS,Cheyenne Regional Jerry Olson Field,Cheyenne,WY,USA,41.15570,-104.81199
|
||||
DRT,Del Rio International Airport,Del Rio,TX,USA,29.37420,-100.92700
|
||||
EFD,Ellington Airport,Houston,TX,USA,29.60729,-95.15879
|
||||
ENV,Wendover Airport,Wendover,UT,USA,40.71870,-114.03099
|
||||
FOE,Topeka Regional Airport - Forbes Field,Topeka,KS,USA,38.95090,-95.66359
|
||||
IPL,Imperial County Airport,Imperial,CA,USA,32.83420,-115.57900
|
||||
IYK,Inyokern Airport,Inyokern,CA,USA,35.65879,-117.8300018
|
||||
LMT,Klamath Falls Airport,Klamath Falls,OR,USA,42.15610,-121.73300
|
||||
MCN,Middle Georgia Regional Airport,Macon,GA,USA,32.69279,-83.64920
|
||||
MOD,Modesto City Co-Harry Sham Field,Modesto,CA,USA,37.62580,-120.95400
|
||||
PGD,Charlotte County Airport,Punta Gorda,FL,USA,26.92020,-81.99050
|
||||
RFD,Chicago Rockford International Airport,Rockford,IL,USA,42.19540,-89.097198
|
||||
SHD,Shenandoah Valley Regional Airport,Staunton,VA,USA,38.26380,-78.89640
|
||||
SPN,Saipan International Airport,Saipan,,CNMI,15.11900,145.72900
|
||||
TKI,Collin County Regional At Mc Kinney Airport,Dallas,TX,USA,33.17789,-96.59049
|
|
|
@ -1,37 +0,0 @@
|
|||
use columnstore_schema;
|
||||
|
||||
create table flights (
|
||||
year smallint,
|
||||
month tinyint,
|
||||
day tinyint,
|
||||
day_of_week tinyint,
|
||||
fl_date date,
|
||||
carrier char(2),
|
||||
tail_num char(6),
|
||||
fl_num smallint,
|
||||
origin varchar(5),
|
||||
dest varchar(5),
|
||||
crs_dep_time char(4),
|
||||
dep_time char(4),
|
||||
dep_delay smallint,
|
||||
taxi_out smallint,
|
||||
wheels_off char(4),
|
||||
wheels_on char(4),
|
||||
taxi_in smallint,
|
||||
crs_arr_time char(4),
|
||||
arr_time char(4),
|
||||
arr_delay smallint,
|
||||
cancelled smallint,
|
||||
cancellation_code smallint,
|
||||
diverted smallint,
|
||||
crs_elapsed_time smallint,
|
||||
actual_elapsed_time smallint,
|
||||
air_time smallint,
|
||||
distance smallint,
|
||||
carrier_delay smallint,
|
||||
weather_delay smallint,
|
||||
nas_delay smallint,
|
||||
security_delay smallint,
|
||||
late_aircraft_delay smallint
|
||||
) engine=columnstore default character set=utf8;
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
use innodb_schema;
|
||||
|
||||
/* load airports data */
|
||||
LOAD DATA INFILE '/Developer-Examples/Bookings/schema/airports.csv' INTO TABLE airports
|
||||
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
|
||||
LINES TERMINATED BY '\n';
|
||||
|
||||
/* load airlines data */
|
||||
LOAD DATA INFILE '/Developer-Examples/Bookings/schema/airlines.csv' INTO TABLE airlines
|
||||
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
|
||||
LINES TERMINATED BY '\n';
|
|
@ -1,77 +0,0 @@
|
|||
use innodb_schema;
|
||||
|
||||
-- Create syntax for TABLE 'airlines'
|
||||
CREATE TABLE `airlines` (
|
||||
`iata_code` char(2) DEFAULT NULL,
|
||||
`airline` varchar(30) DEFAULT NULL,
|
||||
UNIQUE KEY `idx_iata_code` (`iata_code`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- Create syntax for TABLE 'airports'
|
||||
CREATE TABLE `airports` (
|
||||
`iata_code` char(3) DEFAULT NULL,
|
||||
`airport` varchar(80) DEFAULT NULL,
|
||||
`city` varchar(30) DEFAULT NULL,
|
||||
`state` char(2) DEFAULT NULL,
|
||||
`country` varchar(30) DEFAULT NULL,
|
||||
`latitude` float DEFAULT NULL,
|
||||
`longitude` float DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- Create syntax for TABLE 'flights'
|
||||
CREATE TABLE `flights` (
|
||||
`year` smallint(6) DEFAULT NULL,
|
||||
`month` tinyint(4) DEFAULT NULL,
|
||||
`day` tinyint(4) DEFAULT NULL,
|
||||
`day_of_week` tinyint(4) DEFAULT NULL,
|
||||
`fl_date` date DEFAULT NULL,
|
||||
`carrier` char(2) DEFAULT NULL,
|
||||
`tail_num` char(6) DEFAULT NULL,
|
||||
`fl_num` smallint(6) DEFAULT NULL,
|
||||
`origin` varchar(5) DEFAULT NULL,
|
||||
`dest` varchar(5) DEFAULT NULL,
|
||||
`crs_dep_time` char(4) DEFAULT NULL,
|
||||
`dep_time` char(4) DEFAULT NULL,
|
||||
`dep_delay` smallint(6) DEFAULT NULL,
|
||||
`taxi_out` smallint(6) DEFAULT NULL,
|
||||
`wheels_off` char(4) DEFAULT NULL,
|
||||
`wheels_on` char(4) DEFAULT NULL,
|
||||
`taxi_in` smallint(6) DEFAULT NULL,
|
||||
`crs_arr_time` char(4) DEFAULT NULL,
|
||||
`arr_time` char(4) DEFAULT NULL,
|
||||
`arr_delay` smallint(6) DEFAULT NULL,
|
||||
`cancelled` smallint(6) DEFAULT NULL,
|
||||
`cancellation_code` char(1) DEFAULT NULL,
|
||||
`diverted` smallint(6) DEFAULT NULL,
|
||||
`crs_elapsed_time` smallint(6) DEFAULT NULL,
|
||||
`actual_elapsed_time` smallint(6) DEFAULT NULL,
|
||||
`air_time` smallint(6) DEFAULT NULL,
|
||||
`distance` smallint(6) DEFAULT NULL,
|
||||
`carrier_delay` smallint(6) DEFAULT NULL,
|
||||
`weather_delay` smallint(6) DEFAULT NULL,
|
||||
`nas_delay` smallint(6) DEFAULT NULL,
|
||||
`security_delay` smallint(6) DEFAULT NULL,
|
||||
`late_aircraft_delay` smallint(6) DEFAULT NULL,
|
||||
KEY `idx_fl_num_dep_delay` (`fl_num`,`dep_delay`),
|
||||
KEY `idx_fl_num_dep_delay_carrier` (`fl_num`,`dep_delay`,`carrier`),
|
||||
KEY `idx_dep_delay` (`dep_delay`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- Create syntax for TABLE 'tickets'
|
||||
CREATE TABLE `tickets` (
|
||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`fl_date` date NOT NULL,
|
||||
`fl_num` smallint(6) NOT NULL,
|
||||
`carrier` char(2) NOT NULL DEFAULT '',
|
||||
`origin` varchar(5) NOT NULL DEFAULT '',
|
||||
`dest` varchar(5) NOT NULL DEFAULT '',
|
||||
`price` decimal(9,2) NOT NULL DEFAULT 0.00,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
|
||||
|
||||
-- Create syntax for TABLE 'trips'
|
||||
CREATE TABLE `trips` (
|
||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`ticket_id` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
|
|
@ -1,61 +0,0 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# next.js build output
|
||||
.next
|
|
@ -1,23 +0,0 @@
|
|||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
|
@ -1,68 +0,0 @@
|
|||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||
|
||||
## Available Scripts
|
||||
|
||||
In the project directory, you can run:
|
||||
|
||||
### `npm start`
|
||||
|
||||
Runs the app in the development mode.<br />
|
||||
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
||||
|
||||
The page will reload if you make edits.<br />
|
||||
You will also see any lint errors in the console.
|
||||
|
||||
### `npm test`
|
||||
|
||||
Launches the test runner in the interactive watch mode.<br />
|
||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
||||
|
||||
### `npm run build`
|
||||
|
||||
Builds the app for production to the `build` folder.<br />
|
||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||
|
||||
The build is minified and the filenames include the hashes.<br />
|
||||
Your app is ready to be deployed!
|
||||
|
||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
||||
|
||||
### `npm run eject`
|
||||
|
||||
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
|
||||
|
||||
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
||||
|
||||
Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
|
||||
|
||||
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
|
||||
|
||||
## Learn More
|
||||
|
||||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
||||
|
||||
To learn React, check out the [React documentation](https://reactjs.org/).
|
||||
|
||||
### Code Splitting
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
|
||||
|
||||
### Analyzing the Bundle Size
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
|
||||
|
||||
### Making a Progressive Web App
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
|
||||
|
||||
### Deployment
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
|
||||
|
||||
### `npm run build` fails to minify
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
|
|
@ -1,42 +0,0 @@
|
|||
{
|
||||
"name": "client",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.5.0",
|
||||
"@testing-library/user-event": "^7.2.1",
|
||||
"bootstrap": "^4.4.1",
|
||||
"react": "^16.13.1",
|
||||
"react-bootstrap": "^1.0.0",
|
||||
"react-datepicker": "^2.14.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-icons-weather": "^1.0.5",
|
||||
"react-popper": "^1.3.7",
|
||||
"react-scripts": "3.3.0",
|
||||
"react-select": "^3.1.0",
|
||||
"segmented-control": "^0.1.12"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"proxy": "http://localhost:8080"
|
||||
}
|
Przed Szerokość: | Wysokość: | Rozmiar: 15 KiB |
|
@ -1,43 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>Bookings</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
Przed Szerokość: | Wysokość: | Rozmiar: 5.2 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 9.4 KiB |
|
@ -1,25 +0,0 @@
|
|||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
|
@ -1,351 +0,0 @@
|
|||
.app {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.app-logo {
|
||||
height: 40vmin;
|
||||
}
|
||||
|
||||
.app-header {
|
||||
background-color: #003545;
|
||||
min-height: 125px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
padding-top: 10px;
|
||||
margin: 0px;
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sub-title-text {
|
||||
margin: 0px;
|
||||
font-size: small;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.float-left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.float-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.center {
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.width-50 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.header-link {
|
||||
background-color: #E5E1E5;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
height: 65px;
|
||||
display: table;
|
||||
}
|
||||
|
||||
.header-link h3 {
|
||||
display:table-cell;
|
||||
vertical-align:middle
|
||||
}
|
||||
|
||||
.selected {
|
||||
background-color: #96DDCF;
|
||||
}
|
||||
|
||||
.form-nav-panel {
|
||||
border-bottom: #c0c0c0 1px solid;
|
||||
}
|
||||
|
||||
.form-main {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.form-main table {
|
||||
width: 50%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.form-content {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.filter-content {
|
||||
background: #EEEEEE;
|
||||
border-radius: 5px;
|
||||
text-align: left;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.filter-content h2 {
|
||||
margin-top: 0px;
|
||||
margin-left: 5px;
|
||||
color: #003545;
|
||||
}
|
||||
|
||||
.margin-top-10 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.margin-20 {
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 5px;
|
||||
background: #003545;
|
||||
border-color: #E5E1E5;
|
||||
color: #ffffff;
|
||||
font-weight: bold;
|
||||
width: 350px;
|
||||
height: 50px;
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
cursor: pointer;
|
||||
background: #96DDCF;
|
||||
}
|
||||
|
||||
.datepicker {
|
||||
width: 100px;
|
||||
height: 25px;
|
||||
border-radius: 5px;
|
||||
border: #C0C0C0 1px solid;
|
||||
}
|
||||
|
||||
.datepicker {
|
||||
width: 100px;
|
||||
height: 25px;
|
||||
border-radius: 5px;
|
||||
border: #C0C0C0 1px solid;
|
||||
}
|
||||
|
||||
.width-500 {
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
.width-125 {
|
||||
width: 125px;
|
||||
}
|
||||
|
||||
.margin-top-25 {
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.margin-left-10 {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.width-33 {
|
||||
width: 33%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.valign-top {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.flight-content button {
|
||||
width: 125px;
|
||||
}
|
||||
|
||||
.below-0 {
|
||||
margin-bottom: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.item-content {
|
||||
width: 90%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 5px;
|
||||
border: #C0C0C0 1px solid;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.item-content table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.item-content table th {
|
||||
background-color: #003545;
|
||||
color: white;
|
||||
height: 35px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.item-content table td {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.item-content p.subtext {
|
||||
color: red;
|
||||
margin-bottom: 20px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.item-content .header {
|
||||
font-size: 26px;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.item-content .sub-header {
|
||||
font-size: 16px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.score-very-good {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.score-good {
|
||||
color: lightgreen;
|
||||
}
|
||||
|
||||
.score-average {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.score-poor {
|
||||
color: orange;
|
||||
}
|
||||
|
||||
.score-very-poor {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.font-size-20 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.margin-right-25 {
|
||||
margin-right: 25px;
|
||||
}
|
||||
|
||||
.margin-left-10 {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.forecast-title {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.forecast-details {
|
||||
margin-top: 5px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.weather-summary-content {
|
||||
background-color: #E5E1E5;
|
||||
padding: 8px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.margin-left-5 {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.section-label {
|
||||
font-weight: bold;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.section-description {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.estimation-content {
|
||||
font-size: 12px;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.estimation-content p {
|
||||
margin: 0px;
|
||||
font-weight: bold;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.item-content .trip-content:last-child {
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.trip-content table {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.trip-content table tr td {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.trip-score {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 50px;
|
||||
margin-right: 30px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.trip-score p {
|
||||
color: white;
|
||||
height: 100px;
|
||||
line-height: 100px;
|
||||
text-align: center;
|
||||
font-size: 38px;
|
||||
}
|
||||
|
||||
.background-green {
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
.background-gray {
|
||||
background-color: gray;
|
||||
}
|
||||
|
||||
.background-red {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
#popover-basic.popover {
|
||||
max-width: 500px;
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
import React from 'react';
|
||||
import './App.css';
|
||||
import Dashboard from './components/Dashboard';
|
||||
import logo from './plane.png';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div className="app">
|
||||
<header className="app-header">
|
||||
<div>
|
||||
<img className="float-left" src={logo} alt="logo" />
|
||||
<div className="float-right center">
|
||||
<p className="title-text align-left">Bookings</p>
|
||||
<p className="sub-title-text align-left">A MariaDB Smart Transactions Demo</p>
|
||||
</div>
|
||||
<div style={{clear: "both"}} />
|
||||
</div>
|
||||
</header>
|
||||
<Dashboard />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
|
@ -1,9 +0,0 @@
|
|||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import App from './App';
|
||||
|
||||
test('renders learn react link', () => {
|
||||
const { getByText } = render(<App />);
|
||||
const linkElement = getByText(/learn react/i);
|
||||
expect(linkElement).toBeInTheDocument();
|
||||
});
|
|
@ -1,17 +0,0 @@
|
|||
import React, {Component} from 'react';
|
||||
const images = require.context('../images', true);
|
||||
|
||||
export default class AirlineIcon extends Component {
|
||||
getIcon(code) {
|
||||
return images('./' + code + '.png');
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<img src={this.getIcon(this.props.code)} alt={this.props.name} />
|
||||
{this.props.name}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
import React, {Component} from 'react';
|
||||
import FlightSearch from './FlightSearch';
|
||||
import Flights from './Flights';
|
||||
import Trips from './Trips';
|
||||
|
||||
export default class Dashboard extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
flights: [],
|
||||
trips: [],
|
||||
selectedTabIndex: 0
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.loadTrips();
|
||||
}
|
||||
|
||||
async loadTrips() {
|
||||
this.setState({
|
||||
trips: await this.getTrips()
|
||||
})
|
||||
}
|
||||
|
||||
async getTrips() {
|
||||
const response = await fetch('/api/trips');
|
||||
const body = await response.json();
|
||||
if (response.status !== 200) {
|
||||
throw Error(body.message)
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
async executeSearch(params) {
|
||||
this.setState({
|
||||
flights: await this.getFlights(params.origin.code,
|
||||
params.destination.code,
|
||||
params.originDepartureDate)
|
||||
});
|
||||
}
|
||||
|
||||
async getFlights(origin, destination, originDepartureDate) {
|
||||
const response = await fetch('/api/flights?o=' + origin + '&d=' + destination + '&dt=' + originDepartureDate);
|
||||
const body = await response.json();
|
||||
if (response.status !== 200) {
|
||||
throw Error(body.message)
|
||||
}
|
||||
return body;
|
||||
};
|
||||
|
||||
toggleSection(selectedTabIndex) {
|
||||
this.setState({selectedTabIndex});
|
||||
}
|
||||
|
||||
getNavClasses(index) {
|
||||
if (this.state.selectedTabIndex === index) {
|
||||
return "header-link selected width-50 float-left";
|
||||
}
|
||||
else {
|
||||
return "header-link width-50 float-left";
|
||||
}
|
||||
}
|
||||
|
||||
renderSection() {
|
||||
if (this.state.selectedTabIndex === 0) {
|
||||
return (
|
||||
<div className="form-content">
|
||||
<FlightSearch executeSearch={(params) => this.executeSearch(params)} />
|
||||
<Flights flights={this.state.flights} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
else {
|
||||
return (
|
||||
<div>
|
||||
<Trips trips={this.state.trips} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div >
|
||||
<div className="form-nav-panel">
|
||||
<div onClick={() => this.toggleSection(0)} className={this.getNavClasses(0)}>
|
||||
<h3>Book a Trip!</h3>
|
||||
</div>
|
||||
<div onClick={() => this.toggleSection(1)} className={this.getNavClasses(1)}>
|
||||
<h3>Upcoming Trips</h3>
|
||||
</div>
|
||||
<div style={{clear: "both"}} />
|
||||
</div>
|
||||
<div className="form-main">
|
||||
{this.renderSection()}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
import React, {Component} from 'react';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
import { OverlayTrigger, Popover } from 'react-bootstrap';
|
||||
import AirlineIcon from './AirlineIcon';
|
||||
import info from '../images/info.png';
|
||||
|
||||
export default class Flight extends Component {
|
||||
|
||||
renderFlightScore(score) {
|
||||
let cssClass = "float-left margin-left-10 bold ";
|
||||
|
||||
if (score >= 4.5) {
|
||||
cssClass += "score-very-good";
|
||||
}
|
||||
else if (score >= 4.0) {
|
||||
cssClass += "score-good";
|
||||
}
|
||||
else if (score >= 3.0) {
|
||||
cssClass += "score-average";
|
||||
|
||||
}
|
||||
else if (score >= 2.0) {
|
||||
cssClass += "score-poor";
|
||||
}
|
||||
else {
|
||||
cssClass += "score-very-poor";
|
||||
}
|
||||
|
||||
return(
|
||||
<div className="float-left font-size-20">
|
||||
<p className="float-left">
|
||||
Flight score:
|
||||
</p>
|
||||
<p className={cssClass}>
|
||||
{score}
|
||||
</p>
|
||||
<div style={{clear: "both"}} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
getPopover(props,assessment) {
|
||||
return(
|
||||
<Popover id="popover-basic" {...props}>
|
||||
<Popover.Title as="h3">Flight score ({assessment.overall_score}/5.0) </Popover.Title>
|
||||
<Popover.Content>
|
||||
<table cellSpacing="10" cellPadding="10">
|
||||
<tr>
|
||||
<td><p className="section-label">Price score</p></td>
|
||||
<td className="assessment-score" align="right" valign="top">{assessment.price_score}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p className="section-label">Delay score</p>
|
||||
<p className="section-description">This flight is delayed {assessment.delay_percentage}% of the time.</p>
|
||||
</td>
|
||||
<td className="assessment-score" align="right" valign="top">{assessment.delay_score}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p className="section-label">Cancellation score</p>
|
||||
<p className="section-description">This flight is canceled {assessment.cancel_percentage}% of the time.</p>
|
||||
</td>
|
||||
<td className="assessment-score" align="right" valign="top">{assessment.cancel_score}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</Popover.Content>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
||||
getFormattedTime(time) {
|
||||
return time.match(/.{1,2}/g).join(':');
|
||||
}
|
||||
|
||||
getDuration(departure,arrival) {
|
||||
var delta = parseInt(arrival) - parseInt(departure);
|
||||
return this.getFormattedTimeFromInt(delta);
|
||||
}
|
||||
|
||||
getFormattedTimeFromInt(num) {
|
||||
var hours = Math.floor(num / 60);
|
||||
var minutes = parseInt(num % 60);
|
||||
return hours + "h " + minutes + "m";
|
||||
}
|
||||
|
||||
render() {
|
||||
const flight = this.props.flight;
|
||||
|
||||
return (
|
||||
<div className="item-content">
|
||||
<div>
|
||||
<div className="width-33 align-left">
|
||||
<h3>{this.getFormattedTime(flight.dep_time)} - {this.getFormattedTime(flight.arr_time)}</h3>
|
||||
<p className="subtext">Avg. delay: {flight.avg_delay !== null ? Math.round(flight.avg_delay) : 0} minutes</p>
|
||||
</div>
|
||||
<div className="width-33 align-left">
|
||||
<p>Flight duration: {this.getDuration(flight.dep_time,flight.arr_time)}</p>
|
||||
<p className="subtext">Avg. flight duration: {this.getFormattedTimeFromInt(flight.avg_duration)}</p>
|
||||
</div>
|
||||
<div className="width-33 align-right valign-top">
|
||||
<h3>${flight.price}</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="width-33 align-left">
|
||||
<AirlineIcon code={flight.airline_code} name={flight.airline} />
|
||||
</div>
|
||||
<div className="width-33 align-left">
|
||||
<p>{flight.origin} - {flight.dest}</p>
|
||||
</div>
|
||||
<div className="width-33 align-left" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="float-left valign-middle">
|
||||
{this.renderFlightScore(flight.assessment.overall_score)}
|
||||
<div className="float-left valign-middle margin-left-5">
|
||||
<OverlayTrigger
|
||||
trigger="hover"
|
||||
placement="right"
|
||||
overlay={this.getPopover(this.props,flight.assessment)}>
|
||||
<img src={info} alt="?" />
|
||||
</OverlayTrigger>
|
||||
</div>
|
||||
<div style={{clear: "both"}} />
|
||||
</div>
|
||||
<div className="align-right margin-top-25">
|
||||
<button>Select</button>
|
||||
</div>
|
||||
<div style={{clear: "both"}} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,230 +0,0 @@
|
|||
import React, {Component} from 'react';
|
||||
import Select from 'react-select';
|
||||
import { SegmentedControl } from 'segmented-control'
|
||||
import DatePicker from "react-datepicker";
|
||||
import "react-datepicker/dist/react-datepicker.css";
|
||||
import calendar from '../images/calendar.png';
|
||||
|
||||
export default class FlightSearch extends Component {
|
||||
|
||||
state = {
|
||||
type: 0,
|
||||
airlines: [],
|
||||
airports: [],
|
||||
selectedOriginOption: null,
|
||||
selectedDestinationOption: null,
|
||||
count_options: [{ value: 0, label: "0" }, { value: 1, label: "1" }, { value: 2, label: "2" }],
|
||||
selectedAdultOption: { value: 1, label: "1" },
|
||||
selectedChildrenOption: { value: 0, label: "0" }
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleOriginDepartureDateChange = this.handleOriginDepartureDateChange.bind(this);
|
||||
this.handleDestinationDepartureDateChange = this.handleDestinationDepartureDateChange.bind(this);
|
||||
this.executeSearch = this.executeSearch.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.loadAirports();
|
||||
this.loadAirlines();
|
||||
}
|
||||
|
||||
async loadAirlines() {
|
||||
await this.getAirlines()
|
||||
.then(res => {
|
||||
const airlineOptions = res.map(airline => ({
|
||||
value: airline.iata_code,
|
||||
label: airline.airline
|
||||
}));
|
||||
this.setState({ airlines: airlineOptions })
|
||||
})
|
||||
.catch(err => console.log(err));
|
||||
}
|
||||
|
||||
async loadAirports() {
|
||||
await this.getAirports()
|
||||
.then(res => {
|
||||
const airportOptions = res.map(airport => ({
|
||||
value: airport.iata_code,
|
||||
label: airport.airport
|
||||
}));
|
||||
this.setState({ airports: airportOptions })
|
||||
})
|
||||
.catch(err => console.log(err));
|
||||
}
|
||||
|
||||
async getAirlines() {
|
||||
const response = await fetch('/api/airlines');
|
||||
const body = await response.json();
|
||||
if (response.status !== 200) {
|
||||
throw Error(body.message)
|
||||
}
|
||||
return body;
|
||||
};
|
||||
|
||||
async getAirports() {
|
||||
const response = await fetch('/api/airports');
|
||||
const body = await response.json();
|
||||
if (response.status !== 200) {
|
||||
throw Error(body.message)
|
||||
}
|
||||
return body;
|
||||
};
|
||||
|
||||
handleTypeChange(type) {
|
||||
this.setState({type});
|
||||
}
|
||||
|
||||
handleOriginChange = selectedOriginOption => {
|
||||
this.setState({ selectedOriginOption });
|
||||
};
|
||||
|
||||
handleDestinationChange = selectedDestinationOption => {
|
||||
this.setState({ selectedDestinationOption });
|
||||
};
|
||||
|
||||
handleOriginDepartureDateChange(date) {
|
||||
this.setState({
|
||||
originDepartureDate: date
|
||||
});
|
||||
}
|
||||
|
||||
handleDestinationDepartureDateChange(date) {
|
||||
this.setState({
|
||||
destinationDepartureDate: date
|
||||
});
|
||||
}
|
||||
|
||||
getReturnDateCss() {
|
||||
let classes = "form-section float-left margin-left-10";
|
||||
|
||||
if (this.state.type === 0) {
|
||||
classes += " hidden";
|
||||
}
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
async executeSearch() {
|
||||
|
||||
const { selectedOriginOption, selectedDestinationOption} = this.state;
|
||||
|
||||
var params = {
|
||||
origin: {
|
||||
code: selectedOriginOption.value,
|
||||
name: selectedOriginOption.label
|
||||
},
|
||||
destination: {
|
||||
code: selectedDestinationOption.value,
|
||||
name: selectedDestinationOption.label
|
||||
},
|
||||
originDepartureDate: this.state.originDepartureDate
|
||||
};
|
||||
|
||||
if (this.state.type === 1) {
|
||||
params.destinationDepartureDate = this.state.destinationDepartureDate
|
||||
}
|
||||
|
||||
this.props.executeSearch(params);
|
||||
}
|
||||
|
||||
renderAirportOptions(selectedOption, handleChange) {
|
||||
return (
|
||||
<Select
|
||||
className="width-500"
|
||||
value={selectedOption}
|
||||
onChange={handleChange}
|
||||
options={this.state.airports}
|
||||
isClearable="true"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="filter-content">
|
||||
<h2>Search Flights</h2>
|
||||
<table>
|
||||
<tr colSpan="2">
|
||||
<SegmentedControl
|
||||
name="tripType"
|
||||
options={[
|
||||
{ label: "One-way", value: 0, default: true },
|
||||
{ label: "Round trip", value: 1 }
|
||||
]}
|
||||
setValue={val => this.handleTypeChange(val)}
|
||||
style={{ width: 300, color: '#003545' }}
|
||||
/>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div className="form-section">
|
||||
<p>Origin</p>
|
||||
{this.renderAirportOptions(this.state.selectedOriginOption,this.handleOriginChange)}
|
||||
</div>
|
||||
</td>
|
||||
<td >
|
||||
<div className="form-section">
|
||||
<p>Destination</p>
|
||||
{this.renderAirportOptions(this.state.selectedDestinationOption,this.handleDestinationChange)}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div>
|
||||
<div className="form-section float-left">
|
||||
<p>Departing</p>
|
||||
<div>
|
||||
<img className="float-left" src={calendar} alt="cal" />
|
||||
<DatePicker className="datepicker float-left" selected={this.state.originDepartureDate} onChange={this.handleOriginDepartureDateChange} />
|
||||
<div style={{clear: "both"}} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={this.getReturnDateCss()}>
|
||||
<p>Returning</p>
|
||||
<div>
|
||||
<img className="float-left" src={calendar} alt="cal" />
|
||||
<DatePicker className="datepicker float-left" selected={this.state.destinationDepartureDate} onChange={this.handleDestinationDepartureDateChange} />
|
||||
<div style={{clear: "both"}} />
|
||||
</div>
|
||||
</div>
|
||||
<div style={{clear: "both"}} />
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>
|
||||
<div className="form-section float-left">
|
||||
<p>Adults (18+)</p>
|
||||
<Select
|
||||
className="width-125"
|
||||
options={this.state.count_options}
|
||||
value={this.state.selectedAdultOption}
|
||||
/>
|
||||
</div>
|
||||
<div className="form-section float-left margin-left-10">
|
||||
<p>Children (0-17)</p>
|
||||
<Select
|
||||
className="width-125"
|
||||
options={this.state.count_options}
|
||||
value={this.state.selectedChildrenOption}
|
||||
/>
|
||||
</div>
|
||||
<div style={{clear: "both"}} />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan="4">
|
||||
<div className="margin-20 center">
|
||||
<button onClick={this.executeSearch}>Search</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
import React, {Component} from 'react';
|
||||
import Flight from './Flight';
|
||||
|
||||
export default class Flights extends Component {
|
||||
renderFlights() {
|
||||
return this.props.flights.map(flight => (
|
||||
<Flight flight={flight} />
|
||||
))
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="margin-top-10">
|
||||
<div>
|
||||
|
||||
</div>
|
||||
{this.renderFlights()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,196 +0,0 @@
|
|||
import React, {Component} from 'react';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
import { OverlayTrigger, Popover } from 'react-bootstrap';
|
||||
import WeatherIcon from 'react-icons-weather';
|
||||
import AirlineIcon from './AirlineIcon';
|
||||
|
||||
export default class Trip extends Component {
|
||||
|
||||
getPopover(props,assessment) {
|
||||
return(
|
||||
<Popover id="popover-basic" {...props}>
|
||||
<Popover.Title as="h3">Flight score ({assessment.overall_score}/5.0) </Popover.Title>
|
||||
<Popover.Content>
|
||||
<table cellSpacing="10" cellPadding="10">
|
||||
<tr>
|
||||
<td>
|
||||
<p className="section-label">Historical score</p>
|
||||
<p className="section-description">
|
||||
Based on historical analytics this flight has a <b>{assessment.historical_delay_percentage}%</b>
|
||||
chance of being delayed.
|
||||
</p>
|
||||
</td>
|
||||
<td className="assessment-score" align="right" valign="top">{assessment.historical_score}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p className="section-label">Weather score</p>
|
||||
</td>
|
||||
<td className="assessment-score" align="right" valign="top">{assessment.weather_score}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p className="section-label">Delay projection (minutes)</p>
|
||||
<p className="section-description">
|
||||
This flight is delay probabilty has a multiplier of <b>{assessment.weather_delay_multiplier}</b>
|
||||
due to current weather projections.
|
||||
</p>
|
||||
</td>
|
||||
<td className="assessment-score" align="right" valign="top">{assessment.projected_delay}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</Popover.Content>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
||||
getFormattedDate(dateStr) {
|
||||
let date = new Date(dateStr);
|
||||
return date.toDateString();
|
||||
}
|
||||
|
||||
getFormattedTime(time) {
|
||||
return time.match(/.{1,2}/g).join(':');
|
||||
}
|
||||
|
||||
getFormattedOffsetTime(time,offset) {
|
||||
let offsetTime = (parseInt(time) + offset).toString();
|
||||
|
||||
if (offsetTime.length === 3) {
|
||||
return this.getFormattedTime("0" + offsetTime);
|
||||
}
|
||||
|
||||
return this.getFormattedTime(offsetTime);
|
||||
}
|
||||
|
||||
getDuration(departure,arrival) {
|
||||
let delta = (parseInt(arrival) - parseInt(departure)).toString();
|
||||
return this.getFormattedDuration(delta);
|
||||
}
|
||||
|
||||
getFormattedDuration(delta) {
|
||||
if (delta.length === 4) {
|
||||
return delta.substring(0,1) + 'h ' + delta.substring(1,3) + 'm';
|
||||
}
|
||||
else {
|
||||
return delta[0] + 'h ' + delta.substring(1,3) + 'm';
|
||||
}
|
||||
}
|
||||
|
||||
renderFlightScore(assessment) {
|
||||
let cssClass = "assessment-content float-right trip-score ";
|
||||
|
||||
if (assessment.overall_score >= 4.0) {
|
||||
cssClass += "background-green";
|
||||
}
|
||||
else if (assessment.overall_score >= 2.5) {
|
||||
cssClass += "background-gray";
|
||||
|
||||
}
|
||||
else {
|
||||
cssClass += "background-red";
|
||||
}
|
||||
|
||||
return(
|
||||
<div className={cssClass}>
|
||||
<OverlayTrigger
|
||||
trigger="hover"
|
||||
placement="left"
|
||||
overlay={this.getPopover(this.props, assessment)}>
|
||||
<p>{assessment.overall_score}</p>
|
||||
</OverlayTrigger>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderTrips() {
|
||||
// This will handle round-trip rendering
|
||||
//return this.props.trip.map(trip => (
|
||||
|
||||
let trip = this.props.trip;
|
||||
|
||||
return(
|
||||
<div class="trip-content">
|
||||
<div>
|
||||
<div className="header float-left">
|
||||
Depart {trip.origin} - {trip.dest}
|
||||
<p className="sub-header">{this.getFormattedDate(trip.fl_date)}</p>
|
||||
</div>
|
||||
<div className="float-right align-right margin-right-25 weather-summary-content">
|
||||
<div>
|
||||
<div className="float-left forecast-title">{trip.forecast.description}</div>
|
||||
<div className="float-left"><WeatherIcon name="darksky" iconId={trip.forecast.icon} flip="horizontal" rotate="90" /></div>
|
||||
<div style={{clear: "both"}} />
|
||||
</div>
|
||||
<div className="align-left forecast-details">
|
||||
<div className="float-left">
|
||||
<p>Low: {trip.forecast.temp_low}</p>
|
||||
<p>High: {trip.forecast.temp_high}</p>
|
||||
</div>
|
||||
<div className="float-left margin-left-10">
|
||||
<p>Precip: {trip.forecast.precip_probability}</p>
|
||||
<p>Wind: {trip.forecast.wind_speed} mph</p>
|
||||
</div>
|
||||
<div style={{clear: "both"}} />
|
||||
</div>
|
||||
</div>
|
||||
{this.renderFlightScore(trip.assessment)}
|
||||
<div style={{clear: "both"}} />
|
||||
</div>
|
||||
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<th>Flight</th>
|
||||
<th>Departs</th>
|
||||
<th>Arrives</th>
|
||||
<th>Duration</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{trip.airline_code} {trip.fl_num}
|
||||
</td>
|
||||
<td>
|
||||
{this.getFormattedTime(trip.dep_time)}
|
||||
</td>
|
||||
<td>
|
||||
{this.getFormattedTime(trip.arr_time)}
|
||||
</td>
|
||||
<td>
|
||||
{this.getDuration(trip.dep_time,trip.arr_time)}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<AirlineIcon code={trip.airline_code} name={trip.airline} />
|
||||
</td>
|
||||
<td>
|
||||
<div className="estimation-content">
|
||||
<p>Estimated</p>
|
||||
{this.getFormattedOffsetTime(trip.dep_time,trip.assessment.projected_delay)}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div className="estimation-content">
|
||||
<p>Estimated</p>
|
||||
{this.getFormattedOffsetTime(trip.arr_time,trip.assessment.projected_delay)}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
);
|
||||
//))
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="item-content">
|
||||
{this.renderTrips()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
import React, {Component} from 'react';
|
||||
import Trip from './Trip';
|
||||
|
||||
export default class Trips extends Component {
|
||||
renderTrips() {
|
||||
|
||||
return this.props.trips.map(trip => (
|
||||
<Trip trip={trip} />
|
||||
))
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="margin-top-10">
|
||||
{this.renderTrips()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
Przed Szerokość: | Wysokość: | Rozmiar: 5.0 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 1.6 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 5.5 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 8.3 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 1.5 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 4.5 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 4.7 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 5.5 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 5.9 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 7.7 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 6.3 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 6.7 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 1.8 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 15 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 5.3 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 6.4 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 6.7 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 2.2 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 1.2 KiB |
|
@ -1,13 +0,0 @@
|
|||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import * as serviceWorker from './serviceWorker';
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById('root'));
|
||||
|
||||
// If you want your app to work offline and load faster, you can change
|
||||
// unregister() to register() below. Note this comes with some pitfalls.
|
||||
// Learn more about service workers: https://bit.ly/CRA-PWA
|
||||
serviceWorker.unregister();
|
Przed Szerokość: | Wysokość: | Rozmiar: 6.2 KiB |
|
@ -1,137 +0,0 @@
|
|||
// This optional code is used to register a service worker.
|
||||
// register() is not called by default.
|
||||
|
||||
// This lets the app load faster on subsequent visits in production, and gives
|
||||
// it offline capabilities. However, it also means that developers (and users)
|
||||
// will only see deployed updates on subsequent visits to a page, after all the
|
||||
// existing tabs open on the page have been closed, since previously cached
|
||||
// resources are updated in the background.
|
||||
|
||||
// To learn more about the benefits of this model and instructions on how to
|
||||
// opt-in, read https://bit.ly/CRA-PWA
|
||||
|
||||
const isLocalhost = Boolean(
|
||||
window.location.hostname === 'localhost' ||
|
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === '[::1]' ||
|
||||
// 127.0.0.0/8 are considered localhost for IPv4.
|
||||
window.location.hostname.match(
|
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||
)
|
||||
);
|
||||
|
||||
export function register(config) {
|
||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||
// The URL constructor is available in all browsers that support SW.
|
||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
||||
if (publicUrl.origin !== window.location.origin) {
|
||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||
// from what our page is served on. This might happen if a CDN is used to
|
||||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||
|
||||
if (isLocalhost) {
|
||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||
checkValidServiceWorker(swUrl, config);
|
||||
|
||||
// Add some additional logging to localhost, pointing developers to the
|
||||
// service worker/PWA documentation.
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
'This web app is being served cache-first by a service ' +
|
||||
'worker. To learn more, visit https://bit.ly/CRA-PWA'
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// Is not localhost. Just register service worker
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function registerValidSW(swUrl, config) {
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then(registration => {
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing;
|
||||
if (installingWorker == null) {
|
||||
return;
|
||||
}
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === 'installed') {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the updated precached content has been fetched,
|
||||
// but the previous service worker will still serve the older
|
||||
// content until all client tabs are closed.
|
||||
console.log(
|
||||
'New content is available and will be used when all ' +
|
||||
'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
|
||||
);
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onUpdate) {
|
||||
config.onUpdate(registration);
|
||||
}
|
||||
} else {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log('Content is cached for offline use.');
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onSuccess) {
|
||||
config.onSuccess(registration);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error during service worker registration:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function checkValidServiceWorker(swUrl, config) {
|
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl, {
|
||||
headers: { 'Service-Worker': 'script' }
|
||||
})
|
||||
.then(response => {
|
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (
|
||||
response.status === 404 ||
|
||||
(contentType != null && contentType.indexOf('javascript') === -1)
|
||||
) {
|
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Service worker found. Proceed as normal.
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.log(
|
||||
'No internet connection found. App is running in offline mode.'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function unregister() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||
// allows you to do things like:
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import '@testing-library/jest-dom/extend-expect';
|
|
@ -1,35 +0,0 @@
|
|||
var mariadb = require('mariadb');
|
||||
require('dotenv').config();
|
||||
|
||||
// SSL (e.g. SkySQL) connections
|
||||
// * Remember to change the location of "skysql_chain.pem" to wherever you placed it!
|
||||
// * To use just uncomment the two lines below and the 'ssl' property (and value) within the connection pool configuration
|
||||
|
||||
//const fs = require("fs");
|
||||
//const serverCert = [fs.readFileSync("skysql_chain.pem", "utf8")];
|
||||
|
||||
const pool = mariadb.createPool({
|
||||
host: process.env.DB_HOST,
|
||||
user: process.env.DB_USER,
|
||||
password: process.env.DB_PASS,
|
||||
port: process.env.DB_PORT,
|
||||
multipleStatements: true,
|
||||
connectionLimit: 5
|
||||
/*
|
||||
,ssl: {
|
||||
ca: serverCert
|
||||
}*/
|
||||
});
|
||||
|
||||
|
||||
module.exports={
|
||||
getConnection: function(){
|
||||
return new Promise(function(resolve,reject){
|
||||
pool.getConnection().then(function(connection){
|
||||
resolve(connection);
|
||||
}).catch(function(error){
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,818 +0,0 @@
|
|||
{
|
||||
"name": "bookings",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@types/geojson": {
|
||||
"version": "7946.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz",
|
||||
"integrity": "sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ=="
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "13.9.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.9.5.tgz",
|
||||
"integrity": "sha512-hkzMMD3xu6BrJpGVLeQ3htQQNAcOrJjX7WFmtK8zWQpz2UJf13LCFF2ALA7c9OVdvc2vQJeDdjfR35M0sBCxvw=="
|
||||
},
|
||||
"accepts": {
|
||||
"version": "1.3.7",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
|
||||
"integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
|
||||
"requires": {
|
||||
"mime-types": "~2.1.24",
|
||||
"negotiator": "0.6.2"
|
||||
}
|
||||
},
|
||||
"ansi-regex": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
|
||||
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"array-flatten": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
|
||||
},
|
||||
"body-parser": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
|
||||
"integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
|
||||
"requires": {
|
||||
"bytes": "3.1.0",
|
||||
"content-type": "~1.0.4",
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"http-errors": "1.7.2",
|
||||
"iconv-lite": "0.4.24",
|
||||
"on-finished": "~2.3.0",
|
||||
"qs": "6.7.0",
|
||||
"raw-body": "2.4.0",
|
||||
"type-is": "~1.6.17"
|
||||
}
|
||||
},
|
||||
"bytes": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
|
||||
"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
|
||||
},
|
||||
"camelcase": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cliui": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
|
||||
"integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
|
||||
"requires": {
|
||||
"string-width": "^3.1.0",
|
||||
"strip-ansi": "^5.2.0",
|
||||
"wrap-ansi": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||
},
|
||||
"concurrently": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-5.1.0.tgz",
|
||||
"integrity": "sha512-9ViZMu3OOCID3rBgU31mjBftro2chOop0G2u1olq1OuwRBVRw/GxHTg80TVJBUTJfoswMmEUeuOg1g1yu1X2dA==",
|
||||
"requires": {
|
||||
"chalk": "^2.4.2",
|
||||
"date-fns": "^2.0.1",
|
||||
"lodash": "^4.17.15",
|
||||
"read-pkg": "^4.0.1",
|
||||
"rxjs": "^6.5.2",
|
||||
"spawn-command": "^0.0.2-1",
|
||||
"supports-color": "^6.1.0",
|
||||
"tree-kill": "^1.2.2",
|
||||
"yargs": "^13.3.0"
|
||||
}
|
||||
},
|
||||
"content-disposition": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
|
||||
"integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
|
||||
"requires": {
|
||||
"safe-buffer": "5.1.2"
|
||||
}
|
||||
},
|
||||
"content-type": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
|
||||
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
|
||||
},
|
||||
"cookie": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
|
||||
"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
|
||||
},
|
||||
"cookie-signature": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
|
||||
},
|
||||
"date-fns": {
|
||||
"version": "2.11.1",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.11.1.tgz",
|
||||
"integrity": "sha512-3RdUoinZ43URd2MJcquzBbDQo+J87cSzB8NkXdZiN5ia1UNyep0oCyitfiL88+R7clGTeq/RniXAc16gWyAu1w=="
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"decamelize": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
|
||||
},
|
||||
"denque": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz",
|
||||
"integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ=="
|
||||
},
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
|
||||
},
|
||||
"destroy": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
||||
},
|
||||
"dotenv": {
|
||||
"version": "8.2.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
|
||||
"integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="
|
||||
},
|
||||
"ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
|
||||
},
|
||||
"emoji-regex": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
|
||||
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
|
||||
},
|
||||
"encodeurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
|
||||
},
|
||||
"error-ex": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
||||
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
|
||||
"requires": {
|
||||
"is-arrayish": "^0.2.1"
|
||||
}
|
||||
},
|
||||
"escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||
},
|
||||
"etag": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
|
||||
},
|
||||
"express": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
|
||||
"integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
|
||||
"requires": {
|
||||
"accepts": "~1.3.7",
|
||||
"array-flatten": "1.1.1",
|
||||
"body-parser": "1.19.0",
|
||||
"content-disposition": "0.5.3",
|
||||
"content-type": "~1.0.4",
|
||||
"cookie": "0.4.0",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"finalhandler": "~1.1.2",
|
||||
"fresh": "0.5.2",
|
||||
"merge-descriptors": "1.0.1",
|
||||
"methods": "~1.1.2",
|
||||
"on-finished": "~2.3.0",
|
||||
"parseurl": "~1.3.3",
|
||||
"path-to-regexp": "0.1.7",
|
||||
"proxy-addr": "~2.0.5",
|
||||
"qs": "6.7.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"safe-buffer": "5.1.2",
|
||||
"send": "0.17.1",
|
||||
"serve-static": "1.14.1",
|
||||
"setprototypeof": "1.1.1",
|
||||
"statuses": "~1.5.0",
|
||||
"type-is": "~1.6.18",
|
||||
"utils-merge": "1.0.1",
|
||||
"vary": "~1.1.2"
|
||||
}
|
||||
},
|
||||
"finalhandler": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
|
||||
"integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
|
||||
"requires": {
|
||||
"debug": "2.6.9",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"on-finished": "~2.3.0",
|
||||
"parseurl": "~1.3.3",
|
||||
"statuses": "~1.5.0",
|
||||
"unpipe": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"find-up": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
|
||||
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
|
||||
"requires": {
|
||||
"locate-path": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"forwarded": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
|
||||
"integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
|
||||
},
|
||||
"fresh": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
|
||||
},
|
||||
"get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
|
||||
},
|
||||
"hosted-git-info": {
|
||||
"version": "2.8.8",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
|
||||
"integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg=="
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
|
||||
"integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
|
||||
"requires": {
|
||||
"depd": "~1.1.2",
|
||||
"inherits": "2.0.3",
|
||||
"setprototypeof": "1.1.1",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"toidentifier": "1.0.0"
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
},
|
||||
"ipaddr.js": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
|
||||
"integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA=="
|
||||
},
|
||||
"is-arrayish": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
|
||||
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
|
||||
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
|
||||
},
|
||||
"json-parse-better-errors": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
|
||||
"integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
|
||||
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
|
||||
"requires": {
|
||||
"p-locate": "^3.0.0",
|
||||
"path-exists": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
|
||||
},
|
||||
"long": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
|
||||
},
|
||||
"mariadb": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/mariadb/-/mariadb-2.3.1.tgz",
|
||||
"integrity": "sha512-suv+ygoiS+tQSKmxgzJsGV9R+USN8g6Ql+GuMo9k7alD6FxOT/lwebLHy63/7yPZfVtlyAitK1tPd7ZoFhN/Sg==",
|
||||
"requires": {
|
||||
"@types/geojson": "^7946.0.7",
|
||||
"@types/node": ">=8.0.0",
|
||||
"denque": "^1.4.1",
|
||||
"iconv-lite": "^0.5.1",
|
||||
"long": "^4.0.0",
|
||||
"moment-timezone": "^0.5.27"
|
||||
},
|
||||
"dependencies": {
|
||||
"iconv-lite": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.1.tgz",
|
||||
"integrity": "sha512-ONHr16SQvKZNSqjQT9gy5z24Jw+uqfO02/ngBSBoqChZ+W8qXX7GPRa1RoUnzGADw8K63R1BXUMzarCVQBpY8Q==",
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
|
||||
},
|
||||
"merge-descriptors": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
||||
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
|
||||
},
|
||||
"methods": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
||||
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
|
||||
},
|
||||
"mime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.43.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
|
||||
"integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.26",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
|
||||
"integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==",
|
||||
"requires": {
|
||||
"mime-db": "1.43.0"
|
||||
}
|
||||
},
|
||||
"moment": {
|
||||
"version": "2.24.0",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
|
||||
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
|
||||
},
|
||||
"moment-timezone": {
|
||||
"version": "0.5.28",
|
||||
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.28.tgz",
|
||||
"integrity": "sha512-TDJkZvAyKIVWg5EtVqRzU97w0Rb0YVbfpqyjgu6GwXCAohVRqwZjf4fOzDE6p1Ch98Sro/8hQQi65WDXW5STPw==",
|
||||
"requires": {
|
||||
"moment": ">= 2.9.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"negotiator": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
|
||||
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
|
||||
},
|
||||
"normalize-package-data": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
|
||||
"integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
|
||||
"requires": {
|
||||
"hosted-git-info": "^2.1.4",
|
||||
"resolve": "^1.10.0",
|
||||
"semver": "2 || 3 || 4 || 5",
|
||||
"validate-npm-package-license": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"on-finished": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
||||
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
|
||||
"requires": {
|
||||
"ee-first": "1.1.1"
|
||||
}
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz",
|
||||
"integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==",
|
||||
"requires": {
|
||||
"p-try": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"p-locate": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
|
||||
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
|
||||
"requires": {
|
||||
"p-limit": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"p-try": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
|
||||
},
|
||||
"parse-json": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
|
||||
"integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
|
||||
"requires": {
|
||||
"error-ex": "^1.3.1",
|
||||
"json-parse-better-errors": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"parseurl": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
|
||||
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
|
||||
},
|
||||
"path-parse": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
|
||||
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
|
||||
},
|
||||
"path-to-regexp": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
||||
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
|
||||
},
|
||||
"pify": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
|
||||
},
|
||||
"proxy-addr": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz",
|
||||
"integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==",
|
||||
"requires": {
|
||||
"forwarded": "~0.1.2",
|
||||
"ipaddr.js": "1.9.0"
|
||||
}
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
|
||||
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
|
||||
},
|
||||
"range-parser": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
|
||||
},
|
||||
"raw-body": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
|
||||
"integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
|
||||
"requires": {
|
||||
"bytes": "3.1.0",
|
||||
"http-errors": "1.7.2",
|
||||
"iconv-lite": "0.4.24",
|
||||
"unpipe": "1.0.0"
|
||||
}
|
||||
},
|
||||
"read-pkg": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz",
|
||||
"integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=",
|
||||
"requires": {
|
||||
"normalize-package-data": "^2.3.2",
|
||||
"parse-json": "^4.0.0",
|
||||
"pify": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
|
||||
},
|
||||
"require-main-filename": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
|
||||
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.15.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz",
|
||||
"integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==",
|
||||
"requires": {
|
||||
"path-parse": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "6.5.4",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz",
|
||||
"integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==",
|
||||
"requires": {
|
||||
"tslib": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
|
||||
},
|
||||
"send": {
|
||||
"version": "0.17.1",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
|
||||
"integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
|
||||
"requires": {
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"destroy": "~1.0.4",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "~1.7.2",
|
||||
"mime": "1.6.0",
|
||||
"ms": "2.1.1",
|
||||
"on-finished": "~2.3.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"statuses": "~1.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ms": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
|
||||
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve-static": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
|
||||
"integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
|
||||
"requires": {
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"parseurl": "~1.3.3",
|
||||
"send": "0.17.1"
|
||||
}
|
||||
},
|
||||
"set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
|
||||
},
|
||||
"setprototypeof": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
|
||||
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
|
||||
},
|
||||
"spawn-command": {
|
||||
"version": "0.0.2-1",
|
||||
"resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz",
|
||||
"integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A="
|
||||
},
|
||||
"spdx-correct": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
|
||||
"integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
|
||||
"requires": {
|
||||
"spdx-expression-parse": "^3.0.0",
|
||||
"spdx-license-ids": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"spdx-exceptions": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
|
||||
"integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA=="
|
||||
},
|
||||
"spdx-expression-parse": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
|
||||
"integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
|
||||
"requires": {
|
||||
"spdx-exceptions": "^2.1.0",
|
||||
"spdx-license-ids": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"spdx-license-ids": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
|
||||
"integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q=="
|
||||
},
|
||||
"statuses": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
|
||||
},
|
||||
"string-width": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
|
||||
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
|
||||
"requires": {
|
||||
"emoji-regex": "^7.0.1",
|
||||
"is-fullwidth-code-point": "^2.0.0",
|
||||
"strip-ansi": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
|
||||
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
|
||||
"requires": {
|
||||
"ansi-regex": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
|
||||
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"toidentifier": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
||||
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
|
||||
},
|
||||
"tree-kill": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
|
||||
"integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="
|
||||
},
|
||||
"tslib": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
|
||||
"integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA=="
|
||||
},
|
||||
"type-is": {
|
||||
"version": "1.6.18",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
|
||||
"requires": {
|
||||
"media-typer": "0.3.0",
|
||||
"mime-types": "~2.1.24"
|
||||
}
|
||||
},
|
||||
"unpipe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
|
||||
},
|
||||
"utils-merge": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
|
||||
},
|
||||
"validate-npm-package-license": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
|
||||
"integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
|
||||
"requires": {
|
||||
"spdx-correct": "^3.0.0",
|
||||
"spdx-expression-parse": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
|
||||
},
|
||||
"which-module": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
|
||||
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
|
||||
},
|
||||
"wrap-ansi": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
|
||||
"integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.0",
|
||||
"string-width": "^3.0.0",
|
||||
"strip-ansi": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"y18n": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
|
||||
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
|
||||
},
|
||||
"yargs": {
|
||||
"version": "13.3.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
|
||||
"integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
|
||||
"requires": {
|
||||
"cliui": "^5.0.0",
|
||||
"find-up": "^3.0.0",
|
||||
"get-caller-file": "^2.0.1",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^2.0.0",
|
||||
"set-blocking": "^2.0.0",
|
||||
"string-width": "^3.0.0",
|
||||
"which-module": "^2.0.0",
|
||||
"y18n": "^4.0.0",
|
||||
"yargs-parser": "^13.1.2"
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "13.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
|
||||
"integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
|
||||
"requires": {
|
||||
"camelcase": "^5.0.0",
|
||||
"decamelize": "^1.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"name": "bookings",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"start": "concurrently \"npm run server\" \"npm run client\"",
|
||||
"server": "node server.js",
|
||||
"client": "npm start --prefix client"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"body-parser": "^1.19.0",
|
||||
"concurrently": "^5.1.0",
|
||||
"dotenv": "^8.2.0",
|
||||
"express": "^4.17.1",
|
||||
"mariadb": "^2.3.1"
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
let express = require("express"),
|
||||
router = express.Router(),
|
||||
pool = require('../db');
|
||||
|
||||
// GET all airlines
|
||||
router.get("/", async (req, res, next) => {
|
||||
let conn;
|
||||
try {
|
||||
conn = await pool.getConnection();
|
||||
var query = "select * from innodb_schmema.airlines order by airline";
|
||||
var rows = await conn.query(query);
|
||||
res.send(rows);
|
||||
throw err;
|
||||
} finally {
|
||||
if (conn) return conn.release();
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
|
@ -1,22 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
let express = require("express"),
|
||||
router = express.Router(),
|
||||
pool = require('../db');
|
||||
|
||||
// GET all airports
|
||||
router.get("/", async (req, res, next) => {
|
||||
let conn;
|
||||
try {
|
||||
conn = await pool.getConnection();
|
||||
var query = "select iata_code, airport from innodb_schema.airports group by airport, iata_code order by airport";
|
||||
var rows = await conn.query(query);
|
||||
res.send(rows);
|
||||
} catch (err) {
|
||||
throw err;
|
||||
} finally {
|
||||
if (conn) return conn.release();
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
|
@ -1,129 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
let express = require("express"),
|
||||
router = express.Router(),
|
||||
pool = require('../db');
|
||||
|
||||
router.get("/", async (req, res, next) => {
|
||||
let date = new Date(req.query.dt);
|
||||
let origin = req.query.o;
|
||||
let dest = req.query.d;
|
||||
let year = date.getFullYear();
|
||||
let month = date.getMonth() + 1;
|
||||
let day = date.getDate();
|
||||
|
||||
// ignore time offsets
|
||||
let formattedDate = formatDate(year,month,day);
|
||||
//let formattedDate = date;
|
||||
|
||||
let conn;
|
||||
try {
|
||||
conn = await pool.getConnection();
|
||||
|
||||
var query = "select \
|
||||
a.airline, \
|
||||
t.carrier airline_code, \
|
||||
t.origin, \
|
||||
t.dest, \
|
||||
t.price, \
|
||||
a.`airline`, \
|
||||
f.dep_time, \
|
||||
f.arr_time, \
|
||||
fh.avg_delay, \
|
||||
(select avg(arr_time - dep_time) from columnstore_schema.flights \
|
||||
where month = ? and day = ? and origin = ? and dest = ? and carrier = t.carrier and year >= 2014) avg_duration, \
|
||||
fh.delayed_pct, \
|
||||
fh.cancelled_pct \
|
||||
from \
|
||||
innodb_schema.tickets t, \
|
||||
(select * from innodb_schema.flights where year = ? and month = ? and day = ?) f, \
|
||||
(select \
|
||||
a.avg_delay, \
|
||||
round(100 * (a.`delayed` / a.volume), 2) delayed_pct, \
|
||||
round(100 * (a.cancelled / a.volume), 2) cancelled_pct, \
|
||||
a.carrier \
|
||||
from \
|
||||
(select \
|
||||
count(*) volume, \
|
||||
sum(case when dep_delay > 0 then 1 else 0 end) `delayed`, \
|
||||
sum(cancelled) cancelled, \
|
||||
avg(dep_delay) avg_delay, \
|
||||
carrier \
|
||||
from \
|
||||
columnstore_schema.flights \
|
||||
where \
|
||||
year >= 2014 and \
|
||||
month = ? and day = ? and origin = ? and dest = ? group by carrier) a) fh, \
|
||||
innodb_schema.airlines a \
|
||||
where \
|
||||
t.carrier = f.carrier and \
|
||||
t.fl_date = f.fl_date and \
|
||||
t.fl_num = f.fl_num and \
|
||||
t.carrier = fh.carrier and \
|
||||
f.carrier = a.iata_code and \
|
||||
t.fl_date = ? and \
|
||||
t.origin = ? and \
|
||||
t.dest = ?";
|
||||
|
||||
var results = await conn.query(query, [month,day,origin,dest,year,month,day,month,day,origin,dest,formattedDate,origin,dest]);
|
||||
|
||||
if (results.length > 0) {
|
||||
var analyzedResults = analyzeResults(results);
|
||||
res.send(analyzedResults);
|
||||
}
|
||||
else {
|
||||
res.send(results);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
throw err;
|
||||
} finally {
|
||||
if (conn) return conn.release();
|
||||
}
|
||||
});
|
||||
|
||||
function formatDate(year,month,day) {
|
||||
if (month.length < 2)
|
||||
month = '0' + month;
|
||||
if (day.length < 2)
|
||||
day = '0' + day;
|
||||
|
||||
return [year, month, day].join('-');
|
||||
}
|
||||
|
||||
// secret (scoring) sauce
|
||||
function analyzeResults(items) {
|
||||
let prices = items.map(item => item.price)
|
||||
let average_price = getAverage(prices);
|
||||
|
||||
items.forEach(item => {
|
||||
let price_score = round(3.5 * (average_price / item.price), 1);
|
||||
let delay_score = round(5 * ((100 - item.delayed_pct)/100), 1);
|
||||
let cancel_score = round(5 * ((100 - item.cancelled_pct)/100), 1);
|
||||
let overall_score = round((price_score + delay_score + cancel_score) / 3, 1);
|
||||
|
||||
item.assessment = {
|
||||
overall_score: overall_score,
|
||||
price_score: price_score,
|
||||
delay_score: delay_score,
|
||||
delay_percentage: item.delayed_pct,
|
||||
cancel_score: cancel_score,
|
||||
cancel_percentage: item.cancelled_pct
|
||||
};
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
function getAverage(arr) {
|
||||
let reducer = (total, currentValue) => total + currentValue;
|
||||
let sum = arr.reduce(reducer)
|
||||
return sum / arr.length;
|
||||
}
|
||||
|
||||
function round(value, precision) {
|
||||
var multiplier = Math.pow(10, precision || 0);
|
||||
return Math.round(value * multiplier) / multiplier;
|
||||
}
|
||||
|
||||
module.exports = router;
|
|
@ -1,143 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
let express = require("express"),
|
||||
router = express.Router(),
|
||||
pool = require('../db');
|
||||
|
||||
router.get("/", async (req, res, next) => {
|
||||
let conn;
|
||||
try {
|
||||
conn = await pool.getConnection();
|
||||
|
||||
var query = "select \
|
||||
t.fl_num, \
|
||||
a.airline, \
|
||||
t.carrier airline_code, \
|
||||
t.fl_date, \
|
||||
t.origin, \
|
||||
t.dest, \
|
||||
f.dep_time, \
|
||||
f.arr_time, \
|
||||
fh.delayed_pct, \
|
||||
fh.avg_delay \
|
||||
from \
|
||||
innodb_schema.trips tr inner join \
|
||||
innodb_schema.tickets t on tr.ticket_id = t.id inner join \
|
||||
innodb_schema.airlines a on t.carrier = a.iata_code, \
|
||||
(select * from innodb_schema.flights where year >= 2020) f, \
|
||||
(select \
|
||||
a.avg_delay, \
|
||||
round(100 * (a.`delayed` / a.volume), 2) delayed_pct, \
|
||||
round(100 * (a.cancelled / a.volume), 2) cancelled_pct, \
|
||||
a.carrier, \
|
||||
a.day, \
|
||||
a.month \
|
||||
from \
|
||||
(select \
|
||||
count(*) volume, \
|
||||
sum(case when dep_delay > 0 then 1 else 0 end) `delayed`, \
|
||||
sum(cancelled) cancelled, \
|
||||
avg(dep_delay) avg_delay, \
|
||||
carrier, \
|
||||
month, \
|
||||
day \
|
||||
from \
|
||||
columnstore_schema.flights \
|
||||
where \
|
||||
year >= 2014 and \
|
||||
month in (select month(fl_date) from innodb_schema.trips tr inner join innodb_schema.tickets t on tr.ticket_id = t.id) and \
|
||||
day in (select day(fl_date) from innodb_schema.trips tr inner join innodb_schema.tickets t on tr.ticket_id = t.id) \
|
||||
group by \
|
||||
day, \
|
||||
month, \
|
||||
carrier) a) fh \
|
||||
where \
|
||||
t.carrier = f.carrier and \
|
||||
t.fl_date = f.fl_date and \
|
||||
t.fl_num = f.fl_num and \
|
||||
t.carrier = fh.carrier and \
|
||||
fh.month = month(t.fl_date) and \
|
||||
fh.day = day(t.fl_date)";
|
||||
|
||||
var results = await conn.query(query);
|
||||
|
||||
if (results.length > 0) {
|
||||
var analyzedResults = analyzeResults(results);
|
||||
res.send(analyzedResults);
|
||||
}
|
||||
else {
|
||||
res.send(results);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
throw err;
|
||||
} finally {
|
||||
if (conn) return conn.release();
|
||||
}
|
||||
});
|
||||
|
||||
// secret (scoring) sauce
|
||||
function analyzeResults(items) {
|
||||
items.forEach(item => {
|
||||
let forecast = forecasts[item.origin + "_" + item.fl_date.toISOString().substring(0, 10)];
|
||||
|
||||
// Catch all in case the forecast hasn't been updated
|
||||
if (forecast === undefined) {
|
||||
forecast = {
|
||||
description: "Clear",
|
||||
icon: "clear-day",
|
||||
temp_low: "55°F",
|
||||
temp_high: "55°F",
|
||||
precip_probability: 0.2,
|
||||
wind_speed: 10
|
||||
};
|
||||
}
|
||||
|
||||
let weather_score = 5 - 5*(forecast.precip_probability + (forecast.wind_speed/100));
|
||||
let historical_score = round(5 * ((100 - item.delayed_pct)/100), 1);
|
||||
let overall_score = round((weather_score + historical_score) / 2, 1);
|
||||
let weather_delay_multiplier = round((forecast.precip_probability + (forecast.wind_speed/100)) * 5, 3);
|
||||
let projected_delay = round(weather_delay_multiplier * item.avg_delay, 0);
|
||||
|
||||
item.assessment = {
|
||||
overall_score: overall_score,
|
||||
historical_score: historical_score,
|
||||
historical_delay_percentage: item.delayed_pct,
|
||||
weather_score: weather_score,
|
||||
weather_delay_multiplier: weather_delay_multiplier,
|
||||
projected_delay: projected_delay
|
||||
};
|
||||
|
||||
item.forecast = forecast;
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
function round(value, precision) {
|
||||
var multiplier = Math.pow(10, precision || 0);
|
||||
return Math.round(value * multiplier) / multiplier;
|
||||
}
|
||||
|
||||
// You can either tie into an existing Weather Forecast API
|
||||
// or provide hard-coded lookups like the following.
|
||||
var forecasts = {
|
||||
"ORD_2020-02-27": {
|
||||
description: "Snow",
|
||||
icon: "snow",
|
||||
temp_low: "-2°C",
|
||||
temp_high: "-1°C",
|
||||
precip_probability: .6,
|
||||
wind_speed: 15
|
||||
},
|
||||
"LAX_2020-02-28": {
|
||||
description: "Clear",
|
||||
icon: "clear-day",
|
||||
temp_low: "13°C",
|
||||
temp_high: "15°C",
|
||||
precip_probability: 0,
|
||||
wind_speed: 5
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = router;
|
|
@ -1,34 +0,0 @@
|
|||
const express = require('express');
|
||||
const app = express();
|
||||
const port = 8080;
|
||||
const path = require('path');
|
||||
const bodyParser = require("body-parser");
|
||||
|
||||
const airportsRoutes = require("./routes/airportsRoutes");
|
||||
const airlinesRoutes = require("./routes/airlinesRoutes");
|
||||
const flightsRoutes = require("./routes/flightsRoutes");
|
||||
const tripsRoutes = require("./routes/tripsRoutes");
|
||||
|
||||
app.use(bodyParser.json());
|
||||
app.use(bodyParser.urlencoded({ extended: false }));
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
app.use(express.static('client/build'));
|
||||
}
|
||||
|
||||
app.use("/api/airports", airportsRoutes);
|
||||
app.use("/api/airlines", airlinesRoutes);
|
||||
app.use("/api/flights", flightsRoutes);
|
||||
app.use("/api/trips", tripsRoutes);
|
||||
|
||||
app.get("/*", (req, res) => {
|
||||
res.sendFile(path.join(__dirname, "/client/build/index.html"));
|
||||
});
|
||||
|
||||
app.use((err, req, res, next) => {
|
||||
res.status(422).send({ error: err._message });
|
||||
});
|
||||
|
||||
// console.log that your server is up and running
|
||||
app.listen(port, () => console.log(`Listening on port ${port}`));
|
||||
|
|
@ -2,165 +2,3 @@
|
|||
|
||||
This application is no longer being maintained here. It has been moved to [**this repository**](https://github.com/mariadb-corporation/dev-example-flights).
|
||||
|
||||
# Flights
|
||||
|
||||
**Flights** is a web application written in [React.js](https://reactjs.org) and [Node.js](https://nodejs.org) that, backed by the power of the [MariaDB Node.js Connector](https://github.com/MariaDB/mariadb-connector-nodejs) and [MariaDB ColumnStore database](https://mariadb.com/docs/features/mariadb-columnstore/), allows you to analyze over 180 million [flight records from the United States Department of Transportation](https://www.transtats.bts.gov/DL_SelectFields.asp?Table_ID=236&DB_Short_Name=On-Time) in real time without needing to add any indexes!
|
||||
|
||||
<p align="center" spacing="10">
|
||||
<kbd>
|
||||
<img src="media/demo.gif" />
|
||||
</kbd>
|
||||
</p>
|
||||
|
||||
The following will walk you through the steps for getting this application up and running (locally) within minutes! This application is completely open source. Please feel free to use it and the source code as you see fit.
|
||||
|
||||
# Table of Contents
|
||||
1. [Environment and Compatibility](#compatibility)
|
||||
2. [Getting started with MariaDB](#overview)
|
||||
1. [The Basics](#intro-mariadb)
|
||||
2. [Downloading and installing MariaDB ColumnStore](#installation)
|
||||
3. [Requirements](#requirements)
|
||||
4. [Getting started with the app](#getting-started)
|
||||
1. [Get the data, create the schema, and load the data](#data)
|
||||
1. [Grab the code](#grab-code)
|
||||
2. [Build the code](#build-code)
|
||||
3. [Run the app](#run-app)
|
||||
5. [Support and Contribution](#support-contribution)
|
||||
6. [License](#license)
|
||||
|
||||
## Environment and Compatibility <a name="compatibility"></a>
|
||||
|
||||
This sample was created using the following techologies:
|
||||
|
||||
* [MariaDB](https://mariadb.com/products/mariadb-platform/)
|
||||
* [React.js (v.16.12.0)](https://github.com/facebook/react/blob/master/CHANGELOG.md#16120-november-14-2019)
|
||||
* [Node.js (v.12.x)](https://nodejs.org/docs/latest-v12.x/api/index.html)
|
||||
* [NPM (v.6.11.3)](https://docs.npmjs.com/)
|
||||
|
||||
This application was tested on [macOS Mojave v.10.14.6](https://developer.apple.com/documentation/macos_release_notes/macos_mojave_10_14_6_release_notes).
|
||||
|
||||
## Overview <a name="overview"></a>
|
||||
|
||||
### Introduction to MariaDB <a name="intro-mariadb"></a>
|
||||
|
||||
[MariaDB platform](https://mariadb.com/products/mariadb-platform/) unifies [MariaDB TX (transactions)](https://mariadb.com/products/mariadb-platform-transactional/) and [MariaDB AX (analytics)](https://mariadb.com/products/mariadb-platform-analytical/) so transactional applications can retain unlimited historical data and leverage powerful, real-time analytics in order to provide data-driven customers with more information, actionable insight and greater value – and businesses with endless ways to monetize data. It is the enterprise open source database for hybrid transactional/analytical processing at scale.
|
||||
|
||||
<p align="center">
|
||||
<kbd>
|
||||
<img src="media/platform.png" />
|
||||
</kbd>
|
||||
</p>
|
||||
|
||||
### Downloading and installing MariaDB ColumnStore <a name="installation"></a>
|
||||
|
||||
[MariaDB ColumnStore](https://mariadb.com/docs/features/mariadb-columnstore/) extends [MariaDB Server](https://mariadb.com/products/) with distributed storage and massively parallel processing to support scalable, high-performance analytics. It can be deployed as the analytics component of MariaDB Platform using MariaDB MaxScale for change-data-capture and hybrid transactional/analytical query routing, or as a standalone columnar database for interactive, ad hoc analytics at scale. You can find more information on how to download and install ColumnStore [here](https://mariadb.com/downloads/#mariadb_platform-mariadb_columnstore).
|
||||
|
||||
## Requirements <a name="requirements"></a>
|
||||
|
||||
This project assumes you have familiarity with building web applications using ReactJS and NodeJS technologies.
|
||||
|
||||
* Download and install [MariaDB ColumnStore database](https://go.mariadb.com/download-mariadb-server-community.html?utm_source=google&utm_medium=ppc&utm_campaign=MKG-Search-Google-Branded-DL-NA-Server-DL&gclid=CjwKCAiAwZTuBRAYEiwAcr67OUBIqnFBo9rUBhYql3VZV_nhlSKzkwoUv7vhA6gwNdGoBSc2uWe7SBoCX_oQAvD_BwE).
|
||||
* Download and install [NodeJS](https://nodejs.org/).
|
||||
* git (Optional) - this is required if you would prefer to pull the source code from GitHub repo.
|
||||
- Create a [free github account](https://github.com/) if you don’t already have one
|
||||
- git can be downloaded from git-scm.org
|
||||
|
||||
## Getting started <a name="getting-started"></a>
|
||||
|
||||
### Get the data, create the schema, and load the data <a name="data"></a>
|
||||
|
||||
Instructions on retrieving and importing the flights dataset into a MariaDB ColumnStore database can be [here](https://github.com/mariadb-corporation/mariadb-columnstore-samples/tree/master/flights). Please note that he scripts provided within that repository only targets data for the year 2019 (~7.5 million records).
|
||||
|
||||
If you'd like to retrieve data spanning from 1990 to 2019 (~180 million records) please use the following scripts:
|
||||
|
||||
* [get_flight_data.sh](data/get_flight_data.sh)
|
||||
* [create_flights_db.sh](data/create_flights_db.sh)
|
||||
* [load_flights_data.sh](data/load_flights_data.sh)
|
||||
|
||||
### Grab the code <a name="grab-code"></a>
|
||||
|
||||
Download this code directly or use [git](git-scm.org) (through CLI or a client) to retrieve the code.
|
||||
|
||||
### Configure the code <a name="configure-code"></a>
|
||||
|
||||
Configure the MariaDB connection by [adding an .env file to the Node.js project](https://github.com/mariadb-corporation/mariadb-connector-nodejs/blob/master/documentation/promise-api.md#security-consideration).
|
||||
|
||||
Example implementation:
|
||||
|
||||
```
|
||||
DB_HOST=<host_address>
|
||||
DB_PORT=<port_number>
|
||||
DB_USER=<username>
|
||||
DB_PASS=<password>
|
||||
DB_NAME=<database>
|
||||
```
|
||||
|
||||
The environmental variables from `.env` are used within the [db.js](src/db.js) for the MariaDB Node.js Connector configuration pool settings:
|
||||
|
||||
```javascript
|
||||
var mariadb = require('mariadb');
|
||||
require('dotenv').config();
|
||||
|
||||
const pool = mariadb.createPool({
|
||||
host: process.env.DB_HOST,
|
||||
user: process.env.DB_USER,
|
||||
password: process.env.DB_PASS,
|
||||
port: process.env.DB_PORT,
|
||||
multipleStatements: true,
|
||||
connectionLimit: 5
|
||||
});
|
||||
```
|
||||
|
||||
### Build the code <a name="build-code"></a>
|
||||
|
||||
Once you have retrieved a copy of the code you're ready to build and run the project! However, before running the code it's important to point out that the application uses several Node Packages.
|
||||
|
||||
Executing the CLI command
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
within
|
||||
|
||||
* [src](src): the Node.js project
|
||||
* [client](src/client): the React.js project
|
||||
|
||||
folders will target the the relative `package.json` file and [install all dependencies](https://docs.npmjs.com/downloading-and-installing-packages-locally).
|
||||
|
||||
### Run the app <a name="run-app"></a>
|
||||
|
||||
Once you've pulled down the code and have verified that all of the required Node packages are installed you're ready to run the application! It's as easy as 1,2,3.
|
||||
|
||||
1. Using a command line interface (CLI) navigate to the `src` directory.
|
||||
|
||||
<p align="center">
|
||||
<img src="media/cli_root.png" />
|
||||
</p>
|
||||
|
||||
2. Run the command:
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
<p align="center">
|
||||
<img src="media/npm_start.png" />
|
||||
</p>
|
||||
|
||||
3. Open a browser window and navigate to http://localhost:3000.
|
||||
|
||||
<p align="center">
|
||||
<kbd>
|
||||
<img src="media/get_started.png" />
|
||||
</kbd>
|
||||
</p>
|
||||
|
||||
## Support and Contribution <a name="support-contribution"></a>
|
||||
|
||||
Thanks so much for taking a look at the Flights app! As this is a very simple example, there's a lot of potential for customization!
|
||||
|
||||
If you have any questions, comments, or would like to contribute to this or future projects like this please reach out to us directly at developers@mariadb.com or on [Twitter](https://twitter.com/mariadb).
|
||||
|
||||
## License <a name="license"></a>
|
||||
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg?style=plastic)](https://opensource.org/licenses/Apache-2.0)
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/bash
|
||||
SCHEMA_DIR=$(readlink -f ./schema)
|
||||
# create flights database (dropping if exists) with 3 columnstore tables: flights, airports, airlines
|
||||
/usr/bin/mysql --defaults-file=/etc/my.cnf -u root -vvv < $SCHEMA_DIR/schema.sql
|
||||
# load data into dimension tables airports and airlines.
|
||||
/usr/bin/cpimport -m 2 -s ',' -E '"' flights airports -l $SCHEMA_DIR/airports.csv
|
||||
/usr/bin/cpimport -m 2 -s ',' -E '"' flights airlines -l $SCHEMA_DIR/airlines.csv
|
|
@ -1,19 +0,0 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# This script will remotely invoke the bureau of transportation statistics web form to retrieve data by month:
|
||||
# https://www.transtats.bts.gov/DL_SelectFields.asp?Table_ID=236&DB_Short_Name=On-Time
|
||||
# for the specific columns listed in the SQL and utilized by the sample schema.
|
||||
mkdir -p data
|
||||
for y in {1990..2019}; do
|
||||
for m in {1..12}; do
|
||||
yyyymm="$y-$(printf %02d $m)"
|
||||
echo "$yyyymm"
|
||||
curl -L -o data.zip -d "sqlstr=+SELECT+YEAR%2CMONTH%2CDAY_OF_MONTH%2CDAY_OF_WEEK%2CFL_DATE%2CCARRIER%2CTAIL_NUM%2CFL_NUM%2CORIGIN%2CDEST%2CCRS_DEP_TIME%2CDEP_TIME%2CDEP_DELAY%2CTAXI_OUT%2CWHEELS_OFF%2CWHEELS_ON%2CTAXI_IN%2CCRS_ARR_TIME%2CARR_TIME%2CARR_DELAY%2CCANCELLED%2CCANCELLATION_CODE%2CDIVERTED%2CCRS_ELAPSED_TIME%2CACTUAL_ELAPSED_TIME%2CAIR_TIME%2CDISTANCE%2CCARRIER_DELAY%2CWEATHER_DELAY%2CNAS_DELAY%2CSECURITY_DELAY%2CLATE_AIRCRAFT_DELAY+FROM++T_ONTIME+WHERE+Month+%3D$m+AND+YEAR%3D$y" https://www.transtats.bts.gov/DownLoad_Table.asp?Table_ID=236
|
||||
rm -f *.csv
|
||||
unzip data.zip
|
||||
rm -f data.zip
|
||||
mv *.csv $yyyymm.csv
|
||||
tail -n +2 $yyyymm.csv > data/$yyyymm.csv
|
||||
rm -f $yyyymm.csv
|
||||
done
|
||||
done
|
|
@ -1,25 +0,0 @@
|
|||
#!/bin/bash
|
||||
SCHEMA_DIR=$(readlink -f ./schema)
|
||||
# create flights database (dropping if exists) with 3 columnstore tables: flights, airports, airlines
|
||||
/usr/bin/mysql --defaults-file=/etc/my.cnf -u root -vvv < $SCHEMA_DIR/schema.sql
|
||||
# load data into dimension tables airports and airlines.
|
||||
/usr/bin/cpimport -m 2 -s ',' -E '"' flights airports -l $SCHEMA_DIR/airports.csv
|
||||
/usr/bin/cpimport -m 2 -s ',' -E '"' flights airlines -l $SCHEMA_DIR/airlines.csv
|
||||
[root@flight-demo-mdb-cs-single-0 data]# cat
|
||||
load^C
|
||||
[root@flight-demo-mdb-cs-single-0 data]# cat load_flight_data.sh
|
||||
#!/bin/bash
|
||||
# check for argument, if so use as wildcard for file load match, otherwise load everything
|
||||
DATA_DIR=$(readlink -f ./data)
|
||||
filematch="*"
|
||||
if [ $# -eq 1 ]
|
||||
then
|
||||
filematch="*$1*"
|
||||
fi
|
||||
# load the specified files under the data directory with the file pattern match
|
||||
# here we use cpimport mode 2 to force processing at each PM node which has
|
||||
# the advantage of this being runnable as a regular user with a root installation.
|
||||
for f in $DATA_DIR/$filematch.csv; do
|
||||
echo $f
|
||||
/usr/bin/cpimport -m2 -s ',' -E '"' flights flights -l $f
|
||||
done
|
Przed Szerokość: | Wysokość: | Rozmiar: 152 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 886 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 140 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 578 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 233 KiB |
|
@ -1,61 +0,0 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# next.js build output
|
||||
.next
|
|
@ -1,23 +0,0 @@
|
|||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
|
@ -1,68 +0,0 @@
|
|||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||
|
||||
## Available Scripts
|
||||
|
||||
In the project directory, you can run:
|
||||
|
||||
### `npm start`
|
||||
|
||||
Runs the app in the development mode.<br />
|
||||
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
||||
|
||||
The page will reload if you make edits.<br />
|
||||
You will also see any lint errors in the console.
|
||||
|
||||
### `npm test`
|
||||
|
||||
Launches the test runner in the interactive watch mode.<br />
|
||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
||||
|
||||
### `npm run build`
|
||||
|
||||
Builds the app for production to the `build` folder.<br />
|
||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||
|
||||
The build is minified and the filenames include the hashes.<br />
|
||||
Your app is ready to be deployed!
|
||||
|
||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
||||
|
||||
### `npm run eject`
|
||||
|
||||
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
|
||||
|
||||
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
||||
|
||||
Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
|
||||
|
||||
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
|
||||
|
||||
## Learn More
|
||||
|
||||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
||||
|
||||
To learn React, check out the [React documentation](https://reactjs.org/).
|
||||
|
||||
### Code Splitting
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
|
||||
|
||||
### Analyzing the Bundle Size
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
|
||||
|
||||
### Making a Progressive Web App
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
|
||||
|
||||
### Deployment
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
|
||||
|
||||
### `npm run build` fails to minify
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
|
|
@ -1,44 +0,0 @@
|
|||
{
|
||||
"name": "client",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@devexpress/dx-core": "^2.6.0",
|
||||
"@devexpress/dx-grid-core": "^2.6.0",
|
||||
"@devexpress/dx-react-core": "^2.6.0",
|
||||
"@devexpress/dx-react-grid": "^2.6.0",
|
||||
"@devexpress/dx-react-grid-bootstrap3": "^2.6.0",
|
||||
"@devexpress/dx-react-grid-material-ui": "^2.6.0",
|
||||
"@material-ui/core": "^4.9.8",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"material-ui": "^0.20.2",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-scripts": "3.2.0",
|
||||
"react-select": "^3.1.0",
|
||||
"recharts": "^2.0.0-beta.5"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"proxy": "http://localhost:8080"
|
||||
}
|
Przed Szerokość: | Wysokość: | Rozmiar: 15 KiB |
|
@ -1,43 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="logo192.png" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>Flights</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
Przed Szerokość: | Wysokość: | Rozmiar: 8.4 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 22 KiB |
|
@ -1,25 +0,0 @@
|
|||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
|
@ -1,177 +0,0 @@
|
|||
.app {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.app-logo {
|
||||
height: 40vmin;
|
||||
}
|
||||
|
||||
.app-header {
|
||||
background-color: #003545;
|
||||
min-height: 125px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
margin: 0px;
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sub-title-text {
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.form-header {
|
||||
background: #2F99A3;
|
||||
color: white;
|
||||
font-size: 20px;
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
}
|
||||
|
||||
.form-sub-header {
|
||||
background: #2F99A3;
|
||||
color: white;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.form-header > p {
|
||||
margin: 0px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.form-main {
|
||||
width: 75%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.form-main table {
|
||||
width: 90%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.form-content {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.form-section p {
|
||||
margin-bottom: 10px;;
|
||||
}
|
||||
|
||||
.filter-background {
|
||||
background: #E5E1E5;
|
||||
border-radius: 5px;;
|
||||
}
|
||||
|
||||
.airport-picker {
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 5px;
|
||||
background: #003545;
|
||||
border-color: #E5E1E5;
|
||||
color: #ffffff;
|
||||
font-weight: bold;
|
||||
width: 350px;
|
||||
height: 50px;
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
cursor: pointer;
|
||||
background: #96DDCF;
|
||||
}
|
||||
|
||||
.float-left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.float-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.margin-right-150 {
|
||||
margin-right: 150px;
|
||||
}
|
||||
|
||||
.charts-main {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 30px;
|
||||
border: 1px solid #c0c0c0;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.charts-title {
|
||||
font-weight: bold;
|
||||
margin: 25px;
|
||||
}
|
||||
|
||||
.float-right > button {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.form-main > div {
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.select-month {
|
||||
width: 165px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.select-year {
|
||||
width: 100px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.select-day {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.button-search {
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.width-70 {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.image-arrow {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.inline-div-50 {
|
||||
width: 50%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.margin-right-35 {
|
||||
margin-right: 35px;
|
||||
}
|
||||
|
||||
table.table-50 {
|
||||
width: 40%;
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
import React from 'react';
|
||||
import './App.css';
|
||||
import Dashboard from './components/Dashboard';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div className="app">
|
||||
<header className="app-header">
|
||||
<p className="title-text">Real-Time Flight Analytics</p>
|
||||
<p className="sub-title-text">A MariaDB ColumnStore Demo</p>
|
||||
</header>
|
||||
<Dashboard />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
|
@ -1,9 +0,0 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
|
||||
it('renders without crashing', () => {
|
||||
const div = document.createElement('div');
|
||||
ReactDOM.render(<App />, div);
|
||||
ReactDOM.unmountComponentAtNode(div);
|
||||
});
|
|
@ -1,139 +0,0 @@
|
|||
import React, {Component} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
PieChart, Pie, Legend, Tooltip, Cell,
|
||||
BarChart, Bar, XAxis, YAxis, CartesianGrid
|
||||
} from 'recharts';
|
||||
|
||||
export default class AirlineFlightsInfo extends Component {
|
||||
colors = ["#003545","#2F99A3","#ABC74A","#96DDCF",'#0E6488','#424F62'];
|
||||
|
||||
state = {
|
||||
airline_delays: [],
|
||||
delays_comparison: []
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props !== null &&
|
||||
this.props.origin !== null &&
|
||||
this.props.destination !== null &&
|
||||
this.props.airline !== null) {
|
||||
this.load(this.props);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps !== null &&
|
||||
nextProps.origin !== null &&
|
||||
nextProps.destination !== null &&
|
||||
nextProps.airline !== null) {
|
||||
this.load(nextProps);
|
||||
}
|
||||
}
|
||||
|
||||
async load(props) {
|
||||
const origin = props.origin.code;
|
||||
const dest = props.destination.code;
|
||||
const airline = props.airline.code;
|
||||
const yearFrom = props.yearFrom;
|
||||
const yearTo = props.yearTo;
|
||||
const month = props.month;
|
||||
const day = props.day;
|
||||
|
||||
await this.getAirlineDelays(origin, dest, airline, yearFrom, yearTo, month, day)
|
||||
.then(res => {
|
||||
var other = 100 - (res.carrier_delay_pct + res.weather_delay_pct + res.security_delay_pct + res.late_aircraft_delay_pct + res.nas_delay_pct);
|
||||
var airline_delays = [{name: 'Carrier', value: res.carrier_delay_pct},
|
||||
{name: 'Late Aircraft', value: res.late_aircraft_delay_pct},
|
||||
{name: 'NAS', value: res.nas_delay_pct},
|
||||
{name: 'Security', value: res.security_delay_pct},
|
||||
{name: 'Weather', value: res.weather_delay_pct},
|
||||
{name: 'Other', value: other.toFixed(2)}];
|
||||
this.setState({ airline_delays });
|
||||
})
|
||||
.catch(err => console.log(err));
|
||||
|
||||
await this.getDelaysComparison(origin, dest, airline, yearFrom, yearTo, month, day)
|
||||
.then(res => {
|
||||
var delays_comparison = [
|
||||
{name: 'Carrier', Target: res[0].carrier, Average: res[1].carrier},
|
||||
{name: 'Late Aircraft', Target: res[0].late_aircraft, Average: res[1].late_aircraft},
|
||||
{name: 'NAS', Target: res[0].nas, Average: res[1].nas},
|
||||
{name: 'Security', Target: res[0].sec, Average: res[1].sec},
|
||||
{name: 'Weather', Target: res[0].weather, Average: res[1].weather}
|
||||
];
|
||||
this.setState({ delays_comparison })
|
||||
})
|
||||
.catch(err => console.log(err));
|
||||
}
|
||||
|
||||
async getAirlineDelays(origin, dest, airline, yearFrom, yearTo, month, day) {
|
||||
const response = await fetch('/api/flights/airline_delays?o=' + origin + "&dst=" + dest + "&a=" + airline +
|
||||
"&yf=" + yearFrom + "&yt=" + yearTo + "&m=" + month + "&d=" + day);
|
||||
const body = await response.json();
|
||||
if (response.status !== 200) {
|
||||
throw Error(body.message)
|
||||
}
|
||||
return body;
|
||||
};
|
||||
|
||||
async getDelaysComparison(origin, dest, airline, yearFrom, yearTo, month, day) {
|
||||
const response = await fetch('/api/flights/delays_comparison?o=' + origin + "&dst=" + dest + "&a=" + airline +
|
||||
"&yf=" + yearFrom + "&yt=" + yearTo + "&m=" + month + "&d=" + day);
|
||||
const body = await response.json();
|
||||
if (response.status !== 200) {
|
||||
throw Error(body.message)
|
||||
}
|
||||
return body;
|
||||
};
|
||||
|
||||
render() {
|
||||
const { airline_delays, delays_comparison } = this.state;
|
||||
|
||||
return (
|
||||
<div className="charts-main">
|
||||
<div className="form-sub-header">
|
||||
{ !!(this.props.airline) ? this.props.airline.name : ''}
|
||||
</div>
|
||||
<div>
|
||||
<div className="inline-div-50">
|
||||
<p class="charts-title">Delay % By Type</p>
|
||||
<PieChart className="form-content" width={400} height={300}>
|
||||
<Pie isAnimationActive={false} data={airline_delays} cx={200} cy={125} outerRadius={80} fill="#8884d8" label>
|
||||
{
|
||||
airline_delays.map((entry, index) => (
|
||||
<Cell key={`cell-${index}`} fill={this.colors[index]}/>
|
||||
))
|
||||
}
|
||||
</Pie>
|
||||
<Tooltip/>
|
||||
<Legend align="center" />
|
||||
</PieChart>
|
||||
</div>
|
||||
<div className="inline-div-50">
|
||||
<p class="charts-title">Airline (avg minutes) delays vs. All (avg minutes) delays </p>
|
||||
<BarChart className="Form-content" width={400} height={300} data={delays_comparison}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="name" />
|
||||
<YAxis />
|
||||
<Tooltip />
|
||||
<Legend align="center" />
|
||||
<Bar dataKey="Target" fill="#96DDCF" />
|
||||
<Bar dataKey="Average" fill="#0E6488" />
|
||||
</BarChart>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AirlineFlightsInfo.propTypes = {
|
||||
origin: PropTypes.object.isRequired,
|
||||
destination: PropTypes.object.isRequired,
|
||||
airline: PropTypes.string.isRequired,
|
||||
yearFrom: PropTypes.number.isRequired,
|
||||
yearTo: PropTypes.number.isRequired,
|
||||
month: PropTypes.number,
|
||||
day: PropTypes.number
|
||||
};
|
|
@ -1,125 +0,0 @@
|
|||
import React, {Component} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
import {
|
||||
SelectionState,
|
||||
SortingState,
|
||||
IntegratedSorting,
|
||||
} from '@devexpress/dx-react-grid';
|
||||
|
||||
import {
|
||||
Grid,
|
||||
Table,
|
||||
TableHeaderRow,
|
||||
TableSelection
|
||||
} from '@devexpress/dx-react-grid-material-ui';
|
||||
|
||||
export default class AirlinesFlightsInfo extends Component {
|
||||
|
||||
state = {
|
||||
data: [],
|
||||
selection: [],
|
||||
columns: [
|
||||
{ name: 'airline', title: 'Airline' },
|
||||
{ name: 'flight_count', title: 'Flights' },
|
||||
{ name: 'market_share_pct', title: 'Market %' },
|
||||
{ name: 'delayed_pct', title: 'Delayed %' },
|
||||
{ name: 'diverted_pct', title: 'Diverted %' },
|
||||
{ name: 'cancelled_pct', title: 'Cancelled %' }
|
||||
]
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.changeSelection = this.changeSelection.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props !== null &&
|
||||
this.props.origin !== null &&
|
||||
this.props.destination !== null) {
|
||||
this.load(this.props.origin.code, this.props.destination.code,
|
||||
this.props.yearFrom, this.props.yearTo, this.props.month, this.props.day);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps !== null &&
|
||||
nextProps.origin !== null &&
|
||||
nextProps.destination !== null) {
|
||||
this.load(nextProps.origin.code, nextProps.destination.code,
|
||||
nextProps.yearFrom, nextProps.yearTo, nextProps.month, nextProps.day);
|
||||
}
|
||||
}
|
||||
|
||||
async load(origin, dest, yearFrom, yearTo, month, day) {
|
||||
await this.getStats(origin, dest, yearFrom, yearTo, month, day)
|
||||
.then(res => {
|
||||
this.setState({ data: res })
|
||||
})
|
||||
.catch(err => console.log(err));
|
||||
}
|
||||
|
||||
async getStats(origin, dest, yearFrom, yearTo, month, day) {
|
||||
const response = await fetch('/api/flights/airlines_stats?o=' + origin + "&dst=" + dest + "&yf="
|
||||
+ yearFrom + "&yt=" + yearTo + "&m=" + month + "&d=" + day);
|
||||
const body = await response.json();
|
||||
if (response.status !== 200) {
|
||||
throw Error(body.message)
|
||||
}
|
||||
return body;
|
||||
};
|
||||
|
||||
changeSelection(selection) {
|
||||
const lastSelected = selection
|
||||
.find(selected => this.state.selection.indexOf(selected) === -1);
|
||||
|
||||
if (lastSelected !== undefined) {
|
||||
this.setState({ selection: [lastSelected] });
|
||||
var d = this.state.data[lastSelected];
|
||||
if (d !== undefined) {
|
||||
this.props.airlineSelected({ code: d.carrier, name: d.airline});
|
||||
}
|
||||
} else {
|
||||
// NOTE: Uncomment the next line in order to allow clear selection by double-click
|
||||
//this.setState({ selection: [] });
|
||||
//this.props.airlineSelected(null);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { data, columns, selection } = this.state;
|
||||
|
||||
return (
|
||||
<Paper>
|
||||
<Grid
|
||||
rows={data}
|
||||
columns={columns}>
|
||||
<SelectionState
|
||||
selection={selection}
|
||||
onSelectionChange={this.changeSelection}
|
||||
/>
|
||||
<SortingState defaultSorting={[{ columnName: 'cancelled_pct', direction: 'desc' }]} />
|
||||
<IntegratedSorting />
|
||||
<Table />
|
||||
<TableHeaderRow showSortingControls />
|
||||
<TableSelection
|
||||
selectByRowClick
|
||||
highlightRow
|
||||
showSelectionColumn={false}
|
||||
/>
|
||||
</Grid>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AirlinesFlightsInfo.propTypes = {
|
||||
airlineSelected: PropTypes.func.isRequired,
|
||||
origin: PropTypes.object,
|
||||
destination: PropTypes.object,
|
||||
yearFrom: PropTypes.number,
|
||||
yearTo: PropTypes.number,
|
||||
month: PropTypes.number,
|
||||
day: PropTypes.number
|
||||
};
|