Skip to content
Updated Sep 29, 2026 by Pablo Coufal · Owner: analysisactivefeature Edit on GitHub

Table View Settings ​

Business Context ​

Business-Level Definition ​

Every overview table in the product — buildings, gauges, contracts, invoices and the rest — behaves the same way when a user wants to change what it shows. From the menu under the three dots the user opens Column settings, chooses which optional columns to show, puts them in the order that suits their work, and can return to the default at any time. The arrangement is the user's own: it is kept across sign-ins and devices, it is kept separately for each overview, and it never changes what any other user sees.

The export of an overview follows what the user sees: the current search and filters, the columns shown and their order, and — where the overview lets the user pick rows — only the picked rows. Hidden data never appears in an ordinary export unexpectedly.

This document is the product's standard for overview tables. It applies to every current and future overview unless that overview's own analysis names an exception. The first two overviews to adopt it are buildings and gauges; the others adopt it one by one, each bringing its column catalogue.

Requirements Definition ​

Users of the previous system relied on arranging the building and gauge overviews to fit their work: an energy manager looks at consumption and status, a technician at supply point numbers and locations, and both expect to find the overview the way they left it. Without one shared behaviour each screen would solve this differently, or not at all.

Three things matter. The behaviour has to be one behaviour, built once into the shared table, so that learning it on one overview is learning it everywhere. A personal arrangement must stay personal, and must never become a way to see data the user is not allowed to see — including data that differs between customer organisations. And the export must match the screen: a file that silently drops the filter or adds columns nobody chose is a file people stop trusting.

Technical Context ​

User Stories / Use Cases ​

  • As an energy manager, I want to hide the columns I never use in the gauge overview, so the ones I need fit on the screen.
  • As a technician, I want to move the supply point number next to the gauge name, so I can match meters on site at a glance.
  • As any user, I want to find the overview arranged the way I left it after signing in again or on another computer.
  • As any user, I want to return an overview to its default arrangement in one step.
  • As any user, I want to see which columns I cannot hide, so I do not look for a way to remove them.
  • As a keyboard user, I want to change the column order without a mouse.
  • As an energy manager, I want the export to contain exactly the rows and columns I have on screen, across all pages, so the file matches what I checked.
  • As an administrator of a customer organisation, I want a user's saved arrangement never to reveal a column that user is not permitted to see.

UI/UX Design ​

Entry point. The overview's toolbar has a three-dot menu; its first item is Column settings (Nastavit sloupce). An overview with a single meaningful column has no such item.

Column settings panel. A dialog listing every column of the overview the user may see, in the current order.

ElementBehaviour
Row per columnDrag handle, checkbox, column label
Mandatory columnCheckbox checked and disabled, with a lock icon and the tooltip "Tento sloupec nelze skrýt"
Drag handleDrag and drop to reorder; the drop position is shown by an insertion line
KeyboardHandle is focusable; Space picks the row up, Arrow Up / Down moves it, Space drops it, Escape cancels; the change is announced to screen readers. Move up / Move down buttons on each row give the same result without the pick-up gesture
Obnovit výchozíRestores the overview's default selection and order in the panel
PoužítSaves and closes; the table redraws without a page reload
Zrušit / Escape / closeDiscards the changes in the panel
StateWhat is shown
Arrangement never changedDefault columns; the reset action is disabled
Arrangement customisedThe user's columns; a small "upraveno" marker next to the menu
SavingPoužít shows progress; the panel stays open
Save failedThe panel stays open with the error; the table keeps its previous arrangement
Arrangement could not be loadedThe table shows the default arrangement and a non-blocking notice
A saved column is no longer availableIt is simply absent; no message

In the table. The header's vertical separators are visual only in this version: columns are not dragged in the header and their width is not changed or saved. Filtering, sorting, paging and row actions work exactly as without the feature. A filter may use an attribute whose column is hidden; an active filter is always shown as a filter chip, whether or not its column is visible.

Export. The export action exports the current result set with the shown columns in the shown order. Where an overview lets the user select rows, a selection exports only the selected rows and the action says so ("Exportovat vybrané (12)"). An export that would exceed the limit shows the number of rows and asks the user to narrow the filter. An overview that needs hidden or extended data offers it as a separately named action (for example Úplný export), never as the default one.

The design follows the shared components of the frontend (dialog, menu, checkbox, buttons); the drag-and-drop list is a new shared component, used here first.

Functional Requirements ​

  • Provide column settings in the shared table component, so an overview adopts them by supplying a column catalogue rather than by building its own.
  • Define for each adopting overview a column catalogue: every column it offers, its label, whether it is mandatory, whether it is exported, the permission, module or screen context it needs, and the default selection and order.
  • Allow a mandatory status for the record's primary identification and for the row-actions column; mark mandatory columns and refuse to hide them.
  • Let the user show and hide each optional column, reorder the shown columns by drag and drop and by keyboard, and reset to the default.
  • Apply a confirmed change immediately, without reloading the page, and keep the table's filter, sort, page and selection.
  • Save the arrangement automatically on confirmation, per user, per tenant and per overview, persisted across sessions and devices.
  • Never let one user's arrangement change the default or anybody else's arrangement.
  • Reconcile a saved arrangement with the current catalogue on every load: drop unavailable and unpermitted columns, force mandatory ones on, append new optional columns as hidden.
  • Show the default arrangement when no arrangement is saved or it cannot be loaded.
  • Make the default export respect the search, filters, user permissions, shown columns, their order and the selected rows; export every matching row, not only the current page.
  • Export every shown column, including columns the server derives from stored data (consumption, conversions, year-on-year); only a column that exists solely on the screen (row actions) is never exported.
  • Refuse an export above 50 000 rows (a configuration value) with the row count and a request to narrow the filter.
  • Apply the same filters to an overview's export as to its list, for every adopting overview.
  • Name any export of hidden or extended data explicitly; never add hidden data to the default export.
  • Adopt the standard on the building and gauge overviews (the gauge overview both standalone and in a building's tab, sharing one arrangement).

Out of scope for this version: moving columns by dragging the table header, changing and saving column widths, saving filters or sorting, shared or named views, and row selection on the pilot overviews (the export accepts a selection so an overview that adds selection needs no API change).

Internationalization & Localization ​

Column labels, the panel's texts, tooltips and export messages come from the product's labelling mechanism — see GUI Labelling. The catalogue carries label keys, never texts, and the exported header row uses the labels in the user's current language. The saved arrangement holds column keys only, so switching language needs no migration.

Non-Functional Requirements ​

  • Accessibility. The panel meets WCAG 2.1 AA: full keyboard operation including reordering, visible focus, announced moves, labelled controls.
  • Consistency. One shared implementation; an overview that adopts the standard does not re-implement any part of it.
  • Privacy by construction. A stored arrangement is never trusted for access: what may be shown or exported is decided from the user's current permissions on every request.

Performance ​

Loading an arrangement is one indexed read per overview open (by user and key) and must add less than 50 ms to the overview's load; the frontend caches it for the session and invalidates it on save or reset. Saving is one upsert. The export reads at most 50 000 rows, resolves display names in batch, and streams the workbook rather than building it wholly in memory once the row count warrants it.

Transactional Operations ​

Saving and resetting are single statements; the unique key on user and setting makes a save an upsert, and concurrent saves by the same user resolve as last write wins. An export counts and reads its rows in one read-only transaction, so the limit check and the file describe the same data.

TriggerOwner of the triggerWhat this feature does
User opens an adopting overviewOverview screenLoads the reconciled arrangement and renders the table with it
User confirms column settingsUserSaves the arrangement, redraws the table
User resets column settingsUserDeletes the saved arrangement, redraws with the default
User exports an overviewUserSends the filters, shown columns and selection to the overview's export
User's permissions or the tenant's modules changeUsers & Access / Client ManagementNothing is rewritten; the next load and export reconcile against the new catalogue
User loses access to the tenantUsers & AccessThe user's preferences in that tenant are deleted
An overview adopts the standardIts feature analysisAdds its value to Enum - TableViewKey and defines its column catalogue

Related analyses: Building Management and Gauge Management own the pilot overviews and their column catalogues; Users & Access owns users and tenant membership.

Diagrams & Models ​

Opening an overview and changing its columns:

sequenceDiagram
    actor U as User
    participant T as Shared table
    participant A as Tenant API
    participant P as userPreference
    U->>T: Open the gauge overview
    T->>A: GET table-views/gauges/columns
    A->>P: Read the user's row for table.gauges.columns
    P-->>A: Saved arrangement or none
    A->>A: Reconcile with the user's column catalogue
    A-->>T: Columns in order, visibility, mandatory flags
    T-->>U: Table with the user's columns
    U->>T: Column settings, hide and reorder, Apply
    T->>A: PUT table-views/gauges/columns
    A->>A: Validate against the catalogue
    A->>P: Upsert the row
    A-->>T: Reconciled arrangement
    T-->>U: Table redrawn, same filters and page

Which columns a user gets for an overview:

flowchart TD
    A[Overview column catalogue] --> B[Remove columns the user's permissions, modules or tenant exclude]
    B --> C{Saved arrangement?}
    C -->|no| D[Default selection and order]
    C -->|yes| E[Drop saved columns no longer available]
    E --> F[Force mandatory columns visible]
    F --> G[Append new optional columns as hidden]
    G --> H[User's arrangement]
    D --> I[Render and export with this list]
    H --> I

What an export contains:

flowchart TD
    A[Export request: filters, shown columns, selection] --> B{Columns all available to the user?}
    B -->|no| X[Refuse]
    B -->|yes| C{Rows selected?}
    C -->|yes| D[Selected rows that still match and are readable]
    C -->|no| E[All rows matching the filters]
    D --> F{Over the limit?}
    E --> F
    F -->|yes| Y[Refuse with the count]
    F -->|no| G[XLSX: shown columns in shown order]

API Analysis ​

See api-a.md.

Domain Model (ER diagram) & Data Attribute Table ​

erDiagram
    USER ||--o{ USER_PREFERENCE : "owns"
    USER_PREFERENCE }o--|| TABLE_VIEW_KEY : "arranges, for table keys"

The column catalogue is code, not data: it is defined with the overview it describes, because a column is only meaningful together with the code that fills and formats it.

Data ​

No reference data. The pilot catalogues' default columns:

OverviewDefault columns, in orderMandatory
buildingsname, area, sector, floor area, consumption, year-on-year, status, actionsname, actions
gaugesname, building, supply point number, level, distributor tariff, last reading, consumption, year-on-year, status, actionsname, actions

Optional columns, hidden by default:

OverviewOptional columns
buildingstype, level type, address, street, house number, reference number, city, postcode, owner (name, company ID), manager (name, company ID), delegated manager (name, company ID), description, GPS latitude and longitude, archived
gaugesmedium, kind, purpose, archived

The building optional columns are the attributes the building export has always carried, so a user who wants the full address sheet shows those columns once and exports it. The row-actions column is never exported. Consumption, year-on-year and status on both overviews, and last reading on gauges, are derived on the server and are exported like every other shown column. The building column of the gauge overview is offered only on the standalone list; inside a building's tab the building is the context, so the column is not in that screen's catalogue and a shared arrangement simply skips it there.

Test Data ​

Use the E2E tenant named in the overlay's Test Data location, with at least two users in the same tenant, one user who is a member of two tenants, and one user without the permission a column needs. The demo gauges seed provides enough rows to page and to export across pages; an export above the limit is tested with the limit lowered through configuration rather than with 50 000 seeded rows.

Logging ​

The project has no shared logging-conventions document yet, so this feature's events are stated here.

  • .info — arrangement saved or reset: view key, number of visible columns, userId, requestId.
  • .info — export produced: view key, row count, column count, whether a selection was used, duration, requestId.
  • .warn — a saved arrangement contained columns that were dropped on reconciliation: view key, dropped keys, userId.
  • .warn — export refused over the limit: view key, row count, limit, userId.
  • .warn — a save or export named a column not available to the user: view key, column key, userId.

The stored arrangement itself is not logged.

Monitoring ​

Export duration and row count per view key, to show when the synchronous export approaches its practical limit, and the count of refused over-limit exports, which says whether users need an asynchronous export. Everything else follows the project's standard request metrics (none / TBD until the monitoring convention is handed over).

Caching ​

The frontend caches the reconciled arrangement per overview for the session and invalidates it on save, on reset, and on a change of tenant. The backend does not cache: the read is a single indexed row, and a cached arrangement could outlive a permission change.

Backward Compatibility and Migration ​

The previous system kept column arrangements for the object and gauge overviews. They are not migrated: the column identifiers do not map one to one, and a default arrangement is a safe starting point that each user adjusts once.

The two export endpoints are POST requests carrying filters, columns and selection in the body. The frontend is their only caller and moves to them in the same release; the earlier GET export routes are removed rather than kept alongside.

The default building export contains the shown columns rather than the fixed address sheet the previous export produced; that sheet is reproduced by showing the optional address and ownership columns.

An overview that has not adopted the standard keeps its fixed columns and is unaffected.

The feature changes presentation only. Its one legal bearing is that an arrangement is personal data of little weight (a user's display choices, tied to their identifier); it is kept only while the user belongs to the tenant and deleted with the membership. No licence or contract is required.

Cybersecurity Considerations ​

The stored arrangement is treated as untrusted input on every read and write: the user's current permissions, the tenant's modules and the tenant's configuration decide which columns can be shown or exported, and a saved or requested column outside that set is dropped (on read) or refused (on write and export). Every endpoint works on the authenticated user only and takes no user identifier. Preferences live in the tenant schema under its row-level security, so a user's arrangement in one customer organisation cannot be read in another. The export requires the overview's read permission and returns only rows that permission covers, including when a selection names other rows.

Data Privacy. The only personal data is the owner's identifier on each preference, plus the display choices themselves. They are deleted when the user leaves the tenant.

Risk Assessment ​

Business Risks ​

The standard only helps if every overview adopts it the same way; overviews that keep their own column handling would bring back the inconsistency this removes. The mitigation is that the behaviour lives in the shared table and an overview adopts it by supplying a catalogue, and that an exception must be named in that overview's analysis.

An export that differs from the screen erodes trust in every figure the product exports. The export takes its columns and filters from the same state the screen renders, and the building export's missing filter is fixed as part of this work.

Technical Risks ​

RiskConsequenceMitigation
A saved arrangement names a column the user has since lost access toData shown or exported without permissionCatalogue is resolved per request from current permissions; saved columns are filtered, requested columns are refused
An overview's column is renamed or removedSaved arrangements lose that columnUnknown keys are dropped on read; a rename is treated as remove plus add
A new optional column is addedUsers with a saved arrangement see an unexpected columnNew optional columns are appended hidden
Export of a very large result setSlow request, memory pressureRow limit checked before reading; batch name resolution; streaming writer where needed
Drag and drop not usable by keyboard or assistive technologyFeature unusable for some users; accessibility non-complianceKeyboard reordering and move buttons are part of the component's acceptance
Export route changes from GET to POSTA stale client breaksOnly the frontend calls it and ships in the same release
Cascade — the preference store is unavailableOverviews cannot load or save arrangementsOverviews fall back to the default arrangement and keep working; export does not depend on the store

Auditing, Reporting & Measurement ​

Arrangements are personal display settings and are not filed in the audit trail; each row's updatedAt / updatedBy shows when it last changed. Exports are logged with their view, size and requester. Adoption is measured by the number of overviews in Enum - TableViewKey against the number of overviews in the product, and use by the share of users with a saved arrangement per overview.