@massimo-cassandro/minimo 1.33.0 → 1.33.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dev-tools/starter-kit/source_files/{CLAUDE-frontend.md → app/CLAUDE.md} +1 -1
- package/dev-tools/starter-kit/source_files/app/assets/api_htaccess +20 -0
- package/dev-tools/starter-kit/source_files/{layout-critical.css → app/css/layout.critical.css} +1 -1
- package/dev-tools/starter-kit/source_files/app/css/layout.css +0 -0
- package/dev-tools/starter-kit/source_files/app/index.js +1 -0
- package/dev-tools/starter-kit/source_files/root/webpack-config-modules/inline-critical-css.mjs +41 -0
- package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/purgecss-setup.mjs +1 -1
- package/dev-tools/starter-kit/{webpack.config.mjs → source_files/root/webpack.config.mjs} +50 -24
- package/dev-tools/starter-kit/starter-install.sh +163 -82
- package/dev-tools/stylelint-config/test/test.module.scss +9 -0
- package/package.json +1 -1
- package/snippets/php/iviewer.php +488 -0
- package/snippets/twig-symfony/ViewerController.php +549 -0
- package/src/custom-properties.css +29 -0
- package/src/minimo.css +3 -0
- package/src/utilities/dom-builder/dom-builder.js +9 -5
- package/src/web-components/json-table/json-table-component.js +387 -38
- package/src/web-components/json-table/json-table-component.module.css +190 -0
- package/src/web-components/json-table/json-table.minimo.tokens.mjs +195 -0
- package/src/web-components/json-table/readme.md +603 -82
- package/src/web-components/json-table/src/cell-content.js +136 -0
- package/src/web-components/json-table/src/content-utils.js +103 -0
- package/src/web-components/json-table/src/data-types.js +280 -0
- package/src/web-components/json-table/src/defaults.js +377 -58
- package/src/web-components/json-table/src/get-data.js +105 -10
- package/src/web-components/json-table/src/icons.js +80 -0
- package/src/web-components/json-table/src/info-section.js +85 -50
- package/src/web-components/json-table/src/main-builder.js +175 -52
- package/src/web-components/json-table/src/pagination.js +253 -0
- package/src/web-components/json-table/src/parse-cols.js +113 -0
- package/src/web-components/json-table/src/parse-rows.js +81 -0
- package/src/web-components/json-table/src/resolve-params.js +102 -32
- package/src/web-components/json-table/src/search.js +71 -0
- package/src/web-components/json-table/src/sorting.js +111 -0
- package/src/web-components/json-table/src/table-body.js +109 -0
- package/src/web-components/json-table/src/table-builder.js +152 -0
- package/src/web-components/json-table/src/table-tfoot.js +56 -0
- package/src/web-components/json-table/src/table-thead.js +183 -0
- package/src/web-components/json-table/src/update-info.js +43 -24
- package/src/web-components/s-datatable-component/{docs.md → readme.md} +5 -3
- package/src/web-components/s-datatable-component/s-datatable-component.js +1 -1
- package/types/global.d.ts +17 -3
- package/dev-tools/starter-kit/source_files/app_index.js +0 -1
- package/snippets/config-templates/_htaccess +0 -69
- package/snippets/config-templates/robots.txt +0 -5
- package/snippets/config-templates/rollup.config.mjs +0 -115
- /package/dev-tools/starter-kit/source_files/{_root_robots.txt → app/assets/robots.txt} +0 -0
- /package/dev-tools/starter-kit/source_files/{_root_htaccess → app/assets/root_htaccess} +0 -0
- /package/{src → dev-tools/starter-kit/source_files/app/css}/fonts.css +0 -0
- /package/dev-tools/starter-kit/source_files/{favicons-readme.md → app/favicons/favicons-readme.md} +0 -0
- /package/dev-tools/starter-kit/{webpack-template.ejs → source_files/app/tpl/index.ejs} +0 -0
- /package/dev-tools/starter-kit/source_files/{__project__.code-workspace → root/__project__.code-workspace} +0 -0
- /package/dev-tools/starter-kit/source_files/{_browserslistrc → root/_browserslistrc} +0 -0
- /package/dev-tools/starter-kit/source_files/{_editorconfig → root/_editorconfig} +0 -0
- /package/dev-tools/starter-kit/source_files/{_gitignore → root/_gitignore} +0 -0
- /package/dev-tools/starter-kit/source_files/{_prettierrc → root/_prettierrc} +0 -0
- /package/dev-tools/starter-kit/source_files/{eslint.config.mjs → root/eslint.config.mjs} +0 -0
- /package/dev-tools/starter-kit/source_files/{jsconfig.json → root/jsconfig.json} +0 -0
- /package/dev-tools/starter-kit/{package-tpl.json → source_files/root/package-tpl.json} +0 -0
- /package/dev-tools/starter-kit/source_files/{stylelint.config.mjs → root/stylelint.config.mjs} +0 -0
- /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/css-rules.mjs +0 -0
- /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/get-jsConfig-aliases.mjs +0 -0
- /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/mini-svg-data-uri-loader.cjs +0 -0
- /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/postcss.config.mjs +0 -0
- /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/purgecss-variables-safelist.mjs +0 -0
- /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/svg-rules.mjs +0 -0
- /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/svgo.config.mjs +0 -0
- /package/snippets/{config-templates/_github → _github}/dependabot.yml +0 -0
- /package/snippets/{error-pages/error-pages.js → error-pages.js} +0 -0
- /package/snippets/{config-templates/react → react}/offcanvas/offcanvas.jsx +0 -0
- /package/snippets/{config-templates/react → react}/offcanvas/offcanvas.module.scss +0 -0
- /package/snippets/{config-templates → root}/_hintrc.cjs +0 -0
- /package/snippets/{config-templates → root}/_npmignore +0 -0
- /package/snippets/{config-templates → root}/_npmrc +0 -0
- /package/snippets/{config-templates → root}/_stylelintignore +0 -0
- /package/snippets/{config-templates → root}/babel.config--react.json +0 -0
- /package/snippets/{config-templates → root}/babel.config--solidJS.json +0 -0
- /package/snippets/{ImgViewerController.php → twig-symfony/ImgViewerController.php} +0 -0
- /package/snippets/{UnsplashController.php → twig-symfony/UnsplashController.php} +0 -0
- /package/snippets/{config-templates → twig-symfony}/_env.local +0 -0
- /package/snippets/{error-pages → twig-symfony}/bundles/TwigBundle/Exception/error.html.twig +0 -0
- /package/snippets/{flash-messages.html.twig → twig-symfony/flash-messages.html.twig} +0 -0
- /package/snippets/{minimo-form-layout.html.twig → twig-symfony/minimo-form-layout.html.twig} +0 -0
|
@@ -1,74 +1,324 @@
|
|
|
1
1
|
/*! minimo - json-table: defaults */
|
|
2
2
|
|
|
3
|
+
import {
|
|
4
|
+
boolTrueIcon, boolFalseIcon, sortAscArrowIcon, sortDescArrowIcon, sortNoneArrowIcon,
|
|
5
|
+
paginationPrevIcon, paginationNextIcon
|
|
6
|
+
} from './icons.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Content accepted by every cell / heading / info area: plain text, HTML string, number,
|
|
10
|
+
* DOM node or domBuilder array. `null` is rendered as `renderNullAs`, `undefined` lets the
|
|
11
|
+
* default rendering pipeline go on (see `cell-content.js`).
|
|
12
|
+
* @typedef {string|number|Node|DomBuilderItem[]|null|undefined} CellContent
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Icon / markup used for booleans, sort and pagination buttons: an SVG/HTML string (e.g. an
|
|
17
|
+
* `.svg?inline` import), a DOM node, a domBuilder item, or a function returning one of them.
|
|
18
|
+
* @typedef {string|Node|DomBuilderItem|(() => string|Node|DomBuilderItem)} IconDef
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Column cell renderer. Arguments are positional (all optional) to keep the simplest
|
|
23
|
+
* case (`row => row.name`) as short as possible.
|
|
24
|
+
* @callback ColRender
|
|
25
|
+
* @param {Object} row - The data object of the current row
|
|
26
|
+
* @param {HTMLTableRowElement} [tr] - The `<tr>` element of the current row
|
|
27
|
+
* @param {HTMLTableCellElement} [td] - The cell element (`<td>` or `<th scope="row">`)
|
|
28
|
+
* @returns {CellContent|void} Cell content; `undefined` (no `return`) falls back to the data type rendering,
|
|
29
|
+
* `null` to `renderNullAs`
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Footer cell renderer.
|
|
34
|
+
* @callback TfootRender
|
|
35
|
+
* @param {Object[]} rows - The whole filtered data set, or the current page only when `updateFooterOnPageChange` is true
|
|
36
|
+
* @param {HTMLTableCellElement} [td] - The footer cell element
|
|
37
|
+
* @returns {CellContent}
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Column definition (`cols` items).
|
|
42
|
+
*
|
|
43
|
+
* @typedef {Object} ColDefinition
|
|
44
|
+
* @property {string} key - REQUIRED: key of the row object (dot notation allowed for nested values, e.g. `owner.name`)
|
|
45
|
+
* @property {CellContent|(() => CellContent)} [title] - Heading content (text, HTML, Node, domBuilder array or function).
|
|
46
|
+
* When the column is sortable it is the text of the sort button (default: the key itself)
|
|
47
|
+
* @property {string} [dataType] - Data type, one of the `dataTypes` keys. `type` is accepted as an alias (default: 'string')
|
|
48
|
+
* @property {string} [type] - Alias of `dataType`
|
|
49
|
+
* @property {ColRender|string|null} [render] - Cell renderer: a function `(row, tr, td) => content` or,
|
|
50
|
+
* via HTML attribute too, a mustache-like string where `[[key]]` placeholders are replaced with the row
|
|
51
|
+
* values (nested keys allowed). Overrides the data type rendering (default: null)
|
|
52
|
+
* @property {TfootRender|string|null} [tfootRender] - Footer cell content (only when `tfoot` is true): a function
|
|
53
|
+
* `(rows, td) => content`, a static string, or one of the built-in aggregates `'@sum'`, `'@avg'`, `'@min'`,
|
|
54
|
+
* `'@max'`, `'@count'` computed on the column values and formatted by the column data type.
|
|
55
|
+
* `null` renders an empty cell (default: null)
|
|
56
|
+
* @property {boolean} [rowHeading] - When true the cell is a row heading (`<th scope="row">`) (default: false)
|
|
57
|
+
* @property {boolean} [searchable] - Enables the search on this column (default: true)
|
|
58
|
+
* @property {boolean} [sortable] - Enables the sorting on this column (default: true)
|
|
59
|
+
* @property {*|((row: Object) => *)} [sortValue] - Value used for sorting, or function `row => value`.
|
|
60
|
+
* Overrides the data type `sortValue` (default: undefined = data type / raw value)
|
|
61
|
+
* @property {*|((row: Object) => *)} [searchValue] - Same as `sortValue`, for the search (default: undefined)
|
|
62
|
+
* @property {boolean|((params: JsonTableParams) => boolean)} [condition] - When false (or a function returning
|
|
63
|
+
* false) the column is not rendered at all (default: true)
|
|
64
|
+
* @property {string|null} [headerClass] - Class(es) of the `<th>`, replacing the data type ones. When only one of
|
|
65
|
+
* `headerClass`/`cellClass` is set, the other one takes the same value (default: null)
|
|
66
|
+
* @property {string|null} [cellClass] - Class(es) of the body/footer cells, replacing the data type ones (default: null)
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Data type definition (`dataTypes` values). Every function is optional.
|
|
71
|
+
*
|
|
72
|
+
* @typedef {Object} DataTypeDefinition
|
|
73
|
+
* @property {string|null} [headerClass] - Default class(es) of the `<th>` (overridable via `ColDefinition.headerClass`)
|
|
74
|
+
* @property {string|null} [cellClass] - Default class(es) of the cells (overridable via `ColDefinition.cellClass`)
|
|
75
|
+
* @property {((value: *, row: Object, params: JsonTableParams) => string|null)} [internalCellClass] - Class(es) always
|
|
76
|
+
* added to the cells, regardless of `cellClass` (used by the built-in `bool` type for the icon styles)
|
|
77
|
+
* @property {(value: *, row: Object|null, params: JsonTableParams) => CellContent} [render] - Cell renderer; not invoked
|
|
78
|
+
* for `null`/`undefined` values, which are rendered as `renderNullAs`. `row` is null when the function is
|
|
79
|
+
* used to format a footer aggregate (`tfootRender: '@sum'`, ...)
|
|
80
|
+
* @property {(value: *, row: Object, params: JsonTableParams) => *} [sortValue] - Value used for sorting (default: raw value)
|
|
81
|
+
* @property {(value: *, row: Object, params: JsonTableParams) => string} [searchValue] - Value used for searching (default: `String(value)`)
|
|
82
|
+
* @property {Partial<ColDefinition>} [colDefaults] - Column defaults forced by this type (e.g. `{ sortable: false }`),
|
|
83
|
+
* still overridable in the column definition
|
|
84
|
+
* @property {string} [inheritsFrom] - Custom types only: key of the built-in type to extend
|
|
85
|
+
*/
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Consumer class names used by the generated structure. Internal layout classes (CSS module)
|
|
89
|
+
* are always applied in addition to these.
|
|
90
|
+
*
|
|
91
|
+
* @typedef {Object} JsonTableClasses
|
|
92
|
+
* @property {string|null} [wrapper] - Main wrapper (`<section>`: info section + table) (default: null)
|
|
93
|
+
* @property {string|null} [infoOuter] - Outer info container (default: null)
|
|
94
|
+
* @property {string|null} [info] - Info container (info text + search) (default: null)
|
|
95
|
+
* @property {string|null} [resultInfo] - Info text container (default: null)
|
|
96
|
+
* @property {string|null} [search] - Search input wrapper (default: null)
|
|
97
|
+
* @property {string|null} [searchInput] - Search input (default: 'form-control form-control-sm')
|
|
98
|
+
* @property {string|null} [tableWrapper] - Div wrapping the table (default: 'table-responsive')
|
|
99
|
+
* @property {string|null} [table] - `<table>` element (default: 'table table-bordered')
|
|
100
|
+
* @property {string|null} [tableFooter] - Bar below the table holding caption and pagination (default: null)
|
|
101
|
+
* @property {string|null} [caption] - Caption container inside the table footer bar (default: null)
|
|
102
|
+
* @property {string|null} [pagination] - Pagination `<nav>` (default: null)
|
|
103
|
+
* @property {string|null} [paginationBtn] - Pagination buttons (default: 'btn-reset')
|
|
104
|
+
* @property {string|null} [sortBtn] - Sort buttons inside the `<th>` (default: 'btn-reset')
|
|
105
|
+
* @property {string|null} [empty] - The single cell shown when there are no rows (default: null)
|
|
106
|
+
* @property {string|null} [textStart] - Inline-start alignment class (default: null, minimo cells are start-aligned by default)
|
|
107
|
+
* @property {string|null} [textCenter] - Center alignment class (default: 'text-center')
|
|
108
|
+
* @property {string|null} [textEnd] - Inline-end alignment class (default: 'text-end')
|
|
109
|
+
* @property {string|null} [nowrap] - No-wrap class (default: 'text-nowrap')
|
|
110
|
+
* @property {string|null} [numeric] - Tabular figures class, used by numeric types (default: 'text-numeric')
|
|
111
|
+
* @property {string|null} [boolCell] - Extra class of every `bool` cell (default: null)
|
|
112
|
+
* @property {string|null} [boolTrue] - Extra class of `bool` cells whose value is `true` (default: null)
|
|
113
|
+
* @property {string|null} [boolFalse] - Extra class of `bool` cells whose value is `false` (default: null)
|
|
114
|
+
*/
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Texts used by the component. The `{page}` placeholder of the pagination labels is replaced
|
|
118
|
+
* with the page number.
|
|
119
|
+
*
|
|
120
|
+
* @typedef {Object} JsonTableLabels
|
|
121
|
+
* @property {string} [loading] - Loading placeholder (visually hidden) (default: 'Caricamento dati…')
|
|
122
|
+
* @property {string} [searchPlaceholder] - Search input placeholder (default: 'Cerca...')
|
|
123
|
+
* @property {string} [searchTitle] - Search input `title` (default: 'Cerca nella tabella')
|
|
124
|
+
* @property {string} [searchAriaLabel] - Search input `aria-label` (default: 'Filtra risultati')
|
|
125
|
+
* @property {string} [info] - Info text template, placeholders: `{start}`, `{end}`, `{totRec}`, `{filteredRec}`,
|
|
126
|
+
* `{page}`, `{totPages}` (default: 'Stai visualizzando le righe da {start} a {end}, su un totale di {filteredRec} record trovati')
|
|
127
|
+
* @property {string} [noRows] - Info text and empty cell content when the data set is empty (default: 'Nessun record trovato')
|
|
128
|
+
* @property {string} [noResults] - Same as `noRows`, when a search returns nothing (default: 'Nessun risultato per la ricerca')
|
|
129
|
+
* @property {string} [sortAsc] - `aria-label`/`title` of the sort button when the next click sorts ascending
|
|
130
|
+
* (default: 'Ordina questa colonna in senso ascendente (A → Z)')
|
|
131
|
+
* @property {string} [sortDesc] - Same, descending (default: 'Ordina questa colonna in senso discendente (Z → A)')
|
|
132
|
+
* @property {string} [sortNone] - Same, sorting removal (default: 'Rimuovi l’ordinamento a questa colonna')
|
|
133
|
+
* @property {string} [paginationAriaLabel] - `aria-label` of the pagination `<nav>` (default: 'Navigazione pagine')
|
|
134
|
+
* @property {string} [prevPage] - `aria-label`/`title` of the previous page button (default: 'Pagina precedente')
|
|
135
|
+
* @property {string} [nextPage] - Same, next page button (default: 'Pagina successiva')
|
|
136
|
+
* @property {string} [pageTitle] - `aria-label`/`title` of the page buttons (default: 'Vai a pagina {page}')
|
|
137
|
+
* @property {string} [currentPage] - `aria-label`/`title` of the current page button (default: 'Pagina {page}, corrente')
|
|
138
|
+
*/
|
|
139
|
+
|
|
3
140
|
/**
|
|
4
|
-
*
|
|
141
|
+
* Info text function.
|
|
5
142
|
* @callback InfoTextFn
|
|
6
|
-
* @param {number}
|
|
7
|
-
* @param {number}
|
|
8
|
-
* @
|
|
143
|
+
* @param {number} start - Index (1-based) of the first displayed row
|
|
144
|
+
* @param {number} end - Index of the last displayed row
|
|
145
|
+
* @param {number} totRec - Total number of records (unfiltered)
|
|
146
|
+
* @param {number} filteredRec - Number of records after filtering
|
|
147
|
+
* @param {number} page - Current page (1-based)
|
|
148
|
+
* @param {number} totPages - Total number of pages
|
|
149
|
+
* @returns {CellContent}
|
|
9
150
|
*/
|
|
10
151
|
|
|
11
152
|
/**
|
|
12
|
-
*
|
|
153
|
+
* Names of the built-in template parts.
|
|
154
|
+
* @typedef {'infoSection'|'resultInfo'|'search'|'table'|'caption'|'pagination'} TemplateSlot
|
|
155
|
+
*/
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Template item: a domBuilder item (whose `children`/`content` may hold other template items)
|
|
159
|
+
* or a slot placeholder `{ slot: 'name' }` replaced with one of the built-in parts.
|
|
160
|
+
* @typedef {(Omit<DomBuilderItem, 'children'|'content'> & {
|
|
161
|
+
* children?: Array<TemplateItem|string|Node>,
|
|
162
|
+
* content?: DomBuilderItem['content']|TemplateItem[]
|
|
163
|
+
* }) | { slot: TemplateSlot }} TemplateItem
|
|
164
|
+
*/
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Sort state / initial sort definition.
|
|
168
|
+
* @typedef {Object} SortDef
|
|
169
|
+
* @property {string} key - Column key
|
|
170
|
+
* @property {'asc'|'desc'} dir - Direction
|
|
171
|
+
*/
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Names of the query string parameters sent to `jsonUrl` in server-side mode (`serverSide: true`).
|
|
175
|
+
* A `null` value omits the parameter.
|
|
176
|
+
*
|
|
177
|
+
* @typedef {Object} ServerParams
|
|
178
|
+
* @property {string|null} [page] - Requested page, 1-based (default: 'page')
|
|
179
|
+
* @property {string|null} [start] - Index (0-based) of the first requested record, i.e. `(page - 1) * perPage`,
|
|
180
|
+
* handy for `LIMIT start, perPage` queries (default: 'start')
|
|
181
|
+
* @property {string|null} [perPage] - Number of records per page (default: 'perPage')
|
|
182
|
+
* @property {string|null} [sort] - Key of the sorted column; omitted when no sort is active (default: 'sort')
|
|
183
|
+
* @property {string|null} [dir] - Sort direction, `asc`/`desc`; omitted when no sort is active (default: 'dir')
|
|
184
|
+
* @property {string|null} [search] - Search term; omitted when empty (default: 'search')
|
|
185
|
+
*/
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* `<json-table>` parameters (resolved: every key has a value, see `defaults`).
|
|
13
189
|
*
|
|
14
190
|
* Every parameter can be set either as an HTML attribute of the `<json-table>` element
|
|
15
191
|
* (attribute names are case-insensitive, so `jsonurl="…"` and `jsonUrl="…"` are equivalent)
|
|
16
|
-
* or as a property of the object passed to `init()`. Values that are functions
|
|
17
|
-
*
|
|
192
|
+
* or as a property of the object passed to `init()`. Values that are functions can only be
|
|
193
|
+
* set via `init()`. Object parameters (`classes`, `labels`, `dataTypes`, `serverParams`) are
|
|
194
|
+
* merged with the defaults, so only the keys to override need to be passed.
|
|
18
195
|
*
|
|
19
196
|
* Precedence: `init()` > HTML attribute > `JsonTable.setDefaults()` > built-in default.
|
|
20
197
|
*
|
|
21
|
-
* TODO parametri `cols`, data-types, locale, icone, ordinamento, paginazione: da aggiungere negli step successivi
|
|
22
|
-
*
|
|
23
198
|
* @typedef {Object} JsonTableParams
|
|
24
|
-
* @property {boolean}
|
|
25
|
-
* @property {string|null}
|
|
26
|
-
* @property {string|null}
|
|
199
|
+
* @property {boolean} debug - Logs resolved params, columns, data and generated elements to the console (default: false)
|
|
200
|
+
* @property {string|null} jsonUrl - URL of the JSON to fetch. Ignored when `data` is set (default: null)
|
|
201
|
+
* @property {string|null} jsonDataField - Key of the fetched JSON holding the rows array (e.g. `{ data: [...] }`);
|
|
27
202
|
* `null` or an empty string means the JSON root is the rows array itself (default: 'data')
|
|
28
|
-
* @property {
|
|
203
|
+
* @property {string} totRecField - Key of the fetched JSON holding the total number of records (numeric);
|
|
204
|
+
* when missing or not numeric the total is the rows array length (default: 'totRec')
|
|
205
|
+
* @property {string} filteredRecField - Server-side mode only: key of the fetched JSON holding the number of
|
|
206
|
+
* records matching the current search (numeric); when missing the value of `totRecField` is used (default: 'filteredRec')
|
|
207
|
+
* @property {Array<Object>|null} data - Inline rows (array of plain objects); takes precedence over `jsonUrl`.
|
|
29
208
|
* As an HTML attribute it must be a JSON string, which is always treated as the rows array itself
|
|
30
209
|
* (`jsonDataField` is ignored) (default: null)
|
|
31
|
-
* @property {
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* @property {string}
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* @property {
|
|
39
|
-
* @property {
|
|
40
|
-
* @property {
|
|
41
|
-
*
|
|
42
|
-
* @property {
|
|
43
|
-
* @property {
|
|
44
|
-
*
|
|
45
|
-
*
|
|
210
|
+
* @property {ColDefinition[]} cols - REQUIRED: columns definition (default: [])
|
|
211
|
+
* @property {Object<string, DataTypeDefinition>} dataTypes - Custom data types, merged with the built-in ones
|
|
212
|
+
* (`string`, `num`, `id`, `perc`, `percDecimal`, `currency`, `euro`, `date`, `datetime`, `bool`, `email`).
|
|
213
|
+
* A key matching a built-in type overrides only the given properties (default: {})
|
|
214
|
+
* @property {string|Function|null} caption - Table caption, shown below the table (start side of the footer bar)
|
|
215
|
+
* and linked to the table via `aria-labelledby`: a string (plain text or HTML) or, via `init()` only, a function
|
|
216
|
+
* returning a string or a Node (default: null)
|
|
217
|
+
* @property {boolean} search - Whether to render the search input (default: true)
|
|
218
|
+
* @property {number} searchDebounce - Delay (ms) between the last keystroke and the search execution (default: 300)
|
|
219
|
+
* @property {number} perPage - Rows per page; `0` disables the pagination (every row in a single page, no
|
|
220
|
+
* navigation) (default: 25)
|
|
221
|
+
* @property {number} paginationDelta - Number of page buttons shown on each side of the current page (default: 2)
|
|
222
|
+
* @property {boolean} serverSide - Server-side mode: pagination, sorting and search are delegated to the server.
|
|
223
|
+
* Every change triggers a new request to `jsonUrl` (see `serverParams`) and the JSON is expected to hold the
|
|
224
|
+
* rows of the requested page only, plus `totRecField` and `filteredRecField`. Requires `jsonUrl`; `tfoot` is
|
|
225
|
+
* not available in this mode (default: false)
|
|
226
|
+
* @property {ServerParams} serverParams - Server-side mode only: names of the query string parameters (see `ServerParams`)
|
|
227
|
+
* @property {SortDef|null} initialSort - Sort applied on load, e.g. `{ key: 'name', dir: 'asc' }` (default: null)
|
|
228
|
+
* @property {boolean} tfoot - Whether to render the `<tfoot>` (see `ColDefinition.tfootRender`); ignored in
|
|
229
|
+
* server-side mode (default: false)
|
|
230
|
+
* @property {boolean} updateFooterOnPageChange - When true, `tfootRender` receives the rows of the current page
|
|
231
|
+
* only (page subtotals) and the footer is updated on every page change; when false it receives the whole
|
|
232
|
+
* filtered set and is updated on filter changes only (default: false)
|
|
233
|
+
* @property {string|InfoTextFn|null} infoText - Info area content: a mustache-like string (placeholders
|
|
234
|
+
* `{start}`, `{end}`, `{totRec}`, `{filteredRec}`, `{page}`, `{totPages}`) or a function
|
|
235
|
+
* `(start, end, totRec, filteredRec, page, totPages) => content`. `null` uses `labels.info` (default: null)
|
|
236
|
+
* @property {TemplateItem[]|((parts: Object<string, DomBuilderItem>, params: JsonTableParams) => TemplateItem[])} template -
|
|
237
|
+
* Layout of the main wrapper content, as a domBuilder array where `{ slot: 'name' }` items are replaced with the
|
|
238
|
+
* built-in parts `infoSection` (info text + search), `resultInfo`, `search`, `table`, `caption`, `pagination`.
|
|
239
|
+
* `caption` and `pagination` are included in the `table` part (footer bar) unless placed explicitly.
|
|
240
|
+
* A function receiving the parts and returning the array is accepted too (`init()` only)
|
|
241
|
+
* (default: [{ slot: 'infoSection' }, { slot: 'table' }])
|
|
242
|
+
* @property {string} locale - Locale used to format numbers and dates, and to compare strings when sorting (default: 'it-IT')
|
|
243
|
+
* @property {string} currency - ISO 4217 code used by the `currency` data type (default: 'EUR')
|
|
244
|
+
* @property {Intl.DateTimeFormatOptions} datesLocaleOpts - Options for the date part of `date`/`datetime`
|
|
245
|
+
* (default: { year: 'numeric', month: 'short', day: 'numeric' })
|
|
246
|
+
* @property {Intl.DateTimeFormatOptions} timesLocaleOpts - Options for the time part of `datetime`
|
|
247
|
+
* (default: { hour12: false, hour: '2-digit', minute: '2-digit' })
|
|
248
|
+
* @property {Intl.NumberFormatOptions} numbersLocaleOpts - Options for the `num` type (default: { maximumFractionDigits: 2 })
|
|
249
|
+
* @property {Intl.NumberFormatOptions} currPercLocaleOpts - Options for the `currency`/`euro`/`perc`/`percDecimal`
|
|
250
|
+
* types (default: { minimumFractionDigits: 2, maximumFractionDigits: 2 })
|
|
251
|
+
* @property {string|null} renderNullAs - Content shown for `null`/`undefined` values (default: '—')
|
|
252
|
+
* @property {string|null} renderZeroAs - When not null, content shown for numeric values equal to zero (default: null)
|
|
253
|
+
* @property {string|null} renderNaNAs - Content shown by numeric types for non-numeric values (default: '—')
|
|
254
|
+
* @property {IconDef} boolTrueIcon - Icon of `true` values in `bool` columns (default: minimo `check-bold` icon)
|
|
255
|
+
* @property {IconDef} boolFalseIcon - Icon of `false` values in `bool` columns (default: minimo `x-bold` icon)
|
|
256
|
+
* @property {IconDef} sortAscArrowIcon - Sort button icon, ascending sort active (default: minimo `arrow-up` icon)
|
|
257
|
+
* @property {IconDef} sortDescArrowIcon - Sort button icon, descending sort active (default: minimo `arrow-down` icon)
|
|
258
|
+
* @property {IconDef} sortNoneArrowIcon - Sort button icon, no sort active (default: minimo `arrows-down-up` icon)
|
|
259
|
+
* @property {IconDef} paginationPrevIcon - Previous page button icon (default: minimo `caret-left` icon)
|
|
260
|
+
* @property {IconDef} paginationNextIcon - Next page button icon (default: minimo `caret-right` icon)
|
|
261
|
+
* @property {((tr: HTMLTableRowElement, row: Object, params: JsonTableParams) => void)|null} trCallback - Callback
|
|
262
|
+
* invoked after the rendering of every body row (default: null)
|
|
263
|
+
* @property {string|null} tableId - `id` attribute of the `<table>` element (default: null)
|
|
264
|
+
* @property {JsonTableClasses} classes - Consumer class names (see `JsonTableClasses`)
|
|
265
|
+
* @property {JsonTableLabels} labels - Texts (see `JsonTableLabels`)
|
|
46
266
|
*/
|
|
47
267
|
|
|
268
|
+
/**
|
|
269
|
+
* Names of the object params whose value is shallow-merged across the sources
|
|
270
|
+
* (built-in default ← `setDefaults()` ← HTML attribute ← `init()`) instead of being replaced.
|
|
271
|
+
* @type {ReadonlyArray<keyof JsonTableParams>}
|
|
272
|
+
*/
|
|
273
|
+
export const mergedParams = ['classes', 'labels', 'dataTypes', 'serverParams'];
|
|
274
|
+
|
|
48
275
|
/**
|
|
49
276
|
* Built-in defaults.
|
|
50
277
|
*
|
|
51
|
-
* @type {
|
|
278
|
+
* @type {JsonTableParams}
|
|
52
279
|
*
|
|
53
280
|
* @example
|
|
54
281
|
* {
|
|
55
282
|
* debug: false,
|
|
56
283
|
* jsonUrl: null,
|
|
57
284
|
* jsonDataField: 'data',
|
|
285
|
+
* totRecField: 'totRec',
|
|
286
|
+
* filteredRecField: 'filteredRec',
|
|
58
287
|
* data: null,
|
|
288
|
+
* cols: [], // required
|
|
289
|
+
* dataTypes: {},
|
|
59
290
|
* caption: null,
|
|
60
291
|
* search: true,
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
292
|
+
* searchDebounce: 300,
|
|
293
|
+
* perPage: 25, // 0 = no pagination
|
|
294
|
+
* paginationDelta: 2,
|
|
295
|
+
* serverSide: false,
|
|
296
|
+
* serverParams: { page: 'page', start: 'start', perPage: 'perPage', sort: 'sort', dir: 'dir', search: 'search' },
|
|
297
|
+
* initialSort: null, // e.g. { key: 'name', dir: 'asc' }
|
|
298
|
+
* tfoot: false,
|
|
299
|
+
* updateFooterOnPageChange: false,
|
|
300
|
+
* infoText: null, // → labels.info
|
|
301
|
+
* template: [{ slot: 'infoSection' }, { slot: 'table' }],
|
|
302
|
+
* locale: 'it-IT',
|
|
303
|
+
* currency: 'EUR',
|
|
304
|
+
* datesLocaleOpts: { year: 'numeric', month: 'short', day: 'numeric' },
|
|
305
|
+
* timesLocaleOpts: { hour12: false, hour: '2-digit', minute: '2-digit' },
|
|
306
|
+
* numbersLocaleOpts: { maximumFractionDigits: 2 },
|
|
307
|
+
* currPercLocaleOpts: { minimumFractionDigits: 2, maximumFractionDigits: 2 },
|
|
308
|
+
* renderNullAs: '—',
|
|
309
|
+
* renderZeroAs: null,
|
|
310
|
+
* renderNaNAs: '—',
|
|
311
|
+
* boolTrueIcon: '<svg …>', // minimo check-bold
|
|
312
|
+
* boolFalseIcon: '<svg …>', // minimo x-bold
|
|
313
|
+
* sortAscArrowIcon: '<svg …>', // minimo arrow-up
|
|
314
|
+
* sortDescArrowIcon: '<svg …>', // minimo arrow-down
|
|
315
|
+
* sortNoneArrowIcon: '<svg …>', // minimo arrows-down-up
|
|
316
|
+
* paginationPrevIcon: '<svg …>', // minimo caret-left
|
|
317
|
+
* paginationNextIcon: '<svg …>', // minimo caret-right
|
|
318
|
+
* trCallback: null,
|
|
65
319
|
* tableId: null,
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* mainWrapperExtraClass: null,
|
|
69
|
-
* outerInfoExtraClass: null,
|
|
70
|
-
* infoExtraClass: null,
|
|
71
|
-
* infoText: (shown, total) => '…'
|
|
320
|
+
* classes: { … }, // see JsonTableClasses
|
|
321
|
+
* labels: { … } // see JsonTableLabels
|
|
72
322
|
* }
|
|
73
323
|
*/
|
|
74
324
|
export const defaults = {
|
|
@@ -76,30 +326,99 @@ export const defaults = {
|
|
|
76
326
|
|
|
77
327
|
jsonUrl: null,
|
|
78
328
|
jsonDataField: 'data',
|
|
329
|
+
totRecField: 'totRec',
|
|
330
|
+
filteredRecField: 'filteredRec',
|
|
79
331
|
data: null,
|
|
80
332
|
|
|
81
|
-
|
|
333
|
+
cols: [],
|
|
334
|
+
dataTypes: {},
|
|
82
335
|
|
|
336
|
+
caption: null,
|
|
83
337
|
search: true,
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
338
|
+
searchDebounce: 300,
|
|
339
|
+
|
|
340
|
+
perPage: 25,
|
|
341
|
+
paginationDelta: 2,
|
|
342
|
+
serverSide: false,
|
|
343
|
+
serverParams: {
|
|
344
|
+
page: 'page',
|
|
345
|
+
start: 'start',
|
|
346
|
+
perPage: 'perPage',
|
|
347
|
+
sort: 'sort',
|
|
348
|
+
dir: 'dir',
|
|
349
|
+
search: 'search'
|
|
350
|
+
},
|
|
351
|
+
initialSort: null,
|
|
352
|
+
|
|
353
|
+
tfoot: false,
|
|
354
|
+
updateFooterOnPageChange: false,
|
|
355
|
+
infoText: null,
|
|
356
|
+
|
|
357
|
+
template: [{ slot: 'infoSection' }, { slot: 'table' }],
|
|
358
|
+
|
|
359
|
+
locale: 'it-IT',
|
|
360
|
+
currency: 'EUR',
|
|
361
|
+
datesLocaleOpts: { year: 'numeric', month: 'short', day: 'numeric' },
|
|
362
|
+
timesLocaleOpts: { hour12: false, hour: '2-digit', minute: '2-digit' },
|
|
363
|
+
numbersLocaleOpts: { maximumFractionDigits: 2 },
|
|
364
|
+
currPercLocaleOpts: { minimumFractionDigits: 2, maximumFractionDigits: 2 },
|
|
365
|
+
|
|
366
|
+
renderNullAs: '—',
|
|
367
|
+
renderZeroAs: null,
|
|
368
|
+
renderNaNAs: '—',
|
|
369
|
+
|
|
370
|
+
boolTrueIcon,
|
|
371
|
+
boolFalseIcon,
|
|
372
|
+
sortAscArrowIcon,
|
|
373
|
+
sortDescArrowIcon,
|
|
374
|
+
sortNoneArrowIcon,
|
|
375
|
+
paginationPrevIcon,
|
|
376
|
+
paginationNextIcon,
|
|
377
|
+
|
|
378
|
+
trCallback: null,
|
|
88
379
|
|
|
89
380
|
tableId: null,
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
381
|
+
|
|
382
|
+
classes: {
|
|
383
|
+
wrapper: null,
|
|
384
|
+
infoOuter: null,
|
|
385
|
+
info: null,
|
|
386
|
+
resultInfo: null,
|
|
387
|
+
search: null,
|
|
388
|
+
searchInput: 'form-control form-control-sm',
|
|
389
|
+
tableWrapper: 'table-responsive',
|
|
390
|
+
table: 'table table-bordered',
|
|
391
|
+
tableFooter: null,
|
|
392
|
+
caption: null,
|
|
393
|
+
pagination: null,
|
|
394
|
+
paginationBtn: 'btn-reset',
|
|
395
|
+
sortBtn: 'btn-reset',
|
|
396
|
+
empty: null,
|
|
397
|
+
textStart: null,
|
|
398
|
+
textCenter: 'text-center',
|
|
399
|
+
textEnd: 'text-end',
|
|
400
|
+
nowrap: 'text-nowrap',
|
|
401
|
+
numeric: 'text-numeric',
|
|
402
|
+
boolCell: null,
|
|
403
|
+
boolTrue: null,
|
|
404
|
+
boolFalse: null
|
|
405
|
+
},
|
|
406
|
+
|
|
407
|
+
labels: {
|
|
408
|
+
loading: 'Caricamento dati…',
|
|
409
|
+
searchPlaceholder: 'Cerca...',
|
|
410
|
+
searchTitle: 'Cerca nella tabella',
|
|
411
|
+
searchAriaLabel: 'Filtra risultati',
|
|
412
|
+
info: 'Stai visualizzando le righe da {start} a {end}, su un totale di {filteredRec} record trovati',
|
|
413
|
+
noRows: 'Nessun record trovato',
|
|
414
|
+
noResults: 'Nessun risultato per la ricerca',
|
|
415
|
+
sortAsc: 'Ordina questa colonna in senso ascendente (A → Z)',
|
|
416
|
+
sortDesc: 'Ordina questa colonna in senso discendente (Z → A)',
|
|
417
|
+
sortNone: 'Rimuovi l’ordinamento a questa colonna',
|
|
418
|
+
paginationAriaLabel: 'Navigazione pagine',
|
|
419
|
+
prevPage: 'Pagina precedente',
|
|
420
|
+
nextPage: 'Pagina successiva',
|
|
421
|
+
pageTitle: 'Vai a pagina {page}',
|
|
422
|
+
currentPage: 'Pagina {page}, corrente'
|
|
104
423
|
}
|
|
105
424
|
};
|
|
@@ -1,43 +1,129 @@
|
|
|
1
1
|
/*! minimo - json-table: data acquisition */
|
|
2
2
|
|
|
3
3
|
/** @typedef {import('./defaults.js').JsonTableParams} JsonTableParams */
|
|
4
|
+
/** @typedef {import('./defaults.js').SortDef} SortDef */
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Result of `getData()`.
|
|
8
|
+
* @typedef {Object} DataResult
|
|
9
|
+
* @property {Array<Object>} rows - The rows array (the requested page only, in server-side mode)
|
|
10
|
+
* @property {number} totRec - Total number of records: the numeric value of `params.totRecField` in the
|
|
11
|
+
* fetched JSON, `rows.length` otherwise
|
|
12
|
+
* @property {number} filteredRec - Number of records matching the current search: the numeric value of
|
|
13
|
+
* `params.filteredRecField` in the fetched JSON (server-side mode), `totRec` otherwise
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* State of the request in server-side mode.
|
|
18
|
+
* @typedef {Object} ServerRequest
|
|
19
|
+
* @property {number} page - Requested page (1-based)
|
|
20
|
+
* @property {number} perPage - Rows per page
|
|
21
|
+
* @property {SortDef|null} sort - Active sort, or null
|
|
22
|
+
* @property {string} search - Search term ('' = none)
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Reads a numeric field of the fetched JSON; `undefined` when missing or not numeric.
|
|
27
|
+
* @param {*} json - Fetched JSON
|
|
28
|
+
* @param {string|null|undefined} field - Key to read
|
|
29
|
+
* @returns {number|undefined}
|
|
30
|
+
*/
|
|
31
|
+
function numericField(json, field) {
|
|
32
|
+
if (!field || json == null || typeof json !== 'object') {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
const raw = json[field];
|
|
36
|
+
const num = Number(raw);
|
|
37
|
+
return (raw != null && raw !== '' && Number.isFinite(num)) ? num : undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Builds the URL of a server-side request: `params.jsonUrl` plus the query string parameters
|
|
43
|
+
* named in `params.serverParams` (parameters set to `null` are omitted; `sort`/`dir` are sent
|
|
44
|
+
* only when a sort is active, `search` only when not empty). Existing query string parameters
|
|
45
|
+
* of `jsonUrl` are preserved.
|
|
46
|
+
*
|
|
47
|
+
* @param {JsonTableParams} params - Resolved params
|
|
48
|
+
* @param {ServerRequest} request - Request state
|
|
49
|
+
* @returns {string}
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* buildServerUrl(
|
|
53
|
+
* { ...params, jsonUrl: '/api/rows.json?year=2025' },
|
|
54
|
+
* { page: 3, perPage: 25, sort: { key: 'name', dir: 'desc' }, search: 'mar' }
|
|
55
|
+
* );
|
|
56
|
+
* // → '/api/rows.json?year=2025&page=3&start=50&perPage=25&sort=name&dir=desc&search=mar'
|
|
57
|
+
*/
|
|
58
|
+
export function buildServerUrl(params, request) {
|
|
59
|
+
|
|
60
|
+
const url = new URL(String(params.jsonUrl), document.baseURI);
|
|
61
|
+
const names = params.serverParams ?? {};
|
|
62
|
+
|
|
63
|
+
/** @type {(name: string|null|undefined, value: string|number|null|undefined) => void} */
|
|
64
|
+
const set = (name, value) => {
|
|
65
|
+
if (name && value != null && value !== '') {
|
|
66
|
+
url.searchParams.set(name, String(value));
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
set(names.page, request.page);
|
|
71
|
+
set(names.start, (request.page - 1) * request.perPage);
|
|
72
|
+
set(names.perPage, request.perPage);
|
|
73
|
+
set(names.sort, request.sort?.key);
|
|
74
|
+
set(names.dir, request.sort ? request.sort.dir : null);
|
|
75
|
+
set(names.search, request.search);
|
|
76
|
+
|
|
77
|
+
return url.toString();
|
|
78
|
+
}
|
|
79
|
+
|
|
4
80
|
|
|
5
81
|
/**
|
|
6
82
|
* Retrieves the rows array from the configured source.
|
|
7
83
|
*
|
|
8
84
|
* `data` takes precedence over `jsonUrl`. With `jsonUrl` the JSON is fetched and the rows are
|
|
9
|
-
* read from the `jsonDataField` key (`null`/`''` = the JSON root is the array itself)
|
|
85
|
+
* read from the `jsonDataField` key (`null`/`''` = the JSON root is the array itself); when the
|
|
86
|
+
* JSON also holds a numeric `totRecField` key, it is returned as `totRec`, otherwise `totRec` is
|
|
87
|
+
* the rows array length. In server-side mode (`request` given) the URL carries the pagination /
|
|
88
|
+
* sort / search parameters (see `buildServerUrl`) and `filteredRecField` is read too.
|
|
10
89
|
* Returns `null` when no source is configured.
|
|
11
90
|
*
|
|
12
91
|
* @param {JsonTableParams} params - Resolved params (see `resolve-params.js`)
|
|
13
|
-
* @
|
|
92
|
+
* @param {ServerRequest|null} [request=null] - Server-side request state; `null` for a plain request (default: null)
|
|
93
|
+
* @returns {Promise<DataResult|null>} Rows and totals, or `null` when neither `data` nor `jsonUrl` is set
|
|
14
94
|
* @throws {Error} When `data` is not an array, on HTTP/network errors, or when the fetched JSON
|
|
15
95
|
* does not contain an array at `jsonDataField`
|
|
16
96
|
*
|
|
17
97
|
* @example
|
|
18
98
|
* // inline data (jsonUrl ignored)
|
|
19
|
-
* await getData({ ...params, data: [{ id: 1 }], jsonUrl: '/ignored.json' });
|
|
99
|
+
* await getData({ ...params, data: [{ id: 1 }], jsonUrl: '/ignored.json' });
|
|
100
|
+
* // → { rows: [{ id: 1 }], totRec: 1, filteredRec: 1 }
|
|
20
101
|
*
|
|
21
|
-
* // fetched JSON: { data: [...] } (jsonDataField default: 'data')
|
|
102
|
+
* // fetched JSON: { data: [...], totRec: 1500 } (jsonDataField default: 'data', totRecField default: 'totRec')
|
|
22
103
|
* await getData({ ...params, jsonUrl: '/api/rows.json' });
|
|
23
104
|
*
|
|
24
105
|
* // fetched JSON whose root is the array itself
|
|
25
106
|
* await getData({ ...params, jsonUrl: '/api/rows.json', jsonDataField: null });
|
|
107
|
+
*
|
|
108
|
+
* // server-side: GET /api/rows.json?page=2&start=25&perPage=25&search=mar
|
|
109
|
+
* // expected JSON: { data: [...25 rows], totRec: 1500, filteredRec: 40 }
|
|
110
|
+
* await getData({ ...params, jsonUrl: '/api/rows.json', serverSide: true }, { page: 2, perPage: 25, sort: null, search: 'mar' });
|
|
26
111
|
*/
|
|
27
|
-
export async function getData(params) {
|
|
112
|
+
export async function getData(params, request = null) {
|
|
28
113
|
|
|
29
114
|
if (params.data != null) {
|
|
30
115
|
if (!Array.isArray(params.data)) {
|
|
31
116
|
throw new Error('[json-table] `data` deve essere un array di oggetti');
|
|
32
117
|
}
|
|
33
|
-
return params.data;
|
|
118
|
+
return { rows: params.data, totRec: params.data.length, filteredRec: params.data.length };
|
|
34
119
|
}
|
|
35
120
|
|
|
36
121
|
if (params.jsonUrl) {
|
|
37
|
-
const
|
|
122
|
+
const url = request ? buildServerUrl(params, request) : params.jsonUrl;
|
|
123
|
+
const response = await fetch(url);
|
|
38
124
|
|
|
39
125
|
if (!response.ok) {
|
|
40
|
-
throw new Error(`[json-table] ${
|
|
126
|
+
throw new Error(`[json-table] ${url}: risposta HTTP ${response.status}`);
|
|
41
127
|
}
|
|
42
128
|
|
|
43
129
|
const json = await response.json();
|
|
@@ -46,11 +132,20 @@ export async function getData(params) {
|
|
|
46
132
|
|
|
47
133
|
if (!Array.isArray(rows)) {
|
|
48
134
|
throw new Error(
|
|
49
|
-
`[json-table] ${
|
|
135
|
+
`[json-table] ${url}: ` +
|
|
50
136
|
(field ? `il campo \`${field}\` non contiene un array` : 'la risposta non è un array')
|
|
51
137
|
);
|
|
52
138
|
}
|
|
53
|
-
|
|
139
|
+
|
|
140
|
+
const hasFields = field != null && field !== '';
|
|
141
|
+
const totRec = hasFields ? numericField(json, params.totRecField) : undefined;
|
|
142
|
+
const filteredRec = hasFields ? numericField(json, params.filteredRecField) : undefined;
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
rows,
|
|
146
|
+
totRec: totRec ?? rows.length,
|
|
147
|
+
filteredRec: filteredRec ?? totRec ?? rows.length
|
|
148
|
+
};
|
|
54
149
|
}
|
|
55
150
|
|
|
56
151
|
return null;
|