diff options
| -rw-r--r-- | uploader/__init__.py | 12 | ||||
| -rw-r--r-- | uploader/base_routes.py | 5 | ||||
| -rw-r--r-- | uploader/default_settings.py | 4 | ||||
| -rw-r--r-- | uploader/expression_data/views.py | 2 | ||||
| -rw-r--r-- | uploader/flask_extensions.py | 33 | ||||
| -rw-r--r-- | uploader/genotypes/views.py | 2 | ||||
| -rw-r--r-- | uploader/oauth2/views.py | 2 | ||||
| -rw-r--r-- | uploader/phenotypes/views.py | 4 | ||||
| -rw-r--r-- | uploader/platforms/views.py | 2 | ||||
| -rw-r--r-- | uploader/population/views.py | 2 | ||||
| -rw-r--r-- | uploader/publications/views.py | 2 | ||||
| -rw-r--r-- | uploader/route_utils.py | 2 | ||||
| -rw-r--r-- | uploader/samples/views.py | 2 | ||||
| -rw-r--r-- | uploader/species/views.py | 12 | ||||
| -rw-r--r-- | uploader/templates/base.html | 2 | ||||
| -rw-r--r-- | uploader/templates/macro-forms.html | 9 | ||||
| -rw-r--r-- | uploader/templates/populations/sui-base.html | 3 | ||||
| -rw-r--r-- | uploader/templates/populations/sui-view-population.html | 9 | ||||
| -rw-r--r-- | uploader/templates/species/sui-base.html | 2 | ||||
| -rw-r--r-- | uploader/templates/species/sui-view-species.html | 1 | ||||
| -rw-r--r-- | uploader/templates/sui-base.html | 2 | ||||
| -rw-r--r-- | uploader/templates/sui-index.html | 4 |
22 files changed, 82 insertions, 36 deletions
diff --git a/uploader/__init__.py b/uploader/__init__.py index b7f0ab9..7425b38 100644 --- a/uploader/__init__.py +++ b/uploader/__init__.py @@ -22,6 +22,7 @@ from .files.views import files from .species import speciesbp from .publications import pubbp from .oauth2.views import oauth2 +from .flask_extensions import url_for from .expression_data import exprdatabp from .errors import register_error_handlers from .background_jobs import background_jobs_bp @@ -109,17 +110,22 @@ def create_app(config: Optional[dict] = None): setup_logging(app) setup_modules_logging(app.logger, ( "uploader.base_routes", + "uploader.flask_extensions", "uploader.publications.models", "uploader.publications.datatables", "uploader.phenotypes.models")) # setup jinja2 symbols - app.add_template_global(lambda : request.url, name="request_url") + app.add_template_global(user_logged_in) + app.add_template_global(url_for, name="url_for") app.add_template_global(authserver_authorise_uri) + app.add_template_global(lambda : request.url, name="request_url") app.add_template_global(lambda: app.config["GN2_SERVER_URL"], name="gn2server_uri") - app.add_template_global(user_logged_in) - app.add_template_global(lambda : session.user_details()["email"], name="user_email") + app.add_template_global(lambda : session.user_details()["email"], + name="user_email") + app.add_template_global(lambda: app.config["FEATURE_FLAGS_HTTP"], + name="http_feature_flags") Session(app) diff --git a/uploader/base_routes.py b/uploader/base_routes.py index 3d0e1b2..80a15a0 100644 --- a/uploader/base_routes.py +++ b/uploader/base_routes.py @@ -6,12 +6,12 @@ from urllib.parse import urljoin from gn_libs.mysqldb import database_connection from flask import (flash, request, - url_for, redirect, Blueprint, current_app as app, send_from_directory) +from uploader.flask_extensions import url_for from uploader.ui import make_template_renderer from uploader.oauth2.client import user_logged_in from uploader.species.models import all_species, species_by_id @@ -53,8 +53,7 @@ def index(): return redirect(url_for("base.index", streamlined_ui=streamlined_ui)) return redirect(url_for("species.view_species", - species_id=species["SpeciesId"], - streamlined_ui=streamlined_ui)) + species_id=species["SpeciesId"])) def appenv(): diff --git a/uploader/default_settings.py b/uploader/default_settings.py index c5986ab..bb3a967 100644 --- a/uploader/default_settings.py +++ b/uploader/default_settings.py @@ -29,3 +29,7 @@ SESSION_FILESYSTEM_CACHE_HASH_METHOD = None # default: hashlib.md5 JWKS_ROTATION_AGE_DAYS = 7 # Days (from creation) to keep a JWK in use. JWKS_DELETION_AGE_DAYS = 14 # Days (from creation) to keep a JWK around before deleting it. + + +## --- Feature flags --- +FEATURE_FLAGS_HTTP = [] diff --git a/uploader/expression_data/views.py b/uploader/expression_data/views.py index 7629f3e..0b318b7 100644 --- a/uploader/expression_data/views.py +++ b/uploader/expression_data/views.py @@ -11,7 +11,6 @@ from werkzeug.utils import secure_filename from gn_libs.mysqldb import database_connection from flask import (flash, request, - url_for, redirect, Blueprint, current_app as app) @@ -19,6 +18,7 @@ from flask import (flash, from quality_control.errors import InvalidValue, DuplicateHeading from uploader import jobs +from uploader.flask_extensions import url_for from uploader.datautils import order_by_family from uploader.ui import make_template_renderer from uploader.authorisation import require_login diff --git a/uploader/flask_extensions.py b/uploader/flask_extensions.py new file mode 100644 index 0000000..30fbad7 --- /dev/null +++ b/uploader/flask_extensions.py @@ -0,0 +1,33 @@ +"""Custom extensions to the default flask functions/classes.""" +import logging +from typing import Any, Optional + +from flask import (request, current_app as app, url_for as flask_url_for) + +logger = logging.getLogger(__name__) + + +def url_for( + endpoint: str, + _anchor: Optional[str] = None, + _method: Optional[str] = None, + _scheme: Optional[str] = None, + _external: Optional[bool] = None, + **values: Any) -> str: + """Extension to flask's `url_for` function.""" + flags = {} + for flag in app.config["FEATURE_FLAGS_HTTP"]: + flag_value = (request.args.get(flag) or request.form.get(flag) or "").strip() + if bool(flag_value): + flags[flag] = flag_value + continue + continue + + logger.debug("HTTP FEATURE FLAGS: %s, other variables: %s", flags, values) + return flask_url_for(endpoint=endpoint, + _anchor=_anchor, + _method=_method, + _scheme=_scheme, + _external=_external, + **values, + **flags) diff --git a/uploader/genotypes/views.py b/uploader/genotypes/views.py index 54c2444..d991614 100644 --- a/uploader/genotypes/views.py +++ b/uploader/genotypes/views.py @@ -3,12 +3,12 @@ from MySQLdb.cursors import DictCursor from gn_libs.mysqldb import database_connection from flask import (flash, request, - url_for, redirect, Blueprint, render_template, current_app as app) +from uploader.flask_extensions import url_for from uploader.ui import make_template_renderer from uploader.oauth2.client import oauth2_post from uploader.authorisation import require_login diff --git a/uploader/oauth2/views.py b/uploader/oauth2/views.py index 1ee4257..05f8542 100644 --- a/uploader/oauth2/views.py +++ b/uploader/oauth2/views.py @@ -4,13 +4,13 @@ from urllib.parse import urljoin, urlparse, urlunparse from flask import ( flash, jsonify, - url_for, request, redirect, Blueprint, current_app as app) from uploader import session +from uploader.flask_extensions import url_for from uploader import monadic_requests as mrequests from uploader.monadic_requests import make_error_handler diff --git a/uploader/phenotypes/views.py b/uploader/phenotypes/views.py index 15d2b6c..2afd8a3 100644 --- a/uploader/phenotypes/views.py +++ b/uploader/phenotypes/views.py @@ -23,7 +23,6 @@ from gn_libs.mysqldb import database_connection from flask import (flash, request, - url_for, jsonify, redirect, Blueprint, @@ -35,7 +34,8 @@ from r_qtl import exceptions as rqe from uploader import jobs from uploader import session -from uploader.files import save_file#, fullpath +from uploader.files import save_file +from uploader.flask_extensions import url_for from uploader.ui import make_template_renderer from uploader.oauth2.client import oauth2_post from uploader.oauth2.tokens import request_token diff --git a/uploader/platforms/views.py b/uploader/platforms/views.py index d12a9ef..ba0f0ef 100644 --- a/uploader/platforms/views.py +++ b/uploader/platforms/views.py @@ -4,11 +4,11 @@ from gn_libs.mysqldb import database_connection from flask import ( flash, request, - url_for, redirect, Blueprint, current_app as app) +from uploader.flask_extensions import url_for from uploader.ui import make_template_renderer from uploader.authorisation import require_login from uploader.species.models import all_species, species_by_id diff --git a/uploader/population/views.py b/uploader/population/views.py index cfc3b70..8d4ceb7 100644 --- a/uploader/population/views.py +++ b/uploader/population/views.py @@ -7,12 +7,12 @@ from MySQLdb.cursors import DictCursor from gn_libs.mysqldb import database_connection from flask import (flash, request, - url_for, redirect, Blueprint, current_app as app) from uploader.samples.views import samplesbp +from uploader.flask_extensions import url_for from uploader.oauth2.client import oauth2_post from uploader.ui import make_template_renderer from uploader.authorisation import require_login diff --git a/uploader/publications/views.py b/uploader/publications/views.py index 805d6f0..4ec832f 100644 --- a/uploader/publications/views.py +++ b/uploader/publications/views.py @@ -5,12 +5,12 @@ from gn_libs.mysqldb import database_connection from flask import ( flash, request, - url_for, redirect, Blueprint, render_template, current_app as app) +from uploader.flask_extensions import url_for from uploader.authorisation import require_login from uploader.route_utils import redirect_to_next diff --git a/uploader/route_utils.py b/uploader/route_utils.py index 53247e6..4449475 100644 --- a/uploader/route_utils.py +++ b/uploader/route_utils.py @@ -3,7 +3,6 @@ import logging from json.decoder import JSONDecodeError from flask import (flash, - url_for, request, redirect, render_template, @@ -11,6 +10,7 @@ from flask import (flash, from gn_libs.mysqldb import database_connection +from uploader.flask_extensions import url_for from uploader.datautils import base64_encode_dict, base64_decode_to_dict from uploader.population.models import (populations_by_species, population_by_species_and_id) diff --git a/uploader/samples/views.py b/uploader/samples/views.py index 4705a96..f8baf7e 100644 --- a/uploader/samples/views.py +++ b/uploader/samples/views.py @@ -7,13 +7,13 @@ from pathlib import Path from redis import Redis from flask import (flash, request, - url_for, redirect, Blueprint, current_app as app) from uploader import jobs from uploader.files import save_file +from uploader.flask_extensions import url_for from uploader.ui import make_template_renderer from uploader.authorisation import require_login from uploader.input_validation import is_integer_input diff --git a/uploader/species/views.py b/uploader/species/views.py index a490b0f..20acd01 100644 --- a/uploader/species/views.py +++ b/uploader/species/views.py @@ -4,13 +4,13 @@ from pymonad.either import Left, Right, Either from gn_libs.mysqldb import database_connection from flask import (flash, request, - url_for, redirect, Blueprint, current_app as app) from uploader.population import popbp from uploader.platforms import platformsbp +from uploader.flask_extensions import url_for from uploader.ui import make_template_renderer from uploader.oauth2.client import oauth2_get, oauth2_post from uploader.authorisation import require_login, require_token @@ -52,21 +52,19 @@ def view_species(species_id: int): if bool(population): return redirect(url_for("species.populations.view_population", species_id=species_id, - population_id=population["Id"], - streamlined_ui=streamlined_ui)) + population_id=population["Id"])) return render_template( ("species/sui-view-species.html" if bool(streamlined_ui) else "species/view-species.html"), species=species, activelink="view-species", - streamlined_ui=streamlined_ui, populations=populations_by_species(conn, species["SpeciesId"])) flash("Could not find a species with the given identifier.", "alert-danger") - return redirect(url_for( - ("base.index" if streamlined_ui else "species.view_species"), - streamlined_ui=streamlined_ui)) + return redirect(url_for("base.index" + if streamlined_ui + else "species.view_species")) @speciesbp.route("/create", methods=["GET", "POST"]) @require_login diff --git a/uploader/templates/base.html b/uploader/templates/base.html index 3c0d0d4..d521ccb 100644 --- a/uploader/templates/base.html +++ b/uploader/templates/base.html @@ -45,7 +45,7 @@ <aside id="nav-sidebar"> <ul class="nav flex-column"> <li {%if activemenu=="home"%}class="activemenu"{%endif%}> - <a href="/" >Home</a></li> + <a href="{{url_for('base.index')}}" >Home</a></li> <li {%if activemenu=="publications"%}class="activemenu"{%endif%}> <a href="{{url_for('publications.index')}}" title="View and manage publications.">Publications</a></li> diff --git a/uploader/templates/macro-forms.html b/uploader/templates/macro-forms.html new file mode 100644 index 0000000..0ccab32 --- /dev/null +++ b/uploader/templates/macro-forms.html @@ -0,0 +1,9 @@ +{%macro add_http_feature_flags()%} +{%for flag in http_feature_flags():%} +{%if (request.args.get(flag) or request.form.get(flag) or ""):%} +<input type="hidden" + name="{{flag}}" + value="{{(request.args.get(flag) or request.form.get(flag))}}" /> +{%endif%} +{%endfor%} +{%endmacro%} diff --git a/uploader/templates/populations/sui-base.html b/uploader/templates/populations/sui-base.html index 88d3f54..cc01c9e 100644 --- a/uploader/templates/populations/sui-base.html +++ b/uploader/templates/populations/sui-base.html @@ -5,8 +5,7 @@ <li class="breadcrumb-item"> <a href="{{url_for('species.populations.view_population', species_id=species['SpeciesId'], - population_id=population['Id'], - streamlined_ui=streamlined_ui)}}"> + population_id=population['Id'])}}"> {{population["FullName"]}} </a> </li> diff --git a/uploader/templates/populations/sui-view-population.html b/uploader/templates/populations/sui-view-population.html index a9f506a..9b10ad4 100644 --- a/uploader/templates/populations/sui-view-population.html +++ b/uploader/templates/populations/sui-view-population.html @@ -68,8 +68,7 @@ in your data.</p> <a href="{{url_for('species.populations.samples.list_samples', species_id=species.SpeciesId, - population_id=population.Id, - streamlined_ui=streamlined_ui)}}" + population_id=population.Id)}}" title="Upload samples for population '{{population['Name']}}'" class="btn btn-primary">Upload Samples</a> </div> @@ -88,8 +87,7 @@ <a href="{{url_for('species.populations.phenotypes.view_dataset', species_id=species.SpeciesId, population_id=population.Id, - dataset_id=dataset.Id, - streamlined_ui=streamlined_ui)}}" + dataset_id=dataset.Id)}}" title="Upload phenotype data for population '{{population['Name']}}'" class="btn btn-primary">Upload Phenotypes</a> </div> @@ -102,8 +100,7 @@ system will be added. This does not delete any existing data.</p> <a href="{{url_for('species.populations.genotypes.list_genotypes', species_id=species.SpeciesId, - population_id=population.Id, - streamlined_ui=streamlined_ui)}}" + population_id=population.Id)}}" title="Upload genotype information for the '{{population.FullName}}' population of the '{{species.FullName}}' species." class="btn btn-primary">upload genotypes</a> </div> diff --git a/uploader/templates/species/sui-base.html b/uploader/templates/species/sui-base.html index 5d2e6e3..f7b4fef 100644 --- a/uploader/templates/species/sui-base.html +++ b/uploader/templates/species/sui-base.html @@ -3,7 +3,7 @@ {%block breadcrumbs%} {{super()}} <li class="breadcrumb-item"> - <a href="{{url_for('species.view_species', species_id=species['SpeciesId'], streamlined_ui=streamlined_ui)}}"> + <a href="{{url_for('species.view_species', species_id=species['SpeciesId'])}}"> {{species["Name"]|title}} </a> </li> diff --git a/uploader/templates/species/sui-view-species.html b/uploader/templates/species/sui-view-species.html index 5373766..c7ac956 100644 --- a/uploader/templates/species/sui-view-species.html +++ b/uploader/templates/species/sui-view-species.html @@ -1,5 +1,6 @@ {%extends "species/sui-base.html"%} {%from "flash_messages.html" import flash_all_messages%} +{%from "macro-forms.html" import add_http_feature_flags%} {%from "macro-step-indicator.html" import step_indicator%} {%from "species/macro-display-species-card.html" import display_sui_species_card%} diff --git a/uploader/templates/sui-base.html b/uploader/templates/sui-base.html index 4aec354..719a646 100644 --- a/uploader/templates/sui-base.html +++ b/uploader/templates/sui-base.html @@ -52,7 +52,7 @@ <ol class="breadcrumb"> {%block breadcrumbs%} <li class="breadcrumb-item"> - <a href="{{url_for('base.index', streamlined_ui='true')}}">Home</a></li> + <a href="{{url_for('base.index')}}">Home</a></li> {%endblock%} </ol> </nav> diff --git a/uploader/templates/sui-index.html b/uploader/templates/sui-index.html index e6873e2..260ec30 100644 --- a/uploader/templates/sui-index.html +++ b/uploader/templates/sui-index.html @@ -1,5 +1,6 @@ {%extends "sui-base.html"%} {%from "flash_messages.html" import flash_all_messages%} +{%from "macro-forms.html" import add_http_feature_flags%} {%from "macro-step-indicator.html" import step_indicator%} {%block title%}Home{%endblock%} @@ -25,8 +26,7 @@ <div class="row"> <form method="GET" action="{{url_for('base.index')}}" class="form-horizontal"> - <input type="hidden" name="streamlined_ui", value="{{streamlined_ui}}" /> - + {{add_http_feature_flags()}} {%if species | length != 0%} <div style="margin-top:3em;"> <table id="tbl-select-species" class="table compact stripe" |
