From 12b30aa71d10831e9887f100a04ec7d2d6bd7501 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mat=C4=9Bj=20T=C3=BD=C4=8D?=
Date: Thu, 14 Dec 2023 22:57:15 +0100
Subject: [PATCH] Style improvements
---
.../templates/rhcompliance.html | 2 +-
estimage/webapp/__init__.py | 21 +++++++++
estimage/webapp/main/routes.py | 20 ++++-----
estimage/webapp/templates/base.html | 4 +-
estimage/webapp/templates/completion.html | 4 +-
estimage/webapp/templates/epic_view.html | 2 +-
.../templates/epic_view_retrospective.html | 4 +-
estimage/webapp/templates/general_plan.html | 4 +-
estimage/webapp/templates/general_retro.html | 8 ++--
estimage/webapp/templates/issue_view.html | 8 ++--
.../templates/retrospective_overview.html | 4 +-
estimage/webapp/templates/tree_view.html | 4 +-
estimage/webapp/templates/utils.j2 | 10 ++---
estimage/webapp/web_utils.py | 43 +++++++++----------
14 files changed, 79 insertions(+), 59 deletions(-)
diff --git a/estimage/plugins/redhat_compliance/templates/rhcompliance.html b/estimage/plugins/redhat_compliance/templates/rhcompliance.html
index b61dab7..0af0fae 100644
--- a/estimage/plugins/redhat_compliance/templates/rhcompliance.html
+++ b/estimage/plugins/redhat_compliance/templates/rhcompliance.html
@@ -7,7 +7,7 @@
Red Hat Compliance Plugin
- {{ render_form(plugin_form, action=relative_url_for("rhcompliance.sync")) }}
+ {{ render_form(plugin_form, action=head_url_for("rhcompliance.sync")) }}
{% endblock %}
diff --git a/estimage/webapp/__init__.py b/estimage/webapp/__init__.py
index 5d5ff5c..b494d59 100644
--- a/estimage/webapp/__init__.py
+++ b/estimage/webapp/__init__.py
@@ -38,6 +38,12 @@ def get_final_class(self, class_name):
def get_config_option(self, option):
raise NotImplementedError()
+ def get_plugins_in_context(self):
+ raise NotImplementedError()
+
+ def get_correct_context_endpoint(self, endpoint):
+ return endpoint
+
class PluginFriendlySingleheadFlask(PluginFriendlyFlask):
def __init__(self, import_name, ** kwargs):
@@ -55,8 +61,13 @@ def store_plugins_to_config(self):
def get_config_option(self, option):
return self.config[option]
+ def get_plugins_in_context(self):
+ return self.get_config_option("PLUGINS")
+
class PluginFriendlyMultiheadFlask(PluginFriendlyFlask):
+ NON_HEAD_BLUEPRINTS = ("login", "neck")
+
def __init__(self, import_name, ** kwargs):
super().__init__(import_name, ** kwargs)
self._plugin_resolvers = dict()
@@ -80,6 +91,16 @@ def current_head(self):
def get_config_option(self, option):
return self.config["head"][self.current_head][option]
+ def get_correct_context_endpoint(self, endpoint):
+ if (head_name := self.current_head) in self.NON_HEAD_BLUEPRINTS:
+ return super().get_correct_context_endpoint(endpoint)
+ return f"{head_name}.{endpoint}"
+
+ def get_plugins_in_context(self):
+ if self.current_head in self.NON_HEAD_BLUEPRINTS:
+ return dict()
+ return self.get_config_option("PLUGINS")
+
def create_app(config_class=config.Config):
app = PluginFriendlySingleheadFlask(__name__)
diff --git a/estimage/webapp/main/routes.py b/estimage/webapp/main/routes.py
index d970ce7..03b119a 100644
--- a/estimage/webapp/main/routes.py
+++ b/estimage/webapp/main/routes.py
@@ -80,7 +80,7 @@ def move_issue_estimate_to_consensus(task_name):
flask.flash("Consensus not updated, request was not serious")
return flask.redirect(
- web_utils.url_for("main.view_projective_task", task_name=task_name))
+ web_utils.head_url_for("main.view_projective_task", task_name=task_name))
@bp.route('/authoritative/', methods=['POST'])
@@ -103,7 +103,7 @@ def move_consensus_estimate_to_authoritative(task_name):
flask.flash("Authoritative estimate not updated, request was not serious")
return flask.redirect(
- web_utils.url_for("main.view_projective_task", task_name=task_name))
+ web_utils.head_url_for("main.view_projective_task", task_name=task_name))
@bp.route('/estimate/', methods=['POST'])
@@ -129,7 +129,7 @@ def estimate(task_name):
msg += ", ".join(form.get_all_errors())
flask.flash(msg)
return flask.redirect(
- web_utils.url_for("main.view_projective_task", task_name=task_name))
+ web_utils.head_url_for("main.view_projective_task", task_name=task_name))
def tell_of_bad_estimation_input(task_name, task_category, message):
@@ -177,7 +177,7 @@ def view_projective_task(task_name):
authoritative=flask.current_app.get_final_class("AuthoritativeForm")(),
)
breadcrumbs = get_projective_breadcrumbs()
- append_target_to_breadcrumbs(breadcrumbs, t, lambda n: web_utils.url_for("main.view_epic", epic_name=n))
+ append_target_to_breadcrumbs(breadcrumbs, t, lambda n: web_utils.head_url_for("main.view_epic", epic_name=n))
return view_task(t, breadcrumbs, request_forms)
@@ -187,7 +187,7 @@ def view_retro_task(task_name):
t = retro_retrieve_task(task_name)
breadcrumbs = get_retro_breadcrumbs()
- append_target_to_breadcrumbs(breadcrumbs, t, lambda n: web_utils.url_for("main.view_epic_retro", epic_name=n))
+ append_target_to_breadcrumbs(breadcrumbs, t, lambda n: web_utils.head_url_for("main.view_epic_retro", epic_name=n))
return view_task(t, breadcrumbs)
@@ -231,13 +231,13 @@ def view_task(task, breadcrumbs, request_forms=None):
def get_projective_breadcrumbs():
breadcrumbs = collections.OrderedDict()
- breadcrumbs["Planning"] = web_utils.url_for("main.tree_view")
+ breadcrumbs["Planning"] = web_utils.head_url_for("main.tree_view")
return breadcrumbs
def get_retro_breadcrumbs():
breadcrumbs = collections.OrderedDict()
- breadcrumbs["Retrospective"] = web_utils.url_for("main.tree_view_retro")
+ breadcrumbs["Retrospective"] = web_utils.head_url_for("main.tree_view_retro")
return breadcrumbs
@@ -273,7 +273,7 @@ def view_epic(epic_name):
refresh_form.next.data = flask.request.path
breadcrumbs = get_projective_breadcrumbs()
- append_target_to_breadcrumbs(breadcrumbs, t, lambda n: web_utils.url_for("main.view_epic", epic_name=n))
+ append_target_to_breadcrumbs(breadcrumbs, t, lambda n: web_utils.head_url_for("main.view_epic", epic_name=n))
return web_utils.render_template(
'epic_view.html', title='View epic', epic=t, estimate=estimate, model=model, breadcrumbs=breadcrumbs,
@@ -291,7 +291,7 @@ def get_similar_tasks(user_id, task_name, all_targets_by_id):
@bp.route('/')
def index():
- return flask.redirect(web_utils.url_for("main.overview_retro"))
+ return flask.redirect(web_utils.head_url_for("main.overview_retro"))
@bp.route('/refresh', methods=["POST"])
@@ -424,7 +424,7 @@ def view_epic_retro(epic_name):
summary = executive_summary_of_points_and_velocity(t.children)
breadcrumbs = get_retro_breadcrumbs()
- append_target_to_breadcrumbs(breadcrumbs, t, lambda n: web_utils.url_for("main.view_epic_retro", epic_name=n))
+ append_target_to_breadcrumbs(breadcrumbs, t, lambda n: web_utils.head_url_for("main.view_epic_retro", epic_name=n))
return web_utils.render_template(
'epic_view_retrospective.html', title='View epic', breadcrumbs=breadcrumbs,
diff --git a/estimage/webapp/templates/base.html b/estimage/webapp/templates/base.html
index 1a3bbff..5d0f1cd 100644
--- a/estimage/webapp/templates/base.html
+++ b/estimage/webapp/templates/base.html
@@ -19,8 +19,8 @@
{% block navbar %}
{% block navbar_common %}
- {{ render_nav_item(head_prefix ~ 'main.overview_retro', 'Retrospective') }}
- {{ render_nav_item(head_prefix ~ 'main.tree_view', 'Planning') }}
+ {{ render_nav_item(get_head_absolute_endpoint('main.overview_retro'), 'Retrospective') }}
+ {{ render_nav_item(get_head_absolute_endpoint('main.tree_view'), 'Planning') }}
{% endblock %}
{% block navbar_custom %}
{% for name, entrypoint in custom_items.items() %}
diff --git a/estimage/webapp/templates/completion.html b/estimage/webapp/templates/completion.html
index 4c37e6d..a53cfee 100644
--- a/estimage/webapp/templates/completion.html
+++ b/estimage/webapp/templates/completion.html
@@ -10,7 +10,7 @@
Velocity
-
+
@@ -24,7 +24,7 @@ Completion
Estimated time of delivery - between {{ "%.2g" % (summary.completion[0] / 7.0) }} to {{ "%.2g" % (summary.completion[1] / 7.0) }} weeks from now.
-
+
{% endblock completion %}
diff --git a/estimage/webapp/templates/epic_view.html b/estimage/webapp/templates/epic_view.html
index f3d45c4..0736080 100644
--- a/estimage/webapp/templates/epic_view.html
+++ b/estimage/webapp/templates/epic_view.html
@@ -30,7 +30,7 @@ Sum of subtasks
Remaining point cost: {{ utils.render_estimate(model.remaining_point_estimate_of(epic.name)) }}
Nominal point cost: {{ utils.render_estimate(model.nominal_point_estimate_of(epic.name)) }}
-
+
{%- if similar_sized_epics %}
diff --git a/estimage/webapp/templates/epic_view_retrospective.html b/estimage/webapp/templates/epic_view_retrospective.html
index c46182e..65b70e9 100644
--- a/estimage/webapp/templates/epic_view_retrospective.html
+++ b/estimage/webapp/templates/epic_view_retrospective.html
@@ -23,7 +23,7 @@ Burndown
-
+
@@ -35,7 +35,7 @@
Velocity
-
+
{% else -%}
diff --git a/estimage/webapp/templates/general_plan.html b/estimage/webapp/templates/general_plan.html
index 057242d..d2a0a34 100644
--- a/estimage/webapp/templates/general_plan.html
+++ b/estimage/webapp/templates/general_plan.html
@@ -1,6 +1,6 @@
{% extends "base.html" %}
{% block navbar_secondary_common %}
- {{ render_nav_item(head_prefix ~ 'main.tree_view', 'Tree View') }}
- {{ render_nav_item(head_prefix ~ 'persons.planning_workload', 'Workloads') }}
+ {{ render_nav_item(get_head_absolute_endpoint('main.tree_view'), 'Tree View') }}
+ {{ render_nav_item(get_head_absolute_endpoint('persons.planning_workload'), 'Workloads') }}
{% endblock %}
diff --git a/estimage/webapp/templates/general_retro.html b/estimage/webapp/templates/general_retro.html
index c41c3e1..f904644 100644
--- a/estimage/webapp/templates/general_retro.html
+++ b/estimage/webapp/templates/general_retro.html
@@ -1,8 +1,8 @@
{% extends "base.html" %}
{% block navbar_secondary_common %}
- {{ render_nav_item(head_prefix ~ 'main.overview_retro', 'Overview') }}
- {{ render_nav_item(head_prefix ~ 'main.tree_view_retro', 'Tree View') }}
- {{ render_nav_item(head_prefix ~ 'persons.retrospective_workload', 'Workloads') }}
- {{ render_nav_item(head_prefix ~ 'main.completion', 'Completion') }}
+ {{ render_nav_item(get_head_absolute_endpoint('main.overview_retro'), 'Overview') }}
+ {{ render_nav_item(get_head_absolute_endpoint('main.tree_view_retro'), 'Tree View') }}
+ {{ render_nav_item(get_head_absolute_endpoint('persons.retrospective_workload'), 'Workloads') }}
+ {{ render_nav_item(get_head_absolute_endpoint('main.completion'), 'Completion') }}
{% endblock %}
diff --git a/estimage/webapp/templates/issue_view.html b/estimage/webapp/templates/issue_view.html
index 716b74d..e5ca4db 100644
--- a/estimage/webapp/templates/issue_view.html
+++ b/estimage/webapp/templates/issue_view.html
@@ -20,7 +20,7 @@
{{ utils.accordion_with_stuff(
"Estimation", estimate_exists,
("Modify" if estimate_exists else "Create") ~ " the estimate",
- render_form(forms["estimation"], button_map={"submit": "primary", "delete": "danger"}, action=relative_url_for("main.estimate", task_name=task.name))
+ render_form(forms["estimation"], button_map={"submit": "primary", "delete": "danger"}, action=head_url_for("main.estimate", task_name=task.name))
)
}}
{%- endmacro %}
@@ -64,7 +64,7 @@
Estimates
{%- endif %}
-
+
{% if forms %}
@@ -74,7 +74,7 @@ Tracker values
{{ task_authoritative() | indent(8) -}}
{% if "authoritative" in forms -%}
- {{ render_form(forms["authoritative"], action=relative_url_for("main.move_consensus_estimate_to_authoritative", task_name=task.name)) }}
+ {{ render_form(forms["authoritative"], action=head_url_for("main.move_consensus_estimate_to_authoritative", task_name=task.name)) }}
{%- endif %}
@@ -84,7 +84,7 @@ Consensus values
Point cost: {{ utils.render_estimate(context.global_estimate) }}
{% endif %}
{% if "consensus" in forms %}
- {{ render_form(forms["consensus"], button_map={"submit": "primary", "delete": "danger"}, action=relative_url_for("main.move_issue_estimate_to_consensus", task_name=task.name)) }}
+ {{ render_form(forms["consensus"], button_map={"submit": "primary", "delete": "danger"}, action=head_url_for("main.move_issue_estimate_to_consensus", task_name=task.name)) }}
{% endif %}
diff --git a/estimage/webapp/templates/retrospective_overview.html b/estimage/webapp/templates/retrospective_overview.html
index 18a06ee..d532fde 100644
--- a/estimage/webapp/templates/retrospective_overview.html
+++ b/estimage/webapp/templates/retrospective_overview.html
@@ -21,7 +21,7 @@
Burndown
-
+
{% endblock %}
@@ -35,7 +35,7 @@ Velocity
-
+
{% endblock %}
diff --git a/estimage/webapp/templates/tree_view.html b/estimage/webapp/templates/tree_view.html
index c090ff8..75cee90 100644
--- a/estimage/webapp/templates/tree_view.html
+++ b/estimage/webapp/templates/tree_view.html
@@ -12,7 +12,7 @@ Remaining
Grand total: {{ utils.render_estimate(model.remaining_point_estimate) }}
-
+
@@ -21,7 +21,7 @@
Nominal
Grand total: {{ utils.render_estimate(model.nominal_point_estimate) }}
-
+
diff --git a/estimage/webapp/templates/utils.j2 b/estimage/webapp/templates/utils.j2
index 956bef9..5a9635f 100644
--- a/estimage/webapp/templates/utils.j2
+++ b/estimage/webapp/templates/utils.j2
@@ -47,7 +47,7 @@
{% if model.remaining_point_estimate_of(epic.name).expected > 0 %}
-
+
{% endif %}
@@ -65,7 +65,7 @@
{% endmacro %}
{% macro refresh_whatever(target, mode, next) -%}
- {{ render_icon("arrow-clockwise") }}
+ {{ render_icon("arrow-clockwise") }}
{%- endmacro %}
{% set task_type_to_function = {
@@ -74,7 +74,7 @@
} %}
{% macro task_link(task, type) -%}
- {{ task.name }} {{ render_icon("box-arrow-up-right") }}
+ {{ task.name }} {{ render_icon("box-arrow-up-right") }}
{%- endmacro %}
{% macro epic_external_link(epic) -%}
@@ -82,7 +82,7 @@
{%- endmacro %}
{% macro epic_link(epic, endpoint="main.view_epic") -%}
- {{ epic.name }} {{ epic_external_link(epic) }}
+ {{ epic.name }} {{ epic_external_link(epic) }}
{%- endmacro %}
{% macro render_state_short(state) -%}
@@ -212,7 +212,7 @@
{% if refresh_form %}
{{ caller() }}
- {{ render_form(refresh_form, action=relative_url_for("main.refresh")) }}
+ {{ render_form(refresh_form, action=head_url_for("main.refresh")) }}
{% endif %}
{%- endmacro %}
diff --git a/estimage/webapp/web_utils.py b/estimage/webapp/web_utils.py
index a1f84a9..aac018f 100644
--- a/estimage/webapp/web_utils.py
+++ b/estimage/webapp/web_utils.py
@@ -5,19 +5,16 @@
from .. import simpledata as webdata
from .. import utilities, persistence
+
def app_is_multihead(app=None):
if not app:
app = flask.current_app
return "head" in app.config
-def url_for(endpoint, * args, ** kwargs):
- if app_is_multihead():
- head_name = flask.request.blueprints[-1]
- if head_name in ("login", "neck"):
- endpoint = f"{head_name}"
- else:
- endpoint = f"{head_name}.{endpoint}"
+def head_url_for(endpoint, * args, ** kwargs):
+ app = flask.current_app
+ endpoint = app.get_correct_context_endpoint(endpoint)
return flask.url_for(endpoint, * args, ** kwargs)
@@ -76,6 +73,19 @@ def get_user_model(user_id, targets_tree_without_duplicates):
return model
+def get_head_absolute_endpoint(endpoint):
+ return flask.current_app.get_correct_context_endpoint(endpoint)
+
+
+def get_custom_items_dict():
+ custom_items = dict()
+ app = flask.current_app
+ for plugin, (title, endpoint) in CUSTOM_MENU_ITEMS.items():
+ if plugin in app.get_plugins_in_context():
+ custom_items[title] = get_head_absolute_endpoint(endpoint)
+ return custom_items
+
+
def render_template(path, title, **kwargs):
loaded_templates = dict()
loaded_templates["base"] = flask.current_app.jinja_env.get_template("base.html")
@@ -84,22 +94,11 @@ def render_template(path, title, **kwargs):
if flask_login.current_user.is_authenticated:
authenticated_user = flask_login.current_user
# maybe_overriden_path = flask.current_app.config["plugins_templates_overrides"](path)
- head_prefix = ""
- custom_items = dict()
- if "head" in flask.current_app.config:
- head_name = flask.request.blueprints[-1]
- if head_name not in ("login", "neck"):
- head_prefix = f"{head_name}."
- for plugin, (title, endpoint) in CUSTOM_MENU_ITEMS.items():
- if plugin in flask.current_app.get_config_option("PLUGINS"):
- custom_items[title] = head_prefix + endpoint
- else:
- for plugin, (title, endpoint) in CUSTOM_MENU_ITEMS.items():
- if plugin in flask.current_app.get_config_option("PLUGINS"):
- custom_items[title] = endpoint
+ custom_menu_items = get_custom_items_dict()
return flask.render_template(
- path, head_prefix=head_prefix, title=title, authenticated_user=authenticated_user, relative_url_for=url_for,
- custom_items=custom_items, ** kwargs)
+ path, get_head_absolute_endpoint=get_head_absolute_endpoint,
+ title=title, authenticated_user=authenticated_user, head_url_for=head_url_for,
+ custom_items=custom_menu_items, ** kwargs)
def safe_url_to_redirect(candidate):