Release notes

Release 26.04.07

New Features

Mail Proxy and Email Queue

A complete email dispatch subsystem has been introduced:

  • A message_to_send queue table stores outgoing emails together with their sending status. A dedicated dashboard lets operators monitor the queue in real time.

  • A mail-proxy integration layer routes messages through the queue, using the message_to_send formula as the single gatekeeper that decides whether a message is actually sent.

  • The new architecture decouples email generation from delivery, making retry logic and auditing straightforward.

GnrListener - event-driven handler system

A new GnrListener class (gnr.app.gnrlistener) provides a declarative, database-backed publish/subscribe mechanism:

  • Handlers are registered with the @listen decorator and are auto-discovered at start-up both at module level and on package classes.

  • An optional thread-pool executor enables parallel handler execution for high-throughput workloads.

  • Notification payloads are automatically enriched with user, page_id, and ts fields and serialised with toTypedJSON.

  • The polling loop has been delegated to the adapter layer, keeping the core listener free of database-specific code.

Centralised Error Handler

A new centralised errorHandler (PR #677) replaces the scattered per-page error handling:

  • Errors are broadcast via pkgBroadcast so every open page is notified simultaneously.

  • Toast notifications provide immediate, non-intrusive feedback.

  • A traceback viewer allows developers to inspect the full Python stack trace directly in the browser.

REST API Dispatcher (_api)

A new _api dispatcher has been added to the web layer, providing first-class routing for REST API endpoints without requiring a dedicated WSGI application.

ExpandBox Widget

A new expandbox widget based on the HTML5 <details>/<summary> elements has been added to the grouplet system. It provides zero-JavaScript collapsible sections and integrates with the existing grouplet panel infrastructure.

GnrToast Improvements

GnrToast has been extended with two new options:

  • persistent - the toast stays visible until the user explicitly dismisses it.

  • copyable - a copy-to-clipboard button is added to the toast body, useful for error messages or reference codes.

gnr.web.widgets Package

A new Python package gnr.web.widgets has been introduced. Every widget exposes an @element method that returns its Bag-based descriptor, providing a programmatic API for widget introspection and documentation generation.

Sourcerer Integration

GenroPy now ships a built-in service adapter for Sourcerer, registered through the standard service declaration mechanism.

Improvements and Refactoring

CSS / Theme System Modernisation

An extensive CSS overhaul (PR #671 and follow-up commits) affects the entire UI:

  • A design-token system replaces ad-hoc colour literals. All colours are now expressed through a numbered seven-step gray scale (--gray-1 - --gray-7) and semantic aliases (--border-light, --border-strong, etc.).

  • Border-radius values are centralised in CSS custom properties; the --palette-* namespace has been retired in favour of the new tokens.

  • color-mix() calls have been replaced with explicit hex values to maximise browser compatibility.

  • The theme selection mechanism is unified: the GNR_CSS_THEME environment variable now controls the default theme consistently in both default.xml and the Dockerfile.

  • CSS variables have been added for --multibutton-selected-bg, --button-in-grid-bg, --frameindex-tablist-* sizing, and the deletingButton specialisation.

Grid Enhancements

  • Flex grid columns now enforce an automatic minimum width so that column headers are never truncated below their natural size.

  • Widget-in-cell rendering has been overhauled: text centering, the invalid-cell icon, and style-attribute conflicts have all been fixed.

  • The required_columns parameter is now honoured in print-resource grid queries.

  • drawFiller width calculation has been restored to its pre-PR #749 behaviour.

Grouplet Panel

  • GroupletForm now maintains a strict datapath separation between the grouplet's own data and the host page's store, preventing cross-page data leaks.

  • The error indicator is now shown only when there are actual validation errors, not on every field change.

  • The inline _onRemote pattern has been replaced with a proper gnrwdg method, improving reusability.

  • A double-load on the preference page has been eliminated.

Authentication Module

Auth verifiers have been extracted from gnrwebpage into a dedicated module (PR #700), improving separation of concerns and making it easier to swap or extend the verification strategy.

Daemon Package

Daemon initialisation logic has been moved into gnr.web.daemon.service (PR #695, #688), reducing coupling between the CLI entry points and the runtime service objects. The DataCollector (register analyser) has similarly been moved out of the CLI layer.

gnrdeploy Refactoring

The deployment helper has been refactored (PR #706) to separate configuration parsing from execution. A typo that mapped column.type instead of column.dtype was fixed as part of this work.

Siteregisters Module Organisation

Siteregisters modules have been reorganised (PR #733) to follow a clearer package structure, making it easier to locate and extend individual register implementations.

Database Migration Extensions

The gnr db migrate command now accepts a -e/--extension option with possible values txt, json, or sql, giving operators control over the format of generated migration scripts.

PostgreSQL Extension Handling

The gnr database layer now uses CREATE EXTENSION IF NOT EXISTS instead of the previous DROP - CREATE sequence, making migrations idempotent and safe to re-run.

Werkzeug ProxyFix

The ProxyFix WSGI middleware is now automatically applied when the application is running inside Kubernetes, ensuring that REMOTE_ADDR, HTTP_HOST, and scheme headers are correctly resolved behind a reverse proxy.

Frameindex Top Hook

The frameindex top hook is now decorated with @customizable, allowing projects to override the default rendering without monkey-patching. functools.wraps is applied so that the decorated function retains its original __name__.

K8S Generator

K8SGenerator now accepts an optional initContainers argument for providing accessory init containers to the generated Kubernetes manifests.

Services Declarations

Missing name and protocol fields in service declarations have been added, and last_refresh_ts availability in new connections has been fixed.

Autoreload Browser-Open Fix

When Werkzeug autoreload is active together with the -o (open browser) option, the browser is now opened only once by the main monitor process, preventing duplicate tabs on every file change.

Removals and Clean-up

  • Legacy Dojo 1.8 library (dojo_libs/dojo_18) has been removed. The framework now targets a new Dojo internal fork in a non-exclusive way, coexisting with old Dojo 11.

  • ``legacy_packages/gnr`` has been removed.

  • ``example_configuration/demo_site`` has been removed.

  • Dead WSGI code has been deleted (PR #739).

  • The name_full fallback from preference caption resolution has been removed; callers must supply an explicit caption.

  • Tree branch PNG icons have been replaced by pure-CSS triangles, eliminating several image assets.

Bug Fixes

Email

  • The sendMessage method now consults message_to_send as its sole gating condition, preventing duplicate sends and race conditions.

Storage / S3

  • S3 multipart upload ETags (which contain a -<partcount> suffix) are now correctly detected via a len check rather than a fragile string scan. The md5hash helper returns None for multipart ETags instead of raising.

CKEditor

  • The disabled vs readOnly regression introduced in a previous release has been fixed. Disabled CKEditor instances are now visually distinct from read-only ones.

DateTimeTextBox

  • DateTimeTextBox no longer clears its value on blur when the field contains a valid date/time.

Login Form

  • The login_newUser form has been converted from frameForm to boxForm so that it auto-sizes correctly on all viewport sizes.

Document Store

  • The custom rpcmethod in load_document and the handler rpcmethod chain in load_record, save_record, and save_document have been restored after being lost in a previous refactoring.

Web Page

  • userLocalTags now returns a safe empty value instead of None when called from a remoteBuilder context, preventing AttributeError downstream.

  • The --nodebug command-line flag is now correctly evaluated and no longer silently ignored.

  • Debug-level evaluation order has been corrected so that the intended log level is applied from the very first log statement.

Record / BoxForm

  • The record property has been extended to be compatible with BoxForm, removing an incompatibility introduced when grouplet panels were redesigned.

Batch Handler

  • Schedulable batches that do not define a table_script_parameters_pane now correctly show their parameters dialog (PR #679).

  • Batch handler CSS now uses em units and CSS custom properties for consistent scaling; the thermoline label is flex-centred.

Theme / CSS Fixes

  • css_theme default value is now consistent between default.xml and the Dockerfile entry point.

  • The theme editor has been fixed after the CSS variable renaming.

  • Obsolete --radius-* and --palette-* variable references in project and resource CSS files have been updated to the new token names.

  • The framedindex_tablist now uses min-height instead of padding to avoid layout collisions.

  • hiderLayer and hiderMessage readability has been improved.

  • The draft-marker ribbon position is now configurable via a draftMarker option.

  • Duplicate CSS triangle chevrons in the mobile menu are hidden when branchiconright is active.

  • Toolbar background and border-strong colours have been darkened for better contrast.

  • grouplet_chunk_box position: relative has been moved from hardcoded Python into the CSS file.

  • NumberTextBox and other right-aligned inputs now have symmetric padding-right.

  • The quickgrid toolbar contentPane now has a base height so it is always visible.

  • TabContainer border-radius is applied only to the top-right corner to preserve the visual tab-line continuation.

  • The linker error tooltip is now always visible and the scrollable-table header sync issue has been resolved.

  • XSS sanitisation has been added to the dojo_20 toast output.

  • ping_semaphore CSS visibility and TimeTextBox popup styling have been corrected.

  • The ext_ column handler mechanism now correctly supports multiple handlers on the same column (PR #698).

mkthresource

  • Cross-package foreign key relation errors in mkthresource have been fixed (PR #684).

Wizard / Formlet

  • Wizard onLoading of the main form has been fixed.

  • Formlet fields now correctly display error, focus, and disabled visual states.

Preferences

  • The preference page no longer triggers a double load on initialisation.

  • GroupletForm preference indicator now shows only on error conditions.

Miscellaneous

  • _th_mixinResource now operates in safe mode for tables that have no th_ resource, and multidomain error URLs are handled correctly (PR #716).

  • display: flex has been removed from cellContent to restore correct template grid column widths.

  • inline-flex is now used for formbuilder cells inside toolbars.

  • Minor hider background fix removing an unwanted box shadow.