mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-02-05 19:03:30 -05:00
added feature flag
This commit is contained in:
@@ -151,7 +151,7 @@
|
||||
"filename": "app/config.py",
|
||||
"hashed_secret": "577a4c667e4af8682ca431857214b3a920883efc",
|
||||
"is_verified": false,
|
||||
"line_number": 118,
|
||||
"line_number": 121,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
@@ -674,5 +674,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"generated_at": "2025-03-20T18:22:36Z"
|
||||
"generated_at": "2025-04-10T19:35:01Z"
|
||||
}
|
||||
|
||||
1
.github/workflows/checks.yml
vendored
1
.github/workflows/checks.yml
vendored
@@ -167,6 +167,7 @@ jobs:
|
||||
run: make run-flask &
|
||||
env:
|
||||
NOTIFY_ENVIRONMENT: scanning
|
||||
FEATURE_SOCKET_ENABLED: true
|
||||
- name: Run OWASP Baseline Scan
|
||||
uses: zaproxy/action-baseline@v0.14.0
|
||||
with:
|
||||
|
||||
@@ -172,15 +172,15 @@ def _csp(config):
|
||||
|
||||
|
||||
def create_app(application):
|
||||
# @application.context_processor
|
||||
# def inject_feature_flags():
|
||||
@application.context_processor
|
||||
def inject_feature_flags():
|
||||
# this is where feature flags can be easily added as a dictionary within context
|
||||
# feature_about_page_enabled = application.config.get(
|
||||
# "FEATURE_ABOUT_PAGE_ENABLED", False
|
||||
# )
|
||||
# return dict(
|
||||
# FEATURE_ABOUT_PAGE_ENABLED=feature_about_page_enabled,
|
||||
# )
|
||||
feature_socket_enabled = application.config.get(
|
||||
"FEATURE_SOCKET_ENABLED", False
|
||||
)
|
||||
return dict(
|
||||
FEATURE_SOCKET_ENABLED=feature_socket_enabled,
|
||||
)
|
||||
|
||||
@application.context_processor
|
||||
def inject_initial_signin_url():
|
||||
|
||||
@@ -10,29 +10,35 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
const isJobPage = window.location.pathname.includes("/jobs/");
|
||||
if (!isJobPage) return;
|
||||
|
||||
const jobId = document.querySelector("[data-job-id]")?.dataset?.jobId;
|
||||
const jobEl = document.querySelector("[data-job-id]");
|
||||
const jobId = jobEl?.dataset?.jobId;
|
||||
const featureEnabled = jobEl?.dataset?.feature === "true";
|
||||
|
||||
if (!jobId) return;
|
||||
|
||||
const socket = io("http://localhost:6011");
|
||||
|
||||
socket.on("connect", () => {
|
||||
console.log("Connected to Socket.IO server");
|
||||
socket.emit("join", { room: `job-${jobId}` });
|
||||
console.log("join", { room: `job-${jobId}` });
|
||||
});
|
||||
if (featureEnabled) {
|
||||
const socket = io("http://localhost:6011");
|
||||
|
||||
window.addEventListener("beforeunload", () => {
|
||||
socket.emit("leave", { room: `job-${jobId}` });
|
||||
});
|
||||
socket.on("connect", () => {
|
||||
console.log("Connected to Socket.IO server");
|
||||
socket.emit("join", { room: `job-${jobId}` });
|
||||
console.log("join", { room: `job-${jobId}` });
|
||||
});
|
||||
|
||||
const debouncedUpdate = debounce((data) => {
|
||||
updateAllJobSections();
|
||||
}, 1000);
|
||||
window.addEventListener("beforeunload", () => {
|
||||
socket.emit("leave", { room: `job-${jobId}` });
|
||||
});
|
||||
|
||||
socket.on("job_updated", (data) => {
|
||||
if (data.job_id !== jobId) return;
|
||||
debouncedUpdate(data);
|
||||
});
|
||||
const debouncedUpdate = debounce((data) => {
|
||||
updateAllJobSections();
|
||||
}, 1000);
|
||||
|
||||
socket.on("job_updated", (data) => {
|
||||
if (data.job_id !== jobId) return;
|
||||
debouncedUpdate(data);
|
||||
});
|
||||
}
|
||||
|
||||
function updateAllJobSections() {
|
||||
const resourceEl = document.querySelector('[data-socket-update="status"]');
|
||||
|
||||
@@ -89,6 +89,9 @@ class Config(object):
|
||||
}
|
||||
|
||||
|
||||
FEATURE_SOCKET_ENABLED = getenv("FEATURE_SOCKET_ENABLED", "false") == "true"
|
||||
|
||||
|
||||
def _s3_credentials_from_env(bucket_prefix):
|
||||
return {
|
||||
"bucket": getenv(
|
||||
|
||||
@@ -25,15 +25,17 @@ from app.utils.user import user_is_logged_in
|
||||
def check_feature_flags():
|
||||
# Placeholder for future feature flag checks
|
||||
# Example:
|
||||
# if request.path.startswith("/some-feature") and not current_app.config.get("FEATURE_SOME_FEATURE_ENABLED", False):
|
||||
# abort(404)
|
||||
if request.path.startswith("/jobs") and not current_app.config.get(
|
||||
"FEATURE_SOCKET_ENABLED", False
|
||||
):
|
||||
abort(404)
|
||||
pass
|
||||
|
||||
|
||||
@main.route("/test/feature-flags")
|
||||
def test_feature_flags():
|
||||
return jsonify(
|
||||
{"FEATURE_ABOUT_PAGE_ENABLED": current_app.config["FEATURE_ABOUT_PAGE_ENABLED"]}
|
||||
{"FEATURE_SOCKET_ENABLED": current_app.config["FEATURE_SOCKET_ENABLED"]}
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ from functools import partial
|
||||
|
||||
from flask import (
|
||||
Response,
|
||||
current_app,
|
||||
abort,
|
||||
jsonify,
|
||||
redirect,
|
||||
@@ -59,6 +60,7 @@ def view_job(service_id, job_id):
|
||||
filter_args["status"] = set_status_filters(filter_args)
|
||||
return render_template(
|
||||
"views/jobs/job.html",
|
||||
FEATURE_SOCKET_ENABLED=current_app.config["FEATURE_SOCKET_ENABLED"],
|
||||
job=job,
|
||||
status=request.args.get("status", ""),
|
||||
updates_url=url_for(
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
{% from "components/components/back-link/macro.njk" import usaBackLink %}
|
||||
{% from 'components/ajax-block.html' import socket_block %}
|
||||
|
||||
{% block service_page_title %}
|
||||
{{ "Message status" }}
|
||||
{% endblock %}
|
||||
@@ -11,20 +11,33 @@
|
||||
{% block maincolumn_content %}
|
||||
|
||||
{{ page_header("Message status") }}
|
||||
<div
|
||||
data-socket-update="status"
|
||||
data-resource="{{ updates_url }}"
|
||||
data-key="status"
|
||||
data-job-id="{{ job.id }}"
|
||||
>
|
||||
<div data-job-id="{{ job.id }}" data-feature="{{FEATURE_SOCKET_ENABLED}}">
|
||||
{% if not job.finished_processing %}
|
||||
<div
|
||||
data-resource="{{ updates_url }}"
|
||||
{% if FEATURE_SOCKET_ENABLED %}
|
||||
data-socket-update="status"
|
||||
{% else %}
|
||||
data-module="update-content"
|
||||
{% endif %}
|
||||
data-key="status"
|
||||
data-form=""
|
||||
>
|
||||
{% endif %}
|
||||
{{ partials['status']|safe }}
|
||||
{% if not job.finished_processing %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if not finished %}
|
||||
<div
|
||||
data-socket-update="counts"
|
||||
data-job-id="{{ job.id }}"
|
||||
data-resource="{{ updates_url }}"
|
||||
{% if FEATURE_SOCKET_ENABLED %}
|
||||
data-socket-update="counts"
|
||||
{% else %}
|
||||
data-module="update-content"
|
||||
{% endif %}
|
||||
data-key="counts"
|
||||
data-form=""
|
||||
>
|
||||
{% endif %}
|
||||
{{ partials['counts']|safe }}
|
||||
@@ -37,9 +50,12 @@
|
||||
</p>
|
||||
{% if not job.processing_finished %}
|
||||
<div
|
||||
data-socket-update="notifications"
|
||||
data-job-id="{{ job.id }}"
|
||||
data-resource="{{ updates_url }}"
|
||||
{% if FEATURE_SOCKET_ENABLED %}
|
||||
data-socket-update="notifications"
|
||||
{% else %}
|
||||
data-module="update-content"
|
||||
{% endif %}
|
||||
data-key="notifications"
|
||||
data-form=""
|
||||
>
|
||||
@@ -48,7 +64,6 @@
|
||||
{% if not job.processing_finished %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div> </div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -85,7 +85,6 @@ const javascripts = () => {
|
||||
paths.src + 'javascripts/sidenav.js',
|
||||
paths.src + 'javascripts/validation.js',
|
||||
paths.src + 'javascripts/socketio.js',
|
||||
|
||||
])
|
||||
.pipe(plugins.prettyerror())
|
||||
.pipe(
|
||||
|
||||
Reference in New Issue
Block a user