Skip to content

Next release#1688

Merged
jokob-sk merged 7 commits into
mainfrom
next_release
Jun 23, 2026
Merged

Next release#1688
jokob-sk merged 7 commits into
mainfrom
next_release

Conversation

@jokob-sk

@jokob-sk jokob-sk commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • Improvements
    • Refreshed loading skeleton layouts across Settings, devices, logs, presence, system info, events, device details, maintenance, reports, workflows, notifications, and tabs (including dark-theme palette/spacing and larger presence placeholders).
    • Made skeleton transitions faster and more consistent, and improved skeleton show/hide behavior for Settings and App Events.
    • Enhanced in-app navigation with loading indicators on internal clicks and improved sidebar link URLs.
  • New Features
    • MQTT discovery now publishes device connection metadata for sensor and binary sensor entities.
  • Bug Fixes
    • Fixed the Telegram bot token description typo.
    • Corrected the “Enabled settings” wording to “Enabled plugins.”

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 266661b5-a584-4253-9ba4-749b7ef395fd

📥 Commits

Reviewing files that changed from the base of the PR and between 942c4a6 and ac21017.

📒 Files selected for processing (2)
  • front/css/app.css
  • front/php/templates/language/en_us.json

📝 Walkthrough

Walkthrough

The PR restructures loading skeleton CSS and markup across the application, standardizing skeleton fade-out duration to 50ms on most pages (10ms for settings), updates responsive grid layouts for settings and devices skeletons, removes inline min-height constraints from multiple tab containers, refines plugins table rendering and DataTables configuration, adds device connections metadata to MQTT Home Assistant discovery payloads, corrects a Telegram plugin config typo, enhances plugin column rendering, and introduces in-app navigation spinner triggering.

Changes

Skeleton UI and Fade Timing Refactor

Layer / File(s) Summary
Skeleton CSS and color theme infrastructure
front/css/app.css, front/css/dark-patch.css, front/css/system-dark-patch.css
App.css adds --color-darkgray CSS variable, updates .btn-outline hover styling with black background and white text, sets #settingsPage margin-top to 50px. Introduces system info skeleton rules for #panInitCheck .row full width and #appEvents flow-root. Sets skeleton theme variables to white backgrounds. Overhauls skeleton overlay positioning with absolute overlay base on key page containers (#panDetails, #panSessions, #panPresence, #panEvents, #appEvents), updates per-skeleton margin/top/padding/min-height, hides scrollbars in tab skeleton areas. Simplifies .skel-overview-body to padding-only, switches .skel-overview-card to min-width: 100%. Adds .skel-tile-row with negative margins, .skel-tile with bottom margin, and .skel-form-footer-left flex layout. Dark theme colors updated to new palette with #353c42 and #272c30 variants. Adds --color-white, updates .btn:hover color.
Settings skeleton markup, insertion target, and logic
front/php/templates/skel_settings.php, front/settings.php
PHP template restructures overview cards into individual responsive column wrappers (col-xs-12 col-sm-6 col-md-4 col-lg-3 padding-5px). Settings page adds spinnerTarget class to #settingsPage, switches insertion target to #settingsOverviewPanelBody, restructures overview panel markup with dedicated body container. hideSettingsSkeleton() reduces fade to 10ms and hides via hide(). New showSettingsSkeleton() adds settings-loading class and fades in with fadeIn(10). Skeleton shown in outdated-settings branch.
Device list and detail skeletons
front/php/templates/skel_devices.php, front/deviceDetails.php, front/deviceDetailsEdit.php, front/deviceDetailsEvents.php, front/deviceDetailsPresence.php, front/deviceDetailsSessions.php, front/devices.php
Devices skeleton template reworked: .row replaced with .skel-tile-row with intermediate .col-xs-12; tile columns remove padding-5px class. Device details removes inline min-height from tab-content and streamlines tab pane markup. All device detail tabs standardize skeleton fade-out to 50ms.
System info, init check, and presence pages
front/systeminfo.php, front/systeminfoInitCheck.php, front/php/templates/skel_presence.php, front/presence.php
System info removes inline min-height: 430px from tab-content; init check restructures layout from .row to col-12/col-md-6 columns. Presence skeleton chart height increased from 380px to 580px. Presence fade-out reduced to 50ms.
Maintenance logging, events, and other pages fade timing
front/php/templates/skel_tab_maint_logging.php, front/events.php, front/maintenance.php, front/report.php, front/userNotifications.php, front/workflowsCore.php
Maintenance logging skeleton updated with three block-shaped shimmer spans interleaved with two slimmer line spans. Events page moves spinnerTarget class from table to page wrapper. Maintenance and all other pages reduce skeleton fade-out from 250ms to 50ms.
App Events page and skeleton integration
front/appEvents.php, front/appEventsCore.php, front/php/templates/skel_app_events.php
App Events page adds id="appEvents" to main container. Core adds responsive classes to tab pane, extends DataTables success callback to call hideAppEventsSkeleton(), implements new function and 15-second window load timer. New template outputs #skel-app-events container with header and 25 body rows via nested PHP loops.

Plugins UI Updates and Navigation Interaction

Layer / File(s) Summary
Plugins table skeleton, rendering, and configuration
front/php/templates/skel_tab_plugins_table.php, front/pluginsCore.php
Skeleton footer class changed from skel-form-footer to skel-form-footer-left. DataTables ordering enabled. URL and device link cell rendering refined: url_http_https produces dual http:// and https:// links with lock icons; device_name_mac inserts link directly without parentheses. Fade-out reduced to 50ms.
Navigation routing and in-app spinner triggering
front/js/common.js, front/php/templates/header.php
Document-level click handler added to trigger showSpinner() for in-app same-origin navigations (excluding _blank links and downloads). Devices menu link changes to href="devices.php" with retained openUrl handler. Maintenance menu link removes onclick handler, leaves href="#". Settings menu link changes to href="settings.php" with retained handler.

Plugin Integration Fixes and Config Updates

Layer / File(s) Summary
MQTT Home Assistant device connections
front/plugins/_publisher_mqtt/mqtt.py
Device metadata in MQTT discovery config now includes connections field from connections_snippet alongside name for binary_sensor and sensor types.
Telegram config, network markup, and translation
front/plugins/_publisher_telegram/config.json, front/systeminfoNetwork.php, front/php/templates/language/en_us.json
English description for URL setting corrected from "You cat get at …" to "You cat get one …". Network info box header indentation adjusted. Translation string settings_enabled changed from "Enabled settings" to "Enabled plugins".

Possibly related PRs

  • netalertx/NetAlertX#1679: Directly tied to the skeleton refactor; modifies CSS skeleton styling and hide*Skeleton() logic across settings, devices, events, plugins, and workflows pages.
  • netalertx/NetAlertX#1683: MQTT Home Assistant device metadata connections field handling overlaps directly.
  • netalertx/NetAlertX#1684: Overlaps on skeleton markup in front/php/templates/skel_tab_plugins_table.php and .skel-form-footer-left class definition.

Poem

🐇 Hop, hop! The skeletons fade fast—fifty milliseconds bright,
Settings and devices dance in responsive grids of pure delight.
MQTT now whispers device connections with grace,
Navigation spinner springs forth with elegant click,
Breadcrumbs and links align in thoughtful place,
This rabbit refactors with methodical care and cheer,
Making the loading states shimmer crystal clear! ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Next release' is vague and generic, failing to describe the actual changes in the changeset such as skeleton redesigns, loading animations, MQTT device metadata, or UI/styling updates across multiple files. Replace with a specific title that summarizes the main change, such as 'Redesign loading skeletons and accelerate fade animations' or 'Refactor skeleton UI and improve MQTT device metadata'
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch next_release

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@front/plugins/_publisher_telegram/config.json`:
- Line 429: In the config.json file for the _publisher_telegram plugin, locate
the "string" property containing the Telegram bot token description. Replace the
word "cat" with "can" so the text reads "You can get one from..." instead of
"You cat get one from..." to correct the grammatical error in the BotFather link
description.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 148dd359-0893-4cd0-a34b-4bdab5c07b68

📥 Commits

Reviewing files that changed from the base of the PR and between 075c89a and f87142d.

📒 Files selected for processing (6)
  • front/css/app.css
  • front/php/templates/skel_settings.php
  • front/php/templates/skel_tab_maint_logging.php
  • front/plugins/_publisher_mqtt/mqtt.py
  • front/plugins/_publisher_telegram/config.json
  • front/settings.php

Comment thread front/plugins/_publisher_telegram/config.json Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
front/pluginsCore.php (1)

148-150: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Untrusted URL value is injected directly into HTML and link attributes.

Line 149 interpolates raw value into href and inner HTML, which allows markup/script injection via plugin data and keeps _blank opener risk. It also leaves malformed wrapper markup (<span> instead of </span>).

🔒 Suggested hardening
     case 'url':
-      value = `<span><a href="${value}" target="_blank">${value}</a><span>`;
+      {
+        const raw = `${value ?? ''}`.trim();
+        const escapedText = $('<div/>').text(raw).html();
+        try {
+          const parsed = new URL(raw, window.location.origin);
+          const isHttp = parsed.protocol === 'http:' || parsed.protocol === 'https:';
+          if (!isHttp) throw new Error('Unsupported URL scheme');
+          const safeHref = $('<div/>').text(parsed.href).html();
+          value = `<span><a href="${safeHref}" target="_blank" rel="noopener noreferrer">${escapedText}</a></span>`;
+        } catch {
+          value = `<span>${escapedText}</span>`;
+        }
+      }
       break;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@front/pluginsCore.php` around lines 148 - 150, In the URL case block, the raw
value variable is being directly interpolated into both the href attribute and
the link's inner HTML without any escaping or sanitization, which creates a
markup and script injection vulnerability. Fix this by properly escaping the
value before interpolation, ensuring it's safe for use in both HTML content and
attributes. Additionally, correct the malformed closing tag that reads <span>
instead of </span>, and add the rel="noopener noreferrer" attribute to the
anchor element to prevent opener window access risks when using target="_blank".
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@front/css/app.css`:
- Around line 2676-2680: The border declaration in the "bordered containers"
rule uses `none` as the border style, which disables the border rendering for
all the skeleton container classes (.skel-overview-panel, .skel-section,
.skel-plugin-block, .skel-chart-box, .skel-table-box, .skel-detail-info-panel,
.skel-detail-form, .skel-tabs-bar). Replace the `none` value with a valid border
style such as `solid` in the border shorthand property so that the borders are
actually visible using the --skel-border color variable.

In `@front/pluginsCore.php`:
- Line 664: The `ordering: true` setting on line 664 enables sorting on all
plugin config columns, but the DataTable only retrieves a fixed subset of fields
from the GraphQL query. When users attempt to sort by columns not in the
returned dataset, sorting silently proceeds with None values (appearing last)
instead of producing meaningful results. To fix this, either restrict the
`ordering` flag to only be enabled for columns that are guaranteed to be
returned by the GraphQL query (the fixed subset including index, plugin,
objectPrimaryId, objectSecondaryId, dateTimeCreated, dateTimeChanged,
watchedValue1-4, status, extra, userData, foreignKey, syncHubNodeName,
helpVal1-4, objectGuid), or implement validation logic that checks each declared
plugin column definition against the actual query response fields before
allowing it to be sortable.

In `@front/settings.php`:
- Around line 552-556: The showSettingsSkeleton() function is using fadeOut()
before showing the element, which causes flickering when loading retries occur.
Replace the fadeOut() animation with a direct show() call or use fadeIn() if
animation is needed, so the skeleton element displays immediately without first
animating to a hidden state.

---

Outside diff comments:
In `@front/pluginsCore.php`:
- Around line 148-150: In the URL case block, the raw value variable is being
directly interpolated into both the href attribute and the link's inner HTML
without any escaping or sanitization, which creates a markup and script
injection vulnerability. Fix this by properly escaping the value before
interpolation, ensuring it's safe for use in both HTML content and attributes.
Additionally, correct the malformed closing tag that reads <span> instead of
</span>, and add the rel="noopener noreferrer" attribute to the anchor element
to prevent opener window access risks when using target="_blank".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 615a3a2b-d3bb-47cf-b8ad-bce5f551601c

📥 Commits

Reviewing files that changed from the base of the PR and between f87142d and b6327bd.

📒 Files selected for processing (23)
  • front/css/app.css
  • front/css/dark-patch.css
  • front/css/system-dark-patch.css
  • front/deviceDetails.php
  • front/deviceDetailsEdit.php
  • front/deviceDetailsEvents.php
  • front/deviceDetailsPresence.php
  • front/deviceDetailsSessions.php
  • front/devices.php
  • front/events.php
  • front/maintenance.php
  • front/php/templates/skel_devices.php
  • front/php/templates/skel_presence.php
  • front/php/templates/skel_tab_plugins_table.php
  • front/plugins/_publisher_telegram/config.json
  • front/pluginsCore.php
  • front/presence.php
  • front/report.php
  • front/settings.php
  • front/systeminfo.php
  • front/systeminfoInitCheck.php
  • front/userNotifications.php
  • front/workflowsCore.php
✅ Files skipped from review due to trivial changes (15)
  • front/workflowsCore.php
  • front/deviceDetailsPresence.php
  • front/php/templates/skel_presence.php
  • front/php/templates/skel_tab_plugins_table.php
  • front/report.php
  • front/maintenance.php
  • front/systeminfoInitCheck.php
  • front/deviceDetailsEdit.php
  • front/systeminfo.php
  • front/userNotifications.php
  • front/presence.php
  • front/deviceDetailsEvents.php
  • front/plugins/_publisher_telegram/config.json
  • front/devices.php
  • front/deviceDetailsSessions.php

Comment thread front/css/app.css
Comment thread front/pluginsCore.php
paging: true,
searching: true,
ordering: false,
ordering: true,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Collect column names declared in plugin config files.
python - <<'PY'
import json, pathlib, sys

cfg_files = list(pathlib.Path('.').rglob('front/plugins/**/config.json'))
declared = set()

for p in cfg_files:
    try:
        data = json.loads(p.read_text(encoding='utf-8'))
    except Exception:
        continue
    defs = data.get('database_column_definitions') or data.get('data', {}).get('database_column_definitions') or []
    for d in defs:
        col = d.get('column')
        if col:
            declared.add(col)

print("Declared columns:", len(declared))
for c in sorted(declared):
    print(c)
PY

# 2) Print the GraphQL-selected fields from pluginsCore.php for manual contract check.
rg -n -A20 -B5 'query PluginData' front/pluginsCore.php

Repository: netalertx/NetAlertX

Length of output: 1398


🏁 Script executed:

#!/bin/bash
# Get context around line 664 and understand the table configuration
sed -n '650,680p' front/pluginsCore.php | cat -n

Repository: netalertx/NetAlertX

Length of output: 1716


🏁 Script executed:

#!/bin/bash
# Find where the table columns are defined to understand what can be sorted
rg -n "columns:" front/pluginsCore.php -A 50 | head -100

Repository: netalertx/NetAlertX

Length of output: 3862


🏁 Script executed:

#!/bin/bash
# Check if there's any validation or filtering of sort fields before sending to GraphQL
rg -n "sort\." front/pluginsCore.php -B 3 -A 3

Repository: netalertx/NetAlertX

Length of output: 382


🏁 Script executed:

#!/bin/bash
# Examine the GraphQL schema/type definitions to see what fields support sorting
fd -i graphql front/ | head -20

Repository: netalertx/NetAlertX

Length of output: 192


🏁 Script executed:

#!/bin/bash
# Examine the GraphQL query handler to understand sort parameter support
cat front/php/server/query_graphql.php | head -150

Repository: netalertx/NetAlertX

Length of output: 2734


🏁 Script executed:

#!/bin/bash
# Search for sort parameter handling in GraphQL queries
rg -n "sort" front/php/server/query_graphql.php -B 2 -A 5

Repository: netalertx/NetAlertX

Length of output: 157


🏁 Script executed:

#!/bin/bash
# Check for GraphQL type definitions that might define sortable fields
fd -type f -name "*.php" front/php/server | xargs grep -l "sortableBy\|sortField\|orderBy" 2>/dev/null || echo "No matches found"

Repository: netalertx/NetAlertX

Length of output: 345


🏁 Script executed:

#!/bin/bash
# Look at the postPluginGraphQL function to understand the complete request/response flow
rg -n "postPluginGraphQL" front/pluginsCore.php -A 40

Repository: netalertx/NetAlertX

Length of output: 3555


🏁 Script executed:

#!/bin/bash
# Search for GraphQL resolver/schema files
find front -name "*.js" -o -name "*.ts" | xargs grep -l "PluginData\|pluginsEvents\|pluginsHistory" 2>/dev/null | head -10

Repository: netalertx/NetAlertX

Length of output: 157


🏁 Script executed:

#!/bin/bash
# Look for GraphQL implementation in the backend
find . -path ./node_modules -prune -o -type f \( -name "*.js" -o -name "*.py" \) -print | xargs grep -l "PluginQueryOptionsInput\|sort.*field" 2>/dev/null | grep -v node_modules | head -10

Repository: netalertx/NetAlertX

Length of output: 485


🏁 Script executed:

#!/bin/bash
# Check if backend GraphQL has schema definitions
ls -la | grep -i graph
find . -maxdepth 3 -type d -name "*graph*" 2>/dev/null

Repository: netalertx/NetAlertX

Length of output: 157


🏁 Script executed:

#!/bin/bash
# Search for backend implementation directory structure
ls -la back/ 2>/dev/null || ls -la backend/ 2>/dev/null || ls -la server/ 2>/dev/null || echo "No backend dirs found"

Repository: netalertx/NetAlertX

Length of output: 818


🏁 Script executed:

#!/bin/bash
# Check GraphQL types to see what fields are sortable
head -200 server/api_server/graphql_types.py

Repository: netalertx/NetAlertX

Length of output: 10751


🏁 Script executed:

#!/bin/bash
# Look for sort handling in GraphQL endpoint
rg -n "sort" server/api_server/graphql_endpoint.py -B 3 -A 5 | head -100

Repository: netalertx/NetAlertX

Length of output: 2274


🏁 Script executed:

#!/bin/bash
# Check GraphQL helpers for sort field validation
cat server/api_server/graphql_helpers.py | head -150

Repository: netalertx/NetAlertX

Length of output: 4584


🏁 Script executed:

#!/bin/bash
# Search for PluginQueryOptionsInput type definition
rg -n "PluginQueryOptionsInput" server/api_server/ -A 20

Repository: netalertx/NetAlertX

Length of output: 6498


Sorting on undeclared columns won't cause GraphQL errors, but may produce unexpected results.

The review concern is partially incorrect. Enabling ordering: true (line 664) allows sorting by any column from plugin config definitions. However, unlike the original comment suggests, the GraphQL backend accepts all sort field names without validation—it doesn't reject unknown fields or return errors.

When a sort is applied to a field not present in the backend data, the resolver calls x.get(field) which returns None, and sorting proceeds with None values ordered last. The table loads successfully; it doesn't fail or appear empty from GraphQL errors.

However, a legitimate concern remains: plugin columns declared in configs (27 total) can be sorted, but the DataTable only queries a fixed subset of fields (index plugin objectPrimaryId objectSecondaryId dateTimeCreated dateTimeChanged watchedValue1-4 status extra userData foreignKey syncHubNodeName helpVal1-4 objectGuid). If a sortable column isn't in this returned dataset, users experience unexpected sort behavior (sorting by effectively empty values) rather than a clear failure.

Consider restricting sortable columns to only those returned by the GraphQL query, or validate declared column definitions against the query response fields.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@front/pluginsCore.php` at line 664, The `ordering: true` setting on line 664
enables sorting on all plugin config columns, but the DataTable only retrieves a
fixed subset of fields from the GraphQL query. When users attempt to sort by
columns not in the returned dataset, sorting silently proceeds with None values
(appearing last) instead of producing meaningful results. To fix this, either
restrict the `ordering` flag to only be enabled for columns that are guaranteed
to be returned by the GraphQL query (the fixed subset including index, plugin,
objectPrimaryId, objectSecondaryId, dateTimeCreated, dateTimeChanged,
watchedValue1-4, status, extra, userData, foreignKey, syncHubNodeName,
helpVal1-4, objectGuid), or implement validation logic that checks each declared
plugin column definition against the actual query response fields before
allowing it to be sortable.

Comment thread front/settings.php Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
front/pluginsCore.php (1)

152-165: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Encode URL values and improve link accessibility.

The url_http_https case inserts value directly into href attributes without URL encoding. If value contains spaces, quotes, or special characters, it could break the HTML structure or enable injection attacks. Additionally, displaying only lock icons without visible text or tooltips makes it unclear what URL the user is navigating to.

🔒 Proposed fix to add URL encoding and accessibility
 case 'url_http_https':
-  value = `<span>
-            <a href="http://${value}" target="_blank">
-              <i class="fa fa-lock-open "></i>
-            </a>
-            /
-            <a href="https://${value}" target="_blank">
-              <i class="fa fa-lock "></i>
-            </a>
-        </span>`;
+  value = `<span>
+            <a href="http://${encodeURIComponent(value)}" target="_blank" title="http://${encodeSpecialChars(value)}">
+              <i class="fa fa-lock-open"></i>
+            </a>
+            /
+            <a href="https://${encodeURIComponent(value)}" target="_blank" title="https://${encodeSpecialChars(value)}">
+              <i class="fa fa-lock"></i>
+            </a>
+        </span>`;
   break;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@front/pluginsCore.php` around lines 152 - 165, In the `url_http_https` case,
the `value` variable is being directly inserted into the href attributes for
both HTTP and HTTPS links without URL encoding, which could break the HTML or
enable injection attacks if the value contains special characters or quotes.
Additionally, the links only display lock icons without any visible text or
accessibility attributes, making it unclear what URL the user is navigating to.
Fix this by URL encoding the `value` using encodeURIComponent before inserting
it into both `href="http://${value}"` and `href="https://${value}"` attributes,
and add title attributes or visible text labels to the anchor tags to improve
accessibility and user clarity about the destination URLs.
🧹 Nitpick comments (1)
front/js/common.js (1)

957-971: 📐 Maintainability & Code Quality | 🔵 Trivial

Consider the design implications of double-spinner calls and hash-navigation exclusion.

The click handler triggers showSpinner() for in-app navigations, and destination pages (e.g., events.php, deviceDetails.php) also call showSpinner() on load. While this creates two successive calls, the pattern appears intentional: the first call initiates feedback while the old page unloads, and the second call (documented in events.php as "Show initial page loading spinner") ensures visual continuity on the new page. The animations won't overlap since the first spinner is interrupted during page navigation.

The pathname+search comparison also excludes hash changes, so links like devices.php#my_devices won't trigger the spinner when already on devices.php. This behavior likely serves in-page navigation (e.g., scrolling to sections), but creates inconsistent UX if users expect spinner feedback for all navigations.

These appear to be intentional design choices rather than bugs. Consider documenting the intent and confirming the pattern works without visual flicker during page transitions.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@front/js/common.js` around lines 957 - 971, Add inline documentation comments
to the click handler function that explains the intentional design pattern:
clarify that the first showSpinner() call provides initial feedback as the old
page unloads while destination pages trigger a second showSpinner() call for
visual continuity, and note that this double-call pattern is deliberate to
ensure smooth transitions without overlapping animations. Additionally, document
why hash-based navigation (like links to `#my_devices`) are intentionally excluded
from triggering the spinner by adding a comment explaining that the
pathname+search comparison intentionally excludes hash changes to support
in-page navigation scenarios. Consider adding a note confirming that this
pattern has been tested and produces no visual flicker during page transitions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@front/php/templates/header.php`:
- Line 366: The Maintenance menu link at line 366 in the header.php file has
lost its onclick handler, leaving only href="#", which makes the top-level menu
item non-functional. Restore the onclick="openUrl(['./maintenance.php'])"
handler to the anchor tag for the Maintenance menu item to match the pattern
used in the Settings menu link (line 394) and Devices menu link (line 291),
ensuring users can navigate directly to the maintenance.php page and making the
navigation pattern consistent across all treeview menu items.
- Line 291: The anchor tag in header.php with the `openUrl()` onclick handler
does not prevent default link behavior, causing both the onclick function and
the href to be executed, resulting in double navigation. Fix this by either
adding `return false;` to the end of the onclick attribute in the anchor tag so
it becomes `onclick="openUrl([......]); return false;"` OR modify the
`openUrl()` function in common.js (lines 691-713) to return false and prevent
the default link behavior, then update the onclick to use `return
openUrl([......])`

---

Outside diff comments:
In `@front/pluginsCore.php`:
- Around line 152-165: In the `url_http_https` case, the `value` variable is
being directly inserted into the href attributes for both HTTP and HTTPS links
without URL encoding, which could break the HTML or enable injection attacks if
the value contains special characters or quotes. Additionally, the links only
display lock icons without any visible text or accessibility attributes, making
it unclear what URL the user is navigating to. Fix this by URL encoding the
`value` using encodeURIComponent before inserting it into both
`href="http://${value}"` and `href="https://${value}"` attributes, and add title
attributes or visible text labels to the anchor tags to improve accessibility
and user clarity about the destination URLs.

---

Nitpick comments:
In `@front/js/common.js`:
- Around line 957-971: Add inline documentation comments to the click handler
function that explains the intentional design pattern: clarify that the first
showSpinner() call provides initial feedback as the old page unloads while
destination pages trigger a second showSpinner() call for visual continuity, and
note that this double-call pattern is deliberate to ensure smooth transitions
without overlapping animations. Additionally, document why hash-based navigation
(like links to `#my_devices`) are intentionally excluded from triggering the
spinner by adding a comment explaining that the pathname+search comparison
intentionally excludes hash changes to support in-page navigation scenarios.
Consider adding a note confirming that this pattern has been tested and produces
no visual flicker during page transitions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4ceefc85-74ab-4a6d-8011-56d59f710433

📥 Commits

Reviewing files that changed from the base of the PR and between b6327bd and c98e068.

📒 Files selected for processing (4)
  • front/js/common.js
  • front/php/templates/header.php
  • front/pluginsCore.php
  • front/settings.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • front/settings.php


<li class=" treeview <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('devices.php', 'deviceDetails.php') ) ){ echo 'active menu-open'; } ?>">
<a href="#" onclick="openUrl(['./devices.php', './deviceDetails.php'])">
<a href="devices.php" onclick="openUrl(['./devices.php', './deviceDetails.php'])">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Find and examine the openUrl function to check for preventDefault() or return false.

# Search for openUrl function definition
rg -n 'function\s+openUrl' --type=js -A 20

# Also check for arrow function or const assignment
rg -n '(const|let|var)\s+openUrl\s*=' --type=js -A 20

Repository: netalertx/NetAlertX

Length of output: 157


🏁 Script executed:

# Search for openUrl in all file types
rg -n 'openUrl' --type=php -A 5

# Also search in HTML/template files
rg -n 'openUrl' --type=html -A 5

# Check if there's a script directory with JS files using different naming
find front -type f -name "*.js" | head -20

# Also search without type restriction to catch all definitions
rg -n 'openUrl\s*=' -A 10 | head -50

Repository: netalertx/NetAlertX

Length of output: 425


🏁 Script executed:

# Read the header.php file to see context around lines 291 and 366
wc -l front/php/templates/header.php

Repository: netalertx/NetAlertX

Length of output: 192


🏁 Script executed:

# Read relevant sections of header.php - around line 291 and 366
cat -n front/php/templates/header.php | sed -n '280,300p'
cat -n front/php/templates/header.php | sed -n '360,375p'

Repository: netalertx/NetAlertX

Length of output: 2511


🏁 Script executed:

# Search for openUrl definition across entire repository
rg -n 'openUrl' -C 3 | head -100

Repository: netalertx/NetAlertX

Length of output: 157


🏁 Script executed:

# Search more broadly for openUrl - case insensitive, any context
rg -i 'openUrl' 

# Also list all JS files in the front directory
find front -type f \( -name "*.js" -o -name "*.jsx" \)

Repository: netalertx/NetAlertX

Length of output: 157


🏁 Script executed:

# Check if header.php contains inline scripts or function definitions
grep -n '<script' front/php/templates/header.php

# Search for any function that handles URL opening or navigation
rg -n 'function.*Url|onClick|openUrl|forceLoadUrl' -i | head -40

Repository: netalertx/NetAlertX

Length of output: 1649


🏁 Script executed:

# List JS files in js directory
ls -la front/js/ | head -20

# Search specifically in js directory
rg -n 'openUrl' front/js/

# Also search for forceLoadUrl to understand the pattern
rg -n 'forceLoadUrl' front/js/ -A 5

Repository: netalertx/NetAlertX

Length of output: 1680


🏁 Script executed:

# Read the openUrl function implementation in detail
cat -n front/js/common.js | sed -n '691,716p'

Repository: netalertx/NetAlertX

Length of output: 1068


The Devices link will cause double navigation - openUrl() does not prevent default link behavior.

Line 291: <a href="devices.php" onclick="openUrl(['./devices.php', './deviceDetails.php'])"> creates a functional issue. The openUrl() function in front/js/common.js:691-713 checks if the current URL matches any entry in the array, but it does not call preventDefault() or return false. When clicked:

  1. The onclick handler executes openUrl(), which either redirects or does nothing
  2. The browser still follows the href="devices.php" link regardless

This causes redundant navigation. Add return false; to the onclick attribute or modify openUrl() to return false to prevent the default link behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@front/php/templates/header.php` at line 291, The anchor tag in header.php
with the `openUrl()` onclick handler does not prevent default link behavior,
causing both the onclick function and the href to be executed, resulting in
double navigation. Fix this by either adding `return false;` to the end of the
onclick attribute in the anchor tag so it becomes `onclick="openUrl([......]);
return false;"` OR modify the `openUrl()` function in common.js (lines 691-713)
to return false and prevent the default link behavior, then update the onclick
to use `return openUrl([......])`

<!-- Maintenance menu item -->
<li class=" treeview <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('maintenance.php') ) ){ echo 'active menu-open'; } ?>">
<a href="#" onclick="openUrl(['./maintenance.php'])">
<a href="#">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Broken navigation: Maintenance menu link has no functional target.

The onclick="openUrl(['./maintenance.php'])" handler was removed, leaving only href="#". This means clicking the top-level Maintenance menu item now does nothing except scroll to top or toggle the submenu.

While submenu items (lines 377-389) still link to maintenance.php tabs, removing the top-level navigation is inconsistent with:

  • The Settings link (line 394) which retains both href="#" and onclick handler
  • The active state logic (line 365) that checks basename($_SERVER['SCRIPT_NAME']) === 'maintenance.php', implying users should be able to navigate to that page
  • The Devices link (line 291) which now has both href AND onclick

This creates an inconsistent navigation pattern across treeview menu items and potentially prevents direct access to the Maintenance page.

🔧 Proposed fix to restore navigation

Option 1: Restore the onclick handler for consistency with Settings menu:

-          <a href="#">
+          <a href="#" onclick="openUrl(['./maintenance.php'])">

Option 2: Add proper href for consistency with Devices menu:

-          <a href="#">
+          <a href="maintenance.php" onclick="openUrl(['./maintenance.php'])">

Option 3: If treeview toggle is the only intended behavior, remove onclick from all treeview parents for consistency (including Settings line 394).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<a href="#">
<a href="#" onclick="openUrl(['./maintenance.php'])">
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@front/php/templates/header.php` at line 366, The Maintenance menu link at
line 366 in the header.php file has lost its onclick handler, leaving only
href="#", which makes the top-level menu item non-functional. Restore the
onclick="openUrl(['./maintenance.php'])" handler to the anchor tag for the
Maintenance menu item to match the pattern used in the Settings menu link (line
394) and Devices menu link (line 291), ensuring users can navigate directly to
the maintenance.php page and making the navigation pattern consistent across all
treeview menu items.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
front/appEventsCore.php (1)

121-127: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Mirror UI teardown in the AJAX error path.

Line 121-127 does not call hideSpinner() (and should also hide the app-events skeleton), so failed requests can leave loading UI stuck.

Suggested patch
         error: function () {
+          hideSpinner();
+          hideAppEventsSkeleton();
           callback({
             data: [],
             recordsTotal: 0,
             recordsFiltered: 0
           });
         }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@front/appEventsCore.php` around lines 121 - 127, The error callback function
for the AJAX request is not properly tearing down the loading UI when a request
fails, leaving the spinner and app-events skeleton visible. Add `hideSpinner()`
and hide the app-events skeleton element inside the error callback function
(where the callback is invoked with the empty data response) to mirror the UI
teardown that should occur on both successful and failed requests, ensuring the
loading state is properly cleared regardless of the outcome.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@front/css/app.css`:
- Around line 2664-2665: The CSS selector `#skel-app-event` (singular) does not
match the actual DOM element id `#skel-app-events` (plural), causing the skeleton
styling rules to not apply to the intended element. Update all instances of the
`#skel-app-event` selector to `#skel-app-events` (add the 's' to make it plural) in
the CSS file to match the DOM id. This selector mismatch occurs in multiple
locations throughout the file where the selector is defined.

---

Outside diff comments:
In `@front/appEventsCore.php`:
- Around line 121-127: The error callback function for the AJAX request is not
properly tearing down the loading UI when a request fails, leaving the spinner
and app-events skeleton visible. Add `hideSpinner()` and hide the app-events
skeleton element inside the error callback function (where the callback is
invoked with the empty data response) to mirror the UI teardown that should
occur on both successful and failed requests, ensuring the loading state is
properly cleared regardless of the outcome.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7fadc81e-92f6-4026-8eba-a8ea7cf24db7

📥 Commits

Reviewing files that changed from the base of the PR and between c98e068 and 942c4a6.

📒 Files selected for processing (10)
  • front/appEvents.php
  • front/appEventsCore.php
  • front/css/app.css
  • front/css/dark-patch.css
  • front/css/system-dark-patch.css
  • front/devices.php
  • front/php/templates/header.php
  • front/php/templates/skel_app_events.php
  • front/settings.php
  • front/systeminfoNetwork.php
✅ Files skipped from review due to trivial changes (3)
  • front/appEvents.php
  • front/systeminfoNetwork.php
  • front/php/templates/skel_app_events.php
🚧 Files skipped from review as they are similar to previous changes (3)
  • front/php/templates/header.php
  • front/devices.php
  • front/settings.php

Comment thread front/css/app.css Outdated
@jokob-sk jokob-sk merged commit d0adb55 into main Jun 23, 2026
5 of 6 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Jun 24, 2026
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.

1 participant