@optionfactory/ful 4.0.8 → 4.0.10

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/dist/ful.mjs CHANGED
@@ -420,11 +420,12 @@ class HttpRequestBuilder {
420
420
  * @returns {HttpRequestBuilder} the builder
421
421
  */
422
422
  static create(client, method, uri) {
423
+ const [baseUri, queryString = ''] = uri.split('?');
423
424
  return new HttpRequestBuilder(
424
425
  client,
425
426
  method,
426
- uri,
427
- new URLSearchParams(),
427
+ baseUri,
428
+ new URLSearchParams(queryString),
428
429
  new Headers(),
429
430
  undefined,
430
431
  {},
@@ -2423,7 +2424,7 @@ class Pagination extends ParsedElement {
2423
2424
  <nav data-tpl-aria-label="#l10n:t('navigation')" class="user-select-none">
2424
2425
  <ul class="pagination">
2425
2426
  <li class="page-item ms-auto me-2 pagination-index"> {{ #l10n:t('showing', curr.label, total) }}</li>
2426
- <li class="page-item reload me-2"><a role="button"><i data-tpl-class="config.reloadIcon"></i></a></li>
2427
+ <li class="page-item me-2 reload"><a role="button"><i data-tpl-class="config.reloadIcon"></i></a></li>
2427
2428
  <li class="page-item prev">
2428
2429
  <a data-tpl-class="prev.enabled?'page-link':'page-link disabled'" data-tpl-aria-label="#l10n:t('previous')" role="button" data-tpl-data-page="prev.index">
2429
2430
  <i aria-hidden="true" data-tpl-class="config.prevIcon"></i>
@@ -2510,47 +2511,68 @@ class TableSchemaParser {
2510
2511
  if (!schema) {
2511
2512
  throw new Error(`missing expected <schema> in ${nodeOrFragment}`);
2512
2513
  }
2513
- return Nodes.queryChildrenAll(schema, "column")
2514
- .map(el => {
2515
- return {
2516
- sorter: el.getAttribute("sorter"),
2517
- order: el.getAttribute("order"),
2518
- title: TableSchemaParser.#parseTitle(el, template),
2519
- content: TableSchemaParser.#parseContent(el, template)
2514
+ const headersTr = document.createElement("tr");
2515
+ const rowsTr = document.createElement("tr");
2516
+ rowsTr.setAttribute("data-tpl-each", "rows");
2517
+ for (const attr of schema.getAttributeNames()) {
2518
+ const value = schema.getAttribute(attr);
2519
+ headersTr.setAttribute(attr, value ?? '');
2520
+ rowsTr.setAttribute(attr, value ?? '');
2521
+ }
2522
+ const columns = Nodes.queryChildrenAll(schema, "column");
2523
+ const sort = columns.filter(v => v.hasAttribute('order')).map(v => ({sorter: v.getAttribute("sorter"), order: v.getAttribute("order")}))[0] ?? null;
2524
+ for(var column of columns){
2525
+ const maybeTitleTag = Nodes.queryChildren(column, 'title');
2526
+ const sorter = column.getAttribute("sorter");
2527
+ const order = column.getAttribute("order");
2528
+ const titleNode = maybeTitleTag ?? document.createTextNode(column.getAttribute("title") ?? '');
2529
+ maybeTitleTag?.remove();
2530
+ column.removeAttribute("sorter");
2531
+ column.removeAttribute("order");
2532
+ column.removeAttribute("title");
2533
+ const wrappedTitleNode = (!sorter && !order ) ? titleNode : (() => {
2534
+ const fulSorter = document.createElement("ful-sorter");
2535
+ if(sorter){
2536
+ fulSorter.setAttribute("sorter", sorter);
2520
2537
  }
2521
- });
2522
- }
2523
-
2524
- static #parseTitle(el, template) {
2525
- const maybeTitleTag = Nodes.queryChildren(el, 'title');
2526
- if (maybeTitleTag) {
2527
- maybeTitleTag.remove();
2538
+ if(order){
2539
+ fulSorter.setAttribute("order", order);
2540
+ }
2541
+ fulSorter.append(titleNode);
2542
+ return fulSorter;
2543
+ })();
2544
+ const th = document.createElement("th");
2545
+ const td = document.createElement("td");
2546
+ for (const attr of column.getAttributeNames()) {
2547
+ const value = column.getAttribute(attr);
2548
+ th.setAttribute(attr, value ?? '');
2549
+ td.setAttribute(attr, value ?? '');
2550
+ }
2551
+ th.append(wrappedTitleNode);
2552
+ td.append(...column.childNodes);
2553
+ headersTr.append(th);
2554
+ rowsTr.append(td);
2528
2555
  }
2529
- const fragment = maybeTitleTag ? template.withFragment(Fragments.fromChildNodes(maybeTitleTag)).render() : document.createTextNode(el.getAttribute("title") ?? '');
2530
- return {
2531
- classes: el.getAttribute("th-class"),
2532
- fragment
2533
- };
2534
- }
2535
2556
 
2536
- static #parseContent(el, template) {
2537
2557
  return {
2538
- classes: el.getAttribute("td-class"),
2539
- template: template.withFragment(Fragments.fromChildNodes(el))
2558
+ headersTemplate: template.withOverlay({inHeaders: true, inRows: false}).withFragment(Fragments.from(headersTr)),
2559
+ rowsTemplate: template.withOverlay({inHeaders: false, inRows: true}).withFragment(Fragments.from(rowsTr)),
2560
+ sort: sort,
2561
+ length: columns.length
2540
2562
  }
2541
2563
  }
2542
2564
  }
2543
2565
 
2544
- class RemoteTableLoader{
2566
+ class RemoteTableLoader {
2545
2567
  #http;
2546
2568
  #url;
2547
2569
  #method;
2548
- constructor(http, url, method){
2570
+ constructor(http, url, method) {
2549
2571
  this.#http = http;
2550
2572
  this.#url = url;
2551
2573
  this.#method = method;
2552
2574
  }
2553
- async load(pageRequest, sortRequest, filterRequest){
2575
+ async load(pageRequest, sortRequest, filterRequest) {
2554
2576
  const filters = Object.entries(filterRequest).filter(([k, v]) => v);
2555
2577
  return await this.#http.request(this.#method, this.#url)
2556
2578
  .param("page", pageRequest.page)
@@ -2558,12 +2580,12 @@ class RemoteTableLoader{
2558
2580
  .param("sort", sortRequest.order ? `${sortRequest.sorter},${sortRequest.order}` : null)
2559
2581
  .param("filters", filters.length > 0 ? JSON.stringify(Object.fromEntries(filters)) : null)
2560
2582
  .fetchJson();
2561
- }
2583
+ }
2562
2584
  }
2563
2585
 
2564
2586
 
2565
- class TableLoader{
2566
- static create({el, http}){
2587
+ class TableLoader {
2588
+ static create({ el, http }) {
2567
2589
  const url = el.getAttribute("src");
2568
2590
  const method = el.getAttribute("method") ?? 'GET';
2569
2591
  return new RemoteTableLoader(http, url, method);
@@ -2574,18 +2596,18 @@ class Table extends ParsedElement {
2574
2596
  static slots = true;
2575
2597
  static l10n = {
2576
2598
  en: {
2577
- 'notloaded': 'Start searching to see results.',
2599
+ 'initial': 'Start searching to see results.',
2578
2600
  'error': 'Error while loading data:',
2579
2601
  'nodata': 'No elements found.',
2580
2602
  },
2581
2603
  it: {
2582
- 'notloaded': 'Avvia la ricerca per visualizzare i risultati.',
2604
+ 'initial': 'Avvia la ricerca per visualizzare i risultati.',
2583
2605
  'error': 'Errore nel caricamento dei dati:',
2584
2606
  'nodata': 'Nessun elemento trovato.',
2585
2607
  }
2586
2608
  }
2587
- static conf = {
2588
- sortIcon: '',
2609
+ static config = {
2610
+ searchIcon: 'bi bi-search'
2589
2611
  }
2590
2612
  static template = `
2591
2613
  <ful-form data-tpl-if="slots.filters">
@@ -2594,38 +2616,31 @@ class Table extends ParsedElement {
2594
2616
  <div class="table-wrapper">
2595
2617
  <table class="table">
2596
2618
  <caption data-tpl-if="slots.caption">{{{{ slots.caption }}}}</caption>
2597
- <thead>
2598
- <tr>
2599
- <th data-tpl-each="schema" scope="col" data-tpl-class="title.classes">
2600
- {{{{ title.fragment }}}}
2601
- <ful-sorter data-tpl-if="sorter || order" data-tpl-sorter="sorter" data-tpl-order="order"></ful-sorter>
2602
- </th>
2603
- </tr>
2604
- </thead>
2619
+ <thead></thead>
2605
2620
  <tbody></tbody>
2606
- <tbody data-ref="no-autoload">
2621
+ <tbody data-ref="initial">
2607
2622
  <tr>
2608
- <td data-tpl-colspan="schema.length" class="text-center align-middle p-4">
2609
- <i class="bi bi-search" style="font-size: 40px; color: #BDC3CA"></i>
2610
- <p class="mt-3 mb-0" style="color: #BDC3CA">
2611
- {{ #l10n:t('notloaded') }}
2612
- </p>
2623
+ <td data-tpl-colspan="schema.length">
2624
+ <div>
2625
+ <p data-tpl-if="config.searchIcon"><i data-tpl-class="config.searchIcon"></i></p>
2626
+ {{{ #l10n:t('initial') }}}
2627
+ </div>
2613
2628
  </td>
2614
2629
  </tr>
2615
2630
  </tbody>
2616
2631
  <tbody data-ref="loading" hidden>
2617
2632
  <tr>
2618
- <td data-tpl-colspan="schema.length" class="text-center align-middle p-4">
2633
+ <td data-tpl-colspan="schema.length">
2619
2634
  <ful-spinner class="big"></ful-spinner>
2620
2635
  </td>
2621
2636
  </tr>
2622
2637
  </tbody>
2623
2638
  <tbody data-ref="feedback" hidden>
2624
2639
  <tr>
2625
- <td data-tpl-colspan="schema.length" class="text-center align-middle p-4">
2640
+ <td data-tpl-colspan="schema.length">
2626
2641
  <div class="alert alert-danger">
2627
2642
  <p>{{ #l10n:t('error') }}</p>
2628
- <p class="mb-0" data-ref="feedback-error"></p>
2643
+ <div data-ref="feedback-error"></div>
2629
2644
  </div>
2630
2645
  </td>
2631
2646
  </tr>
@@ -2644,11 +2659,7 @@ class Table extends ParsedElement {
2644
2659
  {{ #l10n:t('nodata') }}
2645
2660
  </td>
2646
2661
  </tr>
2647
- <tr data-tpl-each="pageResponse.data" data-tpl-var="row">
2648
- <td data-tpl-each="schema" data-tpl-class="content.classes">
2649
- {{{{ content.template.withOverlay(row).render() }}}}
2650
- </td>
2651
- </tr>
2662
+ {{{{ schema.rowsTemplate.withOverlay({'rows': pageResponse.data}).render() }}}}
2652
2663
  `
2653
2664
  };
2654
2665
  #schema;
@@ -2669,13 +2680,13 @@ class Table extends ParsedElement {
2669
2680
  this.#schema = schema;
2670
2681
  this.#body = table.querySelector(':scope > tbody');
2671
2682
  this.#loading = table.querySelector(":scope > tbody[data-ref=loading]");
2672
- this.#noAutoload = table.querySelector(":scope > tbody[data-ref=no-autoload]");
2683
+ this.#noAutoload = table.querySelector(":scope > tbody[data-ref=initial]");
2673
2684
  this.#feedback = table.querySelector(":scope > tbody[data-ref=feedback]");
2674
2685
  this.#paginator = Nodes.queryChildren(fragment, 'ful-pagination');
2675
2686
  this.#sorters = table.querySelectorAll(':scope > thead ful-sorter') ?? [];
2676
2687
  this.replaceChildren(fragment);
2688
+ schema.headersTemplate.renderTo(this.querySelector('thead'));
2677
2689
  await Rendering.waitForChildren(this);
2678
- const orderFromSchema = schema.find(v => v.order);
2679
2690
 
2680
2691
  const maybeForm = /** @type any */(Nodes.queryChildren(this, 'ful-form'));
2681
2692
  this.#latestRequest = {
@@ -2683,7 +2694,7 @@ class Table extends ParsedElement {
2683
2694
  page: 0,
2684
2695
  size: this.getAttribute("page-size") ? Number(this.getAttribute("page-size")) : 10
2685
2696
  },
2686
- sortRequest: { order: orderFromSchema?.order, sorter: orderFromSchema?.sorter },
2697
+ sortRequest: schema.sort,
2687
2698
  filterRequest: maybeForm?.values ?? {}
2688
2699
  };
2689
2700
  maybeForm?.addEventListener('submit:success', async (evt) => {
@@ -2718,7 +2729,7 @@ class Table extends ParsedElement {
2718
2729
  this.#noAutoload.setAttribute("hidden", "");
2719
2730
  try {
2720
2731
  const loader = Loaders.fromAttributes(this, 'loaders:table');
2721
- const pageResponse =await loader.load(pageRequest, sortRequest, filterRequest);
2732
+ const pageResponse = await loader.load(pageRequest, sortRequest, filterRequest);
2722
2733
  this.#latestRequest = { pageRequest, sortRequest, filterRequest };
2723
2734
  this.#update(pageRequest, sortRequest, filterRequest, pageResponse);
2724
2735
  } catch (/** @type any */error) {