Skip to content

Add map notes with alignment and sharp text rendering - #301

Open
alcatron wants to merge 16 commits into
Cacti:developfrom
alcatron:feat/notes-20261011
Open

alcatron wants to merge 16 commits into
Cacti:developfrom
alcatron:feat/notes-20261011

Conversation

@alcatron

@alcatron alcatron commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Add an Add Note editor action and a dialog for multiline text, left/centre/right alignment, standard colours with a custom picker, fonts, move, clone and delete. New notes default to black Vera Sans at 9 pt and are saved as label-only map nodes with editor hints.

Render note glyphs at twice the density while retaining logical dimensions, coordinates and clickable bounds. Preserve foreground ordering and composite furniture once. Allocate both new canvases before suppressing normal glyphs; if either allocation fails, retain the logical-resolution map and readable note text. Missing or unreadable fonts fall back to a built-in font.

Save configurations through checked atomic replacement under a destination-directory mutex shared with registration and deletion. Compare the exact read revision before replacement so stale edits and repairs cannot overwrite newer content. Create-only writes protect new and cloned map filenames. Missing targets and save failures return errors with neutral retry guidance. Regression tests exercise concurrent creators/readers, stale repairs, raw fragment edits, both canvas allocation failures and process-isolated upgrade stubs.

Validation: affected branch PHP 8.3 and browser regressions pass in isolated Cacti fixtures. The combined changes pass 291 PHP tests (5784 assertions) and 15 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

Note deletion can silently remove connected links, and save/render consistency issues remain.

6 open findings
What changed in this PR

Adds editable map notes and high-density text rendering while preserving logical map dimensions.

Changes:

  • Adds note creation, styling, movement, cloning, deletion, and validation.
  • Renders eligible note text at 2× resolution.
  • Adds localization and engine regression coverage.
File Description
weathermap-cacti-plugin-editor.php Adds note controls and dialog.
js/​editor.js Implements note editor interactions.
lib/​editor.notes.php Validates and persists note data.
lib/​editor.actions.php Adds note save endpoint and metadata.
lib/​editor.inc.php Registers note helpers and translations.
lib/​WeatherMap.notes.php Implements high-density note rendering.
lib/​WeatherMap.class.php Integrates note composition and thumbnail scaling.
lib/​WeatherMapNode.class.php Adds multiline alignment and rendering state.
tests/​Unit/​EditorNotesEngineTest.php Wraps the engine regression test.
tests/​Support/​EditorNotesEngineRegression.php Tests note persistence, rendering, and validation.
locales/​po/​cacti.pot Adds translatable note strings.

🧠 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 js/editor.js
Comment thread lib/editor.actions.php Outdated
http_response_code(400);
return;
}
if (!$map->WriteConfig($mapfile)) http_response_code(500);
Comment thread lib/editor.notes.php
Comment thread js/editor.js
Comment on lines +1715 to +1719
function add_note() {
hide_all_dialogs();
$('#tb_help').addClass('wm-action-help').text(wmEditorText.addNoteHelp);
$('#action').val('place_note');
mapmode('xy');
Comment thread tests/Unit/EditorNotesEngineTest.php
Comment thread tests/Unit/EditorNotesEngineTest.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.

🔵 Needs a closer look

The built-in live view displays high-density PNGs at twice their logical dimensions, and palette labels are not extractable for translation.

2 open findings
4 resolved since last review
Previously missed (4)

In code that hasn't changed since last review

Medium severity Constrain live-view images to logical map dimensions

lib/​WeatherMap.class.php:4186

The high-density output changes the PNG's intrinsic size, but the built-in live-view caller renders ?action=liveviewimage without width/height attributes (weathermap-cacti-plugin.php:206). A 600×300 map with a note is therefore displayed at 1200×600 in live view, contrary to the logical-size guarantee. Update that rendering path to constrain the image to the map's logical dimensions (and add a regression for it).

Low severity Document function parameters and return value in PHPDoc

lib/​WeatherMap.notes.php:29

This new function's PHPDoc does not follow the repository-required shape because its parameter and return value are undocumented. Add typed @param and @return entries.

This issue also appears on line 60 of the same file.

Low severity Indent else-block statement consistently

lib/​WeatherMapNode.class.php:803

The statement inside this else block is not indented one level deeper, unlike the surrounding PHP control structures. Add one tab so the branch structure remains clear.

Low severity Use literal gettext calls for translatable palette labels

weathermap-cacti-plugin-editor.php:390

Passing $label dynamically to __esc() prevents gettext extraction. The regenerated POT contains none of these eight plain colour names, so palette labels cannot be translated. Use literal gettext calls for each array value and regenerate locales/po/cacti.pot.

🧠 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.

🔵 Needs a closer look

High-density rendering incorrectly excludes notes beneath non-overlapping higher-layer nodes, and note deletion displays an inaccurate confirmation.

2 open findings
Previously missed (2)

In code that hasn't changed since last review

Medium severity Use note-specific confirmation for deleting notes

js/​editor.js:587

The note-specific wmEditorText.noteDelete message added by this change is never used. Calling delete_node() shows the generic node confirmation and appends “The Cacti device and graphs will remain,” which is inaccurate for a label-only note. Use a note-aware confirmation (while still warning about any connected links) and omit the device message.

Medium severity Scan all layers to preserve non-overlapping sharp notes

lib/​WeatherMap.notes.php:43

This only scans the single highest real z-layer. For example, a note at the default layer 600 plus a non-overlapping node at layer 700 starts with an empty $notes list and returns no sharp notes, so the note loses high-density rendering even though the later node does not overlap it. This also contradicts the stated behavior that later nodes block only annotations they overlap. Traverse the sorted layers in draw order so eligible notes are collected before later nodes are checked for overlap, while retaining the conservative handling for links and overlapping objects.

🧠 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

High-density composition can reorder higher map layers, and localized interfaces may select the wrong default font.

3 open findings
Previously missed (6)

In code that hasn't changed since last review

Medium severity Select bundled fonts using stable identifiers, not localized labels

js/​editor.js:1748

This default-font lookup depends on the English option label. When Vera 9 is already registered, wm_style_font_options() uses its numeric font ID instead of the bundled: value; in a locale that translates the label, neither condition matches and the note silently defaults to font 3 rather than Vera Sans 9 pt. Expose and select a stable bundled-font identifier (for example, a data attribute) instead of matching localized display text.

Low severity Use cacti_count() instead of raw count()

lib/​WeatherMap.notes.php:85

Use the repository's cacti_count() wrapper for this new production code instead of raw count(), as required by the plugin's compatibility convention.

Low severity Use cacti_count() instead of raw count()

lib/​WeatherMapNode.class.php:371

New or edited Cacti plugin code should use the repository's count wrappers rather than raw count(). Replace this with cacti_count($noteLines) to follow the plugin-wide compatibility convention.

Low severity Add required PHPDoc to named helper

tests/​Support/​EditorNotesEngineRegression.php:34

This new named helper is missing the repository-required PHPDoc shape (description, @param entries, and @return). Add a block documenting the assertion value, message, and void return before the function.

This issue also appears on line 152 of the same file.

Low severity Use cacti_count() in test code

tests/​Support/​EditorNotesEngineRegression.php:119

Use cacti_count() rather than raw count() in this new test code as well, matching the repository's required Cacti compatibility wrapper convention.

Low severity Add required PHPDoc to test method

tests/​Unit/​EditorNotesEngineTest.php:31

The new test method is missing the PHPDoc block required for every PHP function/method in this repository. Add a one-line description and @return void while retaining the process-isolation attributes.

🧠 Review effort: Balanced

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

Comment thread js/editor.js
Comment on lines +578 to +582
$('#note_move').off('click').on('click', function() {
$('#param').val($('#note_name').val());
$('#node_name').val($('#note_name').val());
hide_dialog('dlgNoteProperties');
move_node();
Comment thread js/editor.js
Comment on lines +584 to +587
$('#note_delete').off('click').on('click', function() {
$('#param').val($('#note_name').val());
$('#node_name').val($('#note_name').val());
delete_node();
Comment thread js/editor.js Outdated
Comment thread lib/WeatherMap.notes.php Outdated
Comment thread lib/WeatherMapNode.class.php Outdated
Comment thread tests/Support/EditorNotesEngineRegression.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.

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

Comment thread lib/editor.notes.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.

Comment thread lib/WeatherMap.config.php Outdated
* @return resource|false The exclusive lock handle, or false on failure.
*/
function acquire() {
$path = dirname(__DIR__) . '/configs/.weathermap-config.lock';
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.

Comment thread lib/editor.actions.php Outdated
Comment thread lib/editor.notes.php
Comment thread CHANGELOG.md
Comment thread js/editor.js
error: function() {
if (savingNote) {
if (noteAction !== 'set_note_properties') show_note(noteTarget);
$('#wm-note-error').text(wmEditorText.noteError).show();

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.

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 lib/WeatherMap.config.php Outdated
Comment on lines +91 to +98
$mustExist = $mustExist || file_exists($filename);
$lock = acquire(dirname($filename));
if (!$lock) return false;
$temp = false;
$stream = false;
try {
clearstatcache(true, $filename);
if ($mustExist && !is_file($filename)) return false;
Comment thread lib/WeatherMap.notes.php Outdated
Comment on lines +70 to +71
$image = imagecreatetruecolor($map->width * 2, $map->height * 2);
imagecopyresampled($image, $map->image, 0, 0, 0, 0, $map->width * 2, $map->height * 2, $map->width, $map->height);
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