Skip to content

Add traffic colour presets and optional high-load link pulsing - #302

Open
alcatron wants to merge 42 commits into
Cacti:developfrom
alcatron:feat/colours-pulse-20261011
Open

alcatron wants to merge 42 commits into
Cacti:developfrom
alcatron:feat/colours-pulse-20261011

Conversation

@alcatron

@alcatron alcatron commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Add traffic colour presets, live range previews and Custom/Advanced scale editing while preserving other named scales. Default (Classic) remains the default for new maps. Validate parser-compatible scale names and serialized numeric ranges, support existing long names and negative custom units, and exclude unsupported gradient end values.

Place map background image and colour controls together in Map Properties. Cancelled colour edits remain local until submission. Successful editor and colour saves reload the complete editor state through a clean view URL, retaining the selected filename and return destination without replaying mutation actions. Use themed section headings, translated labels and accessible names for palette selects and advanced colour inputs. The colour endpoint returns a revision on load/save; the dialog retains that token and the save endpoint requires it, independently of other feature PRs. Missing or stale tokens return HTTP 409 with reload guidance. The endpoint holds the shared config-directory mutex from before reading/checking through checked atomic persistence, reusing that caller-owned lock in WriteConfig and releasing it in finally. Engine writers use the same atomic persistence protocol; deletion and registration share the directory lock. A forked regression submits two requests with one revision and asserts exactly one successful save and one HTTP 409, with the winning colours retained. JSON error documentation reflects the appropriate HTTP statuses.

Add optional colour-matched pulsing on link directions at 80%+ utilisation. Use rendered geometry, mask labels and nodes, support via paths and Safari's native SVG filters, and pause for reduced-motion/hidden-page settings. Cycle refresh fetches only the authorized current map and replaces the image, glow metadata and its sibling hotspot map together. Browser regressions model the production sibling-map structure and check refreshed usemap/coordinates/destinations, presets, Custom, preview, save and errors.

General editor saves display localized HTTP 409 reload guidance and other save-failure messages without dismissing the form. The initial controls and revision use the same snapshot. An unread root configuration is rejected instead of returning default colours. Editor tokens and atomic writes validate included-file revisions; contended external dependencies fail safely and read-only includes remain usable. Creation stops on failure with retry guidance, and read-only config registration remains supported.

Symlink writers retain the logical mutex and also lock the resolved target, so direct and aliased saves cannot bypass CAS. Non-string JSON payloads and unsupported gradient values receive HTTP 400.

Scale serialization uses dot decimals regardless of the server numeric locale, including unit-suffixed ranges. Save and Enter submission restore the active dialog action.

Resolve complete symlink INCLUDE paths before selecting dependency locks; check root revisions after acquiring all locks.

Mutation routes require loaded revisions. Colour-read GETs omit CSRF tokens, while save POSTs retain them. Scale names are bounded to 1024 ASCII characters on the server and in the UI.

Enter in advanced colour fields uses the colour save payload and revision. At least one DEFAULT traffic range is required. Absolute unresolved root/INCLUDE paths preserve parent-directory aliases. Physical destinations are frozen for atomic writes and canonical mutex directories are deduplicated. Translated accessible names cover Scale, From, To and Label inputs. Captured root target identity binds page tokens and commits; canonical destinations, logical/physical INCLUDE snapshots and source-root copy dependencies preserve snapshot consistency.

Validation: affected branch PHP 8.3 and browser regressions pass in isolated Cacti fixtures. The combined changes pass 292 PHP tests (5860 assertions) and 16 browser regression programs. Changed-line coverage passes at 100% of measured production lines; existing controller/entry-point exemptions remain. Syntax, whitespace, translation and manifest checks pass. These revisions have not been deployed to the live installation.

Based on current develop, including the merged icon picker and gallery resize. Shared editor files overlap with the other feature PRs.

Copilot AI 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.

🟡 Changes recommended

Scale-reference validation can miss same-named nodes and links, and the new UI also has unresolved localization and repository-header requirements.

7 open findings
What changed in this PR

Adds editable traffic colour presets, map styling controls, and optional high-load link pulsing across the editor, renderer, and viewer.

Changes:

  • Adds colour presets, advanced scale editing, background colour, and pulse settings.
  • Adds rendered-link glow metadata, browser animation, masking, and reduced-motion handling.
  • Adds PHP and browser regression coverage.
File Description
weathermap-cacti-plugin-editor.php Adds colour and map appearance controls.
lib/​editor.colours.php Validates and saves colour settings.
lib/​editor.actions.php Adds colour endpoints and background saving.
lib/​editor.new-map-preset.php Enables pulsing for new maps.
lib/​WeatherMap.animation.php Builds viewer animation metadata.
lib/​WeatherMap.class.php Embeds animation metadata in HTML.
lib/​WeatherMapLink.class.php Stores rendered arrow coordinates.
lib/​WeatherMap.functions.php Captures straight and curved link geometry.
js/​editor.js Implements presets, pickers, preview, and saving.
js/​weathermap.js Renders and manages pulsing overlays.
css/​editor.css Styles colour-management controls.
css/​weathermap.css Defines pulse animation and motion fallback.
locales/​po/​cacti.pot Updates translation template entries.
tests/​Unit/​TrafficAnimationTest.php Runs traffic animation regression coverage.
tests/​Unit/​EditorAssetsTest.php Runs editor asset regression coverage.
tests/​Support/​TrafficAnimationRegression.php Exercises animation geometry and settings.
tests/​Support/​EditorAssetsRegression.php Exercises colour persistence and validation.
tests/​Support/​NewMapPresetEngineRegression.php Verifies pulse defaults and copying.
tests/​Browser/​TrafficGlowTest.cjs Tests browser glow behavior and cleanup.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread lib/WeatherMap.animation.php Outdated
Comment thread lib/editor.colours.php
Comment thread weathermap-cacti-plugin-editor.php Outdated
Comment thread tests/Support/EditorAssetsRegression.php
Comment thread tests/Support/TrafficAnimationRegression.php
Comment thread tests/Unit/EditorAssetsTest.php
Comment thread tests/Unit/TrafficAnimationTest.php

Copilot AI 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.

🔵 Needs a closer look

Scale validation can lose valid configurations, icon-scale references are incomplete, and detached maps can retain listeners.

0 open findings

7 resolved since last review
Previously missed (4)

In code that hasn't changed since last review

Medium severity Client-side minimum blocks negative scale ranges

js/​editor.js:1706

This client-side min=0 prevents editing negative ranges even though the map engine supports them, so existing custom scales cannot be retained through the advanced editor. Leave the number inputs unrestricted and let the server enforce finiteness, magnitude, and range ordering.

Medium severity Detached holders are not cleaned up after map removal

js/​weathermap.js:168

ResizeObserver observes box-size changes, not DOM removal, so removing a map through loadPageNoHeader() does not guarantee align() runs. The document/window/media listeners then retain the detached holder indefinitely; the test only simulates cleanup by manually invoking the observer. Track initialized holders and explicitly clean disconnected ones on AJAX completion, or use a removal observer.

Medium severity Scale name validation does not match parser grammar

lib/​editor.colours.php:56

This accepts names that the map parser cannot read: ReadConfig() requires a leading letter and then only letters, digits, or underscores, while this allows leading digits and hyphens. Saving a name such as 1-hour writes a SCALE line that is dropped on reload. Match the parser’s grammar here.

This issue also appears in the following locations of the same file:

  • line 57
  • line 62
Medium severity Deletion guard ignores icon scale references

lib/​editor.colours.php:77

Nodes can also reference a colour scale through useiconscale/ICONSCALE, but this deletion guard checks only usescale. A scale used solely to colour an icon can therefore be removed, leaving the saved node with a dangling scale reference and broken icon colouring. Validate both node scale fields.

🧠 Review effort: Balanced

Copilot AI 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.

🟡 Changes recommended

Duplicate numeric ranges can corrupt scale state, and Live View does not receive the new animation metadata.

1 open finding
Previously missed (4)

In code that hasn't changed since last review

Medium severity Add pulse metadata to Live View output

lib/​WeatherMap.class.php:4545

Pulse metadata is only added to MakeHTML() output. The advertised Live View path renders a fresh map but emits a bare image and image-map areas in weathermap-cacti-plugin.php:191-210, so maps opened via action=liveview never receive data-wm-traffic and cannot pulse. Route that view through this HTML generation or emit the same holder metadata there.

Low severity Document helper parameters and return value

lib/​WeatherMap.animation.php:26

This helper's one-line comment omits its parameter and return contract. Add a complete PHPDoc block for the map argument and returned metadata array.

Low severity Document endpoint helper inputs and response

lib/​editor.actions.php:1148

This new endpoint helper lacks a PHPDoc contract for its map path/action inputs and response behavior. Add the expected parameter and return documentation.

Low severity Document helper input validation and return types

lib/​editor.colours.php:26

The comment does not document this helper's input and return types. Add a full PHPDoc contract, including that non-string or malformed values may be rejected.

This issue also appears in the following locations of the same file:

  • line 31
  • line 46

🧠 Review effort: Balanced

Comment thread lib/editor.colours.php Outdated

Copilot AI 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.

🟡 Changes recommended

Large custom scale values can collide during serialization and silently lose ranges after reload.

1 open finding
1 resolved since last review
Previously missed (2)

In code that hasn't changed since last review

Medium severity Add an accessible name to the native color picker

js/​editor.js:1688

This native colour picker has no accessible name; the surrounding <summary> labels the disclosure, not the input. Add a localized aria-label (or an associated <label>) so screen-reader users can identify the control.

Low severity Localize the changed description and option label

weathermap-cacti-plugin-editor.php:645

The newly changed description and option label bypass gettext, so this part of Map Properties remains English in translated installations. Wrap both strings with the plugin text domain and regenerate locales/po/cacti.pot.

🧠 Review effort: Balanced

Comment thread lib/editor.colours.php Outdated

Copilot AI 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.

🟡 Changes recommended

Valid existing scale names can be rejected, and the new editor preset workflow lacks browser regression coverage.

3 open findings

🧠 Review effort: Balanced

Comment thread lib/editor.colours.php Outdated
Comment thread js/editor.js

Copilot AI 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.

🟡 Changes recommended

The Gradient End control exposes a None value that the server rejects, causing valid-looking editor submissions to fail.

4 open findings

🧠 Review effort: Balanced

Comment thread js/editor.js Outdated

Copilot AI 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.

Comment thread js/editor.js Outdated
Comment thread js/weathermap.js
Comment thread weathermap-cacti-plugin-editor.php Outdated
Comment thread lib/editor.actions.php Outdated
@alcatron

Copy link
Copy Markdown
Contributor Author

Addressed in 6be014f. The two additional review-summary findings are addressed. The colour_data GET omits the CSRF token; only the state-changing save POST includes it. The browser regression verifies both requests. Submitted scale names are limited to 1024 ASCII characters, with the same maxlength in the UI; this leaves space for every bounded numeric/colour/label field below the parser line limit. Regressions reject 1025/5000-character names and roundtrip the 1024-character boundary with extreme permitted ranges, a gradient and a 200-character label. Validation: 292 PHP tests (5834 assertions), 16 browser regression programs; measured coverage, syntax, translation, manifest and whitespace checks pass. The live installation is unchanged.

Copilot AI 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.

🟡 Changes recommended

Empty DEFAULT scales, Enter-based colour saves, symlink dependency tracking, and a stale-token regression fixture remain incorrect.

1 open finding
1 resolved since last review
Previously missed (3)

In code that hasn't changed since last review

Medium severity Enter key incorrectly submits the generic form

js/​editor.js:1897

Pressing Enter in an advanced colour text/number input submits #frmMain, but the generic form contains no colours_json and uses WMConfigRevision rather than this dialog's wmColourRevision. The request therefore reaches set_map_colours and fails with HTTP 400 instead of performing the same save as this button. Bind Enter within #dlgColours to prevent the form submission and trigger #wm-colours-save.

Medium severity Include symlink retargeting is missed by dependency checks

lib/​WeatherMap.class.php:2482

Recording only the resolved target does not detect an INCLUDE symlink being retargeted. If the alias points to A when loaded and is later changed to B, dependenciesMatch() still hashes A and the root save can succeed even though the root now includes B. Track/check the logical include path as well as the physical target (the latter is still needed for target-directory locking).

Medium severity Empty DEFAULT scale is not preserved across save and reload

lib/​editor.colours.php:80

This validation permits a payload containing only named-scale rows. WriteConfig() then emits no SCALE DEFAULT directive, and ReadConfig() automatically recreates the Classic DEFAULT scale whenever it sees zero DEFAULT rows (WeatherMap.class.php:3375-3403). The save therefore reports success but the user's “no DEFAULT ranges” state changes on the next reload. Require at least one DEFAULT row (or introduce a parser-compatible persisted representation for an empty DEFAULT scale).

🧠 Review effort: Balanced

Comment thread tests/Support/EditorAssetsRegression.php
@alcatron

Copy link
Copy Markdown
Contributor Author

Addressed in 0bef96b. All three additional review-summary findings are addressed. Enter in advanced colour text/number inputs prevents the generic form submission and triggers the colour dialog save with colours_json and wmColourRevision; the browser regression verifies the POST payload. INCLUDE snapshots record both the physical target hash and logical alias target/hash, detecting symlink retargeting even when the replacement file has identical bytes while retaining physical-directory locking. A regression rejects a retargeted alias and accepts a fresh reload. Payloads with no DEFAULT traffic row now return validation errors before changing the map, rather than silently regaining Classic on reload. Validation: 292 PHP tests (5845 assertions), 16 browser regression programs; measured coverage, syntax, translation, manifest and whitespace checks pass. The live installation is unchanged.

Copilot AI 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.

🟡 Changes recommended

Root symlink retargeting can bypass the intended CAS identity guarantee and overwrite a different configuration file.

2 open findings
1 resolved since last review

🧠 Review effort: Balanced

Comment thread lib/WeatherMap.config.php Outdated
Comment thread lib/WeatherMap.config.php Outdated

Copilot AI 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.

🟡 Changes recommended

The colour endpoint can misclassify a root-symlink revision conflict as HTTP 500 instead of HTTP 409.

1 open finding
2 resolved since last review

🧠 Review effort: Balanced

Comment thread lib/editor.actions.php Outdated

Copilot AI 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.

🟡 Changes recommended

Parent-directory symlink retargeting can bypass snapshot identity checks, and several advanced inputs remain unnamed for assistive technology.

1 open finding
1 resolved since last review
Previously missed (1)

In code that hasn't changed since last review

Low severity Add accessible names to scale, range, and label inputs

js/​editor.js:1821

The Scale, From, To, and Label inputs have no accessible name: the adjacent table headers provide table context but are not labels in the accessible-name computation. Screen-reader users therefore encounter unnamed edit controls, despite the colour controls having explicit aria-labels. Add translated labels (via <label> or aria-label) for each generated input.

🧠 Review effort: Balanced

Comment thread lib/WeatherMap.class.php Outdated
@alcatron

Copy link
Copy Markdown
Contributor Author

Addressed the additional accessibility finding in 38c4369. Generated Scale, From, To and Label inputs now have translated aria-labels supplied through wmEditorText and the plugin gettext helpers. The browser regression uses translated names and verifies all four controls expose them. The translation template was regenerated. Combined validation: 292 PHP tests and 16 browser regression programs; all branch and required coverage, syntax, translation, manifest and whitespace checks pass. The live installation is unchanged.

@alcatron

Copy link
Copy Markdown
Contributor Author

Merged the latest develop (including #301) into this branch and resolved the conflicts while preserving the directory-alias snapshot checks and accessible advanced colour inputs from 38c4369.

Validation on 5459fdc: 291 PHP tests passed (5,817 assertions); all browser regression programs passed; PHP/JavaScript syntax, whitespace, manifest and translation checks passed. Measured changed production PHP coverage is 100% (135/135 lines), with the existing entry-point/controller exemptions. GitHub now reports the branch as mergeable.

Copilot AI 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.

🟡 Changes recommended

Colour edits originating from included configurations can report success but be overwritten when the map reloads.

1 open finding
1 resolved since last review

🧠 Review effort: Balanced

Comment thread lib/editor.colours.php

Copilot AI 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.

🟡 Changes recommended

Saving currently converts relative INCLUDE directives into installation-specific absolute paths, breaking configuration portability.

1 open finding
1 resolved since last review
Previously missed (3)

In code that hasn't changed since last review

Low severity Add required blank lines to function PHPDoc

lib/​WeatherMap.config.php:32

This new function’s PHPDoc omits the required blank separation around its @param and @return sections. Use the repository-mandated PHPDoc shape so generated documentation and static tooling receive a consistent contract.

Low severity Add required PHPDoc block to test method

tests/​Unit/​EditorAssetsTest.php:31

The newly added test method lacks the PHPDoc block required for every PHP function/method in this repository. Add a one-line behavior description, a blank line, and @return void before the PHPUnit attributes.

Low severity Add required PHPDoc block to test method

tests/​Unit/​TrafficAnimationTest.php:31

The newly added test method lacks the PHPDoc block required for every PHP function/method in this repository. Add a one-line behavior description, a blank line, and @return void before the PHPUnit attributes.

🧠 Review effort: Balanced

Comment thread lib/WeatherMap.class.php
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.

2 participants