Blog

Version 26.04.07

New Features

Mail Proxy and Email Queue

  • 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 (#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
    /

    elements has been added to the grouplet system. It provides zero-JavaScript collapsible sections and integrates with the existing grouplet panel infrastructure.

GnrToast Improvements

  • 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

  • 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.xmland the Dockerfile.
  • CSS variables have been added for --multibutton-selected-bg, --button-in-grid-bg, --frameindex-tablist-* sizing, and the deletingButtonspecialisation.

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 (#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 (#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 (#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 (#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 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 (#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 - 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 (#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 (#698).

mkthresource

  • Cross-package foreign key relation errors in mkthresource have been fixed (#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 (#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.