Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions gateway/.envs/example/django.env
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,13 @@ SVI_SERVER_API_KEY=

# BUSINESS LOGIC
# ------------------------------------------------------------------------------
# Recommended `False` in production
SDS_NEW_USERS_APPROVED_ON_CREATION=True
# Recommended `false` in production
SDS_NEW_USERS_APPROVED_ON_CREATION=true

# VISUALIZATIONS
# ------------------------------------------------------------------------------
# Enable or disable the visualizations feature (defaults to true if not set)
VISUALIZATIONS_ENABLED=true

# MATPLOTLIB
# ------------------------------------------------------------------------------
Expand Down
15 changes: 10 additions & 5 deletions gateway/.envs/example/django.prod-example.env
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@
# ====================== PRODUCTION ENV ======================
# GENERAL
# ------------------------------------------------------------------------------
# DJANGO_READ_DOT_ENV_FILE=True
# DJANGO_READ_DOT_ENV_FILE=true
DJANGO_SETTINGS_MODULE=config.settings.production
DJANGO_SECRET_KEY=
DJANGO_ADMIN_URL=
DJANGO_ALLOWED_HOSTS=localhost,sds.crc.nd.edu
SITE_DOMAIN=sds.crc.nd.edu
USE_HTTPS=True
USE_HTTPS=true

# SECURITY
# ------------------------------------------------------------------------------
# Traefik already redirects users, so we can disable it here:
DJANGO_SECURE_SSL_REDIRECT=False
DJANGO_SECURE_SSL_REDIRECT=false

# OAUTH
# ------------------------------------------------------------------------------
Expand All @@ -35,7 +35,7 @@ SENTRY_ENVIRONMENT=production

# DJANGO-ALLAUTH
# ------------------------------------------------------------------------------
DJANGO_ACCOUNT_ALLOW_REGISTRATION=True
DJANGO_ACCOUNT_ALLOW_REGISTRATION=true

# GUNICORN
# ------------------------------------------------------------------------------
Expand Down Expand Up @@ -81,7 +81,12 @@ OPENSEARCH_VERIFY_CERTS=false

# BUSINESS LOGIC
# ------------------------------------------------------------------------------
SDS_NEW_USERS_APPROVED_ON_CREATION=False
SDS_NEW_USERS_APPROVED_ON_CREATION=false

# VISUALIZATIONS
# ------------------------------------------------------------------------------
# Enable or disable the visualizations feature (defaults to true if not set)
VISUALIZATIONS_ENABLED=true

# MATPLOTLIB
# ------------------------------------------------------------------------------
Expand Down
4 changes: 3 additions & 1 deletion gateway/config/api_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
router.register(r"assets/files", FileViewSet, basename="files")
router.register(r"assets/captures", CaptureViewSet, basename="captures")
router.register(r"assets/datasets", DatasetViewSet, basename="datasets")
router.register(r"visualizations", VisualizationViewSet, basename="visualizations")

if settings.VISUALIZATIONS_ENABLED:
router.register(r"visualizations", VisualizationViewSet, basename="visualizations")

app_name = "api"
urlpatterns = [
Expand Down
8 changes: 8 additions & 0 deletions gateway/config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,14 @@ def __get_random_token(length: int) -> str:
default=False,
)

# Visualizations
# ------------------------------------------------------------------------------
# Enable or disable the visualizations feature
VISUALIZATIONS_ENABLED: bool = env.bool(
"VISUALIZATIONS_ENABLED",
default=True,
)

# File upload limits
# ------------------------------------------------------------------------------
# Maximum number of files that can be uploaded at once
Expand Down
14 changes: 9 additions & 5 deletions gateway/config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,20 @@
# User management
path("users/", include("sds_gateway.users.urls", namespace="users")),
path("accounts/", include("allauth.urls")),
# Visualizations
path(
"visualizations/",
include("sds_gateway.visualizations.urls", namespace="visualizations"),
),
# Your stuff: custom urls includes go here
# ...
# Media files
*static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT),
]

# Conditionally include visualizations
if settings.VISUALIZATIONS_ENABLED:
urlpatterns += [
path(
"visualizations/",
include("sds_gateway.visualizations.urls", namespace="visualizations"),
),
]
if settings.DEBUG:
# Static file serving when using Gunicorn + Uvicorn for local web socket development
urlpatterns += staticfiles_urlpatterns()
Expand Down
27 changes: 26 additions & 1 deletion gateway/sds_gateway/conftest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# ruff: noqa: E402

import os
from pathlib import Path

import django
import pytest
Expand All @@ -11,7 +12,9 @@
# without calling setup we get the "apps aren't loaded yet" error
django.setup()

# now we can import the models
# now we can import the models and settings
from django.conf import settings

from sds_gateway.users.models import User
from sds_gateway.users.tests.factories import UserFactory

Expand All @@ -24,3 +27,25 @@ def _media_storage(settings, tmpdir) -> None:
@pytest.fixture
def user(db) -> User:
return UserFactory()


def pytest_collection_modifyitems(config, items):
"""Deselect visualization tests entirely if feature is disabled."""
if settings.VISUALIZATIONS_ENABLED:
return

# Remove visualization tests from collection
deselected = []
remaining = []

for item in items:
# Check if test is in visualizations module
item_path = Path(str(item.fspath))
if "visualizations" in item_path.parts and "tests" in item_path.parts:
deselected.append(item)
else:
remaining.append(item)

if deselected:
config.hook.pytest_deselected(items=deselected)
items[:] = remaining
4 changes: 3 additions & 1 deletion gateway/sds_gateway/templates/users/file_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,9 @@ <h5 class="modal-title" id="uploadResultModalLabel">Upload Result</h5>
<!-- Capture Details Modal -->
{% include "users/partials/capture_modal.html" %}
<!-- Visualization Selection Modal -->
{% include "visualizations/partials/visualization_modal.html" with visualization_compatibility=visualization_compatibility %}
{% if VISUALIZATIONS_ENABLED %}
{% include "visualizations/partials/visualization_modal.html" with visualization_compatibility=visualization_compatibility %}
{% endif %}
<!-- Web Download Modal -->
{% include "users/partials/web_download_modal.html" %}
{% endblock body %}
Expand Down
28 changes: 16 additions & 12 deletions gateway/sds_gateway/templates/users/partials/capture_modal.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@
<div class="modal-header">
<h5 class="modal-title" id="capture-modal-label">Capture Details</h5>
<div class="d-flex align-items-center">
<!-- Visualize button - opens visualization selection modal -->
<button type="button"
class="btn btn-primary me-2 d-none"
id="visualize-btn"
title="Select visualization for this capture"
data-bs-toggle="modal"
data-bs-target="#visualization-modal"
data-capture-uuid=""
data-capture-type="">
<i class="bi bi-graph-up me-1"></i>Visualize
</button>
{% if VISUALIZATIONS_ENABLED %}
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The VISUALIZATIONS_ENABLED setting needs to be made available to templates through a context processor. Currently, the templates reference this variable using {% if VISUALIZATIONS_ENABLED %}, but there's no context processor that exposes this setting. You should add a context processor in gateway/sds_gateway/context_processors.py that returns VISUALIZATIONS_ENABLED from the settings, similar to how allauth_settings is exposed in the users app.

Copilot uses AI. Check for mistakes.
<!-- Visualize button - opens visualization selection modal -->
<button type="button"
class="btn btn-primary me-2 d-none"
id="visualize-btn"
title="Select visualization for this capture"
data-bs-toggle="modal"
data-bs-target="#visualization-modal"
data-capture-uuid=""
data-capture-type="">
<i class="bi bi-graph-up me-1"></i>Visualize
</button>
{% endif %}
<button type="button"
class="btn-close"
data-bs-dismiss="modal"
Expand All @@ -41,4 +43,6 @@ <h5 class="modal-title" id="capture-modal-label">Capture Details</h5>
</div>
</div>
<!-- Include the visualization modal with context -->
{% include "visualizations/partials/visualization_modal.html" with visualization_compatibility=visualization_compatibility %}
{% if VISUALIZATIONS_ENABLED %}
{% include "visualizations/partials/visualization_modal.html" with visualization_compatibility=visualization_compatibility %}
{% endif %}
Loading