aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2023-06-16 10:53:08 +0300
committerFrederick Muriuki Muriithi2023-06-20 13:36:50 +0300
commit883a7cba581f34eba48978746e2ff8bbb93020d8 (patch)
tree433c1b0b6db451b841810b2fdb4f2fd07bc9377b
parent7127095f2b2c54175d1360c1ddb3e0f87b6ede98 (diff)
downloadgenenetwork2-883a7cba581f34eba48978746e2ff8bbb93020d8.tar.gz
Add `create_app()` application factory
Create the application and set up configs and other things within an application factory function. Fix obvious egregious errors preventing the application from starting up correctly.
-rw-r--r--wqflask/base/data_set/__init__.py2
-rw-r--r--wqflask/base/data_set/datasetgroup.py3
-rw-r--r--wqflask/gn2_main.py60
-rw-r--r--wqflask/run_gunicorn.py2
-rw-r--r--wqflask/runserver.py2
-rw-r--r--wqflask/utility/authentication_tools.py4
-rw-r--r--wqflask/utility/startup_config.py4
-rw-r--r--wqflask/wqflask/__init__.py172
-rw-r--r--wqflask/wqflask/app_errors.py5
-rw-r--r--wqflask/wqflask/oauth2/client.py34
-rw-r--r--wqflask/wqflask/oauth2/request_utils.py7
-rw-r--r--wqflask/wqflask/templates/base.html18
-rw-r--r--wqflask/wqflask/templates/search_result_page.html24
-rw-r--r--wqflask/wqflask/templates/show_trait.html30
-rw-r--r--wqflask/wqflask/templates/tool_buttons.html2
-rw-r--r--wqflask/wqflask/views.py1
16 files changed, 188 insertions, 182 deletions
diff --git a/wqflask/base/data_set/__init__.py b/wqflask/base/data_set/__init__.py
index ad51e47e..c2c0aef1 100644
--- a/wqflask/base/data_set/__init__.py
+++ b/wqflask/base/data_set/__init__.py
@@ -115,7 +115,7 @@ def datasets(group_name, this_group=None, redis_conn=Redis()):
dataset_menu.append(dict(tissue=tissue_name,
datasets=[(dataset, dataset_short)]))
- if get_setting_bool("USE_REDIS"):
+ if get_setting_bool(app, "USE_REDIS"):
redis_conn.set(key, pickle.dumps(dataset_menu, pickle.HIGHEST_PROTOCOL))
redis_conn.expire(key, 60 * 5)
diff --git a/wqflask/base/data_set/datasetgroup.py b/wqflask/base/data_set/datasetgroup.py
index 90c59a1e..a44cf18d 100644
--- a/wqflask/base/data_set/datasetgroup.py
+++ b/wqflask/base/data_set/datasetgroup.py
@@ -15,6 +15,7 @@ from wqflask.database import database_connection
from utility.configuration import (
locate,
flat_files,
+ get_setting,
flat_file_exists,
get_setting_bool,
locate_ignore_error)
@@ -128,7 +129,7 @@ class DatasetGroup:
return study_samples
def get_genofiles(self):
- jsonfile = "%s/%s.json" % (webqtlConfig.GENODIR, self.name)
+ jsonfile = "%s/%s.json" % (get_setting(app, "WEBQTL_GENODIR"), self.name)
try:
f = open(jsonfile)
except:
diff --git a/wqflask/gn2_main.py b/wqflask/gn2_main.py
new file mode 100644
index 00000000..923a35d3
--- /dev/null
+++ b/wqflask/gn2_main.py
@@ -0,0 +1,60 @@
+"""Main app creation module"""
+import time
+
+from flask import g, session, request
+
+from wqflask import create_app
+from wqflask.user_session import UserSession
+from gn3.authentication import DataRole, AdminRole
+
+app = create_app()
+
+@app.before_request
+def before_request():
+ g.request_start_time = time.time()
+ g.request_time = lambda: "%.5fs" % (time.time() - g.request_start_time)
+
+ token = session.get("oauth2_token", False)
+ if token and not bool(session.get("user_details", False)):
+ config = current_app.config
+ client = OAuth2Session(
+ config["OAUTH2_CLIENT_ID"], config["OAUTH2_CLIENT_SECRET"],
+ token=token)
+ resp = client.get(
+ urljoin(config["GN_SERVER_URL"], "oauth2/user"))
+ user_details = resp.json()
+ session["user_details"] = user_details
+
+ if user_details.get("error") == "invalid_token":
+ flash(user_details["error_description"], "alert-danger")
+ flash("You are now logged out.", "alert-info")
+ session.pop("user_details", None)
+ session.pop("oauth2_token", None)
+
+@app.context_processor
+def include_admin_role_class():
+ return {'AdminRole': AdminRole}
+
+
+@app.context_processor
+def include_data_role_class():
+ return {'DataRole': DataRole}
+
+@app.before_request
+def get_user_session():
+ g.user_session = UserSession()
+ # I think this should solve the issue of deleting the cookie and redirecting to the home page when a user's session has expired
+ if not g.user_session:
+ response = make_response(redirect(url_for('login')))
+ response.set_cookie('session_id_v2', '', expires=0)
+ return response
+
+@app.after_request
+def set_user_session(response):
+ if hasattr(g, 'user_session'):
+ if not request.cookies.get(g.user_session.cookie_name):
+ response.set_cookie(g.user_session.cookie_name,
+ g.user_session.cookie)
+ else:
+ response.set_cookie('session_id_v2', '', expires=0)
+ return response
diff --git a/wqflask/run_gunicorn.py b/wqflask/run_gunicorn.py
index 03f310eb..af117466 100644
--- a/wqflask/run_gunicorn.py
+++ b/wqflask/run_gunicorn.py
@@ -9,7 +9,7 @@
print("===> Starting up Gunicorn process")
-from wqflask import app
+from gn2_main import app
from utility.startup_config import app_config
app_config()
diff --git a/wqflask/runserver.py b/wqflask/runserver.py
index 8f01425e..fed3d356 100644
--- a/wqflask/runserver.py
+++ b/wqflask/runserver.py
@@ -7,7 +7,7 @@
#
# /sbin/iptables -A INPUT -p tcp -i eth0 -s ! 71.236.239.43 --dport 5003 -j DROP
-from wqflask import app
+from gn2_main import app
from utility.startup_config import app_config
from utility.configuration import get_setting, get_setting_int
diff --git a/wqflask/utility/authentication_tools.py b/wqflask/utility/authentication_tools.py
index 3d732228..0f48d26f 100644
--- a/wqflask/utility/authentication_tools.py
+++ b/wqflask/utility/authentication_tools.py
@@ -37,7 +37,7 @@ def check_resource_availability(dataset, user_id, trait_id=None):
return webqtlConfig.SUPER_PRIVILEGES
response = None
- the_url = f"{get_setting('GN_PROXY_URL')}available?resource={resource_id}&user={user_id}"
+ the_url = f"{get_setting(app, 'GN_PROXY_URL')}available?resource={resource_id}&user={user_id}"
try:
response = json.loads(requests.get(the_url).content)
except:
@@ -94,7 +94,7 @@ def get_group_code(dataset):
def check_admin(resource_id=None):
the_url = (
- f"{get_setting('GN_PROXY_URL')}available?resource={resource_id}"
+ f"{get_setting(app, 'GN_PROXY_URL')}available?resource={resource_id}"
f"&user={g.user_session.user_id}")
try:
response = json.loads(requests.get(the_url).content)['admin']
diff --git a/wqflask/utility/startup_config.py b/wqflask/utility/startup_config.py
index 5ab43b1a..59f78d55 100644
--- a/wqflask/utility/startup_config.py
+++ b/wqflask/utility/startup_config.py
@@ -1,6 +1,4 @@
-
-from wqflask import app
-
+"""Utility to print out some startup messages."""
from utility.configuration import show_settings
from utility.configuration import get_setting_int
from utility.configuration import get_setting
diff --git a/wqflask/wqflask/__init__.py b/wqflask/wqflask/__init__.py
index 86370183..3b7551e6 100644
--- a/wqflask/wqflask/__init__.py
+++ b/wqflask/wqflask/__init__.py
@@ -17,8 +17,6 @@ from utility.tools import set_mandatory_settings
from utility.hmac import data_hmac, url_for_hmac
from utility.configuration import tempdir, override_from_envvars
-from gn3.authentication import DataRole, AdminRole
-
from wqflask.database import parse_db_url
from wqflask.user_session import UserSession
from wqflask.group_manager import group_management
@@ -42,115 +40,6 @@ from wqflask.oauth2.request_utils import user_details, authserver_authorise_uri
from wqflask.jupyter_notebooks import jupyter_notebooks
-app = Flask(__name__)
-
-
-# See http://flask.pocoo.org/docs/config/#configuring-from-files
-# Note no longer use the badly named WQFLASK_OVERRIDES (nyi)
-app.config.from_envvar('GN2_SETTINGS')
-
-DB_HOST, DB_USER, DB_PASS, DB_NAME, DB_PORT = parse_db_url(app.config.get('SQL_URI'))
-app.config["DB_HOST"] = DB_HOST
-app.config["DB_USER"] = DB_USER
-app.config["DB_PASS"] = DB_PASS
-app.config["DB_NAME"] = DB_NAME
-app.config["DB_PORT"] = DB_PORT
-
-app.jinja_env.globals.update(
- undefined=jinja2.StrictUndefined,
- numify=formatting.numify,
- logged_in=user_logged_in,
- authserver_authorise_uri=authserver_authorise_uri,
- user_details=user_details,
- num_collections=num_collections,
- url_for_hmac=url_for_hmac,
- data_hmac=data_hmac)
-
-app.config["SESSION_REDIS"] = redis.from_url(app.config["REDIS_URL"])
-
-# Override settings
-app = override_from_envvars(app)
-app = set_mandatory_settings(app)
-app = webqtlConfig.init_app(app)
-
-# Registering blueprints
-app.register_blueprint(toplevel)
-app.register_blueprint(glossary_blueprint, url_prefix="/glossary")
-app.register_blueprint(references_blueprint, url_prefix="/references")
-app.register_blueprint(links_blueprint, url_prefix="/links")
-app.register_blueprint(policies_blueprint, url_prefix="/policies")
-app.register_blueprint(environments_blueprint, url_prefix="/environments")
-app.register_blueprint(facilities_blueprint, url_prefix="/facilities")
-app.register_blueprint(blogs_blueprint, url_prefix="/blogs")
-app.register_blueprint(news_blueprint, url_prefix="/news")
-app.register_blueprint(jupyter_notebooks, url_prefix="/jupyter_notebooks")
-
-app.register_blueprint(resource_management, url_prefix="/resource-management")
-app.register_blueprint(metadata_edit, url_prefix="/datasets/")
-app.register_blueprint(group_management, url_prefix="/group-management")
-app.register_blueprint(jobs_bp, url_prefix="/jobs")
-app.register_blueprint(oauth2, url_prefix="/oauth2")
-
-from wqflask.decorators import AuthorisationError
-from wqflask.app_errors import (
- handle_generic_exceptions, handle_authorisation_error)
-app.register_error_handler(Exception, handle_generic_exceptions)
-app.register_error_handler(AuthorisationError, handle_authorisation_error)
-
-server_session = Session(app)
-
-@app.before_request
-def before_request():
- g.request_start_time = time.time()
- g.request_time = lambda: "%.5fs" % (time.time() - g.request_start_time)
-
- token = session.get("oauth2_token", False)
- if token and not bool(session.get("user_details", False)):
- config = current_app.config
- client = OAuth2Session(
- config["OAUTH2_CLIENT_ID"], config["OAUTH2_CLIENT_SECRET"],
- token=token)
- resp = client.get(
- urljoin(config["GN_SERVER_URL"], "oauth2/user"))
- user_details = resp.json()
- session["user_details"] = user_details
-
- if user_details.get("error") == "invalid_token":
- flash(user_details["error_description"], "alert-danger")
- flash("You are now logged out.", "alert-info")
- session.pop("user_details", None)
- session.pop("oauth2_token", None)
-
-@app.context_processor
-def include_admin_role_class():
- return {'AdminRole': AdminRole}
-
-
-@app.context_processor
-def include_data_role_class():
- return {'DataRole': DataRole}
-
-@app.before_request
-def get_user_session():
- g.user_session = UserSession()
- # I think this should solve the issue of deleting the cookie and redirecting to the home page when a user's session has expired
- if not g.user_session:
- response = make_response(redirect(url_for('login')))
- response.set_cookie('session_id_v2', '', expires=0)
- return response
-
-
-@app.after_request
-def set_user_session(response):
- if hasattr(g, 'user_session'):
- if not request.cookies.get(g.user_session.cookie_name):
- response.set_cookie(g.user_session.cookie_name,
- g.user_session.cookie)
- else:
- response.set_cookie('session_id_v2', '', expires=0)
- return response
-
-
from wqflask import group_manager
from wqflask import resource_manager
from wqflask import search_results
@@ -160,5 +49,62 @@ from wqflask import update_search_results
from wqflask import docs
from wqflask import db_info
-import wqflask.views
-import wqflask.partial_correlations_views
+def create_app():
+ """Create the application object."""
+ app = Flask(__name__)
+
+
+ # See http://flask.pocoo.org/docs/config/#configuring-from-files
+ # Note no longer use the badly named WQFLASK_OVERRIDES (nyi)
+ app.config.from_envvar('GN2_SETTINGS')
+
+ DB_HOST, DB_USER, DB_PASS, DB_NAME, DB_PORT = parse_db_url(app.config.get('SQL_URI'))
+ app.config["DB_HOST"] = DB_HOST
+ app.config["DB_USER"] = DB_USER
+ app.config["DB_PASS"] = DB_PASS
+ app.config["DB_NAME"] = DB_NAME
+ app.config["DB_PORT"] = DB_PORT
+
+ app.jinja_env.globals.update(
+ undefined=jinja2.StrictUndefined,
+ numify=formatting.numify,
+ logged_in=user_logged_in,
+ authserver_authorise_uri=authserver_authorise_uri,
+ user_details=user_details,
+ num_collections=num_collections,
+ url_for_hmac=url_for_hmac,
+ data_hmac=data_hmac)
+
+ app.config["SESSION_REDIS"] = redis.from_url(app.config["REDIS_URL"])
+
+ # Override settings
+ app = override_from_envvars(app)
+ app = set_mandatory_settings(app)
+ app = webqtlConfig.init_app(app)
+
+ # Registering blueprints
+ app.register_blueprint(toplevel)
+ app.register_blueprint(glossary_blueprint, url_prefix="/glossary")
+ app.register_blueprint(references_blueprint, url_prefix="/references")
+ app.register_blueprint(links_blueprint, url_prefix="/links")
+ app.register_blueprint(policies_blueprint, url_prefix="/policies")
+ app.register_blueprint(environments_blueprint, url_prefix="/environments")
+ app.register_blueprint(facilities_blueprint, url_prefix="/facilities")
+ app.register_blueprint(blogs_blueprint, url_prefix="/blogs")
+ app.register_blueprint(news_blueprint, url_prefix="/news")
+ app.register_blueprint(jupyter_notebooks, url_prefix="/jupyter_notebooks")
+
+ app.register_blueprint(resource_management, url_prefix="/resource-management")
+ app.register_blueprint(metadata_edit, url_prefix="/datasets/")
+ app.register_blueprint(group_management, url_prefix="/group-management")
+ app.register_blueprint(jobs_bp, url_prefix="/jobs")
+ app.register_blueprint(oauth2, url_prefix="/oauth2")
+
+ from wqflask.decorators import AuthorisationError
+ from wqflask.app_errors import (
+ handle_generic_exceptions, handle_authorisation_error)
+ app.register_error_handler(Exception, handle_generic_exceptions)
+ app.register_error_handler(AuthorisationError, handle_authorisation_error)
+
+ server_session = Session(app)
+ return app
diff --git a/wqflask/wqflask/app_errors.py b/wqflask/wqflask/app_errors.py
index c24fc9be..0a1f87ec 100644
--- a/wqflask/wqflask/app_errors.py
+++ b/wqflask/wqflask/app_errors.py
@@ -1,9 +1,12 @@
"""Handle errors at the application's top-level"""
+import os
+import sys
+import random
import datetime
import traceback
import werkzeug
-from flask import request, render_template, current_app as app
+from flask import request, make_response, render_template, current_app as app
from wqflask.decorators import AuthorisationError
diff --git a/wqflask/wqflask/oauth2/client.py b/wqflask/wqflask/oauth2/client.py
index 2a06b156..91cbb3e9 100644
--- a/wqflask/wqflask/oauth2/client.py
+++ b/wqflask/wqflask/oauth2/client.py
@@ -9,6 +9,8 @@ from pymonad.maybe import Just, Maybe, Nothing
from pymonad.either import Left, Right, Either
from authlib.integrations.requests_client import OAuth2Session
+from utility.configuration import get_setting
+
from wqflask.oauth2 import session
from wqflask.oauth2.checks import user_logged_in
@@ -17,10 +19,9 @@ SCOPE = ("profile group role resource register-client user masquerade "
def oauth2_client():
def __client__(token) -> OAuth2Session:
- from utility.tools import (
- GN_SERVER_URL, OAUTH2_CLIENT_ID, OAUTH2_CLIENT_SECRET)
return OAuth2Session(
- OAUTH2_CLIENT_ID, OAUTH2_CLIENT_SECRET,
+ get_setting(app, "OAUTH2_CLIENT_ID"),
+ get_setting(app, "OAUTH2_CLIENT_SECRET"),
scope=SCOPE, token_endpoint_auth_method="client_secret_post",
token=token)
return session.user_token().either(
@@ -39,13 +40,12 @@ def __no_token__(_err) -> Left:
def oauth2_get(uri_path: str, data: dict = {}, **kwargs) -> Either:
def __get__(token) -> Either:
- from utility.tools import (
- GN_SERVER_URL, OAUTH2_CLIENT_ID, OAUTH2_CLIENT_SECRET)
client = OAuth2Session(
- OAUTH2_CLIENT_ID, OAUTH2_CLIENT_SECRET,
+ get_setting(app, "OAUTH2_CLIENT_ID"),
+ get_setting(app, "OAUTH2_CLIENT_SECRET"),
token=token, scope=SCOPE)
resp = client.get(
- urljoin(GN_SERVER_URL, uri_path),
+ urljoin(get_setting(app, "GN_SERVER_URL"), uri_path),
data=data,
**kwargs)
if resp.status_code == 200:
@@ -59,13 +59,13 @@ def oauth2_post(
uri_path: str, data: Optional[dict] = None, json: Optional[dict] = None,
**kwargs) -> Either:
def __post__(token) -> Either:
- from utility.tools import (
- GN_SERVER_URL, OAUTH2_CLIENT_ID, OAUTH2_CLIENT_SECRET)
client = OAuth2Session(
- OAUTH2_CLIENT_ID, OAUTH2_CLIENT_SECRET,
+ get_setting(app, "OAUTH2_CLIENT_ID"),
+ get_setting(app, "OAUTH2_CLIENT_SECRET"),
token=token, scope=SCOPE)
resp = client.post(
- urljoin(GN_SERVER_URL, uri_path), data=data, json=json,
+ urljoin(get_setting(app, "GN_SERVER_URL"), uri_path),
+ data=data, json=json,
**kwargs)
if resp.status_code == 200:
return Right(resp.json())
@@ -75,22 +75,20 @@ def oauth2_post(
return session.user_token().either(__no_token__, __post__)
def no_token_get(uri_path: str, **kwargs) -> Either:
- from utility.tools import GN_SERVER_URL
- resp = requests.get(urljoin(GN_SERVER_URL, uri_path), **kwargs)
+ resp = requests.get(urljoin(
+ get_setting(app, "GN_SERVER_URL"), uri_path), **kwargs)
if resp.status_code == 200:
return Right(resp.json())
return Left(resp)
def no_token_post(uri_path: str, **kwargs) -> Either:
- from utility.tools import (
- GN_SERVER_URL, OAUTH2_CLIENT_ID, OAUTH2_CLIENT_SECRET)
data = kwargs.get("data", {})
the_json = kwargs.get("json", {})
request_data = {
**data,
**the_json,
- "client_id": OAUTH2_CLIENT_ID,
- "client_secret": OAUTH2_CLIENT_SECRET
+ "client_id": get_setting(app, "OAUTH2_CLIENT_ID"),
+ "client_secret": get_setting(app, "OAUTH2_CLIENT_SECRET")
}
new_kwargs = {
**{
@@ -99,7 +97,7 @@ def no_token_post(uri_path: str, **kwargs) -> Either:
},
("data" if bool(data) else "json"): request_data
}
- resp = requests.post(urljoin(GN_SERVER_URL, uri_path),
+ resp = requests.post(urljoin(get_setting(app, "GN_SERVER_URL"), uri_path),
**new_kwargs)
if resp.status_code == 200:
return Right(resp.json())
diff --git a/wqflask/wqflask/oauth2/request_utils.py b/wqflask/wqflask/oauth2/request_utils.py
index 992720f1..b7d57ad8 100644
--- a/wqflask/wqflask/oauth2/request_utils.py
+++ b/wqflask/wqflask/oauth2/request_utils.py
@@ -7,16 +7,17 @@ from flask import (
flash, request, session, url_for, redirect, Response, render_template,
current_app as app)
+from utility.configuration import get_setting
+
from .client import SCOPE, oauth2_get
def authserver_authorise_uri():
- from utility.tools import GN_SERVER_URL, OAUTH2_CLIENT_ID
req_baseurl = urlparse(request.base_url)
host_uri = f"{req_baseurl.scheme}://{req_baseurl.netloc}/"
return urljoin(
- GN_SERVER_URL,
+ get_setting(app, "GN_SERVER_URL"),
"oauth2/authorise?response_type=code"
- f"&client_id={OAUTH2_CLIENT_ID}"
+ f"&client_id={get_setting(app, 'OAUTH2_CLIENT_ID')}"
f"&redirect_uri={urljoin(host_uri, 'oauth2/code')}")
def raise_unimplemented():
diff --git a/wqflask/wqflask/templates/base.html b/wqflask/wqflask/templates/base.html
index 1328d229..5a881f51 100644
--- a/wqflask/wqflask/templates/base.html
+++ b/wqflask/wqflask/templates/base.html
@@ -12,7 +12,7 @@
</script>
<link rel="icon" type="image/png" sizes="64x64" href="/static/new/images/CITGLogo.png">
<link rel="apple-touch-icon" type="image/png" sizes="64x64" href="/static/new/images/CITGLogo.png">
- <link REL="stylesheet" TYPE="text/css" href="{{ url_for('css', filename='bootstrap/css/bootstrap.css') }}" />
+ <link REL="stylesheet" TYPE="text/css" href="{{ url_for('toplevel.main_views.css', filename='bootstrap/css/bootstrap.css') }}" />
<link REL="stylesheet" TYPE="text/css" href="/static/new/css/bootstrap-custom.css" />
<link REL="stylesheet" TYPE="text/css" href="/static/new/css/non-responsive.css" />
<link REL="stylesheet" TYPE="text/css" href="/static/new/css/docs.css" />
@@ -30,10 +30,10 @@
border-radius: 1rem;
}
table.dataTable thead .sorting_asc {
- background-image: url({{ url_for("js", filename="DataTables/images/sort_asc_disabled.png") }});
+ background-image: url({{ url_for("toplevel.main_views.js", filename="DataTables/images/sort_asc_disabled.png") }});
}
table.dataTable thead .sorting_desc {
- background-image: url({{ url_for("js", filename="DataTables/images/sort_desc_disabled.png") }});
+ background-image: url({{ url_for("toplevel.main_views.js", filename="DataTables/images/sort_desc_disabled.png") }});
}
@@ -336,8 +336,8 @@
<!-- <button class="btn btn-primary">Save changes</button>-->
<!--</div>-->
</div>
- <script src="{{ url_for('js', filename='jquery/jquery.min.js') }}" type="text/javascript"></script>
- <script src="{{ url_for('js', filename='bootstrap/js/bootstrap.min.js') }}" type="text/javascript"></script>
+ <script src="{{ url_for('toplevel.main_views.js', filename='jquery/jquery.min.js') }}" type="text/javascript"></script>
+ <script src="{{ url_for('toplevel.main_views.js', filename='bootstrap/js/bootstrap.min.js') }}" type="text/javascript"></script>
<script src="/static/new/javascript/search_autocomplete.js"></script>
<script>
//http://stackoverflow.com/questions/11521763/bootstrap-scrollspy-not-working
@@ -389,11 +389,11 @@
});
</script>
- <script src="{{ url_for('js', filename='jquery-cookie/jquery.cookie.js') }}" type="text/javascript"></script>
+ <script src="{{ url_for('toplevel.main_views.js', filename='jquery-cookie/jquery.cookie.js') }}" type="text/javascript"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
- <!-- <script src="{{ url_for('js', filename='jquery-ui/jquery-ui.min.js') }}" type="text/javascript"></script> -->
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='colorbox/jquery.colorbox-min.js') }}"></script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='js_alt/parsley.min.js') }}"></script>
+ <!-- <script src="{{ url_for('toplevel.main_views.js', filename='jquery-ui/jquery-ui.min.js') }}" type="text/javascript"></script> -->
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='colorbox/jquery.colorbox-min.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='js_alt/parsley.min.js') }}"></script>
{% block js %}
{% endblock %}
<script type="text/javascript">
diff --git a/wqflask/wqflask/templates/search_result_page.html b/wqflask/wqflask/templates/search_result_page.html
index 495c5669..fb92b9ed 100644
--- a/wqflask/wqflask/templates/search_result_page.html
+++ b/wqflask/wqflask/templates/search_result_page.html
@@ -1,10 +1,10 @@
{% extends "base.html" %}
{% block title %}Search Results{% endblock %}
{% block css %}
- <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='DataTables/css/jquery.dataTables.css') }}" />
- <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='fontawesome/css/font-awesome.min.css') }}" />
- <link rel="stylesheet" type="text/css" href="{{ url_for('js', filename='DataTablesExtensions/buttonStyles/css/buttons.dataTables.min.css') }}">
- <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='fontawesome/css/all.min.css') }}"/>
+ <link rel="stylesheet" type="text/css" href="{{ url_for('toplevel.main_views.css', filename='DataTables/css/jquery.dataTables.css') }}" />
+ <link rel="stylesheet" type="text/css" href="{{ url_for('toplevel.main_views.css', filename='fontawesome/css/font-awesome.min.css') }}" />
+ <link rel="stylesheet" type="text/css" href="{{ url_for('toplevel.main_views.js', filename='DataTablesExtensions/buttonStyles/css/buttons.dataTables.min.css') }}">
+ <link rel="stylesheet" type="text/css" href="{{ url_for('toplevel.main_views.css', filename='fontawesome/css/all.min.css') }}"/>
<link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" type="text/css" href="/static/new/css/show_trait.css" />
<link rel="stylesheet" type="text/css" href="static/new/css/trait_list.css" />
@@ -153,14 +153,14 @@
{% endblock %}
{% block js %}
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='js_alt/md5.min.js') }}"></script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTables/js/jquery.dataTables.min.js') }}"></script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTablesExtensions/scroller/js/dataTables.scroller.min.js') }}"></script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='jszip/jszip.min.js') }}"></script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTablesExtensions/plugins/sorting/natural.js') }}"></script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTablesExtensions/buttons/js/dataTables.buttons.min.js') }}"></script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTablesExtensions/buttons/js/buttons.colVis.min.js') }}"></script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='fontawesome/js/all.min.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='js_alt/md5.min.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='DataTables/js/jquery.dataTables.min.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='DataTablesExtensions/scroller/js/dataTables.scroller.min.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='jszip/jszip.min.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='DataTablesExtensions/plugins/sorting/natural.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='DataTablesExtensions/buttons/js/dataTables.buttons.min.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='DataTablesExtensions/buttons/js/buttons.colVis.min.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='fontawesome/js/all.min.js') }}"></script>
<script language="javascript" type="text/javascript" src="/static/new/javascript/search_results.js"></script>
<script language="javascript" type="text/javascript" src="/static/new/javascript/table_functions.js"></script>
diff --git a/wqflask/wqflask/templates/show_trait.html b/wqflask/wqflask/templates/show_trait.html
index 84231d34..3b3a8ac7 100644
--- a/wqflask/wqflask/templates/show_trait.html
+++ b/wqflask/wqflask/templates/show_trait.html
@@ -8,9 +8,9 @@
<link rel="stylesheet" type="text/css" href="/static/new/css/box_plot.css" />
<link rel="stylesheet" type="text/css" href="/static/new/css/prob_plot.css" />
<link rel="stylesheet" type="text/css" href="/static/new/css/scatter-matrix.css" />
- <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='d3-tip/d3-tip.css') }}" />
- <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='DataTables/css/jquery.dataTables.css') }}" />
- <link rel="stylesheet" type="text/css" href="{{ url_for('css', filename='nouislider/nouislider.min.css') }}" />
+ <link rel="stylesheet" type="text/css" href="{{ url_for('toplevel.main_views.css', filename='d3-tip/d3-tip.css') }}" />
+ <link rel="stylesheet" type="text/css" href="{{ url_for('toplevel.main_views.css', filename='DataTables/css/jquery.dataTables.css') }}" />
+ <link rel="stylesheet" type="text/css" href="{{ url_for('toplevel.main_views.css', filename='nouislider/nouislider.min.css') }}" />
<link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" type="text/css" href="/static/new/css/trait_list.css" />
<link rel="stylesheet" type="text/css" href="/static/new/css/show_trait.css" />
@@ -139,13 +139,13 @@
$('.collapse').collapse()
</script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='d3js/d3.min.js') }}"></script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='js_alt/underscore.min.js') }}"></script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='underscore-string/underscore.string.min.js') }}"></script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='d3-tip/d3-tip.js') }}"></script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='js_alt/jstat.min.js') }}"></script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='shapiro-wilk/shapiro-wilk.js') }}"></script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='plotly/plotly.min.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='d3js/d3.min.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='js_alt/underscore.min.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='underscore-string/underscore.string.min.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='d3-tip/d3-tip.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='js_alt/jstat.min.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='shapiro-wilk/shapiro-wilk.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='plotly/plotly.min.js') }}"></script>
<script language="javascript" type="text/javascript" src="/static/new/javascript/colorbrewer.js"></script>
<script language="javascript" type="text/javascript" src="/static/new/javascript/stats.js"></script>
@@ -154,11 +154,11 @@
<script language="javascript" type="text/javascript" src="/static/new/javascript/compare_traits_scatterplot.js"></script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTables/js/jquery.dataTables.js') }}"></script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTablesExtensions/plugins/sorting/scientific.js') }}"></script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTablesExtensions/plugins/sorting/natural.js') }}"></script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='DataTablesExtensions/scroller/js/dataTables.scroller.min.js') }}"></script>
- <script language="javascript" type="text/javascript" src="{{ url_for('js', filename='nouislider/nouislider.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='DataTables/js/jquery.dataTables.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='DataTablesExtensions/plugins/sorting/scientific.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='DataTablesExtensions/plugins/sorting/natural.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='DataTablesExtensions/scroller/js/dataTables.scroller.min.js') }}"></script>
+ <script language="javascript" type="text/javascript" src="{{ url_for('toplevel.main_views.js', filename='nouislider/nouislider.js') }}"></script>
<script language="javascript" type="text/javascript" src="/static/new/javascript/table_functions.js"></script>
<script language="javascript" type="text/javascript" src="/static/new/javascript/create_datatable.js"></script>
<script language="javascript" type="text/javascript" src="/static/new/javascript/initialize_show_trait_tables.js"></script>
diff --git a/wqflask/wqflask/templates/tool_buttons.html b/wqflask/wqflask/templates/tool_buttons.html
index c6d1476c..95064dbb 100644
--- a/wqflask/wqflask/templates/tool_buttons.html
+++ b/wqflask/wqflask/templates/tool_buttons.html
@@ -32,7 +32,7 @@
<button id="partial-correlations"
class="btn btn-primary submit_special"
- data-url="{{url_for('partial_correlations')}}"
+ data-url="{{url_for('toplevel.partial_correlations.partial_correlations')}}"
title="Run partial correlations with the selected traits">
Partial Correlations
</button>
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index ebd273af..689e3436 100644
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -30,7 +30,6 @@ from flask import current_app as app
from flask import g
from flask import Response
from flask import request
-from flask import make_response
from flask import render_template
from flask import send_from_directory
from flask import redirect