Skip to content

Commit

Permalink
09.05.18 v1.4.3
Browse files Browse the repository at this point in the history
  • Loading branch information
answerquest committed May 9, 2018
1 parent 771a72e commit fd9d587
Show file tree
Hide file tree
Showing 23 changed files with 1,997 additions and 2,091 deletions.
1,454 changes: 727 additions & 727 deletions GTFS/db.json

Large diffs are not rendered by default.

18 changes: 11 additions & 7 deletions GTFSManager.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
print('static GTFS Manager')
print('\n\nstatic GTFS Manager')
print('Fork it on Github: https://github.com/WRI-Cities/static-GTFS-manager/')
print('Starting up the program, loading dependencies, please wait...\n\n')

Expand All @@ -15,12 +15,13 @@
from tinydb import TinyDB, Query
from tinydb.operations import delete
import webbrowser
from Cryptodome.PublicKey import RSA
from Cryptodome.PublicKey import RSA #uses pycryptodomex package.. disambiguates from pycrypto, pycryptodome
import shutil # used in fareChartUpload to fix header if changed
import pathlib
from math import sin, cos, sqrt, atan2, radians
# import requests
from json.decoder import JSONDecodeError # used to catch corrupted DB file when tinyDB loads it.
import signal, sys # for catching Ctrl+C and exiting gracefully.

# setting constants
root = os.path.dirname(__file__)
Expand Down Expand Up @@ -1252,7 +1253,13 @@ def make_app():
(r"/(.*)", tornado.web.StaticFileHandler, {"path": root, "default_filename": "index.html"})
])

# for catching Ctrl+C and exiting gracefully. From https://nattster.wordpress.com/2013/06/05/catch-kill-signal-in-python/
def signal_term_handler(signal, frame):
print('\nClosing Program.\nThank you for using GTFS Manager. Website: https://github.com/WRI-Cities/static-GTFS-manager/\n')
sys.exit(0)

if __name__ == "__main__":
signal.signal(signal.SIGINT, signal_term_handler)
app = make_app()
port = int(os.environ.get("PORT", 5000))
app.listen(port)
Expand All @@ -1261,8 +1268,5 @@ def make_app():
logmessage("Open " + thisURL + " in your Browser if you don't see it opening automatically within 5 seconds.")
tornado.ioloop.IOLoop.current().start()

'''
# UNZIP a zip file, from https://stackoverflow.com/a/36662770/4355695
with zipfile.ZipFile("file.zip","r") as zip_ref:
zip_ref.extractall("targetdir")
'''


2 changes: 1 addition & 1 deletion GTFSserverfunctions.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def exportGTFS (dbfile, folder):
zf.close()
db.close()

returnmessage = '<p>Success! Generated GTFS feed at <a href="' + folder + 'gtfs.zip' + '">' + folder + 'gtfs.zip<a></b>. Click to download.</p>'
returnmessage = '<p>Success! Generated GTFS feed at <a href="' + folder + 'gtfs.zip' + '">' + folder + 'gtfs.zip<a></b>. Click to download.</p><p>You can validate the feed on <a href="https://gtfsfeedvalidator.transitscreen.com/" target="_blank">GTFS Feed Validator</a> website.</p>'

end = time.time()
logmessage("Function to export GTFS from db took {} seconds.".format(round(end-start,2)))
Expand Down
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

![Screenshot](https://github.com/WRI-Cities/static-GTFS-manager/raw/master/extra_files/gtfs-routes-screenshot.png)


A browser-based user interface for creating, editing, exporting of static GTFS (General Transit Feed Specification Reference) feeds for a public transit authority.

**Development Status** : V 1.4.2 is ready, open for Beta Testing. And Windows binary is available too now. See [Releases page](https://github.com/WRI-Cities/static-GTFS-manager/releases/).
**Development Status** : V 1.4.3 is ready, open for Beta Testing. And Windows binary is available too now. See [Releases page](https://github.com/WRI-Cities/static-GTFS-manager/releases/).

## Intro
This project is the result of a collaboration between WRI ([World Resources Institute](http://wri-india.org/)) and KMRL ([Kochi Metro Rail Limited](http://kochimetro.org)).

Initially developed for use by KMRL, the source code has been open-sourced so it can grow and get better with community inputs and help for creating GTFS feeds for other transit agencies too.
Expand All @@ -21,6 +21,12 @@ It also implements a [GTFS extension for translations](https://developers.google

Lead programmer up till April 2018: [Nikhil VJ](https://answerquest.github.io) from Pune, India.

See this and many more GTFS related resources listed on **[Awesome Transit](https://github.com/CUTR-at-USF/awesome-transit#gtfs-tools)**, a one-stop community listing for all things GTFS.

## Demo Videos
[![GTFS Manager Runthrough video](http://img.youtube.com/vi/n8BuDM51QyU/0.jpg)](https://www.youtube.com/embed/n8BuDM51QyU?rel=0&autoplay=1 "GTFS Manager Runthrough video")

[Demonstration of XML Import feature](https://www.youtube.com/watch?v=_JYVtm-6iJg)

## Run on your system

Expand Down
Binary file added extra_files/demo-video.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ <h1 align="center"><img src="extra_files/GTFS.png" height="100%" width="auto" al
<div id="instructions" class="container">
<h4>Instructions</h4>
<div>
<p align="center"><a href="https://www.youtube.com/embed/n8BuDM51QyU?rel=0&autoplay=1" target="_blank"><img class="videothumb" src="extra_files/demo-video.jpg"><br><small>Click here to see a demo video.</small></a></p>
<ul>
<li>This is the home/main page of the tool. It gives you and overview of your data, and here you can import/export your GTFS feeds.</li>
<li>There are 4 sections on this page:</li>
Expand Down
2 changes: 1 addition & 1 deletion js/commonfuncs.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// ############################
// CONSTANTS
const VERSION = 'v1.4.2';
const VERSION = 'v1.4.3';
const APIpath = 'API/';
const CURRENCY = 'INR';
const route_type_options = {0:"0-Tram, Streetcar, Light rail", 1:"1-Subway, Metro", 2:"2-Rail", 3:"3-Bus",4:"4-Ferry" };
Expand Down
17 changes: 15 additions & 2 deletions js/fares.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// Global variables
var allStopsKeyed = '';

// #########################################
// Function-variables to be used in tabulator

// set dynamic dropdown for fare_ids, reading from fare attributes table
var fareList = function(cell){
var data = $("#fare-attributes-table").tabulator("getData");
Expand All @@ -27,6 +30,16 @@ var zoneIdLister = function(cell) {
return zoneIdListGlobal;
}

var faresTotal = function(values, data, calcParams){
var calc = values.length;
return calc + ' fares total';
}

var fareRulesTotal = function(values, data, calcParams){
var calc = values.length;
return calc + ' rules total';
}

//#########################
// defining tables
$("#fare-attributes-table").tabulator({
Expand All @@ -39,7 +52,7 @@ $("#fare-attributes-table").tabulator({
columns:[ //Define Table Columns
// stop_id,stop_name,stop_lat,stop_lon,zone_id,wheelchair_boarding
{rowHandle:true, formatter:"handle", headerSort:false, frozen:true, width:30, minWidth:30},
{title:"fare_id", field:"fare_id", editor:"input", headerFilter:"input", width:100, validator:["string", "minLength:2"] },
{title:"fare_id", field:"fare_id", editor:"input", headerFilter:"input", width:100, validator:["string", "minLength:2"], bottomCalc:faresTotal },
{title:"price", field:"price", editor:"input", headerFilter:"input", width:70, validator:["required","numeric"] },
{title:"payment_method", field:"payment_method", editor:"select", editorParams:{0:"0 - on boarding", 1:"1 - before boarding"}, headerSort:false, width:100 },
{title:"transfers", field:"transfers", editor:"select", editorParams:{'':'blank - Unlimited transfers', 0:"0 - No transfers", 1:"1 - Once allowed"}, headerSort:false, width:80 },
Expand Down Expand Up @@ -103,7 +116,7 @@ $("#fare-rules-simple-table").tabulator({
columns:[ //Define Table Columns
// stop_id,stop_name,stop_lat,stop_lon,zone_id,wheelchair_boarding
{rowHandle:true, formatter:"handle", headerSort:false, frozen:true, width:30, minWidth:30},
{title:"fare_id", field:"fare_id", headerFilter:"input", width:100, editor:"select", editorParams:fareList, tooltip:"Fare Id. Corresponds to a price set in Fare Attributes tab." },
{title:"fare_id", field:"fare_id", headerFilter:"input", width:120, editor:"select", editorParams:fareList, tooltip:"Fare Id. Corresponds to a price set in Fare Attributes tab.", bottomCalc:fareRulesTotal },
{title:"origin_id", field:"origin_id", editor:"select", editorParams:zoneIdLister, headerFilter:"input", width:100, tooltip:"Origin Zone Id. Journey starting from this zone. Zones defined in Stops page." },
{title:"destination_id", field:"destination_id", editor:"select", editorParams:zoneIdLister, headerFilter:"input", width:100, tooltip:"Desitnation Zone Id. Journey ending in this zone. Zones defined in Stops page." },
{title:"route_id", field:"route_id", editor:"select", editorParams:routeIdLister, headerFilter:"input", width:100, tooltip:"If this fare rule only applies to a particular route then select the route here." },
Expand Down
16 changes: 12 additions & 4 deletions js/homepage.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,14 @@ function exportGTFS() {

//reject if its blank
if (! commit.length) {
alert('Please give a valid name for the commit.');
return;
$('#exportGTFSlog').html('<div class="alert alert-danger">Please give a valid name for the commit.</div>');
shakeIt('commitName'); return;
}
var pw = $("#password").val();
if ( ! pw.length ) {
$('#exportGTFSlog').html('<div class="alert alert-danger">Please enter the password.</div>');
shakeIt('password'); return;
}

$("#exportGTFSlog").html('Initated commit.. please wait..');

Expand All @@ -110,10 +114,14 @@ function gtfsImportZip() {
// idiot-proofing: check if the files have been uploaded or not.
if( document.getElementById('gtfsZipFile').value == '') {
$('#importGTFSStatus').html('<div class="alert alert-warning">Please select a file first! ;)</div>');
return;
shakeIt('gtfsZipFile'); return;
}

var pw = $("#password").val();
if ( ! pw.length ) {
$('#importGTFSStatus').html('<div class="alert alert-danger">Please enter the password.</div>');
shakeIt('password'); return;
}
$("#importGTFSStatus").html('Importing GTFS file, please wait..');

var formData = new FormData();
Expand Down Expand Up @@ -166,7 +174,7 @@ function gtfsBlankSlate() {
},
error: function(jqXHR, exception) {
console.log('API/gtfsBlankSlate GET request failed.');
$("#gtfsBlankSlateStatus").text(jqXHR.responseText);
$("#gtfsBlankSlateStatus").html('<span class="alert alert-danger">' + jqXHR.responseText + '</span>');
}
});
}
22 changes: 19 additions & 3 deletions js/misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,22 @@ var globalValueFrom = '';
var globalValueTo = '';
var globalTableKeys = [];

// #########################################
// Function-variables to be used in tabulator
var translationsTotal = function(values, data, calcParams){
var calc = values.length;
return calc + ' translations total';
}

var calendarTotal = function(values, data, calcParams){
var calc = values.length;
return calc + ' services total';
}

var agencyTotal = function(values, data, calcParams){
var calc = values.length;
return calc + ' agencies total';
}

//####################
// Tabulator tables
Expand All @@ -27,7 +43,7 @@ $("#calendar-table").tabulator({

columns:[
{rowHandle:true, formatter:"handle", headerSort:false, frozen:true, width:30, minWidth:30 },
{title:"service_id", field:"service_id", frozen:true, headerFilter:"input", headerFilterPlaceholder:"filter by id" },
{title:"service_id", field:"service_id", frozen:true, headerFilter:"input", headerFilterPlaceholder:"filter by id", bottomCalc:calendarTotal },
{title:"monday", field:"monday", editor:"select", editorParams:operationalChoices, headerSort:false },
{title:"tuesday", field:"tuesday", editor:"select", editorParams:operationalChoices, headerSort:false },
{title:"wednesday", field:"wednesday", editor:"select", editorParams:operationalChoices, headerSort:false },
Expand Down Expand Up @@ -58,7 +74,7 @@ $("#agency-table").tabulator({
columns:[
{rowHandle:true, formatter:"handle", headerSort:false, frozen:true, width:30, minWidth:30 },
{title:"agency_id", field:"agency_id", editor:"input", headerSort:false },
{title:"agency_name", field:"agency_name", editor:"input", headerSort:false },
{title:"agency_name", field:"agency_name", editor:"input", headerSort:false, bottomCalc:agencyTotal },
{title:"agency_url", field:"agency_url", editor:"input", headerSort:false },
{title:"agency_timezone", field:"agency_timezone", editor:"input", headerSort:false, tooltip:'Get your timezone from TZ column in https://en.wikipedia.org/wiki/List_of_tz_database_time_zones' }

Expand All @@ -76,7 +92,7 @@ $("#translations-table").tabulator({
// agency_id,agency_name,agency_url,agency_timezone
columns:[
{rowHandle:true, formatter:"handle", headerSort:false, frozen:true, width:30, minWidth:30 },
{title:"trans_id", field:"trans_id", editor:"input", headerFilter:"input", headerSort:false, width:120 },
{title:"trans_id", field:"trans_id", editor:"input", headerFilter:"input", headerSort:false, width:120, bottomCalc:translationsTotal },
{title:"lang", field:"lang", editor:"input", headerFilter:"input", headerSort:false },
{title:"translation", field:"translation", editor:"input", headerFilter:"input", headerSort:false, width:150, formatter:function(cell, formatterParams){
return "<big>" + cell.getValue() + '</big>'; //return the contents of the cell;
Expand Down
19 changes: 12 additions & 7 deletions js/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ var allStops = [], stop_id_list =[], remaining0=[], remaining1=[], route_id_list


// #########################################
// function-variable to be used in tabulator,
// Function-variables to be used in tabulator

var agencyListGlobal = {}; // global variable
var agencyLister = function(cell) {
Expand All @@ -18,6 +18,11 @@ var agencyLister = function(cell) {
// getPythonAgency() function will make API call and load agencies listin into this global variable.
}

var routesTotal = function(values, data, calcParams){
var calc = values.length;
return calc + ' routes total';
}

// #########################################
// Construct tables
$("#routes-table").tabulator({
Expand All @@ -34,7 +39,7 @@ $("#routes-table").tabulator({
{title:"Num", width:40, formatter: "rownum", frozen:true,}, // row numbering
{title:"route_id", field:"route_id", frozen:true, headerFilter:"input", headerFilterPlaceholder:"filter by id", validator:["string", "minLength:2"] },
{title:"route_short_name", field:"route_short_name", editor:"input", headerFilter:"input", headerFilterPlaceholder:"filter by name", validator:["required","string", "minLength:2"] },
{title:"route_long_name", field:"route_long_name", editor:"input", headerFilter:"input", headerFilterPlaceholder:"filter by name" },
{title:"route_long_name", field:"route_long_name", editor:"input", headerFilter:"input", headerFilterPlaceholder:"filter by name", bottomCalc:routesTotal },
{title:"route_type", field:"route_type", editor:"select", editorParams:route_type_options, formatter:"lookup", formatterParams:route_type_lookup, headerSort:false },
{title:"route_color", field:"route_color", headerSort:false, editor:"input" },
{title:"route_text_color", field:"route_text_color", headerSort:false, editor:"input" },
Expand Down Expand Up @@ -569,7 +574,7 @@ function saveRoutes() {

var pw = $("#password").val();
if ( ! pw ) {
$('#routeSaveStatus').html('Please enter the password.');
$('#routeSaveStatus').html('<span class="alert alert-danger">Please enter the password.</span>');
shakeIt('password'); return;
}

Expand All @@ -582,20 +587,20 @@ function saveRoutes() {
xhr.onload = function () {
if (xhr.status === 200) {
console.log('Successfully sent data via POST to server API/saveRoutes, resonse received: ' + xhr.responseText);
$('#routeSaveStatus').text('Saved changes to routes.txt.');
$('#routeSaveStatus').html('<span class="alert alert-success">Saved changes to routes.txt.</span>');
// reload routes data from DB, and repopulate route selector for sequence
getPythonRoutes();
} else {
console.log('Server POST request to API/saveRoutes failed. Returned status of ' + xhr.status + ', reponse: ' + xhr.responseText );
$('#routeSaveStatus').text('Failed to save. Message: ' + xhr.responseText);
$('#routeSaveStatus').html('<span class="alert alert-danger">Failed to save. Message: ' + xhr.responseText + '</span>');
}
}
xhr.send(JSON.stringify(data)); // this is where POST differs from GET : we can send a payload instead of just url arguments.

}

function saveSequence() {
$('#sequenceSaveStatus').html('Saving sequence to DB, please wait...');
$('#sequenceSaveStatus').html('<span class="alert alert-info">Saving sequence to DB, please wait...</span>');

// forget global sequences, retrieve latest sequence data straight from tables.
var sequence0 = $("#sequence-0-table").tabulator('getData');
Expand Down Expand Up @@ -836,7 +841,7 @@ function uploadShape() {
var pw = $("#password").val();
if ( ! pw ) {
shakeIt('password');
$('#uploadShapeStatus').html('please enter the password.');
$('#uploadShapeStatus').html('Please enter the password.');
return;
}
var route_id = selected_route_id;
Expand Down
Loading

0 comments on commit fd9d587

Please sign in to comment.