@smartbit4all/ng-client 7.2.4 → 7.2.6
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/HTML-WIDGET.md +110 -4
- package/MIGRATION-7.0.md +9 -0
- package/WIDGETS.md +3 -1
- package/fesm2022/smartbit4all-ng-client.mjs +148 -44
- package/fesm2022/smartbit4all-ng-client.mjs.map +1 -1
- package/package.json +1 -1
- package/smartbit4all-ng-client-7.2.6.tgz +0 -0
- package/types/smartbit4all-ng-client.d.ts +684 -677
- package/smartbit4all-ng-client-7.2.4.tgz +0 -0
package/HTML-WIDGET.md
CHANGED
|
@@ -38,6 +38,7 @@ A `DIV` widget változatlanul megmarad; a HTML widget annak a használatnak a re
|
|
|
38
38
|
| `root` | dot-path a kontextus `data`-jához képest, amihez minden helyőrző relatív; **objektumot** nevez; üres = a `data` maga |
|
|
39
39
|
| `fields` | a widget által olvasott abszolút pathok — a builder származtatja a helyőrzőkből, a kliens **nem** olvassa |
|
|
40
40
|
| `css` | a widget stíluslapja, a html mellett utazik — lásd *Stíluslap* |
|
|
41
|
+
| `icons` | az **ikon-szótár**: `kulcs → ImageResource`, amit az ikon-slotok `data-sb4-icon-key`-jel címeznek — lásd *Ikon-slot* |
|
|
41
42
|
|
|
42
43
|
A **feloldási kontextus** nézeten a `ComponentModel` (`data` + `valueSets`), grid-kártyán a sor
|
|
43
44
|
(`GridRow.data`) a gridet mutató oldal `valueSets`-ével. Ha a `root` listát, egyetlen értéket vagy
|
|
@@ -55,6 +56,20 @@ layoutBuilder(view).vForm(f -> f
|
|
|
55
56
|
vagy template-kulcsból (`h.template(ctx, "CONTACT_ENTRY_LIST")`): a kulcs a szerveren oldódik fel,
|
|
56
57
|
a dróton nem utazik.
|
|
57
58
|
|
|
59
|
+
A html sima szöveg, tehát a `Tag` builder helyett **text blockként** is írható — így a sablon
|
|
60
|
+
ugyanúgy néz ki, ahogy a kliens megkapja:
|
|
61
|
+
|
|
62
|
+
```java
|
|
63
|
+
.html("""
|
|
64
|
+
<div class="card">
|
|
65
|
+
<smart-icon data-sb4-icon="{{typeIcon}}"></smart-icon>
|
|
66
|
+
<b>{{name}}</b>
|
|
67
|
+
</div>""")
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
A `html(String, Object...)` `String.format`-tal illeszti be az argumentumokat (akciókód,
|
|
71
|
+
toolbar-id), ilyenkor a szövegben a `%` `%%`.
|
|
72
|
+
|
|
58
73
|
## Stíluslap
|
|
59
74
|
|
|
60
75
|
A widget a kinézetét is hozhatja: a `css` mezőben egy CSS-szöveget, amit a kliens a dokumentum
|
|
@@ -217,7 +232,9 @@ Logika-mentes Mustache-részhalmaz. Ugyanezt a nyelvtant olvassa a Java-oldali
|
|
|
217
232
|
|
|
218
233
|
- Hiányzó, `null` vagy `null`-on átvezető path → **üres string, csendben**.
|
|
219
234
|
- Primitív → `String(v)` (`false` → `false`, `0` → `0`).
|
|
220
|
-
- Objektum vagy lista `{{p}}`-ként → üres + `console.warn`.
|
|
235
|
+
- Objektum vagy lista `{{p}}`-ként → üres + `console.warn`. Egyetlen kivétel: egy **ikon-slot**
|
|
236
|
+
név-attribútumának teljes értékeként az objektum az ikon `ImageResource`-a lesz — lásd
|
|
237
|
+
*Ikon-slot*.
|
|
221
238
|
- Minden behelyettesített érték HTML-escape (`& < > " '`). URL-attribútumban (`href="{{url}}"`)
|
|
222
239
|
nincs séma-szűrés: az érték a szerver saját modelljéből jön, a szerző felel érte.
|
|
223
240
|
|
|
@@ -300,7 +317,9 @@ escape-pel), a pipe-ok balról jobbra láncolhatók, a kimenetük is escape-en m
|
|
|
300
317
|
|
|
301
318
|
| Hol | Mi történik |
|
|
302
319
|
|---|---|
|
|
303
|
-
| Java-builder (`build()`) | `IllegalArgumentException`: párosítatlan / keresztezett szekció, raw tag, érvénytelen path vagy `root`, a `root` fölé mutató `../`, ismeretlen pipe, rossz pipe-szintaxis, üres `data-sb4-toolbar` / `data-sb4-action`
|
|
320
|
+
| Java-builder (`build()`) | `IllegalArgumentException`: párosítatlan / keresztezett szekció, raw tag, érvénytelen path vagy `root`, a `root` fölé mutató `../`, ismeretlen pipe, rossz pipe-szintaxis, üres `data-sb4-toolbar` / `data-sb4-action` /
|
|
321
|
+
`data-sb4-icon` / `data-sb4-icon-key`, `data-sb4-icon` és `data-sb4-icon-key` ugyanazon az elemen |
|
|
322
|
+
| Java-builder (`build()`) | `IllegalStateException`: a sablonban álló literál ikon-kulcs, amit az ikon-szótár nem tartalmaz |
|
|
304
323
|
| Java-builder (`build()`), `resolveHtml` | `IllegalStateException`: feloldatlan szerver-helyőrző (`${alias:/`), lásd *A szerver-fázis* |
|
|
305
324
|
| kliens | nem dob: `console.error`, és a html **feloldatlanul** kerül ki — látható hiba, nem üres kártya |
|
|
306
325
|
|
|
@@ -344,6 +363,92 @@ nézeten az oldalét). Java: `Tag.toolbar(id)` / `Tag.toolbar(id, toolbarPropert
|
|
|
344
363
|
- A kliens csak akkor írja újra a html-t, ha a feloldás eredménye **megváltozott**; változatlan
|
|
345
364
|
eredménynél a hidratált toolbarok élnek tovább.
|
|
346
365
|
|
|
366
|
+
## Ikon-slot
|
|
367
|
+
|
|
368
|
+
```html
|
|
369
|
+
<smart-icon data-sb4-icon="mail" data-sb4-icon-color="warn"></smart-icon>
|
|
370
|
+
<smart-icon data-sb4-icon="{{typeIcon}}"></smart-icon>
|
|
371
|
+
<smart-icon data-sb4-icon-key="{{type}}"></smart-icon>
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
A kliens a marker-elembe egy **valódi `smart-icon`-t hidratál**, ugyanazt a komponenst, amit a
|
|
375
|
+
gomb, a grid-cella és a form használ. Java: `Tag.icon(name)`, `Tag.icon(name, color)`,
|
|
376
|
+
`Tag.icon(imageResource)`, `Tag.iconKey(key)`, a szótár a widget-builderen: `h.icon(key, resource)`
|
|
377
|
+
/ `h.icons(map)`.
|
|
378
|
+
|
|
379
|
+
Az ikon címe négyféle lehet, és mindegyiknek megvan a maga esete:
|
|
380
|
+
|
|
381
|
+
| Forma | Mit ad az ikonnak | Mikor |
|
|
382
|
+
|---|---|---|
|
|
383
|
+
| `data-sb4-icon="mail"` | `icon` input: a név előbb a regisztrált svg-névterekben, aztán Material-ligatúraként | fix ikon, vagy adatból jövő **ikonnév** |
|
|
384
|
+
| `data-sb4-icon="{{typeIcon}}"`, az érték **objektum** | `imageResource` input | soronként más erőforrás (feltöltött kép, `ImageSettingApi` a modellben) |
|
|
385
|
+
| `data-sb4-icon="{…}"` (JSON) | `imageResource` input | a page által **egyszer** feloldott erőforrás (`Tag.icon(resource)`) |
|
|
386
|
+
| `data-sb4-icon-key="{{type}}"` | `imageResource` input a **szótárból** | véges típus → ikon leképezés |
|
|
387
|
+
|
|
388
|
+
- **`data-sb4-icon-color`**: a `color` input, vagyis téma- vagy host-osztálynév (`primary`,
|
|
389
|
+
`text-primary`, `warn` …), **nem** CSS-szín. Csak a név-formához való: az `ImageResource` a saját
|
|
390
|
+
`color`-ját hozza. Elhagyva a komponens alapértelmezése (`primary`) marad.
|
|
391
|
+
- **Objektum csak ott**, ahol az attribútum értéke pontosan egy helyőrző. Szöveggel keverve
|
|
392
|
+
(`data-sb4-icon="ic-{{typeIcon}}"`), pipe-pal vagy listán az érték a nyelvtan általános szabálya
|
|
393
|
+
szerint üres marad, warninggal. A feloldó az objektumot egy **renderelésenként újrahúzott,
|
|
394
|
+
véletlen tokennel** adja át a hidratálásnak, hogy adatból ne lehessen másik ikon erőforrására
|
|
395
|
+
hivatkozni.
|
|
396
|
+
- **Üres cím** (nincs ikonja ennek a sornak) → néma kihagyás, az elem üresen marad. A sablonban
|
|
397
|
+
**szó szerint üres** marker (`data-sb4-icon=""`) viszont `build()`-hiba, ahogy a toolbarnál.
|
|
398
|
+
- **Ismeretlen szótárkulcs** → nincs ikon, egy warning. A sablonban álló **literál** kulcsot, ami
|
|
399
|
+
nincs a szótárban, már a `build()` elutasítja.
|
|
400
|
+
- Egy elemen **nem állhat** a `data-sb4-icon` és a `data-sb4-icon-key` egyszerre: `build()`-hiba, a
|
|
401
|
+
kliens a kulcsot használja és warningot ír.
|
|
402
|
+
- A marker `class` és `style` attribútuma a helyén marad (a hidratálás a marker-elembe rendereli a
|
|
403
|
+
komponenst), a méretezés a widget CSS-éből megy: `.card-icon mat-icon { font-size: … }`.
|
|
404
|
+
- Az ikon a nevét a regiszterben keresi meg, ezért **egy microtaskkal később** jelenik meg — a
|
|
405
|
+
kliens ettől még ugyanabban a renderelésben írja ki a html-t.
|
|
406
|
+
|
|
407
|
+
### Példa: típus szerinti ikon egy ImageResource-ból
|
|
408
|
+
|
|
409
|
+
A szerveren az `ImageSettingApi` képezi le a típust ikonra (`images-*.properties`):
|
|
410
|
+
|
|
411
|
+
```properties
|
|
412
|
+
ContactType.EMAIL={"identifier":"mail","color":"accent","tooltip":{"tooltip":"E-mail cím"}}
|
|
413
|
+
ContactType.PHONE={"identifier":"call","color":"primary","tooltip":{"tooltip":"Telefonszám"}}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
**Soronként más erőforrás** — az objektum az adatban utazik:
|
|
417
|
+
|
|
418
|
+
```java
|
|
419
|
+
row.getData().put("typeIcon", imageSettingApi.get("ContactType", type.name()));
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
```html
|
|
423
|
+
<div class="pg-row">
|
|
424
|
+
<smart-icon data-sb4-icon="{{typeIcon}}"></smart-icon>
|
|
425
|
+
<b>{{name}}</b>
|
|
426
|
+
</div>
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
**Véges leképezés** — az erőforrás egyszer utazik, a sor csak a kódot viszi:
|
|
430
|
+
|
|
431
|
+
```java
|
|
432
|
+
.htmlColumn("type", h -> h
|
|
433
|
+
.icon("EMAIL", imageSettingApi.get("ContactType", "EMAIL"))
|
|
434
|
+
.icon("PHONE", imageSettingApi.get("ContactType", "PHONE"))
|
|
435
|
+
.html("""
|
|
436
|
+
<div class="pg-row">
|
|
437
|
+
<smart-icon data-sb4-icon-key="{{type}}"></smart-icon>
|
|
438
|
+
<b>{{name}}</b>
|
|
439
|
+
</div>"""))
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Mindkettőből ugyanaz lesz a DOM-ban:
|
|
443
|
+
|
|
444
|
+
```html
|
|
445
|
+
<smart-icon data-sb4-icon="…"><mat-icon class="mat-accent material-icons">mail</mat-icon></smart-icon>
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
A szótár a **sablon** része (`HtmlProperties.icons`), nem a soré: a sima HTML widgetnél is egyszer
|
|
449
|
+
megy le, és egy újra-feloldás már a leküldött erőforrások közül választ. Nem tévesztendő össze a
|
|
450
|
+
`GridRow.icons`-szal, ami a **cella értéke mellé** rajzolt ikonokat írja le.
|
|
451
|
+
|
|
347
452
|
## Akció-trigger
|
|
348
453
|
|
|
349
454
|
```html
|
|
@@ -468,7 +573,7 @@ gridBuilder.htmlColumn("name", h -> h.html(t -> t
|
|
|
468
573
|
.toolbar("ROW_TOOLBAR")))
|
|
469
574
|
```
|
|
470
575
|
|
|
471
|
-
- **Ugyanaz a bean, mint a widgeté** (`HtmlProperties`): `html`, `root`, `fields`, `css`, és
|
|
576
|
+
- **Ugyanaz a bean, mint a widgeté** (`HtmlProperties`): `html`, `root`, `fields`, `css`, `icons`, és
|
|
472
577
|
ugyanaz a nyelvtan, pipe-készlet, escape, stíluslap- és hibakezelés. A `root` a **sor `data`-jához** relatív; a
|
|
473
578
|
`valueSets` a gridet mutató oldalé.
|
|
474
579
|
- A sablon az oszlop **minden érték-renderelését** kiváltja, a `typeClass` szerinti dátum-,
|
|
@@ -518,7 +623,8 @@ gridBuilder.htmlColumn("name", h -> h.html(t -> t
|
|
|
518
623
|
`root = "card"`, ha a sor `data`-jában a kártya a `card` oszlop alatt van. Amit a kliens-dialektus
|
|
519
624
|
szándékosan nem tud, annak a helye:
|
|
520
625
|
|
|
521
|
-
- **ikon
|
|
626
|
+
- **ikon**: ikon-slot (`data-sb4-icon` / `data-sb4-icon-key`), a leképezés az `ImageSettingApi`-ban;
|
|
627
|
+
értékfüggő megjelenés egyébként: szerver-származtatott mező, vagy érték-alapú CSS-osztály
|
|
522
628
|
(`contact-card-icon-{{channelType}}`);
|
|
523
629
|
- **feltétel egy érték egyenlőségére**: sor-layout kulcs (`row.rowLayout`), vagy szerver-származtatott
|
|
524
630
|
logikai mező + `{{?…}}` őr;
|
package/MIGRATION-7.0.md
CHANGED
|
@@ -1874,6 +1874,15 @@ Additive, with **one behaviour change** and one removed field. The reference is
|
|
|
1874
1874
|
going out.
|
|
1875
1875
|
Inside a `{{#section}}` a placeholder reads the surrounding scope only when it says so,
|
|
1876
1876
|
`{{../title}}`: one step per entering section, never above the widget's root.
|
|
1877
|
+
- **Icon slots (in the tree, released after 7.2.4)**: an element in the html marked with
|
|
1878
|
+
`data-sb4-icon` hydrates into a
|
|
1879
|
+
`smart-icon` — the same component a button or a cell uses. The marker addresses a name
|
|
1880
|
+
(`data-sb4-icon="mail"`, coloured by `data-sb4-icon-color`, a theme or host class name), an
|
|
1881
|
+
`ImageResource` (a placeholder that resolves to one, or the json `Tag.icon(resource)` writes
|
|
1882
|
+
in), or a key of the template's icon dictionary (`data-sb4-icon-key`,
|
|
1883
|
+
`HtmlProperties.icons`), which sends a finite type-to-icon mapping once with the template
|
|
1884
|
+
rather than once per row. An address that resolves to nothing renders no icon and says
|
|
1885
|
+
nothing; an unknown dictionary key warns. Nothing changes for a host that sends no icon slot.
|
|
1877
1886
|
- **Row layouts**: a cards grid can carry its card layouts once per grid
|
|
1878
1887
|
(`GridViewDescriptor.rowLayouts`, picked per row by `GridRow.rowLayout`) instead of once per
|
|
1879
1888
|
row. The per-row `layoutDescriptor.GRID_ROW_LAYOUT` still works and wins over them; a
|
package/WIDGETS.md
CHANGED
|
@@ -155,7 +155,9 @@ toolbar slot of the html the backend sent (`<smart-ui-action-toolbar data-sb4-to
|
|
|
155
155
|
such a toolbar resolves by the very same pull: a `SmartActionHost` above it if one has a list, the
|
|
156
156
|
screen component otherwise. That is why a row layout's html gets the row's actions on a grid card
|
|
157
157
|
with no code of its own, and a table cell rendered from a column template gets them the same way.
|
|
158
|
-
An action trigger (`data-sb4-action`) looks its action up in the same list
|
|
158
|
+
An action trigger (`data-sb4-action`) looks its action up in the same list, and an icon slot
|
|
159
|
+
(`data-sb4-icon`, `data-sb4-icon-key`) hydrates into a `smart-icon` the same way. See
|
|
160
|
+
`HTML-WIDGET.md`.
|
|
159
161
|
|
|
160
162
|
**A `UiActionModel` is frozen.** Every field is `readonly`, and `[uiActionModels]` takes
|
|
161
163
|
`readonly UiActionModel[]`. Build a new entry; never edit one. Writing into an entry a
|
|
@@ -6162,18 +6162,6 @@ const APIS$4 = [DefaultService$1];
|
|
|
6162
6162
|
* Do not edit the class manually.
|
|
6163
6163
|
*/
|
|
6164
6164
|
|
|
6165
|
-
/**
|
|
6166
|
-
* Form layout definition
|
|
6167
|
-
* Contains form layout definition objects.
|
|
6168
|
-
*
|
|
6169
|
-
* The version of the OpenAPI document: 1.0.0
|
|
6170
|
-
* Contact: info@it4all.hu
|
|
6171
|
-
*
|
|
6172
|
-
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
6173
|
-
* https://openapi-generator.tech
|
|
6174
|
-
* Do not edit the class manually.
|
|
6175
|
-
*/
|
|
6176
|
-
|
|
6177
6165
|
var RecordingUploaderPropertiesOpenDirectionEnum;
|
|
6178
6166
|
(function (RecordingUploaderPropertiesOpenDirectionEnum) {
|
|
6179
6167
|
RecordingUploaderPropertiesOpenDirectionEnum["RIGHT"] = "RIGHT";
|
|
@@ -9653,6 +9641,79 @@ function enumAttribute(marker, name, values, ctx) {
|
|
|
9653
9641
|
}
|
|
9654
9642
|
return value;
|
|
9655
9643
|
}
|
|
9644
|
+
/**
|
|
9645
|
+
* Turns every icon slot under the container into a live `smart-icon` rendered into the marker
|
|
9646
|
+
* element itself. A slot addresses its icon in one of three ways, and an empty address — the
|
|
9647
|
+
* ordinary case of a row that has no icon — is skipped without a word:
|
|
9648
|
+
*
|
|
9649
|
+
* - `data-sb4-icon` with a name, which the icon resolves against the registered svg namespaces
|
|
9650
|
+
* and falls back to a material ligature, optionally coloured by `data-sb4-icon-color`;
|
|
9651
|
+
* - `data-sb4-icon` with an image resource, either as the token the resolver left for an object
|
|
9652
|
+
* valued placeholder or as the JSON a backend builder wrote in;
|
|
9653
|
+
* - `data-sb4-icon-key` with a key of the template's icon dictionary, which travels once however
|
|
9654
|
+
* many rows read it.
|
|
9655
|
+
*
|
|
9656
|
+
* The refs are the caller's, like the toolbars': destroy them before the html is rewritten.
|
|
9657
|
+
*/
|
|
9658
|
+
function hydrateIcons(container, ctx, icons) {
|
|
9659
|
+
const refs = [];
|
|
9660
|
+
container
|
|
9661
|
+
.querySelectorAll('[data-sb4-icon], [data-sb4-icon-key]')
|
|
9662
|
+
.forEach((marker) => {
|
|
9663
|
+
const key = marker.getAttribute('data-sb4-icon-key');
|
|
9664
|
+
const name = marker.getAttribute('data-sb4-icon');
|
|
9665
|
+
if (key !== null && name !== null) {
|
|
9666
|
+
ctx.warn('an icon slot addresses both a name and a dictionary key, the key is used');
|
|
9667
|
+
}
|
|
9668
|
+
const ref = createComponent(SmartIconComponent, {
|
|
9669
|
+
hostElement: marker,
|
|
9670
|
+
elementInjector: ctx.elementInjector,
|
|
9671
|
+
environmentInjector: ctx.environmentInjector,
|
|
9672
|
+
});
|
|
9673
|
+
if (key !== null) {
|
|
9674
|
+
const resource = icons.dictionary?.[key];
|
|
9675
|
+
if (key && !resource) {
|
|
9676
|
+
ctx.warn(`the icon dictionary has no '${key}'`);
|
|
9677
|
+
}
|
|
9678
|
+
ref.setInput('imageResource', resource);
|
|
9679
|
+
}
|
|
9680
|
+
else {
|
|
9681
|
+
const resource = imageResource(name, icons, ctx);
|
|
9682
|
+
if (resource) {
|
|
9683
|
+
ref.setInput('imageResource', resource);
|
|
9684
|
+
}
|
|
9685
|
+
else {
|
|
9686
|
+
ref.setInput('icon', name || undefined);
|
|
9687
|
+
ref.setInput('color', marker.getAttribute('data-sb4-icon-color') ?? undefined);
|
|
9688
|
+
}
|
|
9689
|
+
}
|
|
9690
|
+
// Without a zone nothing else would ever refresh a view that is in no template.
|
|
9691
|
+
ctx.appRef.attachView(ref.hostView);
|
|
9692
|
+
ref.changeDetectorRef.detectChanges();
|
|
9693
|
+
refs.push(ref);
|
|
9694
|
+
});
|
|
9695
|
+
return refs;
|
|
9696
|
+
}
|
|
9697
|
+
/** The resource an address stands for, undefined when it is a plain icon name. */
|
|
9698
|
+
function imageResource(address, icons, ctx) {
|
|
9699
|
+
if (icons.objects.has(address)) {
|
|
9700
|
+
return icons.objects.get(address);
|
|
9701
|
+
}
|
|
9702
|
+
if (address.startsWith('sb4-img:')) {
|
|
9703
|
+
ctx.warn(`the image resource of '${address}' is not from this render, the icon is left empty`);
|
|
9704
|
+
return {};
|
|
9705
|
+
}
|
|
9706
|
+
if (!address.startsWith('{')) {
|
|
9707
|
+
return undefined;
|
|
9708
|
+
}
|
|
9709
|
+
try {
|
|
9710
|
+
return JSON.parse(address);
|
|
9711
|
+
}
|
|
9712
|
+
catch {
|
|
9713
|
+
ctx.warn(`an icon slot holds html that is not an image resource: ${address.substring(0, 40)}`);
|
|
9714
|
+
return {};
|
|
9715
|
+
}
|
|
9716
|
+
}
|
|
9656
9717
|
|
|
9657
9718
|
/** Pipes that must have an argument, and pipes that must not; the Java scanner checks the same. */
|
|
9658
9719
|
const PIPES_REQUIRING_ARGUMENT = ['label'];
|
|
@@ -9730,6 +9791,8 @@ function formatNumber(v, digitsInfo, ctx) {
|
|
|
9730
9791
|
}
|
|
9731
9792
|
|
|
9732
9793
|
const IDENTIFIER = '[A-Za-z_][A-Za-z0-9_]*';
|
|
9794
|
+
/** The whole value of an icon slot's name attribute: only there may a placeholder give an object. */
|
|
9795
|
+
const ICON_ATTRIBUTE = /data-sb4-icon\s*=\s*"$/i;
|
|
9733
9796
|
const PATH = new RegExp(`^((?:\\.\\./)*)(${IDENTIFIER}(?:\\.${IDENTIFIER})*)$`);
|
|
9734
9797
|
const PIPE_NAME = new RegExp(IDENTIFIER, 'y');
|
|
9735
9798
|
function resolveTemplate(template, scope, ctx) {
|
|
@@ -9738,11 +9801,33 @@ function resolveTemplate(template, scope, ctx) {
|
|
|
9738
9801
|
nodes = parse(template);
|
|
9739
9802
|
}
|
|
9740
9803
|
catch (e) {
|
|
9741
|
-
return { html: template, errors: [e.message] };
|
|
9804
|
+
return { html: template, errors: [e.message], objects: new Map(), identity: template };
|
|
9742
9805
|
}
|
|
9743
9806
|
const out = [];
|
|
9744
|
-
|
|
9745
|
-
|
|
9807
|
+
const sink = { prefix: `sb4-img:${nonce()}:`, objects: new Map() };
|
|
9808
|
+
render(nodes, [scope], ctx, out, sink);
|
|
9809
|
+
const html = out.join('');
|
|
9810
|
+
return { html, errors: [], objects: sink.objects, identity: identityOf(html, sink) };
|
|
9811
|
+
}
|
|
9812
|
+
/** The html with each token replaced by its object, so an unchanged render stays unchanged. */
|
|
9813
|
+
function identityOf(html, sink) {
|
|
9814
|
+
let identity = html;
|
|
9815
|
+
sink.objects.forEach((value, token) => {
|
|
9816
|
+
let written;
|
|
9817
|
+
try {
|
|
9818
|
+
written = JSON.stringify(value) ?? '';
|
|
9819
|
+
}
|
|
9820
|
+
catch {
|
|
9821
|
+
written = token.substring(sink.prefix.length);
|
|
9822
|
+
}
|
|
9823
|
+
identity = identity.split(token).join(written);
|
|
9824
|
+
});
|
|
9825
|
+
return identity;
|
|
9826
|
+
}
|
|
9827
|
+
function nonce() {
|
|
9828
|
+
return typeof crypto !== 'undefined' && crypto.randomUUID
|
|
9829
|
+
? crypto.randomUUID()
|
|
9830
|
+
: String(Math.random()).substring(2);
|
|
9746
9831
|
}
|
|
9747
9832
|
/** Walks a dot-path; a missing, null or non-object step anywhere gives undefined. */
|
|
9748
9833
|
function lookupPath(scope, path) {
|
|
@@ -9823,6 +9908,9 @@ function parse(template) {
|
|
|
9823
9908
|
...(path === '.' ? { parents: 0, path } : parsePath(path, tag, open)),
|
|
9824
9909
|
pipes: pipe < 0 ? [] : parsePipes(content.substring(pipe + 1), tag),
|
|
9825
9910
|
tag,
|
|
9911
|
+
resource: pipe < 0 &&
|
|
9912
|
+
template[end + 2] === '"' &&
|
|
9913
|
+
ICON_ATTRIBUTE.test(template.substring(pos, start)),
|
|
9826
9914
|
});
|
|
9827
9915
|
}
|
|
9828
9916
|
pos = end + 2;
|
|
@@ -9909,38 +9997,38 @@ function skipSpaces(s, i) {
|
|
|
9909
9997
|
* `scopes` holds one entry per open entering section above the root scope, the innermost last;
|
|
9910
9998
|
* the parser has already checked that no `../` reaches below its bottom.
|
|
9911
9999
|
*/
|
|
9912
|
-
function render(nodes, scopes, ctx, out) {
|
|
10000
|
+
function render(nodes, scopes, ctx, out, sink) {
|
|
9913
10001
|
const scope = scopes[scopes.length - 1];
|
|
9914
10002
|
for (const node of nodes) {
|
|
9915
10003
|
if (node.kind === 'text') {
|
|
9916
10004
|
out.push(node.text);
|
|
9917
10005
|
}
|
|
9918
10006
|
else if (node.kind === 'value') {
|
|
9919
|
-
out.push(renderValue(node, scopes, ctx));
|
|
10007
|
+
out.push(renderValue(node, scopes, ctx, sink));
|
|
9920
10008
|
}
|
|
9921
10009
|
else {
|
|
9922
10010
|
const value = lookup(scopes, node);
|
|
9923
10011
|
if (node.sigil === '^') {
|
|
9924
10012
|
if (!truthy(value)) {
|
|
9925
|
-
render(node.children, scopes, ctx, out);
|
|
10013
|
+
render(node.children, scopes, ctx, out, sink);
|
|
9926
10014
|
}
|
|
9927
10015
|
}
|
|
9928
10016
|
else if (!truthy(value)) {
|
|
9929
10017
|
continue;
|
|
9930
10018
|
}
|
|
9931
10019
|
else if (node.sigil === '?') {
|
|
9932
|
-
render(node.children, scopes, ctx, out);
|
|
10020
|
+
render(node.children, scopes, ctx, out, sink);
|
|
9933
10021
|
}
|
|
9934
10022
|
else if (Array.isArray(value)) {
|
|
9935
|
-
value.forEach((item) => render(node.children, [...scopes, item], ctx, out));
|
|
10023
|
+
value.forEach((item) => render(node.children, [...scopes, item], ctx, out, sink));
|
|
9936
10024
|
}
|
|
9937
10025
|
else if (typeof value === 'object') {
|
|
9938
|
-
render(node.children, [...scopes, value], ctx, out);
|
|
10026
|
+
render(node.children, [...scopes, value], ctx, out, sink);
|
|
9939
10027
|
}
|
|
9940
10028
|
else {
|
|
9941
10029
|
ctx.warn(`{{#${node.source}}} entered a single value; use {{?${node.source}}} to guard on it`);
|
|
9942
10030
|
// Still a level, so `../` inside counts the same as the server's field derivation does.
|
|
9943
|
-
render(node.children, [...scopes, scope], ctx, out);
|
|
10031
|
+
render(node.children, [...scopes, scope], ctx, out, sink);
|
|
9944
10032
|
}
|
|
9945
10033
|
}
|
|
9946
10034
|
}
|
|
@@ -9948,7 +10036,7 @@ function render(nodes, scopes, ctx, out) {
|
|
|
9948
10036
|
function lookup(scopes, path) {
|
|
9949
10037
|
return lookupPath(scopes[scopes.length - 1 - path.parents], path.path);
|
|
9950
10038
|
}
|
|
9951
|
-
function renderValue(node, scopes, ctx) {
|
|
10039
|
+
function renderValue(node, scopes, ctx, sink) {
|
|
9952
10040
|
let value = node.path === '.' ? scopes[scopes.length - 1] : lookup(scopes, node);
|
|
9953
10041
|
for (const pipe of node.pipes) {
|
|
9954
10042
|
// Own names only: `constructor` and the like must not reach Object.prototype.
|
|
@@ -9963,6 +10051,12 @@ function renderValue(node, scopes, ctx) {
|
|
|
9963
10051
|
return '';
|
|
9964
10052
|
}
|
|
9965
10053
|
if (typeof value === 'object') {
|
|
10054
|
+
// An icon slot takes an image resource as it stands; everywhere else an object is nothing.
|
|
10055
|
+
if (node.resource && !Array.isArray(value)) {
|
|
10056
|
+
const token = `${sink.prefix}${sink.objects.size}`;
|
|
10057
|
+
sink.objects.set(token, value);
|
|
10058
|
+
return token;
|
|
10059
|
+
}
|
|
9966
10060
|
ctx.warn(`${node.tag} names an object or a list, rendered empty`);
|
|
9967
10061
|
return '';
|
|
9968
10062
|
}
|
|
@@ -10203,17 +10297,23 @@ function injectSmartHtmlRenderer(container) {
|
|
|
10203
10297
|
untracked(() => triggers.mark());
|
|
10204
10298
|
}, /* @ts-ignore */
|
|
10205
10299
|
...(ngDevMode ? [{ debugName: "marking" }] : /* istanbul ignore next */ []));
|
|
10206
|
-
const
|
|
10300
|
+
const destroyHydrated = () => {
|
|
10207
10301
|
refs.forEach((ref) => ref.destroy());
|
|
10208
10302
|
refs = [];
|
|
10209
10303
|
};
|
|
10210
|
-
const write = (
|
|
10211
|
-
current =
|
|
10212
|
-
// Rewriting the html does not destroy the toolbars hydrated into it.
|
|
10213
|
-
|
|
10304
|
+
const write = (resolved) => {
|
|
10305
|
+
current = resolved;
|
|
10306
|
+
// Rewriting the html does not destroy the toolbars and icons hydrated into it.
|
|
10307
|
+
destroyHydrated();
|
|
10214
10308
|
// Trusted as authored by the backend; every value the resolver put in is escaped.
|
|
10215
|
-
container.innerHTML = html;
|
|
10216
|
-
refs =
|
|
10309
|
+
container.innerHTML = resolved.html;
|
|
10310
|
+
refs = [
|
|
10311
|
+
...hydrateToolbars(container, hydration),
|
|
10312
|
+
...hydrateIcons(container, hydration, {
|
|
10313
|
+
dictionary: resolved.icons,
|
|
10314
|
+
objects: resolved.objects,
|
|
10315
|
+
}),
|
|
10316
|
+
];
|
|
10217
10317
|
triggers.mark();
|
|
10218
10318
|
};
|
|
10219
10319
|
const cancelLeave = () => {
|
|
@@ -10222,7 +10322,7 @@ function injectSmartHtmlRenderer(container) {
|
|
|
10222
10322
|
container.classList.remove(LEAVING_CLASS);
|
|
10223
10323
|
};
|
|
10224
10324
|
/** Plays what the style sheets give the leaving class, then writes the latest pending html. */
|
|
10225
|
-
const leaveThenWrite = (
|
|
10325
|
+
const leaveThenWrite = (resolved) => {
|
|
10226
10326
|
// Only what the class starts counts; an entry or endless animation already running does not.
|
|
10227
10327
|
const running = new Set(container.getAnimations({ subtree: true }));
|
|
10228
10328
|
container.classList.add(LEAVING_CLASS);
|
|
@@ -10231,10 +10331,10 @@ function injectSmartHtmlRenderer(container) {
|
|
|
10231
10331
|
.filter((animation) => !running.has(animation));
|
|
10232
10332
|
if (!leaving.length) {
|
|
10233
10333
|
container.classList.remove(LEAVING_CLASS);
|
|
10234
|
-
write(
|
|
10334
|
+
write(resolved);
|
|
10235
10335
|
return;
|
|
10236
10336
|
}
|
|
10237
|
-
pending =
|
|
10337
|
+
pending = resolved;
|
|
10238
10338
|
const token = ++leave;
|
|
10239
10339
|
Promise.race([
|
|
10240
10340
|
Promise.allSettled(leaving.map((animation) => animation.finished)),
|
|
@@ -10253,30 +10353,32 @@ function injectSmartHtmlRenderer(container) {
|
|
|
10253
10353
|
// the action list the triggers read.
|
|
10254
10354
|
render: (newTemplate, context) => untracked(() => {
|
|
10255
10355
|
template = newTemplate;
|
|
10256
|
-
const
|
|
10356
|
+
const result = resolveTemplate(template, context.data, {
|
|
10257
10357
|
valueSets: context.valueSets,
|
|
10258
10358
|
locale: locale(),
|
|
10259
10359
|
warn,
|
|
10260
10360
|
});
|
|
10261
|
-
|
|
10361
|
+
const resolved = { ...result, icons: context.icons };
|
|
10362
|
+
result.errors.forEach((error) => report(`the html is left unresolved: ${error}`, console.error));
|
|
10363
|
+
const unchanged = resolved.identity === current?.identity;
|
|
10262
10364
|
if (pending !== undefined) {
|
|
10263
10365
|
// Mid-leave the latest html wins; back to the one on screen, nothing leaves after all.
|
|
10264
|
-
if (
|
|
10366
|
+
if (unchanged) {
|
|
10265
10367
|
cancelLeave();
|
|
10266
10368
|
}
|
|
10267
10369
|
else {
|
|
10268
|
-
pending =
|
|
10370
|
+
pending = resolved;
|
|
10269
10371
|
}
|
|
10270
10372
|
return;
|
|
10271
10373
|
}
|
|
10272
|
-
if (
|
|
10374
|
+
if (unchanged) {
|
|
10273
10375
|
return;
|
|
10274
10376
|
}
|
|
10275
10377
|
if (current === undefined) {
|
|
10276
|
-
write(
|
|
10378
|
+
write(resolved);
|
|
10277
10379
|
return;
|
|
10278
10380
|
}
|
|
10279
|
-
leaveThenWrite(
|
|
10381
|
+
leaveThenWrite(resolved);
|
|
10280
10382
|
}),
|
|
10281
10383
|
useCss: (newCss) => {
|
|
10282
10384
|
const next = newCss || undefined;
|
|
@@ -10291,7 +10393,7 @@ function injectSmartHtmlRenderer(container) {
|
|
|
10291
10393
|
disposed = true;
|
|
10292
10394
|
releaseCss();
|
|
10293
10395
|
marking.destroy();
|
|
10294
|
-
|
|
10396
|
+
destroyHydrated();
|
|
10295
10397
|
triggers.dispose();
|
|
10296
10398
|
},
|
|
10297
10399
|
};
|
|
@@ -10319,6 +10421,7 @@ class SmartHtmlWidgetComponent {
|
|
|
10319
10421
|
this.renderer.render(properties?.html ?? '', {
|
|
10320
10422
|
data: this.scope(model?.data, properties?.root, properties?.html),
|
|
10321
10423
|
valueSets: model?.valueSets,
|
|
10424
|
+
icons: properties?.icons,
|
|
10322
10425
|
});
|
|
10323
10426
|
});
|
|
10324
10427
|
}
|
|
@@ -13111,7 +13214,7 @@ class SmartHtmlCellComponent {
|
|
|
13111
13214
|
}
|
|
13112
13215
|
ngOnChanges() {
|
|
13113
13216
|
this.actionHost.actionModels.set(rowActionModels(this.row, this.gridIdentifier));
|
|
13114
|
-
const { html, root, css } = this.template;
|
|
13217
|
+
const { html, root, css, icons } = this.template;
|
|
13115
13218
|
const scope = rootScope(this.row.data, root);
|
|
13116
13219
|
if (scope === undefined && root && this.warnedRoot !== root) {
|
|
13117
13220
|
this.warnedRoot = root;
|
|
@@ -13122,6 +13225,7 @@ class SmartHtmlCellComponent {
|
|
|
13122
13225
|
this.renderer.render(html ?? '', {
|
|
13123
13226
|
data: scope,
|
|
13124
13227
|
valueSets: this.smartComponent?.model?.valueSets,
|
|
13228
|
+
icons,
|
|
13125
13229
|
});
|
|
13126
13230
|
}
|
|
13127
13231
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartHtmlCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
@@ -22468,11 +22572,11 @@ class SmartFilterParamsComponent {
|
|
|
22468
22572
|
}
|
|
22469
22573
|
}
|
|
22470
22574
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartFilterParamsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
22471
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: SmartFilterParamsComponent, isStandalone: true, selector: "smart-filter-group-params", inputs: { service: { classPropertyName: "service", publicName: "service", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "filterVcRef", first: true, predicate: ["smartFilter"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "@if (service().model?.showGroups && !service().model?.readOnly) {\r\n <div\r\n class=\"targetGroupFilterParamsContainer\"\r\n >\r\n <!-- <ng-template #smartFilter></ng-template> -->\r\n <!-- <div class=\"dataSource-options\" *ngIf=\"service.model?.extarnalDatabase\">\r\n <div class=\"dataSource-btns\">\r\n <div class=\"dataSource-btn\">K\u00FCls\u0151 adatb\u00E1zis</div>\r\n <div class=\"dataSource-btn dataSource-btn-disabled\">Bels\u0151 adatb\u00E1zis</div>\r\n </div>\r\n <div class=\"dataSource-add-database\">\r\n <div class=\"dataSource-add-database-title\">\r\n <smart-icon icon=\"Ic24_View_Table\" color=\"sucess\"></smart-icon>\r\n Adatb\u00E1zis\r\n </div>\r\n <button title=\"add\" mat-icon-button (click)=\"addDataSource()\">\r\n <smart-icon icon=\"Ic24_Plus_Circle\" color=\"success\"></smart-icon>\r\n </button>\r\n </div>\r\n </div> -->\r\n <div class=\"sections\">\r\n @if (expandableSectionsFromExcel) {\r\n <smart-expandable-section\r\n class=\"excel\"\r\n [data]=\"expandableSectionsFromExcel!\"\r\n ></smart-expandable-section>\r\n }\r\n @for (data of expandableSections; track data) {\r\n <smart-expandable-section\r\n [data]=\"data\"\r\n ></smart-expandable-section>\r\n }\r\n </div>\r\n</div>\r\n}\r\n", styles: [".targetGroupFilterParamsContainer{padding:1.5rem;display:flex;flex-direction:column;gap:2.5rem;height:calc(100% - 3rem);overflow:auto;border-right:2px solid var(--primary-dark-color)}.sections{display:flex;flex-direction:column;gap:.25rem}.targetGroupFilterParamsContainer .excel::ng-deep .mat-expansion-panel-body{background-color:var(--success-lighter-color)}.targetGroupFilterParamsContainer .excel::ng-deep .mat-expansion-panel-header.mat-expanded{background-color:var(--success-color)!important}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-body{padding:0 0 0 1rem!important;background-color:var(--light-blue-color)}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-header{background-color:var(--primary-light-color);padding:.75rem;height:auto}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-header-title{color:var(--primary-lighter-color);font-weight:600}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-header.mat-expanded{background-color:var(--accent-color)!important;padding:.75rem;height:auto}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-header.mat-expanded .mat-expansion-panel-header-title{color
|
|
22575
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: SmartFilterParamsComponent, isStandalone: true, selector: "smart-filter-group-params", inputs: { service: { classPropertyName: "service", publicName: "service", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "filterVcRef", first: true, predicate: ["smartFilter"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "@if (service().model?.showGroups && !service().model?.readOnly) {\r\n <div\r\n class=\"targetGroupFilterParamsContainer\"\r\n >\r\n <!-- <ng-template #smartFilter></ng-template> -->\r\n <!-- <div class=\"dataSource-options\" *ngIf=\"service.model?.extarnalDatabase\">\r\n <div class=\"dataSource-btns\">\r\n <div class=\"dataSource-btn\">K\u00FCls\u0151 adatb\u00E1zis</div>\r\n <div class=\"dataSource-btn dataSource-btn-disabled\">Bels\u0151 adatb\u00E1zis</div>\r\n </div>\r\n <div class=\"dataSource-add-database\">\r\n <div class=\"dataSource-add-database-title\">\r\n <smart-icon icon=\"Ic24_View_Table\" color=\"sucess\"></smart-icon>\r\n Adatb\u00E1zis\r\n </div>\r\n <button title=\"add\" mat-icon-button (click)=\"addDataSource()\">\r\n <smart-icon icon=\"Ic24_Plus_Circle\" color=\"success\"></smart-icon>\r\n </button>\r\n </div>\r\n </div> -->\r\n <div class=\"sections\">\r\n @if (expandableSectionsFromExcel) {\r\n <smart-expandable-section\r\n class=\"excel\"\r\n [data]=\"expandableSectionsFromExcel!\"\r\n ></smart-expandable-section>\r\n }\r\n @for (data of expandableSections; track data) {\r\n <smart-expandable-section\r\n [data]=\"data\"\r\n ></smart-expandable-section>\r\n }\r\n </div>\r\n</div>\r\n}\r\n", styles: [".targetGroupFilterParamsContainer{padding:1.5rem;display:flex;flex-direction:column;gap:2.5rem;height:calc(100% - 3rem);overflow:auto;border-right:2px solid var(--primary-dark-color)}.sections{display:flex;flex-direction:column;gap:.25rem}.targetGroupFilterParamsContainer .excel::ng-deep .mat-expansion-panel-body{background-color:var(--success-lighter-color)}.targetGroupFilterParamsContainer .excel::ng-deep .mat-expansion-panel-header.mat-expanded{background-color:var(--success-color)!important}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-body{padding:0 0 0 1rem!important;background-color:var(--light-blue-color)}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-header{background-color:var(--primary-light-color);padding:.75rem;height:auto}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-header-title{color:var(--primary-lighter-color);font-weight:600}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-header.mat-expanded{background-color:var(--sb4-expansion-panel-expanded-bg-color, var(--accent-color))!important;padding:.75rem;height:auto}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-header.mat-expanded .mat-expansion-panel-header-title{color:var(--sb4-expansion-panel-expanded-title-color, #fff)!important}.dataSource-btns{display:flex;flex-direction:row;justify-content:space-around;background-color:var(--success-lighter-color);height:44px;padding:8px 12px;align-items:center;border:1.5px solid var(--success-color);border-left:6px solid var(--success-color);border-radius:4px}.dataSource-btn{display:flex;padding:1rem 2rem;justify-content:center;align-items:center;background-color:var(--success-color);border-radius:4px;cursor:pointer}.dataSource-btn-disabled{background-color:var(--success-lighter-color);cursor:auto}.dataSource-add-database{display:flex;flex-direction:row;justify-content:space-between;background-color:var(--success-lighter-color);padding:8px;border-radius:4px}.dataSource-add-database-title{display:flex;flex-direction:row;gap:1rem;align-items:center}.dataSource-options{display:flex;flex-direction:column;gap:1rem}\n"], dependencies: [{ kind: "component", type: ExpandableSectionComponent, selector: "smart-expandable-section", inputs: ["data", "index"] }] }); }
|
|
22472
22576
|
}
|
|
22473
22577
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartFilterParamsComponent, decorators: [{
|
|
22474
22578
|
type: Component,
|
|
22475
|
-
args: [{ selector: 'smart-filter-group-params', imports: [ExpandableSectionComponent], template: "@if (service().model?.showGroups && !service().model?.readOnly) {\r\n <div\r\n class=\"targetGroupFilterParamsContainer\"\r\n >\r\n <!-- <ng-template #smartFilter></ng-template> -->\r\n <!-- <div class=\"dataSource-options\" *ngIf=\"service.model?.extarnalDatabase\">\r\n <div class=\"dataSource-btns\">\r\n <div class=\"dataSource-btn\">K\u00FCls\u0151 adatb\u00E1zis</div>\r\n <div class=\"dataSource-btn dataSource-btn-disabled\">Bels\u0151 adatb\u00E1zis</div>\r\n </div>\r\n <div class=\"dataSource-add-database\">\r\n <div class=\"dataSource-add-database-title\">\r\n <smart-icon icon=\"Ic24_View_Table\" color=\"sucess\"></smart-icon>\r\n Adatb\u00E1zis\r\n </div>\r\n <button title=\"add\" mat-icon-button (click)=\"addDataSource()\">\r\n <smart-icon icon=\"Ic24_Plus_Circle\" color=\"success\"></smart-icon>\r\n </button>\r\n </div>\r\n </div> -->\r\n <div class=\"sections\">\r\n @if (expandableSectionsFromExcel) {\r\n <smart-expandable-section\r\n class=\"excel\"\r\n [data]=\"expandableSectionsFromExcel!\"\r\n ></smart-expandable-section>\r\n }\r\n @for (data of expandableSections; track data) {\r\n <smart-expandable-section\r\n [data]=\"data\"\r\n ></smart-expandable-section>\r\n }\r\n </div>\r\n</div>\r\n}\r\n", styles: [".targetGroupFilterParamsContainer{padding:1.5rem;display:flex;flex-direction:column;gap:2.5rem;height:calc(100% - 3rem);overflow:auto;border-right:2px solid var(--primary-dark-color)}.sections{display:flex;flex-direction:column;gap:.25rem}.targetGroupFilterParamsContainer .excel::ng-deep .mat-expansion-panel-body{background-color:var(--success-lighter-color)}.targetGroupFilterParamsContainer .excel::ng-deep .mat-expansion-panel-header.mat-expanded{background-color:var(--success-color)!important}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-body{padding:0 0 0 1rem!important;background-color:var(--light-blue-color)}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-header{background-color:var(--primary-light-color);padding:.75rem;height:auto}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-header-title{color:var(--primary-lighter-color);font-weight:600}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-header.mat-expanded{background-color:var(--accent-color)!important;padding:.75rem;height:auto}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-header.mat-expanded .mat-expansion-panel-header-title{color
|
|
22579
|
+
args: [{ selector: 'smart-filter-group-params', imports: [ExpandableSectionComponent], template: "@if (service().model?.showGroups && !service().model?.readOnly) {\r\n <div\r\n class=\"targetGroupFilterParamsContainer\"\r\n >\r\n <!-- <ng-template #smartFilter></ng-template> -->\r\n <!-- <div class=\"dataSource-options\" *ngIf=\"service.model?.extarnalDatabase\">\r\n <div class=\"dataSource-btns\">\r\n <div class=\"dataSource-btn\">K\u00FCls\u0151 adatb\u00E1zis</div>\r\n <div class=\"dataSource-btn dataSource-btn-disabled\">Bels\u0151 adatb\u00E1zis</div>\r\n </div>\r\n <div class=\"dataSource-add-database\">\r\n <div class=\"dataSource-add-database-title\">\r\n <smart-icon icon=\"Ic24_View_Table\" color=\"sucess\"></smart-icon>\r\n Adatb\u00E1zis\r\n </div>\r\n <button title=\"add\" mat-icon-button (click)=\"addDataSource()\">\r\n <smart-icon icon=\"Ic24_Plus_Circle\" color=\"success\"></smart-icon>\r\n </button>\r\n </div>\r\n </div> -->\r\n <div class=\"sections\">\r\n @if (expandableSectionsFromExcel) {\r\n <smart-expandable-section\r\n class=\"excel\"\r\n [data]=\"expandableSectionsFromExcel!\"\r\n ></smart-expandable-section>\r\n }\r\n @for (data of expandableSections; track data) {\r\n <smart-expandable-section\r\n [data]=\"data\"\r\n ></smart-expandable-section>\r\n }\r\n </div>\r\n</div>\r\n}\r\n", styles: [".targetGroupFilterParamsContainer{padding:1.5rem;display:flex;flex-direction:column;gap:2.5rem;height:calc(100% - 3rem);overflow:auto;border-right:2px solid var(--primary-dark-color)}.sections{display:flex;flex-direction:column;gap:.25rem}.targetGroupFilterParamsContainer .excel::ng-deep .mat-expansion-panel-body{background-color:var(--success-lighter-color)}.targetGroupFilterParamsContainer .excel::ng-deep .mat-expansion-panel-header.mat-expanded{background-color:var(--success-color)!important}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-body{padding:0 0 0 1rem!important;background-color:var(--light-blue-color)}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-header{background-color:var(--primary-light-color);padding:.75rem;height:auto}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-header-title{color:var(--primary-lighter-color);font-weight:600}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-header.mat-expanded{background-color:var(--sb4-expansion-panel-expanded-bg-color, var(--accent-color))!important;padding:.75rem;height:auto}.targetGroupFilterParamsContainer::ng-deep .mat-expansion-panel-header.mat-expanded .mat-expansion-panel-header-title{color:var(--sb4-expansion-panel-expanded-title-color, #fff)!important}.dataSource-btns{display:flex;flex-direction:row;justify-content:space-around;background-color:var(--success-lighter-color);height:44px;padding:8px 12px;align-items:center;border:1.5px solid var(--success-color);border-left:6px solid var(--success-color);border-radius:4px}.dataSource-btn{display:flex;padding:1rem 2rem;justify-content:center;align-items:center;background-color:var(--success-color);border-radius:4px;cursor:pointer}.dataSource-btn-disabled{background-color:var(--success-lighter-color);cursor:auto}.dataSource-add-database{display:flex;flex-direction:row;justify-content:space-between;background-color:var(--success-lighter-color);padding:8px;border-radius:4px}.dataSource-add-database-title{display:flex;flex-direction:row;gap:1rem;align-items:center}.dataSource-options{display:flex;flex-direction:column;gap:1rem}\n"] }]
|
|
22476
22580
|
}], ctorParameters: () => [], propDecorators: { service: [{ type: i0.Input, args: [{ isSignal: true, alias: "service", required: true }] }], filterVcRef: [{
|
|
22477
22581
|
type: ViewChild,
|
|
22478
22582
|
args: ['smartFilter', { read: ViewContainerRef }]
|