from CSAir_server import *
import os
from flask import Flask, render_template, request, redirect
from werkzeug import utils
app = Flask(__name__) # Initialize the Flask application
app.config['UPLOAD_FOLDER'] = 'uploads/' # This is the path to the upload directory
app.config['ALLOWED_EXTENSIONS'] = set(['json']) # These are the extension that we are accepting to be uploaded
# For a given file, return whether it's an allowed type or not
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in app.config['ALLOWED_EXTENSIONS']
log = ServerLog()
route_log = ServerLog()
route_stats = {}
@app.route('/')
def display_main():
"""
Display the home page/cities page
:return: the home page/cities page
"""
try:
code = request.args.get('code').upper()
except AttributeError:
code = None
rm = request.args.get('rm')
if rm is not None: # remove a node.
if graph.remove_node(rm):
log.log_yellow(rm + " successfully removed.")
s_text = get_stats(graph) # get overall stats.
city_menu = generate_city_menu(graph) # generate the city menu
h_text = n_to_br(print_hubs(graph)) # get hubs info
c_text = n_to_br(print_continents(graph)) # get continents info
#set city params to none for HTML rendering
c_info, continent, country, latitude, longitude, name, pop, region, timezone, wx_url = set_city_params_to_none()
if code is not None: # if city exists, get city info.
c_info = n_to_br(lookup(graph, code))
city_node = graph.find_node(code)
if city_node is None:
log.log_yellow(code + " does not exist.")
return redirect("/")
current_city = city_node.get_object()
name = current_city.name
country = current_city.country
continent = current_city.continent
timezone = current_city.timezone
latitude = current_city.latitude
longitude = current_city.longitude
pop = current_city.population
region = current_city.region
if country == "US" or country == "USA": # Add weather button if the city is in the US
wx_url = 'http://aviationweather.gov/adds/metars/index.php?submit=1&station_ids=K' + code \
+ '&chk_metars=on&hoursStr=2&std_trans=translated&chk_tafs=on'
#render the HTML and return.
return render_template('city.html', cities=sorted(graph.get_nodes()), map_url=generate_map_url(graph),
city_menu=city_menu, c_info=c_info, s_info=s_text, code=code, log=log.get_log(), hubs=h_text,
conts=c_text, WX_url=wx_url, country=country, name=name, continent=continent,
timezone=timezone, latitude=latitude, longitude=longitude, pop=pop, region=region)
@app.route('/<path:fname>')
def display_static(fname):
"""
Static route to send CSS and JS.
:param fname: requested filename
:return: the file
"""
#send_static_file will guess the correct MIME type
return app.send_static_file(fname)
@app.route('/routes')
def display_routes():
"""
Display the routes page
:return: routes page
"""
add, clear, dest, direction, distance, noquery, rm, route_str, source = get_route_args(request)
if clear == "routes": # clear route query history
route_log.clear()
if add is not None: # add new route.
if add_route_helper(graph, source, dest, distance, direction):
log.log_green("Successfully added route: " + source + " to " + dest)
else:
log.log_yellow("Unable to add route: " + source + " to " + dest)
route_str = source + "-" + dest # set route string to display new route.
elif rm is not None: # remove route.
if remove_route_helper(graph, source, dest, direction):
log.log_green("Successfully removed route: " + source + " to " + dest)
else:
log.log_yellow("Unable to remove route: " + source + " to " + dest)
route = generate_shortest_route(graph, source, dest, rm, add, log) # generate list of nodes in the route.
if route is None: # If we did not find shortest route, assume they specified a manual route
route = generate_route_list(route_str)
else: # Otherwise, generate the route string for the log.
route_str = generate_route_string(route)
url_string = generate_map_url_from_list(graph, route)
#finish the url string and create log string.
if route_str is not None:
log_string = '<a href="/routes?route=' + route_str + '&noquery=y">' + route_str + "</a><br>"
if noquery is None:
route_log.append(log_string)
#get route statistics
route_stats_str = ""
if route is not None:
route_stats_str = n_to_br(route_helper(graph, route))
if "Error" in route_stats_str:
url_string = generate_map_url(graph)
log.log_yellow("Did not find route: " + route_str)
city_menu = generate_city_menu(graph)
return render_template('routes.html', cities=sorted(graph.get_nodes()), map_url=url_string, city_menu=city_menu, log=log.get_log(), route_log=route_log.get_log(), r_info=route_stats_str)
@app.route('/save.json')
def export_json():
save_json(graph, "static\save.json")
return app.send_static_file("save.json")
@app.route('/upload', methods=['POST'])
def upload():
"""
Route that will process the file upload
Adapted from: http://flask.pocoo.org/docs/0.10/patterns/fileuploads/
and http://runnable.com/UiPcaBXaxGNYAAAL/how-to-upload-a-file-to-the-server-in-flask-for-python
:return:
"""
# Get the name of the uploaded file
file = request.files['file']
# Check if the file is one of the allowed types/extensions
if file and allowed_file(file.filename):
# Make the filename safe, remove unsupported chars
filename = utils.secure_filename(file.filename)
# Move the file form the temporal folder to
# the upload folder we setup
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
# Redirect the user to the uploaded_file route, which
# will basically show on the browser the uploaded file
log.log_green("Successfully uploaded " + filename)
if merge_json(graph, "uploads/" + filename):
log.log_green("Successfully merged data.")
else:
log.log_yellow("Failed to merge data.")
else:
log.log_yellow("Failed to upload " + file.filename)
return redirect('/')
@app.route('/add_city')
def add_city():
"""
Handle the Add city form request.
:return: The city page or Home page if city was not added.
"""
try:
code = request.args.get('cityCode').upper()
except AttributeError:
code = None
api = request.args.get('api')
edit = request.args.get('edit')
if edit == "true":
print("Edit is true!")
old_code = request.args.get('old_code')
node = graph.find_node(old_code)
graph.remove_node(node, False)
#add city from Wunderground API
if api == "true" and code is not None:
if json_api_request(graph, code) is True:
return_string = code + " successfully added from Wunderground API."
else:
return_string = "Error: Unable to add " + code + " from API."
else: # otherwise get manual arguments.
continent, country, latitude, longitude, name, population, region, timezone = get_add_city_args(request)
return_string = add_city_helper(graph, code, name, country, continent,
timezone, latitude, longitude, population, region)
if "Error" in return_string:
#if modifying the city failed, add the old one back to the graph.
log.log_yellow(return_string)
if edit == "true":
graph.add_node(node.get_object(), node)
log.log_yellow("Editing " + code + " failed:")
else:
#edit current routes to match new information!
log.log_green(return_string)
if edit == "true":
update_routes(graph, code, old_code)
log.log_green("Editing " + code + " succeeded:")
return redirect('/?code=' + code)
return redirect('/')
graph = load_initial_json(False)
#app.run(debug=True)
app.run()