Appearance
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.
| Element | Behaviour |
|---|---|
| Row per column | Drag handle, checkbox, column label |
| Mandatory column | Checkbox checked and disabled, with a lock icon and the tooltip "Tento sloupec nelze skrýt" |
| Drag handle | Drag and drop to reorder; the drop position is shown by an insertion line |
| Keyboard | Handle 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žít | Saves and closes; the table redraws without a page reload |
| Zrušit / Escape / close | Discards the changes in the panel |
| State | What is shown |
|---|---|
| Arrangement never changed | Default columns; the reset action is disabled |
| Arrangement customised | The user's columns; a small "upraveno" marker next to the menu |
| Saving | Použít shows progress; the panel stays open |
| Save failed | The panel stays open with the error; the table keeps its previous arrangement |
| Arrangement could not be loaded | The table shows the default arrangement and a non-blocking notice |
| A saved column is no longer available | It 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.
Processes & Related Systems / Components
| Trigger | Owner of the trigger | What this feature does |
|---|---|---|
| User opens an adopting overview | Overview screen | Loads the reconciled arrangement and renders the table with it |
| User confirms column settings | User | Saves the arrangement, redraws the table |
| User resets column settings | User | Deletes the saved arrangement, redraws with the default |
| User exports an overview | User | Sends the filters, shown columns and selection to the overview's export |
| User's permissions or the tenant's modules change | Users & Access / Client Management | Nothing is rewritten; the next load and export reconcile against the new catalogue |
| User loses access to the tenant | Users & Access | The user's preferences in that tenant are deleted |
| An overview adopts the standard | Its feature analysis | Adds 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"
- userPreference — created by this feature; one personal setting per user, tenant and key.
- JSON-DAT: userPreference.value — the shape of a table arrangement and its reconciliation rules.
- Enum - TableViewKey — the overviews that have adopted the standard.
- user — the owner, referenced by identifier across the platform boundary.
- building, gauge — the rows the pilot overviews show and export.
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:
| Overview | Default columns, in order | Mandatory |
|---|---|---|
buildings | name, area, sector, floor area, consumption, year-on-year, status, actions | name, actions |
gauges | name, building, supply point number, level, distributor tariff, last reading, consumption, year-on-year, status, actions | name, actions |
Optional columns, hidden by default:
| Overview | Optional columns |
|---|---|
buildings | type, 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 |
gauges | medium, 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.
Legal Context
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
| Risk | Consequence | Mitigation |
|---|---|---|
| A saved arrangement names a column the user has since lost access to | Data shown or exported without permission | Catalogue is resolved per request from current permissions; saved columns are filtered, requested columns are refused |
| An overview's column is renamed or removed | Saved arrangements lose that column | Unknown keys are dropped on read; a rename is treated as remove plus add |
| A new optional column is added | Users with a saved arrangement see an unexpected column | New optional columns are appended hidden |
| Export of a very large result set | Slow request, memory pressure | Row limit checked before reading; batch name resolution; streaming writer where needed |
| Drag and drop not usable by keyboard or assistive technology | Feature unusable for some users; accessibility non-compliance | Keyboard reordering and move buttons are part of the component's acceptance |
| Export route changes from GET to POST | A stale client breaks | Only the frontend calls it and ships in the same release |
| Cascade — the preference store is unavailable | Overviews cannot load or save arrangements | Overviews 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.