Skip to content

fix: Guac UI dark theme, working End Session button, and themed overlay#3020

Merged
kevoreilly merged 3 commits into
kevoreilly:masterfrom
wmetcalf:fix/guac-ui-theme-and-session
May 15, 2026
Merged

fix: Guac UI dark theme, working End Session button, and themed overlay#3020
kevoreilly merged 3 commits into
kevoreilly:masterfrom
wmetcalf:fix/guac-ui-theme-and-session

Conversation

@wmetcalf
Copy link
Copy Markdown
Contributor

Summary

The Guacamole pages (wait, session, error) used bare unstyled HTML while the rest of CAPE uses Bootstrap dark theme. This PR applies the CAPE dark theme consistently and fixes the End Session button which was silently failing.

Changes

  • wait.html: CAPE navbar, dark card, animated progress bar, themed "View Task" button. Replaces plain <body>Hang on....

  • index.html: Thin bg-dark toolbar with CAPE logo (graphic/cape.png), task ID link, and "End Session" button. Guacamole canvas fills remaining viewport height. Error overlay uses dark CAPE styling with green "Session Complete" / red "Session Error" states.

  • error.html: Full CAPE dark theme with navbar, centered error card.

  • guac-main.css: Dark overlay dialog (background: #212529), removes old jQuery UI .inner white styling.

  • guac-main.js stopTask(): Three fixes:

    1. Sends X-CSRFToken header (POST was returning 403)
    2. Redirects to task status page on success
    3. Shows spinner while in flight; re-enables button on error
  • apiv2/views.py: Enable user_stop (was enabled = no by default); the End Session POST was processed but user_stop.enabled gated the actual VM signal.

Test plan

  • Open a running interactive task → verify dark themed session page
  • Wait for VM-not-ready → verify dark themed wait page with animated progress bar
  • Click End Session → verify spinner appears, then redirect to task status
  • Let session expire naturally → verify themed "Session Complete" overlay with "View Task" link

🤖 Generated with Claude Code

- wait.html / error.html / index.html: Apply CAPE Bootstrap dark theme
  (bg-dark, navbar header, Bootstrap components) to match the rest of
  the UI. Previously these pages used bare unstyled HTML.

- index.html toolbar: Thin bg-dark bar with CAPE logo, task link, and
  End Session button; Guacamole canvas fills remaining viewport height.

- guac-main.js stopTask(): Add X-CSRFToken header so the POST succeeds
  under Django CSRF protection. Redirect to task status page on success.
  Show spinner on button while request is in flight.

- guac-main.js disconnect overlay: When the Guacamole connection drops,
  show the #launch_error overlay via CSS display:block instead of the
  jQuery UI .dialog() widget (which was never loaded). Normal session end
  shows green "Session Complete"; unexpected disconnect shows red
  "Session Error".

- guac-main.css: Dark overlay styling for the disconnect dialog using
  CAPE colors (#212529 bg, white text).

- apiv2/views.py tasks_status: Enable user_stop (was disabled) so
  End Session POST actually signals the guest VM to complete.
Copilot AI review requested due to automatic review settings May 12, 2026 16:19
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request focuses on UI improvements for the Guacamole console, including a new toolbar, updated error and wait pages using Bootstrap, and a dark theme. It also updates the tasks_status API to support both session and API key authentication and improves the stopTask JavaScript function with CSRF protection and better user feedback. Feedback was provided regarding the significant removal of the yara_uploader functionality and the use of hardcoded inline styles in the Guacamole index template that duplicate existing CSS classes.

I am having trouble creating individual review comments. Click here to see my feedback.

web/apiv2/views.py (2910-3099)

high

The yara_uploader function and its associated logic (including imports for yara, plyara, and sqlalchemy.select, as well as the ALLOWED_YARA_CATEGORIES constant) have been entirely removed in this PR. This appears to be a significant deletion of functionality that is not mentioned in the pull request title or description. If this was unintentional (e.g., due to an incorrect rebase or accidental deletion), please restore the code. If it was intentional, it should be explicitly documented as it represents a breaking change to the API.

web/guac/templates/guac/index.html (34-41)

medium

The error dialog overlay uses hardcoded inline styles that largely duplicate the .dialog and .inner classes defined in web/static/css/guac-main.css. Using the CSS classes instead of inline styles improves maintainability and ensures consistency across the UI. Note that the colors in the inline styles (e.g., #212529) also differ slightly from the ones defined in the CSS file (#1e1e2e).

            <div class="dialog" id="launch_error">
                <div class="inner">
                    <h6 id="dialog-heading" class="mb-2"><i class="fas fa-exclamation-triangle me-1 text-danger"></i>Session Error</h6>
                    <p class="message mb-1 small" style="color:#adb5bd;"></p>
                    <p class="error_msg mb-2 small" style="color:#6c757d;"></p>
                    <a id="taskStatus" href="/submit/status/{{ task_id }}/" class="btn btn-sm btn-outline-light"><i class="fas fa-tasks me-1"></i>View Task</a>
                </div>
            </div>

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the Guacamole (interactive VNC) UI to match CAPE’s Bootstrap dark theme and adjusts the “End Session” flow by changing the client-side stop request and the tasks_status API authentication behavior.

Changes:

  • Reworks Guacamole templates (wait.html, index.html, error.html) to use CAPE dark-theme styling and more consistent navigation/controls.
  • Updates guac-main.js error overlay handling and modifies stopTask() to send a CSRF header, show an in-flight spinner, and redirect after the request.
  • Modifies apiv2/tasks/status authentication decorators/imports, and (as part of this diff) removes the yara_uploader endpoint from web/apiv2/views.py.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
web/static/js/guac-main.js Updates overlay rendering and changes the stop-task request/UX (CSRF header, spinner, redirect).
web/static/css/guac-main.css Restyles the Guacamole error overlay to match the dark theme.
web/guac/templates/guac/wait.html Replaces bare HTML with CAPE dark theme + navbar and a “View Task” action.
web/guac/templates/guac/index.html Adds a dark toolbar + redesigned overlay and wires up the updated stop behavior.
web/guac/templates/guac/error.html Replaces bare HTML with CAPE dark theme + navbar and an error card.
web/apiv2/views.py Changes auth handling for tasks_status and removes yara_uploader (breaking if URLs still reference it).
Comments suppressed due to low confidence (1)

web/apiv2/views.py:2907

  • yara_uploader was removed from this module, but web/apiv2/urls.py still registers views.yara_uploader. This will break URLconf loading (AttributeError) and prevent the web app/API from starting. Either restore the view or remove/update the URL route.
@csrf_exempt
@api_view(["GET"])
def dist_tasks_notification(request, task_id: int):
    dist_db = dist_session()
    tasks = dist_db.query(DTask).filter_by(main_task_id=task_id).order_by(DTask.id.desc()).all()
    if not tasks:
        return Response({"error": True, "error_value": f"No tasks found with main_task_id: {task_id}"})
    for task in tasks:
        # main_db.set_status(task.main_task_id, TASK_REPORTED)
        # log.debug("reporting main_task_id: {}".format(task.main_task_id))
        task.notificated = True


Comment thread web/apiv2/views.py Outdated
Comment on lines +25 to +30
from rest_framework.authentication import SessionAuthentication
from rest_framework.decorators import api_view, authentication_classes
from rest_framework.response import Response

from apikey.authentication import ApiKeyAuthentication

Comment on lines +13 to +18
<script src="{% static 'js/jquery.js' %}"></script>
</head>
<body class="bg-dark text-white">

{% include "header.html" %}

Comment on lines +13 to +17
<script src="{% static 'js/jquery.js' %}"></script>
</head>
<body>
{% block content %}
<div class="alert alert-secondary">
<h4>Error</h4>
<p>{{error_msg}}</p>
<script>
switch ('{{error}}') {
case 'remote session':
var task_url = location.origin + 'submit/status/{{task_id}}';
break;
}
document.getElementById("taskStatus").addEventListener("click", function() {
location.replace(task_url);
}, false);
</script>
<body class="bg-dark text-white">
{% include "header.html" %}
<div class="container mt-5">
Comment on lines +187 to +203
var apiUrl = location.origin + "/apiv2/tasks/status/" + taskId + "/";
fetch(apiUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCsrfToken(),
},
body: JSON.stringify({ status: 'finish' }),
})
.then(response => response.json())
.then(data => console.log('Response:', data))
.catch(error => console.error('Error:', error));
.then(function(data) {
location.replace(location.origin + '/submit/status/' + taskId + '/');
})
.catch(function(error) {
console.error('Error:', error);
if (btn) { btn.disabled = false; btn.innerHTML = '<i class="fas fa-stop-circle me-1"></i>End Session'; }
});
<script src="{% static 'js/guac-main.js' %}"></script>
<script src="{% static 'js/guacamole-1.4.0-all.min.js' %}"></script>
<script src="{% static 'js/jquery.js' %}"></script>
<script src="{% static 'js/jquery-ui.min.js' %}"></script>
@kevoreilly kevoreilly merged commit 338f0d3 into kevoreilly:master May 15, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants