Feature/form list restyle - #21
Open
tulas75 wants to merge 19 commits into
Open
Conversation
…lbar Reuse the shared <dino-search-filters-bar> + FiltersService + ListDataSource on the form-data Map view so switching Tabella<->Mappa preserves the filter (via the ?filters= query param) and both views apply identical filtering semantics. Replaces the bespoke client-side #filtersContainer / applyFilters() with a reactive marker pipeline driven by FiltersService.queryString. Toolbar restyle (search-filters-bar): - remove the "Search by keywords" field - add an always-visible toolbar row: Tabella|Mappa segmented switcher (left), Filtri avanzati + Esporta labeled buttons (right), replacing the old icon-only buttons; presets stay inside the collapsible FILTRI panel - viewList()/switchView() + queryParamsHandling:'preserve' for state transfer Map view (forms-map): - breadcrumb + count toolbar matching the table - ListDataSource wiring (schema, node visibility, metric basic filters, data headers) mirroring FormsListComponent; export via shared ExportList - remove now-unused text-input-autocomp Add transloco keys: Table, Map, Advanced filters, pin (eng + ita). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…l, selection action-row Toolbar (search-filters-bar): - move Add / Import actions into the toolbar (before Filtri/Esporta) via a projected [toolbarActions] slot; remove the floating FABs from forms-list - merge the collapsible Simple filters and the Advanced dialog into one Filtri modal with Semplice/Avanzati tabs (Cerca commits advanced, Chiudi discards; simple filters apply live); 3-column layouts, padding - Filtri button shows a count badge of applied filters (simple + advanced) - Table/Map switcher always shown on form-data lists; Map toggle disabled when the schema has no location; align map toolbar + count with the table List (dino-list): - add a selection action-row above the table: single-selection shows row actions as icons that expand to labelled icons on hover; multi-selection shows bulk actions; a placeholder hint when nothing is selected - remove the per-row floating actions column; drop 'actions' from displayedColumns - relocate the Columns selector into the action-row; uniform 40px, pill-shaped buttons i18n: add Simple, Advanced, Advanced filters, Table, Map, pin, selected, Columns, Clear selection and the selection hint to all locales (eng, ita, fra, esp, prt, ukr, ar, uga). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t restyle
Form-data view switcher:
- rename the Tabella toggle to Dati ('Table' -> 'Data' key) and add a third AI
toggle routing to /forms/:id/datachat, preserving the ?filters= param
- hide Filtri, Esporta, the projected toolbar actions and the filter chips on
the AI view; new viewSwitcherOnly input skips initFilters where no filter is
displayed
- the AI page mounts the switcher and drops its DataChat breadcrumb
DataChat:
- remove the start-up 'Here is your data!' table and the suggested_questions
blob: the chat opens empty
- create the PandasAI agent on the first question instead of on entering the
chat, so that opening the AI view is not charged; keep it alive while the
User stays inside the form section and destroy it (enddatachat) only when
leaving it. Completion mode no longer posts enddatachat: it has no agent
- conversations are stored permanently in a dedicated IndexedDB database
(DataChatStore), scoped by user and form schema, outside RxDB: they are
never synced with the backend and survive the logout collections wipe
- new conversations sidebar (opt-in), welcome block with starter questions,
and a send button beside the chat input
- feedback is available in datachat mode too, the answer entry carries its
question so the feedback request can quote it, and the source of the
request tells the two chats apart (dinoapp-ragai / dinoapp-datachat)
- chat entries restyled as answer cards with source cards, an actions row
(rating, copy, regenerate) and suggested questions as rows
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Ports the work of 491080a onto the restyled chat, which had rebuilt the same files: the logic is the one of that commit, its four new blocks are expressed in the current answer card. The DataChat API turned its silent truncation and its dropped charts into explicit data, and the client was the only reason a user could still read a partial answer as a complete one. Table previews and export: - type the reply and map the additive fields (total_rows, total_columns, preview_rows, truncated, download_url, download_filename, note) for every response type, reading the truncated flag instead of inferring it - show how large the result really is before the table, say when columns were dropped, and display a note verbatim, whether or not the result is truncated - download the complete csv through HttpClient with the api key and user email headers, and hand the file to the host app, which saves it natively on device and through an anchor on the web - request the export outside the interceptors: JWTInterceptor reads any 400 as an expired token, and the export endpoint answers 400 when its agent is gone - map an export failure by status only: a blob response type leaves the body unparsed and a 403 answers with html. An expired token is expected, not an error worth reporting - render a null cell as an em dash: not analyzed is not a value Charts: - render the charts of any answer, prompted or not, in a new DataChatChart drawn directly on chart.js, with a color vision safe palette per theme - resolve the api plot kinds, draw a horizontal bar as chart.js 2 horizontalBar and keep the categories in the order they arrive - validate a specification before drawing it, and say that a chart is missing rather than throwing or leaving a blank canvas - never drop a malformed series: a chart missing a series looks complete - keep the further charts of a chart answer: its value is the primary chart and its charts are the others, so overwriting them lost the answer's own extras - accept a correctly encoded image, so that the api can stop wrapping its images in a python bytes repr independently of this client Stored conversations: - store the rows of a tabular answer and build its table again when the conversation is displayed again: a component instance cannot be stored - never store an export link: an export lives as long as the chat session Rating an answer: - rate a table with its rows and a chart with its title: a tabular answer has no prose of its own, and the api rejects an empty answer - copy a table as tab separated text, which a spreadsheet understands Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- color every snackbar with the theme's primary, its message white and its action label white and bold. The snackbar styles are injected at runtime by the component and read the material tokens, which the theme sets on html: overriding them on the container is what recolors the action label. The import wizard keeps its own success and error panels - give the buttons of the form data section the radius of the other sections, i.e. the one of the import wizard: the view switcher and the toolbar buttons, the selection actions and the columns button of the list, and the buttons of the chat. A chip stays a pill Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The selection action row replaced them with the actions of the selected row, which costs a click and a checkbox to reach what used to be one hover away. - restore the actions column and its 'actions' displayed column: the main actions of a row, revealed when the row is hovered or focused - drop the three dots opening the actions dialog: every action of a row is still available from the selection row above, which lists them all - center the icons on the right edge of the row. The cell has no width of its own, so the icons are taken out of the flow as a group instead of being laid out one slot each, which left them at the bottom of the row - give them the icon size of the actions of the selection row Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…nged Opening the chat validated the stored api key and asked the api for the credits of the user, which cannot have changed: nothing is spent until the agent is created, on the first question. Both the agent creation and every answer already refresh them. The credits of a key entered for the first time are still read once: without a stored key the api is not asked for them at all, so they would stay unknown. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Every column of a list takes the same share of the width, so a column of long answers is as wide as one of dates and the User cannot trade one for the other. Angular Material does not resize columns: only the experimental package does, which this drags a grip of its own instead of depending on. - add a grip on the right edge of a header cell. It swallows its own pointer events: that cell is the drag source reordering the columns, and the button sorting them - size the resized columns through a stylesheet of the list, rather than a binding on every cell: a cell is rendered by the table, in a view of its own, and a width must follow the pointer without waiting for a change detection and hold for the rows rendered later. The rules are marked important: the width of a column is otherwise given by selectors of a higher specificity, which would keep a column from being made narrower than the default - store the width of a column in its header, which the columns preset of the list already saves and reads back - let the text of a cell use the width of its column, instead of ellipsizing at 200px whatever the column: without this, widening a column shows nothing more - reset the columns from their dialog: the ones displayed, their order and their widths, dropping the preset of the User Two bugs found on the way, both older than this: - a column dropped in the wrong place. Only the columns of the data are dragged, so the indexes of the event count those alone, while they were applied to the displayed columns, which the checkbox and the actions belong to as well - the headers of the section were overwritten by the preferences of the User, as the list set them on itself through their own input. The input alone is a default now, the list applies its preferences through _applyHeaders, and a width is stored replacing a header instead of writing into it: with no preference stored, those are the very objects the section holds Narrow the checkbox column, which used to hold the bulk actions. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ns into the toolbar The toolbar restyle of 0906a50 removed the keyword field of the filters bar, which the form data does not need, its filters being in the Filters modal. That bar is shared by every list, so the search went away from the sections that have nothing else: users, groups, notifications, reports, the aggregation list and every metric section. - display the keyword field again, beside the view switcher, through a keywordSearch input which defaults to true: the form list and the form map turn it off, everything else has it back. The AI view never displays it: it initializes no filter, so a field of its own would search nothing - only the field had been removed: the control of the bar, the filter item the FiltersService builds from it and the query the ListDataSource makes of it were all still there, so nothing else was needed - move the floating buttons of these sections into the toolbar, as the form list already does: Add, Import, Filters, Export. The credits a report costs are displayed on its button, as the floating one displayed them - the toolbar gives the keyword field all the width its actions leave The tour anchor of the report button is on a button of the section now, so its directive is always imported, as in the form list. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The filters lived in the url alone: leaving a section dropped them, and coming back displayed everything again. Whoever works with the same filters every day had to apply them every time, the only alternative being the named presets, which are global and have to be saved and loaded by hand. - store the filters of a section as they are applied, and apply them again when it is opened. What is stored is what the url carries, so the whole mechanism is the one already there: the filters are encoded where they were encoded, and applied through loadPreset, where a preset is applied - put the filters back in the url, replacing the entry: the section then reads, and is shared, exactly as if they had just been applied. A url carrying filters wins over the stored ones: a link must display what it says - forget a section when its last filter is removed: filtering nothing is a choice of its own - drop a stored value that cannot be read, which would otherwise break the loading of the filters of every section from then on - give the sections one way of identifying themselves, sectionStorageKey, which the columns preset already defined and now shares: the two cannot drift apart, and the map, which is not a list, can identify its form as its table does - azzera filtri: a button of the Filters modal dropping every filter of the section, the applied ones and the ones staged in the Advanced tab The FiltersService is a singleton holding the root route, so it cannot tell which section is displayed: the list and the map tell it. The filters of the sections are cleared on logout, as the columns and the presets already were. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The export dialog was the last screen of the list area still on the old look: two stacked toolbars and a tab per slide, each tab a one-column selection list. On a form with many slides there was no way to search a field, no idea of how much was selected, no confirm row, and the four fields-and-formats options sat in a single multi-select where two of them are mutually exclusive and were kept apart by a disabled expression in the template. - lay the dialog out as header, dropdown, body and footer: the scope and the format as segmented controls in the header, the sections in a sidebar driving a searchable grid of field cards, the selected count and Annulla/Esporta in the footer - turn the fields and formats multi-select into a menu: the two checkboxes stay checkboxes, the value format becomes a radio group with a Default option, so the exclusion is the shape of the control instead of a rule on top of it. It still drives the same _dataAnalysis$ and _separateColumns$ the engine reads - move the field selection out of the DOM and into the component, one Set of names per section. It had to move: only the active section is rendered now, and the tabs were the only thing keeping the others alive. _getFieldsFromTabs becomes _getSelectedFields and _getSectionFields, its two overloads meaning two different things at the five places that called it - open the dialog large, 1200px by 85vh, under its own panel class The export engine is untouched: the same fields go in and the same file comes out. Metrics keeps the same component, its schema having no slides: the body and the dropdown are absent and the dialog is header and footer alone. The colours come from an --exp-* token set with a dark override, as datachat and the import wizard already do, in place of a hardcoded purple; the global dialog padding rule this file leaked to every dialog of the app is gone, scoped to the export panel. The bottom sheet and the toggle button go away with the old template: the bottom sheet had no caller, its opener in the filters bar removed with it. The four fields-and-formats labels were missing from every translation file and rendered in English everywhere, Italian included: they are translated now, along with the fifteen strings of the new layout. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…port dialog The two modals open from the same toolbar and read as one screen, but their headers had drifted: the Filtri title was lighter and a hair smaller than Esporta dati, and its Semplice/Avanzati toggles kept the Material defaults, taller than the segmented controls of the export header and grey where those are tinted with the primary colour. - give the heading the same 18px 600 of the export title - give the tabs the same segmented control: 40px tall, 8px radius, the selected one tinted with the primary colour Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ented controls The Tutti/Qualsiasi toggle of the Advanced tab was the last one left on the Material defaults, taller and grey beside the Semplice/Avanzati tabs right above it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ght it needs Metrics have no slides, so the dialog is its header and its footer alone, but it was opened at the same fixed 85vh as the form export: below the two rows lay an empty grey area taller than the whole modal. - open the dialog at auto height when there are no fields to pick, keeping 85vh as the ceiling of the form one, which fills it with the sections and the grid Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A field card is one cell of the grid: a long label is ellipsized, and long labels are the rule in a form of any size, so choosing what to export meant guessing between two fields cut at the same word. - give every field card the tooltip of its label, as the sections of the sidebar already had, and let both wrap up to 420px instead of being ellipsized in turn Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The checkbox column was cut to 76px, and a cell is `box-sizing: border-box`: after its 3px border and its padding that left 65px of content. A checkbox is 40px and each status icon is a 34px box - 24px plus the `padding: 5px` that `_table-base.scss` gives every icon in a cell - so the invalid form icon did not fit even on its own, and a cell is `overflow: hidden`: it was cut in half. Widening the column back would have been paying, on every row, for the two icons that only some rows carry - a column has one width for all of them. So the status leaves the flow instead: `.dino-row-status` stacks the badges on the left edge of the row, out of the flow, and the column goes down to 61px, the width of its checkbox. A row with nothing to report now has no gap at all, and one with both has room for both. The bar at the start of a flagged row takes the warn colour, so the status is legible the whole way down the list and not only once the eye is on the row. The conditions behind it move into `isInvalidRow` / `hasFilesToUploadRow` / `hasStatusRow`, so the bar and the badges cannot disagree on what counts. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…imple ones included
The chips under the toolbar only stood for the advanced filters. The simple
ones - date, metric, user, group, status - live in fields the Filters modal
hides as soon as it is closed, so the only trace left of them was the count on
the Filters button: the list showed fewer rows than the section holds and
nothing said why.
- the chips row reads the whole applied set ('all'), hiding only `keyword`,
the one field the bar keeps visible with a value and a button to clear it
- a basic chip is labelled after the field it comes from ('From date', 'User',
'Form status', following the placeholders) and carries the value that field
displays: the status label, the user's full name, the group name, the metric
name with its secondary attribute, the date in the locale format. No
operator and no quotes: `$regex` is an implementation detail of a field the
user filled in by picking from a list.
- a basic filter keeps its place in the list once its field has been used, so
only the ones actually carrying a value get a chip
- removing a basic chip empties the field behind it, which clears the multiple
selection and the metric checkboxes with it, instead of dropping the filter
and leaving the field looking as if it were still applied
The field a chip filters on now reads in semibold, in the advanced chips too,
so the eye separates it from the value at a glance. The listbox also loses the
`aria-label` "Fish selection" it had carried over from the Material docs.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…lection read as a list `multipleName.join()` separates with a bare comma, so a field with several metrics chosen - and its chip - ran the names together: `AFRUZA BOICHUK,AMIN,Angela KURLOU`. Joining with ', ' tells them apart. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…chosen list its options again Reopening the Filters modal after applying a metric, status, user or group filter left that field dead: the panel listed nothing, so nothing could be clicked and the only way out was Reset filters. Two things met. The option lists are built once, in `initFilters`, as cold streams fed by the field `valueChanges`, and the modal lives in an `ng-template`: every open builds a fresh view whose `async` subscribes to those streams from scratch, and a cold `valueChanges` emits nothing on subscribe, so the panel started empty and waited for the field to be edited. Meanwhile the field held the option chosen, which is an object and not a search term, and the `switchMap` answers a non-term with `[]`: no query ever ran. `showOptions` could not help either - it turns the value back into a term only when it is null, which is why resetting the filters was the one thing that worked. - `_searchTerms` wraps the `valueChanges` of a field in a `defer`, so every subscription starts with the term the field holds right then: the text typed in it, or '' when it carries an option already chosen, which searches the whole list. The four option fields share it, and a field displaying a selection now lists all the options with the checkboxes of the selected ones already ticked, `_setupMetricsCheckboxes` running on the query result. - the 800ms of the metric fields move inside the helper, debouncing the typing alone: the panel is ready as the modal opens instead of 800ms later. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.