@decaf-ts/for-angular 0.0.46 → 0.0.48
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 +1 -1
- package/fesm2022/decaf-ts-for-angular.mjs +697 -410
- package/fesm2022/decaf-ts-for-angular.mjs.map +1 -1
- package/index.d.ts +155 -238
- package/package.json +3 -4
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { HTML5InputTypes, parseValueByType, HTML5CheckTypes, escapeHtml, parseToNumber, RenderingEngine, DecafComponent, UIKeys, RenderingError, UIMediaBreakPoints, DecafEventHandler } from '@decaf-ts/ui-decorators';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
3
|
import { InjectionToken, NgModule, isDevMode, reflectComponentType, Injector, createEnvironmentInjector, runInInjectionContext, createComponent, inject, NgZone, Injectable, ChangeDetectorRef, Renderer2, EventEmitter, ElementRef, Input, Output, ViewChild, Inject, Directive, EnvironmentInjector, ViewContainerRef, TemplateRef, Component, HostListener, CUSTOM_ELEMENTS_SCHEMA, ViewEncapsulation } from '@angular/core';
|
|
4
4
|
import * as i1$1 from '@angular/common';
|
|
5
5
|
import { CommonModule, Location, NgComponentOutlet } from '@angular/common';
|
|
6
6
|
import { VALIDATION_PARENT_KEY, ValidationKeys, DEFAULT_PATTERNS, Validation, Primitives, ComparisonValidationKeys, PathProxyEngine, Model, ModelKeys, isValidDate as isValidDate$1, parseDate, sf, ReservedModels } from '@decaf-ts/decorator-validation';
|
|
7
|
-
import {
|
|
7
|
+
import { OperationKeys, InternalError, NotFoundError } from '@decaf-ts/db-decorators';
|
|
8
8
|
import * as i1 from '@angular/forms';
|
|
9
9
|
import { FormGroup, FormControl, FormsModule, ReactiveFormsModule, FormArray, AbstractControl, Validators } from '@angular/forms';
|
|
10
10
|
import { InjectableRegistryImp } from '@decaf-ts/injectable-decorators';
|
|
11
11
|
import { TranslateModule, TranslatePipe, TranslateParser, provideTranslateService, TranslateLoader, provideTranslateParser, TranslateService } from '@ngx-translate/core';
|
|
12
|
-
import { Logging
|
|
13
|
-
import {
|
|
12
|
+
import { Logging } from '@decaf-ts/logging';
|
|
13
|
+
import { Repository, OrderDirection, Condition } from '@decaf-ts/core';
|
|
14
|
+
import { uses, Metadata, apply, metadata } from '@decaf-ts/decoration';
|
|
14
15
|
import { faker } from '@faker-js/faker';
|
|
15
16
|
import { Router, NavigationEnd, NavigationStart } from '@angular/router';
|
|
16
17
|
import { forkJoin, Subject, BehaviorSubject, fromEvent, merge, of, Observable, timer, firstValueFrom, debounceTime } from 'rxjs';
|
|
@@ -21,7 +22,6 @@ import { IonModal, IonSpinner, IonButton, IonButtons, IonContent, IonHeader, Ion
|
|
|
21
22
|
import { addIcons } from 'ionicons';
|
|
22
23
|
import * as allIcons from 'ionicons/icons';
|
|
23
24
|
import { chevronUpOutline, chevronDownOutline, createOutline, trashOutline, addOutline, alertCircleOutline, arrowUpOutline, arrowDownOutline, searchOutline, closeOutline, chevronForwardOutline, chevronBackOutline, arrowBackOutline, arrowForwardOutline } from 'ionicons/icons';
|
|
24
|
-
import { apply, metadata } from '@decaf-ts/reflection';
|
|
25
25
|
import { DomSanitizer, Title } from '@angular/platform-browser';
|
|
26
26
|
import { MenuController } from '@ionic/angular';
|
|
27
27
|
|
|
@@ -50,7 +50,7 @@ import { MenuController } from '@ionic/angular';
|
|
|
50
50
|
* @memberOf module:lib/engine/constants
|
|
51
51
|
*/
|
|
52
52
|
const AngularEngineKeys = {
|
|
53
|
-
REFLECT:
|
|
53
|
+
REFLECT: `angular`,
|
|
54
54
|
DYNAMIC: 'dynamic-component',
|
|
55
55
|
ANNOTATIONS: '__annotations__',
|
|
56
56
|
ECMP: 'ecmp',
|
|
@@ -63,9 +63,9 @@ const AngularEngineKeys = {
|
|
|
63
63
|
RENDERED_ID: 'rendered-as-{0}',
|
|
64
64
|
PARENT: '_parent',
|
|
65
65
|
VALIDATION_PARENT_KEY: VALIDATION_PARENT_KEY,
|
|
66
|
-
FLAVOUR:
|
|
66
|
+
FLAVOUR: 'angular',
|
|
67
67
|
LOADED: 'engineLoaded',
|
|
68
|
-
DARK_PALETTE_CLASS: 'dcf-palette-dark'
|
|
68
|
+
DARK_PALETTE_CLASS: 'dcf-palette-dark',
|
|
69
69
|
};
|
|
70
70
|
/**
|
|
71
71
|
* @description Form validation state constants.
|
|
@@ -138,7 +138,6 @@ var LoggerLevels;
|
|
|
138
138
|
LoggerLevels[LoggerLevels["ERROR"] = 4] = "ERROR";
|
|
139
139
|
LoggerLevels[LoggerLevels["CRITICAL"] = 5] = "CRITICAL";
|
|
140
140
|
})(LoggerLevels || (LoggerLevels = {}));
|
|
141
|
-
;
|
|
142
141
|
/**
|
|
143
142
|
* @description Route direction constants.
|
|
144
143
|
* @summary Defines the possible navigation directions in the application.
|
|
@@ -294,10 +293,10 @@ const DefaultListEmptyOptions = {
|
|
|
294
293
|
showButton: false,
|
|
295
294
|
icon: 'folder-open-outline',
|
|
296
295
|
buttonText: 'locale.empty.button',
|
|
297
|
-
link: ''
|
|
296
|
+
link: '',
|
|
298
297
|
};
|
|
299
298
|
const DefaultModalOptions = {
|
|
300
|
-
component:
|
|
299
|
+
component: '',
|
|
301
300
|
showBackdrop: true,
|
|
302
301
|
backdropDismiss: false,
|
|
303
302
|
animated: true,
|
|
@@ -310,12 +309,12 @@ const ActionRoles = {
|
|
|
310
309
|
confirm: 'confirm',
|
|
311
310
|
submit: 'submit',
|
|
312
311
|
clear: 'clear',
|
|
313
|
-
back: 'back'
|
|
312
|
+
back: 'back',
|
|
314
313
|
};
|
|
315
314
|
const WindowColorSchemes = {
|
|
316
315
|
light: 'light',
|
|
317
316
|
dark: 'dark',
|
|
318
|
-
undefined: 'undefined'
|
|
317
|
+
undefined: 'undefined',
|
|
319
318
|
};
|
|
320
319
|
const ElementSizes = {
|
|
321
320
|
xsmall: 'xsmall',
|
|
@@ -341,7 +340,7 @@ const LayoutGridGaps = {
|
|
|
341
340
|
medium: 'medium',
|
|
342
341
|
large: 'large',
|
|
343
342
|
collapse: 'collapse',
|
|
344
|
-
none: ''
|
|
343
|
+
none: '',
|
|
345
344
|
};
|
|
346
345
|
const ListItemPositions = {
|
|
347
346
|
uid: 'uid',
|
|
@@ -511,7 +510,10 @@ const LOCALE_ROOT_TOKEN = new InjectionToken('LOCALE_ROOT_TOKEN');
|
|
|
511
510
|
* // Inject any arbitrary value
|
|
512
511
|
* { provide: CPTKN, useValue: { key: 'value', data: [1, 2, 3] } }
|
|
513
512
|
*/
|
|
514
|
-
const CPTKN = new InjectionToken('CPTKN', {
|
|
513
|
+
const CPTKN = new InjectionToken('CPTKN', {
|
|
514
|
+
providedIn: 'root',
|
|
515
|
+
factory: () => '',
|
|
516
|
+
});
|
|
515
517
|
/**
|
|
516
518
|
* @description Injection token for i18n resource configuration.
|
|
517
519
|
* @summary Used to provide configuration for internationalization resources, including
|
|
@@ -549,29 +551,35 @@ function provideDynamicComponents(...components) {
|
|
|
549
551
|
* @memberOf module:lib/for-angular-common.module
|
|
550
552
|
* @example
|
|
551
553
|
* // Get repository by model class
|
|
552
|
-
* const userRepo =
|
|
554
|
+
* const userRepo = getModelAndRepository(User);
|
|
553
555
|
*
|
|
554
556
|
* // Get repository by model name
|
|
555
|
-
* const productRepo =
|
|
557
|
+
* const productRepo = getModelAndRepository('Product');
|
|
556
558
|
*
|
|
557
559
|
* // Use repository for queries
|
|
558
560
|
* const users = await userRepo.findAll();
|
|
559
561
|
*/
|
|
560
|
-
function
|
|
562
|
+
function getModelAndRepository(model) {
|
|
561
563
|
try {
|
|
562
|
-
const modelName = (typeof model === Primitives.STRING
|
|
563
|
-
|
|
564
|
+
const modelName = (typeof model === Primitives.STRING
|
|
565
|
+
? model
|
|
566
|
+
: model.constructor.name);
|
|
567
|
+
const constructor = Model.get((modelName.charAt(0).toUpperCase() + modelName.slice(1)));
|
|
564
568
|
if (!constructor)
|
|
565
|
-
|
|
569
|
+
return undefined;
|
|
566
570
|
const dbAdapterFlavour = getOnWindow(DB_ADAPTER_PROVIDER) || undefined;
|
|
567
571
|
if (dbAdapterFlavour)
|
|
568
572
|
uses(dbAdapterFlavour)(constructor);
|
|
569
|
-
const
|
|
573
|
+
const repository = Repository.forModel(constructor);
|
|
570
574
|
model = new constructor();
|
|
571
|
-
|
|
575
|
+
const pk = Model.pk(repository.class);
|
|
576
|
+
if (!pk)
|
|
577
|
+
return undefined;
|
|
578
|
+
return { repository, model, pk };
|
|
572
579
|
}
|
|
573
580
|
catch (error) {
|
|
574
|
-
|
|
581
|
+
getLogger(getModelAndRepository).warn(error?.message || error);
|
|
582
|
+
return undefined;
|
|
575
583
|
}
|
|
576
584
|
}
|
|
577
585
|
/**
|
|
@@ -596,13 +604,12 @@ function getModelRepository(model) {
|
|
|
596
604
|
* provideDbAdapter(PostgresAdapter, { host: 'localhost', port: 5432 })
|
|
597
605
|
* ]
|
|
598
606
|
*/
|
|
599
|
-
function provideDbAdapter(
|
|
600
|
-
const adapter = new
|
|
607
|
+
function provideDbAdapter(clazz, options = {}, flavour) {
|
|
608
|
+
const adapter = new clazz(options);
|
|
601
609
|
if (flavour)
|
|
602
610
|
flavour = adapter.flavour;
|
|
603
|
-
// Log and expose adapter flavour globally
|
|
604
611
|
getLogger(provideDbAdapter).info(`Using ${adapter.constructor.name} ${flavour} as Db Provider`);
|
|
605
|
-
|
|
612
|
+
setOnWindow(DB_ADAPTER_PROVIDER, flavour);
|
|
606
613
|
return {
|
|
607
614
|
provide: DB_ADAPTER_PROVIDER_TOKEN,
|
|
608
615
|
useValue: adapter,
|
|
@@ -614,7 +621,7 @@ function provideDbAdapter(adapterClass, options = {}, flavour) {
|
|
|
614
621
|
* @description Base logger instance for the for-angular module.
|
|
615
622
|
* @memberOf module:lib/for-angular-common.module
|
|
616
623
|
*/
|
|
617
|
-
const log = Logging.for(
|
|
624
|
+
const log = Logging.for('for-angular');
|
|
618
625
|
/**
|
|
619
626
|
* @description Retrieves a logger instance for the given context.
|
|
620
627
|
* @summary Creates or retrieves a namespaced logger instance using the Decaf logging system.
|
|
@@ -640,7 +647,7 @@ const CommonModules = [
|
|
|
640
647
|
FormsModule,
|
|
641
648
|
ReactiveFormsModule,
|
|
642
649
|
TranslateModule,
|
|
643
|
-
TranslatePipe
|
|
650
|
+
TranslatePipe,
|
|
644
651
|
];
|
|
645
652
|
/**
|
|
646
653
|
* @description Main Angular module for the Decaf framework.
|
|
@@ -1416,6 +1423,7 @@ class NgxFormService {
|
|
|
1416
1423
|
partFormGroup[BaseComponentProps.FORM_GROUP_COMPONENT_PROPS] = {
|
|
1417
1424
|
childOf: childOf || '',
|
|
1418
1425
|
isMultiple: isMultiple,
|
|
1426
|
+
required: parentProps?.required ?? false,
|
|
1419
1427
|
name: part,
|
|
1420
1428
|
pk,
|
|
1421
1429
|
[ModelKeys.MODEL]: {},
|
|
@@ -1963,13 +1971,27 @@ class NgxFormService {
|
|
|
1963
1971
|
if (control instanceof FormArray) {
|
|
1964
1972
|
const totalGroups = control.length;
|
|
1965
1973
|
const hasValid = control.controls.some(control => control.valid);
|
|
1966
|
-
|
|
1974
|
+
const parentProps = control[BaseComponentProps.FORM_GROUP_COMPONENT_PROPS] || {};
|
|
1975
|
+
const childControl = control.at(0);
|
|
1976
|
+
if (totalGroups === 1) {
|
|
1977
|
+
const parent = childControl.parent;
|
|
1978
|
+
if (!parentProps.required) {
|
|
1979
|
+
parent.setErrors(null);
|
|
1980
|
+
parent.updateValueAndValidity({ emitEvent: true });
|
|
1981
|
+
childControl.disable();
|
|
1982
|
+
}
|
|
1983
|
+
else {
|
|
1984
|
+
this.validateFields(childControl);
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
else if (totalGroups > 1 && hasValid) {
|
|
1967
1988
|
for (let i = control.length - 1; i >= 0; i--) {
|
|
1968
1989
|
const childControl = control.at(i);
|
|
1969
1990
|
// disable no valid groups on array
|
|
1970
1991
|
if (!childControl.valid) {
|
|
1971
|
-
childControl.parent
|
|
1972
|
-
|
|
1992
|
+
const parent = childControl.parent;
|
|
1993
|
+
parent.setErrors(null);
|
|
1994
|
+
parent.updateValueAndValidity({ emitEvent: true });
|
|
1973
1995
|
childControl.disable();
|
|
1974
1996
|
}
|
|
1975
1997
|
else {
|
|
@@ -2169,7 +2191,9 @@ class DecafFakerRepository {
|
|
|
2169
2191
|
}
|
|
2170
2192
|
get repository() {
|
|
2171
2193
|
if (!this._repository) {
|
|
2172
|
-
const modelName = typeof this.model === 'string'
|
|
2194
|
+
const modelName = typeof this.model === 'string'
|
|
2195
|
+
? this.model
|
|
2196
|
+
: this.model.constructor.name;
|
|
2173
2197
|
const constructor = Model.get(modelName);
|
|
2174
2198
|
if (!constructor)
|
|
2175
2199
|
throw new InternalError(`Cannot find model ${modelName}. was it registered with @model?`);
|
|
@@ -2190,23 +2214,23 @@ class DecafFakerRepository {
|
|
|
2190
2214
|
if (!this._repository)
|
|
2191
2215
|
this._repository = this.repository;
|
|
2192
2216
|
}
|
|
2193
|
-
async generateData(
|
|
2194
|
-
const limit =
|
|
2195
|
-
if (!
|
|
2196
|
-
|
|
2197
|
-
if (!
|
|
2198
|
-
|
|
2217
|
+
async generateData(values, key, keyType) {
|
|
2218
|
+
const limit = values ? Object.values(values || {}).length : this.limit;
|
|
2219
|
+
if (!key)
|
|
2220
|
+
key = Model.pk(this.repository.class);
|
|
2221
|
+
if (!keyType)
|
|
2222
|
+
keyType = Metadata.type(this.repository.class, key).name.toLowerCase();
|
|
2199
2223
|
const props = Object.keys(this.model).filter((k) => {
|
|
2200
|
-
if (
|
|
2224
|
+
if (keyType === Primitives.STRING)
|
|
2201
2225
|
return !['updatedBy', 'createdAt', 'createdBy', 'updatedAt'].includes(k);
|
|
2202
|
-
return ![
|
|
2226
|
+
return ![key, 'updatedBy', 'createdAt', 'createdBy', 'updatedAt'].includes(k);
|
|
2203
2227
|
});
|
|
2204
2228
|
const dataProps = {};
|
|
2205
2229
|
for (const prop of props) {
|
|
2206
|
-
const type =
|
|
2207
|
-
switch (
|
|
2230
|
+
const type = Metadata.type(this.repository.class, prop);
|
|
2231
|
+
switch (type.name.toLowerCase()) {
|
|
2208
2232
|
case 'string':
|
|
2209
|
-
dataProps[prop] = () => `${faker.lorem.word()} ${
|
|
2233
|
+
dataProps[prop] = () => `${faker.lorem.word()} ${key === prop ? ' - ' + faker.number.int({ min: 1, max: 200 }) : ''}`;
|
|
2210
2234
|
break;
|
|
2211
2235
|
case 'step':
|
|
2212
2236
|
dataProps[prop] = () => faker.lorem.word();
|
|
@@ -2232,20 +2256,25 @@ class DecafFakerRepository {
|
|
|
2232
2256
|
}
|
|
2233
2257
|
}
|
|
2234
2258
|
const data = getFakerData(limit, dataProps, typeof this.model === 'string' ? this.model : this.model?.constructor.name);
|
|
2235
|
-
if (!
|
|
2259
|
+
if (!values)
|
|
2236
2260
|
return data;
|
|
2237
|
-
const
|
|
2261
|
+
const _values = Object.values(values);
|
|
2238
2262
|
const iterated = [];
|
|
2239
2263
|
function getPkValue(item) {
|
|
2240
|
-
if (
|
|
2241
|
-
const randomIndex = Math.floor(Math.random() *
|
|
2242
|
-
const selected =
|
|
2243
|
-
const value =
|
|
2244
|
-
|
|
2245
|
-
|
|
2264
|
+
if (_values.length > 0) {
|
|
2265
|
+
const randomIndex = Math.floor(Math.random() * _values.length);
|
|
2266
|
+
const selected = _values.splice(randomIndex, 1)[0];
|
|
2267
|
+
const value = keyType === Primitives.STRING
|
|
2268
|
+
? selected
|
|
2269
|
+
: keyType === Primitives.NUMBER
|
|
2270
|
+
? parseToNumber(selected)
|
|
2271
|
+
: keyType === Array.name
|
|
2272
|
+
? [selected]
|
|
2273
|
+
: selected;
|
|
2274
|
+
item[key] = value;
|
|
2246
2275
|
}
|
|
2247
|
-
if (!iterated.includes(item[
|
|
2248
|
-
iterated.push(item[
|
|
2276
|
+
if (!iterated.includes(item[key])) {
|
|
2277
|
+
iterated.push(item[key]);
|
|
2249
2278
|
return item;
|
|
2250
2279
|
}
|
|
2251
2280
|
return undefined;
|
|
@@ -2254,11 +2283,12 @@ class DecafFakerRepository {
|
|
|
2254
2283
|
return data
|
|
2255
2284
|
.map((d) => getPkValue(d))
|
|
2256
2285
|
.filter((item) => {
|
|
2257
|
-
if (!item || uids.has(item[
|
|
2286
|
+
if (!item || uids.has(item[key]) || !item[key] || item[key] === undefined)
|
|
2258
2287
|
return false;
|
|
2259
|
-
uids.add(item[
|
|
2288
|
+
uids.add(item[key]);
|
|
2260
2289
|
return true;
|
|
2261
|
-
})
|
|
2290
|
+
})
|
|
2291
|
+
.filter(Boolean);
|
|
2262
2292
|
}
|
|
2263
2293
|
}
|
|
2264
2294
|
function getFakerData(limit = 100, data, model) {
|
|
@@ -2267,12 +2297,14 @@ function getFakerData(limit = 100, data, model) {
|
|
|
2267
2297
|
const item = {};
|
|
2268
2298
|
for (const [key, value] of Object.entries(data)) {
|
|
2269
2299
|
const val = value();
|
|
2270
|
-
item[key] = val
|
|
2300
|
+
item[key] = val?.constructor === Date ? formatDate(val) : val;
|
|
2271
2301
|
}
|
|
2272
2302
|
// if ((item as any)?.['code'])
|
|
2273
2303
|
// (item as any).code = `${index}`;
|
|
2274
2304
|
// item.id = index;
|
|
2275
2305
|
// item.createdAt = faker.date.past({ refDate: '2025-01-01' });
|
|
2306
|
+
if (item['productCode'])
|
|
2307
|
+
item['productCode'] = `${index}`;
|
|
2276
2308
|
index = index + 1;
|
|
2277
2309
|
return (!model ? item : Model.build(item, model));
|
|
2278
2310
|
});
|
|
@@ -2408,7 +2440,8 @@ class NgxRenderingEngine extends RenderingEngine {
|
|
|
2408
2440
|
* @memberOf module:lib/engine/NgxRenderingEngine
|
|
2409
2441
|
*/
|
|
2410
2442
|
fromFieldDefinition(fieldDef, vcr, injector, tpl, registryFormId = Date.now().toString(36).toUpperCase(), createComponent = true, formGroup) {
|
|
2411
|
-
const cmp = fieldDef?.['component'] ||
|
|
2443
|
+
const cmp = fieldDef?.['component'] ||
|
|
2444
|
+
NgxRenderingEngine.components(fieldDef.tag);
|
|
2412
2445
|
const component = cmp.constructor;
|
|
2413
2446
|
const componentMetadata = reflectComponentType(component);
|
|
2414
2447
|
if (!componentMetadata) {
|
|
@@ -2416,7 +2449,7 @@ class NgxRenderingEngine extends RenderingEngine {
|
|
|
2416
2449
|
}
|
|
2417
2450
|
const { inputs: possibleInputs } = componentMetadata;
|
|
2418
2451
|
const inputs = { ...fieldDef.props };
|
|
2419
|
-
const unmappedKeys = Object.keys(inputs).filter(input => {
|
|
2452
|
+
const unmappedKeys = Object.keys(inputs).filter((input) => {
|
|
2420
2453
|
const isMapped = possibleInputs.find(({ propName }) => propName === input);
|
|
2421
2454
|
if (!isMapped)
|
|
2422
2455
|
delete inputs[input];
|
|
@@ -2432,13 +2465,17 @@ class NgxRenderingEngine extends RenderingEngine {
|
|
|
2432
2465
|
// const hasFormRoot = Object.values(possibleInputs).some(({propName}) => propName === AngularEngineKeys.PARENT_FORM);
|
|
2433
2466
|
// if (hasFormRoot && !inputs?.[AngularEngineKeys.PARENT_FORM] && formGroup)
|
|
2434
2467
|
// inputs[AngularEngineKeys.PARENT_FORM] = formGroup;
|
|
2468
|
+
if (operation !== OperationKeys.CREATE && hiddenOn.includes(OperationKeys.CREATE)) {
|
|
2469
|
+
fieldDef.props = { ...fieldDef.props, ...{ readonly: true, type: HTML5InputTypes.TEXT } };
|
|
2470
|
+
}
|
|
2435
2471
|
const result = {
|
|
2436
2472
|
component,
|
|
2437
2473
|
inputs,
|
|
2438
2474
|
injector,
|
|
2439
2475
|
};
|
|
2440
2476
|
if (fieldDef.rendererId)
|
|
2441
|
-
result.inputs['rendererId'] =
|
|
2477
|
+
result.inputs['rendererId'] =
|
|
2478
|
+
fieldDef.rendererId;
|
|
2442
2479
|
// process children
|
|
2443
2480
|
// generating DOM
|
|
2444
2481
|
// const projectable = NgxRenderingEngine._projectable;
|
|
@@ -2446,11 +2483,12 @@ class NgxRenderingEngine extends RenderingEngine {
|
|
|
2446
2483
|
// const template = [];
|
|
2447
2484
|
const hasChildren = Object.values(possibleInputs).some(({ propName }) => propName === AngularEngineKeys.CHILDREN);
|
|
2448
2485
|
const hasModel = Object.values(possibleInputs).some(({ propName }) => propName === ModelKeys.MODEL);
|
|
2449
|
-
const componentInputs = Object.assign(inputs,
|
|
2486
|
+
const componentInputs = Object.assign(inputs, hasModel ? { model: this._model } : {}, hasChildren ? { children: fieldDef?.['children'] || [] } : {});
|
|
2450
2487
|
if (createComponent) {
|
|
2451
2488
|
vcr.clear();
|
|
2452
2489
|
const componentInstance = NgxRenderingEngine.createComponent(component, componentInputs, injector, componentMetadata, vcr, []);
|
|
2453
|
-
result.component = NgxRenderingEngine._instance =
|
|
2490
|
+
result.component = NgxRenderingEngine._instance =
|
|
2491
|
+
componentInstance;
|
|
2454
2492
|
}
|
|
2455
2493
|
if (fieldDef.children?.length) {
|
|
2456
2494
|
if (!NgxRenderingEngine._parentProps && inputs?.['pages']) {
|
|
@@ -2458,8 +2496,9 @@ class NgxRenderingEngine extends RenderingEngine {
|
|
|
2458
2496
|
// NgxRenderingEngine._projectable = false;
|
|
2459
2497
|
}
|
|
2460
2498
|
result.children = fieldDef.children.map((child) => {
|
|
2461
|
-
|
|
2462
|
-
//
|
|
2499
|
+
const readonly = operation === OperationKeys.UPDATE && (child?.props?.hidden || []).includes(OperationKeys.CREATE);
|
|
2500
|
+
// const hiddenOn = (child?.props?.hidden || []) as string[];
|
|
2501
|
+
// // moved to ui decorators
|
|
2463
2502
|
// if (child?.children?.length) {
|
|
2464
2503
|
// child.children = child.children.filter(c => {
|
|
2465
2504
|
// const hiddenOn = c?.props?.hidden || [];
|
|
@@ -2468,7 +2507,15 @@ class NgxRenderingEngine extends RenderingEngine {
|
|
|
2468
2507
|
// })
|
|
2469
2508
|
// }
|
|
2470
2509
|
// if (!hiddenOn?.length || !(hiddenOn as CrudOperations[]).includes(operation as CrudOperations))
|
|
2471
|
-
|
|
2510
|
+
if (!readonly) {
|
|
2511
|
+
NgxFormService.addControlFromProps(registryFormId, child.props, {
|
|
2512
|
+
...inputs,
|
|
2513
|
+
...(NgxRenderingEngine._parentProps || {}),
|
|
2514
|
+
});
|
|
2515
|
+
}
|
|
2516
|
+
else {
|
|
2517
|
+
child.props = { ...child.props, ...{ readonly: true } };
|
|
2518
|
+
}
|
|
2472
2519
|
return this.fromFieldDefinition(child, vcr, injector, tpl, registryFormId, false, formGroup);
|
|
2473
2520
|
});
|
|
2474
2521
|
}
|
|
@@ -2504,24 +2551,29 @@ class NgxRenderingEngine extends RenderingEngine {
|
|
|
2504
2551
|
}
|
|
2505
2552
|
static createHostComponent(component, props = {}, injector) {
|
|
2506
2553
|
if (!injector)
|
|
2507
|
-
injector =
|
|
2554
|
+
injector =
|
|
2555
|
+
NgxRenderingEngine._injector ||
|
|
2556
|
+
Injector.create({ providers: [], parent: Injector.NULL });
|
|
2508
2557
|
const envInjector = createEnvironmentInjector([], injector);
|
|
2509
2558
|
let cmp = {};
|
|
2510
2559
|
runInInjectionContext(envInjector, () => {
|
|
2511
2560
|
const host = document.createElement('div');
|
|
2512
|
-
component =
|
|
2561
|
+
component =
|
|
2562
|
+
typeof component === Primitives.STRING
|
|
2563
|
+
? NgxRenderingEngine.components(component)
|
|
2564
|
+
: component;
|
|
2513
2565
|
if (!host)
|
|
2514
2566
|
throw new Error('Cant create host element for component');
|
|
2515
2567
|
cmp = createComponent(component, {
|
|
2516
2568
|
environmentInjector: envInjector,
|
|
2517
|
-
hostElement: host
|
|
2569
|
+
hostElement: host,
|
|
2518
2570
|
});
|
|
2519
2571
|
const metadata = reflectComponentType(component);
|
|
2520
2572
|
if (!metadata)
|
|
2521
2573
|
throw new InternalError(`Metadata for component ${component} not found.`);
|
|
2522
2574
|
const { inputs: possibleInputs } = metadata;
|
|
2523
2575
|
const inputs = { ...props };
|
|
2524
|
-
const unmappedKeys = Object.keys(inputs).filter(input => {
|
|
2576
|
+
const unmappedKeys = Object.keys(inputs).filter((input) => {
|
|
2525
2577
|
const isMapped = possibleInputs.find(({ propName }) => propName === input);
|
|
2526
2578
|
if (!isMapped)
|
|
2527
2579
|
delete inputs[input];
|
|
@@ -2607,7 +2659,8 @@ class NgxRenderingEngine extends RenderingEngine {
|
|
|
2607
2659
|
const props = fieldDef.props;
|
|
2608
2660
|
if (!NgxRenderingEngine._operation)
|
|
2609
2661
|
NgxRenderingEngine._operation = props?.operation || undefined;
|
|
2610
|
-
const isArray = (props?.pages && props?.pages >= 1 ||
|
|
2662
|
+
const isArray = (props?.pages && props?.pages >= 1) ||
|
|
2663
|
+
props?.multiple === true;
|
|
2611
2664
|
const formGroup = NgxFormService.createForm(formId, isArray);
|
|
2612
2665
|
result = this.fromFieldDefinition(fieldDef, vcr, injector, tpl, formId, true, formGroup);
|
|
2613
2666
|
if (result.component)
|
|
@@ -2671,20 +2724,6 @@ class NgxRenderingEngine extends RenderingEngine {
|
|
|
2671
2724
|
throw new InternalError(`No Component registered under ${selector}`);
|
|
2672
2725
|
return this._components[selector];
|
|
2673
2726
|
}
|
|
2674
|
-
/**
|
|
2675
|
-
* @description Generates a key for reflection metadata storage.
|
|
2676
|
-
* @summary This static method generates a key for reflection metadata by prefixing the input key
|
|
2677
|
-
* with the Angular engine's reflection prefix. This is used for storing and retrieving
|
|
2678
|
-
* metadata in a namespaced way to avoid conflicts with other metadata.
|
|
2679
|
-
* @param {string} key - The base key to prefix
|
|
2680
|
-
* @return {string} The prefixed key for reflection metadata
|
|
2681
|
-
* @static
|
|
2682
|
-
* @override
|
|
2683
|
-
* @memberOf module:lib/engine/NgxRenderingEngine
|
|
2684
|
-
*/
|
|
2685
|
-
static key(key) {
|
|
2686
|
-
return `${AngularEngineKeys.REFLECT}${key}`;
|
|
2687
|
-
}
|
|
2688
2727
|
/**
|
|
2689
2728
|
* @description Sets input properties on a component instance.
|
|
2690
2729
|
* @summary This static utility method sets input properties on a component instance
|
|
@@ -2720,7 +2759,7 @@ class NgxRenderingEngine extends RenderingEngine {
|
|
|
2720
2759
|
*/
|
|
2721
2760
|
static setInputs(component, inputs, metadata) {
|
|
2722
2761
|
function parseInputValue(component, input) {
|
|
2723
|
-
Object.keys(input).forEach(key => {
|
|
2762
|
+
Object.keys(input).forEach((key) => {
|
|
2724
2763
|
const value = input[key];
|
|
2725
2764
|
if (typeof value === 'object' && !!value)
|
|
2726
2765
|
return parseInputValue(component, value);
|
|
@@ -2786,6 +2825,10 @@ var operations = {
|
|
|
2786
2825
|
"delete": {
|
|
2787
2826
|
success: "Successfully deleted item with {0} {1}.",
|
|
2788
2827
|
error: "Error deleting item with {0} {1}."
|
|
2828
|
+
},
|
|
2829
|
+
multiple: {
|
|
2830
|
+
success: "Successfully processed all operations.",
|
|
2831
|
+
error: "Error processing operations."
|
|
2789
2832
|
}
|
|
2790
2833
|
};
|
|
2791
2834
|
var component = {
|
|
@@ -2795,7 +2838,8 @@ var component = {
|
|
|
2795
2838
|
cancel: "Cancel",
|
|
2796
2839
|
not_unique: "The value entered already exists. Value {0}",
|
|
2797
2840
|
max_items: "You can create up to {0} items.",
|
|
2798
|
-
max_items_reached: "Maximum of {0} items reached."
|
|
2841
|
+
max_items_reached: "Maximum of {0} items reached.",
|
|
2842
|
+
empty: "No items found."
|
|
2799
2843
|
},
|
|
2800
2844
|
list: {
|
|
2801
2845
|
pagination: "Showing page <span class=\"text-bold\">{0} of {1}</span>",
|
|
@@ -3463,7 +3507,7 @@ catch (e) {
|
|
|
3463
3507
|
* @implements {OnChanges}
|
|
3464
3508
|
* @memberOf module:lib/engine/NgxComponentDirective
|
|
3465
3509
|
*/
|
|
3466
|
-
class NgxComponentDirective extends
|
|
3510
|
+
class NgxComponentDirective extends DecafComponent {
|
|
3467
3511
|
/**
|
|
3468
3512
|
* @description Constructor for NgxComponentDirective.
|
|
3469
3513
|
* @summary Initializes the directive by setting up the component name, locale root,
|
|
@@ -3506,7 +3550,7 @@ class NgxComponentDirective extends LoggedClass {
|
|
|
3506
3550
|
* @summary Defines how fields from the data model should be mapped to properties used by the component.
|
|
3507
3551
|
* This allows for flexible data binding between the model and the component's display logic. Can be
|
|
3508
3552
|
* provided as a static object mapping or as a function for dynamic mapping transformations.
|
|
3509
|
-
* @type {Record<string, string> | FunctionLike}
|
|
3553
|
+
* @type {Record<string, string> | FunctionLike | Record<string, FunctionLike>}
|
|
3510
3554
|
* @default {}
|
|
3511
3555
|
* @memberOf module:lib/engine/NgxComponentDirective
|
|
3512
3556
|
*/
|
|
@@ -3528,9 +3572,9 @@ class NgxComponentDirective extends LoggedClass {
|
|
|
3528
3572
|
* The operation affects form validation, field availability, and the specific repository
|
|
3529
3573
|
* method called during data submission.
|
|
3530
3574
|
*
|
|
3531
|
-
* @type {OperationKeys
|
|
3575
|
+
* @type {OperationKeys}
|
|
3532
3576
|
* @default OperationKeys.READ
|
|
3533
|
-
*
|
|
3577
|
+
* @memberOf module:lib/engine/NgxComponentDirective
|
|
3534
3578
|
*/
|
|
3535
3579
|
this.operation = OperationKeys.READ;
|
|
3536
3580
|
/**
|
|
@@ -3587,7 +3631,7 @@ class NgxComponentDirective extends LoggedClass {
|
|
|
3587
3631
|
* @type {NgxMediaService}
|
|
3588
3632
|
* @memberOf module:lib/engine/NgxComponentDirective
|
|
3589
3633
|
*/
|
|
3590
|
-
this.mediaService =
|
|
3634
|
+
this.mediaService = inject(NgxMediaService);
|
|
3591
3635
|
/**
|
|
3592
3636
|
* @description Angular Renderer2 service for platform-agnostic DOM manipulation.
|
|
3593
3637
|
* @summary Injected service that provides a safe, platform-agnostic way to manipulate DOM elements.
|
|
@@ -3618,6 +3662,16 @@ class NgxComponentDirective extends LoggedClass {
|
|
|
3618
3662
|
* @memberOf module:lib/engine/NgxComponentDirective
|
|
3619
3663
|
*/
|
|
3620
3664
|
this.listenEvent = new EventEmitter();
|
|
3665
|
+
/**
|
|
3666
|
+
* @description Event emitter for custom component events.
|
|
3667
|
+
* @summary Emits custom events that occur within child components or the component itself.
|
|
3668
|
+
* This allows parent components to listen for and respond to user interactions or
|
|
3669
|
+
* state changes. Events are passed up the component hierarchy to enable coordinated
|
|
3670
|
+
* behavior across the application.
|
|
3671
|
+
* @type {EventEmitter<IBaseCustomEvent>}
|
|
3672
|
+
* @memberOf module:lib/engine/NgxComponentDirective
|
|
3673
|
+
*/
|
|
3674
|
+
this.refreshEvent = new EventEmitter();
|
|
3621
3675
|
/**
|
|
3622
3676
|
* @description Angular Router instance for programmatic navigation.
|
|
3623
3677
|
* @summary Injected Router service used for programmatic navigation between routes
|
|
@@ -3635,7 +3689,7 @@ class NgxComponentDirective extends LoggedClass {
|
|
|
3635
3689
|
* and other properties needed to render list items correctly. The tag property
|
|
3636
3690
|
* identifies which component should be used to render each item in a list.
|
|
3637
3691
|
* Additional properties can be included to customize the rendering behavior.
|
|
3638
|
-
* @type {Record<string,
|
|
3692
|
+
* @type {Record<string, FieldDefinition>}
|
|
3639
3693
|
* @default {tag: ""}
|
|
3640
3694
|
* @memberOf module:lib/engine/NgxComponentDirective
|
|
3641
3695
|
*/
|
|
@@ -3662,16 +3716,6 @@ class NgxComponentDirective extends LoggedClass {
|
|
|
3662
3716
|
* @memberOf module:lib/engine/NgxComponentDirective
|
|
3663
3717
|
*/
|
|
3664
3718
|
this.route = "";
|
|
3665
|
-
/**
|
|
3666
|
-
* @description Initialization status flag for the component.
|
|
3667
|
-
* @summary Tracks whether the component has completed its initialization process.
|
|
3668
|
-
* This flag is used to prevent duplicate initialization and to determine if
|
|
3669
|
-
* certain operations that require initialization can be performed.
|
|
3670
|
-
* @type {boolean}
|
|
3671
|
-
* @default false
|
|
3672
|
-
* @memberOf module:lib/engine/NgxComponentDirective
|
|
3673
|
-
*/
|
|
3674
|
-
this.initialized = false;
|
|
3675
3719
|
/**
|
|
3676
3720
|
* @description Controls whether borders are displayed around the component.
|
|
3677
3721
|
* @summary Boolean flag that determines if the component should be visually outlined with borders.
|
|
@@ -3681,22 +3725,14 @@ class NgxComponentDirective extends LoggedClass {
|
|
|
3681
3725
|
* @default false
|
|
3682
3726
|
*/
|
|
3683
3727
|
this.borders = false;
|
|
3684
|
-
/**
|
|
3685
|
-
* @description Reference to CRUD operation constants for template usage.
|
|
3686
|
-
* @summary Exposes the OperationKeys enum to the component template, enabling
|
|
3687
|
-
* conditional rendering and behavior based on operation types. This protected
|
|
3688
|
-
* readonly property ensures that template logic can access operation constants
|
|
3689
|
-
* while maintaining encapsulation and preventing accidental modification.
|
|
3690
|
-
* @protected
|
|
3691
|
-
* @readonly
|
|
3692
|
-
* @memberOf module:lib/engine/NgxComponentDirective
|
|
3693
|
-
*/
|
|
3694
|
-
this.OperationKeys = OperationKeys;
|
|
3695
3728
|
/**
|
|
3696
3729
|
* @description Angular Location service.
|
|
3697
|
-
* @summary Injected service that provides access to the browser's URL and history.
|
|
3698
|
-
*
|
|
3699
|
-
*
|
|
3730
|
+
* @summary Injected service that provides direct access to the browser's URL and history.
|
|
3731
|
+
* Unlike the Router, Location allows for low-level manipulation of the browser's history stack
|
|
3732
|
+
* and URL path, such as programmatically navigating back or forward, or updating the URL without
|
|
3733
|
+
* triggering a route change. This is useful for scenarios where you need to interact with the
|
|
3734
|
+
* browser history or URL outside of Angular's routing system, such as closing modals, handling
|
|
3735
|
+
* popstate events, or supporting custom navigation logic.
|
|
3700
3736
|
*
|
|
3701
3737
|
* @private
|
|
3702
3738
|
* @type {Location}
|
|
@@ -3715,13 +3751,24 @@ class NgxComponentDirective extends LoggedClass {
|
|
|
3715
3751
|
* @memberOf module:lib/engine/NgxComponentDirective
|
|
3716
3752
|
*/
|
|
3717
3753
|
this.isModalChild = false;
|
|
3718
|
-
this.
|
|
3754
|
+
this.handlers = {};
|
|
3755
|
+
this.events = {};
|
|
3756
|
+
/**
|
|
3757
|
+
* @description Indicates whether a refresh operation is in progress.
|
|
3758
|
+
* @summary When true, the component is currently fetching new data. This is used
|
|
3759
|
+
* to control loading indicators and prevent duplicate refresh operations from
|
|
3760
|
+
* being triggered simultaneously.
|
|
3761
|
+
*
|
|
3762
|
+
* @type {boolean}
|
|
3763
|
+
* @default false
|
|
3764
|
+
*/
|
|
3765
|
+
this.refreshing = false;
|
|
3766
|
+
this.componentName = componentName || 'NgxComponentDirective';
|
|
3719
3767
|
this.localeRoot = localeRoot;
|
|
3720
3768
|
if (!this.localeRoot && this.componentName)
|
|
3721
3769
|
this.localeRoot = this.componentName;
|
|
3722
3770
|
if (this.localeRoot)
|
|
3723
3771
|
this.getLocale(this.localeRoot);
|
|
3724
|
-
this.logger = this.log;
|
|
3725
3772
|
this.uid = `${this.componentName}-${generateRandomValue(8)}`;
|
|
3726
3773
|
}
|
|
3727
3774
|
/**
|
|
@@ -3735,6 +3782,11 @@ class NgxComponentDirective extends LoggedClass {
|
|
|
3735
3782
|
ngOnDestroy() {
|
|
3736
3783
|
this.mediaService.destroy();
|
|
3737
3784
|
}
|
|
3785
|
+
//TODO: Pass to ui decoretators
|
|
3786
|
+
async refresh(...args) {
|
|
3787
|
+
this.log.for(this.refresh).debug(`Refresh called with args: ${args}`);
|
|
3788
|
+
this.refreshEvent.emit(true);
|
|
3789
|
+
}
|
|
3738
3790
|
/**
|
|
3739
3791
|
* @description Getter for the current locale context identifier.
|
|
3740
3792
|
* @summary Returns the current locale identifier by calling the getLocale method.
|
|
@@ -3758,10 +3810,9 @@ class NgxComponentDirective extends LoggedClass {
|
|
|
3758
3810
|
get repository() {
|
|
3759
3811
|
try {
|
|
3760
3812
|
if (!this._repository) {
|
|
3761
|
-
this._repository =
|
|
3813
|
+
this._repository = getModelAndRepository(this.model)?.repository;
|
|
3762
3814
|
if (this.model && !this.pk)
|
|
3763
|
-
this.pk =
|
|
3764
|
-
this._repository.pk || 'id';
|
|
3815
|
+
this.pk = Model.pk(this._repository?.class);
|
|
3765
3816
|
}
|
|
3766
3817
|
}
|
|
3767
3818
|
catch (error) {
|
|
@@ -3769,6 +3820,9 @@ class NgxComponentDirective extends LoggedClass {
|
|
|
3769
3820
|
}
|
|
3770
3821
|
return this._repository;
|
|
3771
3822
|
}
|
|
3823
|
+
set repository(repository) {
|
|
3824
|
+
this._repository = repository;
|
|
3825
|
+
}
|
|
3772
3826
|
/**
|
|
3773
3827
|
* @description Angular lifecycle hook for handling input property changes.
|
|
3774
3828
|
* @summary Responds to changes in component input properties, specifically monitoring changes
|
|
@@ -3779,7 +3833,7 @@ class NgxComponentDirective extends LoggedClass {
|
|
|
3779
3833
|
* @return {void}
|
|
3780
3834
|
* @memberOf module:lib/engine/NgxComponentDirective
|
|
3781
3835
|
*/
|
|
3782
|
-
ngOnChanges(changes) {
|
|
3836
|
+
async ngOnChanges(changes) {
|
|
3783
3837
|
if (changes[BaseComponentProps.MODEL]) {
|
|
3784
3838
|
const { currentValue } = changes[BaseComponentProps.MODEL];
|
|
3785
3839
|
if (currentValue)
|
|
@@ -3788,6 +3842,44 @@ class NgxComponentDirective extends LoggedClass {
|
|
|
3788
3842
|
if (!this.initialized)
|
|
3789
3843
|
this.initialized = true;
|
|
3790
3844
|
}
|
|
3845
|
+
// if (changes[UIKeys.HANDLERS]) {
|
|
3846
|
+
// const { currentValue, previousValue } = changes[UIKeys.HANDLERS];
|
|
3847
|
+
// if (currentValue && typeof currentValue !== previousValue) {
|
|
3848
|
+
// for(const key in currentValue) {
|
|
3849
|
+
// const event = currentValue[key]();
|
|
3850
|
+
// if (event && typeof event === 'function') {
|
|
3851
|
+
// const clazz = new event();
|
|
3852
|
+
// this.handlers[key] = clazz[key].bind(this);
|
|
3853
|
+
// console.log(this.handlers);
|
|
3854
|
+
// }
|
|
3855
|
+
// }
|
|
3856
|
+
// }
|
|
3857
|
+
// }
|
|
3858
|
+
if (changes[UIKeys.EVENTS]) {
|
|
3859
|
+
const { currentValue, previousValue } = changes[UIKeys.EVENTS];
|
|
3860
|
+
if (currentValue && currentValue !== previousValue) {
|
|
3861
|
+
if (!this._repository)
|
|
3862
|
+
this._repository = this.repository;
|
|
3863
|
+
for (const key in currentValue) {
|
|
3864
|
+
const event = currentValue[key]();
|
|
3865
|
+
if (event && typeof event === 'function') {
|
|
3866
|
+
try {
|
|
3867
|
+
const clazz = new event();
|
|
3868
|
+
this.events[key] = clazz[key].bind(this);
|
|
3869
|
+
if (event[key] instanceof Promise) {
|
|
3870
|
+
await clazz[key].bind(this)();
|
|
3871
|
+
}
|
|
3872
|
+
else {
|
|
3873
|
+
clazz[key].bind(this)();
|
|
3874
|
+
}
|
|
3875
|
+
}
|
|
3876
|
+
catch (error) {
|
|
3877
|
+
this.log.for(this.ngOnChanges).warn(`Error occurred while processing event "${key}": ${error?.message || error}`);
|
|
3878
|
+
}
|
|
3879
|
+
}
|
|
3880
|
+
}
|
|
3881
|
+
}
|
|
3882
|
+
}
|
|
3791
3883
|
if (changes[BaseComponentProps.LOCALE_ROOT] || changes[BaseComponentProps.COMPONENT_NAME])
|
|
3792
3884
|
this.locale = this.localeContext;
|
|
3793
3885
|
if (this.enableDarkMode)
|
|
@@ -3811,23 +3903,8 @@ class NgxComponentDirective extends LoggedClass {
|
|
|
3811
3903
|
return await firstValueFrom(this.translateService.get(phrase, (params || {})));
|
|
3812
3904
|
;
|
|
3813
3905
|
}
|
|
3814
|
-
/**
|
|
3815
|
-
* @description Initializes the component asynchronously with custom logic.
|
|
3816
|
-
* @summary Abstract initialization method that can be overridden by child components to perform
|
|
3817
|
-
* custom initialization logic. By default, it simply sets the initialized flag to true.
|
|
3818
|
-
* Child components can extend this method to load data, configure settings, or perform
|
|
3819
|
-
* other setup operations required before the component is fully functional.
|
|
3820
|
-
* @protected
|
|
3821
|
-
* @param {...unknown[]} args - Variable number of arguments that can be used by child implementations
|
|
3822
|
-
* @return {Promise<void>} A promise that resolves when initialization is complete
|
|
3823
|
-
* @memberOf module:lib/engine/NgxComponentDirective
|
|
3824
|
-
*/
|
|
3825
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3826
|
-
async initialize(...args) {
|
|
3827
|
-
this.initialized = true;
|
|
3828
|
-
}
|
|
3829
3906
|
checkDarkMode() {
|
|
3830
|
-
this.mediaService.isDarkMode().subscribe(isDark => {
|
|
3907
|
+
this.mediaService.isDarkMode().subscribe((isDark) => {
|
|
3831
3908
|
this.isDarkMode = isDark;
|
|
3832
3909
|
this.mediaService.toggleClass([this.component], AngularEngineKeys.DARK_PALETTE_CLASS, this.isDarkMode);
|
|
3833
3910
|
});
|
|
@@ -4004,7 +4081,7 @@ class NgxComponentDirective extends LoggedClass {
|
|
|
4004
4081
|
* end
|
|
4005
4082
|
* @memberOf module:lib/engine/NgxComponentDirective
|
|
4006
4083
|
*/
|
|
4007
|
-
async handleEvent(event) {
|
|
4084
|
+
async handleEvent(event, repository) {
|
|
4008
4085
|
let name = "";
|
|
4009
4086
|
const log = this.log.for(this.handleEvent);
|
|
4010
4087
|
if (event instanceof CustomEvent) {
|
|
@@ -4019,8 +4096,11 @@ class NgxComponentDirective extends LoggedClass {
|
|
|
4019
4096
|
if (!handlers[name])
|
|
4020
4097
|
return log.debug(`No handler found for event ${name}`);
|
|
4021
4098
|
try {
|
|
4022
|
-
const clazz = new handlers[name](
|
|
4023
|
-
const
|
|
4099
|
+
const clazz = new handlers[name]();
|
|
4100
|
+
const handler = clazz.handle.bind(this);
|
|
4101
|
+
//const clazz = new event();
|
|
4102
|
+
// this.events[key] = clazz[key].bind(this);
|
|
4103
|
+
const result = handler(event);
|
|
4024
4104
|
return (result instanceof Promise) ?
|
|
4025
4105
|
await result : result;
|
|
4026
4106
|
}
|
|
@@ -4030,6 +4110,10 @@ class NgxComponentDirective extends LoggedClass {
|
|
|
4030
4110
|
}
|
|
4031
4111
|
this.listenEvent.emit(event);
|
|
4032
4112
|
}
|
|
4113
|
+
// passed for ui decorators
|
|
4114
|
+
// async submit(...args: unknown[]): Promise<any> {
|
|
4115
|
+
// this.log.for(this.submit).info(`submit for ${this.componentName} with ${JSON.stringify(args)}`);
|
|
4116
|
+
// }
|
|
4033
4117
|
/**
|
|
4034
4118
|
* @description Determines if a specific operation is allowed in the current context.
|
|
4035
4119
|
* @summary This method checks if an operation is included in the list of available
|
|
@@ -4056,7 +4140,9 @@ class NgxComponentDirective extends LoggedClass {
|
|
|
4056
4140
|
isAllowed(operation) {
|
|
4057
4141
|
if (!this.operations)
|
|
4058
4142
|
return false;
|
|
4059
|
-
return this.operations.includes(operation) &&
|
|
4143
|
+
return (this.operations.includes(operation) &&
|
|
4144
|
+
this.operation !== OperationKeys.CREATE &&
|
|
4145
|
+
((this.operation || '').toLowerCase() !== operation || !this.operation));
|
|
4060
4146
|
}
|
|
4061
4147
|
/**
|
|
4062
4148
|
* @description Navigates to a different operation for the current model.
|
|
@@ -4093,7 +4179,7 @@ class NgxComponentDirective extends LoggedClass {
|
|
|
4093
4179
|
return this.router.navigateByUrl(page);
|
|
4094
4180
|
}
|
|
4095
4181
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgxComponentDirective, deps: [{ token: CPTKN }, { token: CPTKN }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
4096
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.9", type: NgxComponentDirective, isStandalone: true, inputs: { enableDarkMode: "enableDarkMode", isDarkMode: "isDarkMode", name: "name", childOf: "childOf", uid: "uid", model: "model", modelId: "modelId", pk: "pk", mapper: "mapper", operations: "operations", operation: "operation", row: "row", col: "col", className: "className", locale: "locale", item: "item", props: "props", route: "route", borders: "borders", isModalChild: "isModalChild" }, outputs: { listenEvent: "listenEvent" }, host: { properties: { "attr.id": "uid" } }, viewQueries: [{ propertyName: "component", first: true, predicate: ["component"], descendants: true, read: ElementRef, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0 }); }
|
|
4182
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.9", type: NgxComponentDirective, isStandalone: true, inputs: { enableDarkMode: "enableDarkMode", isDarkMode: "isDarkMode", name: "name", childOf: "childOf", uid: "uid", model: "model", modelId: "modelId", value: "value", pk: "pk", mapper: "mapper", operations: "operations", operation: "operation", row: "row", col: "col", className: "className", locale: "locale", item: "item", props: "props", route: "route", borders: "borders", isModalChild: "isModalChild", handlers: "handlers", events: "events" }, outputs: { listenEvent: "listenEvent", refreshEvent: "refreshEvent" }, host: { properties: { "attr.id": "uid" } }, viewQueries: [{ propertyName: "component", first: true, predicate: ["component"], descendants: true, read: ElementRef, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0 }); }
|
|
4097
4183
|
}
|
|
4098
4184
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgxComponentDirective, decorators: [{
|
|
4099
4185
|
type: Directive,
|
|
@@ -4121,6 +4207,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
|
|
|
4121
4207
|
type: Input
|
|
4122
4208
|
}], modelId: [{
|
|
4123
4209
|
type: Input
|
|
4210
|
+
}], value: [{
|
|
4211
|
+
type: Input
|
|
4124
4212
|
}], pk: [{
|
|
4125
4213
|
type: Input
|
|
4126
4214
|
}], mapper: [{
|
|
@@ -4137,6 +4225,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
|
|
|
4137
4225
|
type: Input
|
|
4138
4226
|
}], listenEvent: [{
|
|
4139
4227
|
type: Output
|
|
4228
|
+
}], refreshEvent: [{
|
|
4229
|
+
type: Output
|
|
4140
4230
|
}], locale: [{
|
|
4141
4231
|
type: Input
|
|
4142
4232
|
}], item: [{
|
|
@@ -4149,6 +4239,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
|
|
|
4149
4239
|
type: Input
|
|
4150
4240
|
}], isModalChild: [{
|
|
4151
4241
|
type: Input
|
|
4242
|
+
}], handlers: [{
|
|
4243
|
+
type: Input
|
|
4244
|
+
}], events: [{
|
|
4245
|
+
type: Input
|
|
4152
4246
|
}] } });
|
|
4153
4247
|
|
|
4154
4248
|
class NgxRenderableComponentDirective extends NgxComponentDirective {
|
|
@@ -4687,9 +4781,9 @@ class NgxFormFieldDirective extends NgxComponentDirective {
|
|
|
4687
4781
|
* @return {void}
|
|
4688
4782
|
* @public
|
|
4689
4783
|
*/
|
|
4690
|
-
ngOnChanges(changes) {
|
|
4784
|
+
async ngOnChanges(changes) {
|
|
4691
4785
|
if (!this.initialized)
|
|
4692
|
-
super.ngOnChanges(changes);
|
|
4786
|
+
await super.ngOnChanges(changes);
|
|
4693
4787
|
if (changes['activeFormGroupIndex'] && this.multiple &&
|
|
4694
4788
|
!changes['activeFormGroupIndex'].isFirstChange() && changes['activeFormGroupIndex'].currentValue !== this.activeFormGroupIndex) {
|
|
4695
4789
|
this.activeFormGroupIndex = changes['activeFormGroupIndex'].currentValue;
|
|
@@ -4811,8 +4905,39 @@ function Dynamic() {
|
|
|
4811
4905
|
if (!metadata)
|
|
4812
4906
|
throw new InternalError(`Could not find Component metadata. @Dynamic decorator must come above @Component`);
|
|
4813
4907
|
NgxRenderingEngine.registerComponent(metadata.selector, original);
|
|
4814
|
-
}, metadata(
|
|
4908
|
+
}, metadata(Metadata.key(AngularEngineKeys.REFLECT, AngularEngineKeys.DYNAMIC), true));
|
|
4815
4909
|
}
|
|
4910
|
+
// export interface UICustomEvents {
|
|
4911
|
+
// render: () => HandlerLike;
|
|
4912
|
+
// init: () => FunctionLike;
|
|
4913
|
+
// }
|
|
4914
|
+
// export function uion(event: string, handler: FunctionLike) {
|
|
4915
|
+
// return (target: any, propertyKey?: any) => {
|
|
4916
|
+
// const metadata = {
|
|
4917
|
+
// [event]: handler,
|
|
4918
|
+
// };
|
|
4919
|
+
// propMetadata(getUIAttributeKey(propertyKey, 'handlers'), metadata)(
|
|
4920
|
+
// target,
|
|
4921
|
+
// propertyKey
|
|
4922
|
+
// );
|
|
4923
|
+
// };
|
|
4924
|
+
// // return (model: unknown, property: unknown) => {
|
|
4925
|
+
// // const meta: UIHandlerMetadata = {
|
|
4926
|
+
// // [event]: handler,
|
|
4927
|
+
// // };
|
|
4928
|
+
// // return metadata(
|
|
4929
|
+
// // getUIAttributeKey(property as string, 'on'),
|
|
4930
|
+
// // meta
|
|
4931
|
+
// // )(model, property);
|
|
4932
|
+
// // };
|
|
4933
|
+
// }
|
|
4934
|
+
// export function uionrender(handler: FunctionLike) {
|
|
4935
|
+
// return uion("render", handler);
|
|
4936
|
+
// }
|
|
4937
|
+
// @uion(op, handler)
|
|
4938
|
+
// @uionrender(handler){
|
|
4939
|
+
// return uion("redenr", handler)
|
|
4940
|
+
// }
|
|
4816
4941
|
|
|
4817
4942
|
/**
|
|
4818
4943
|
* @module module:lib/components/model-renderer/model-renderer.component
|
|
@@ -4866,7 +4991,7 @@ class ModelRendererComponent extends NgxRenderableComponentDirective {
|
|
|
4866
4991
|
* @description Refreshes the rendered model
|
|
4867
4992
|
* @param {string | M} model - The model to be rendered
|
|
4868
4993
|
*/
|
|
4869
|
-
refresh(model) {
|
|
4994
|
+
async refresh(model) {
|
|
4870
4995
|
model =
|
|
4871
4996
|
typeof model === 'string'
|
|
4872
4997
|
? Model.build({}, model)
|
|
@@ -4881,7 +5006,7 @@ class ModelRendererComponent extends NgxRenderableComponentDirective {
|
|
|
4881
5006
|
* @description Lifecycle hook that is called when data-bound properties of a directive change
|
|
4882
5007
|
* @param {SimpleChanges} changes - Object containing changes
|
|
4883
5008
|
*/
|
|
4884
|
-
ngOnChanges(changes) {
|
|
5009
|
+
async ngOnChanges(changes) {
|
|
4885
5010
|
if (changes[BaseComponentProps.MODEL]) {
|
|
4886
5011
|
const { currentValue } = changes[BaseComponentProps.MODEL];
|
|
4887
5012
|
this.refresh(currentValue);
|
|
@@ -4920,12 +5045,12 @@ class NgxParentComponentDirective extends NgxComponentDirective {
|
|
|
4920
5045
|
constructor() {
|
|
4921
5046
|
super(...arguments);
|
|
4922
5047
|
/**
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
5048
|
+
* @description Unique identifier for the current record.
|
|
5049
|
+
* @summary A unique identifier for the current record being displayed or manipulated.
|
|
5050
|
+
* This is typically used in conjunction with the primary key for operations on specific records.
|
|
5051
|
+
*
|
|
5052
|
+
* @type {string | number}
|
|
5053
|
+
*/
|
|
4929
5054
|
this.page = 1;
|
|
4930
5055
|
/**
|
|
4931
5056
|
* @description Unique identifier for the current record.
|
|
@@ -5047,7 +5172,7 @@ class NgxParentComponentDirective extends NgxComponentDirective {
|
|
|
5047
5172
|
const content = this.children[page];
|
|
5048
5173
|
this.activePage = undefined;
|
|
5049
5174
|
this.preloadCards = [...new Array(1)];
|
|
5050
|
-
this.timerSubscription = timer(
|
|
5175
|
+
this.timerSubscription = timer(25).subscribe(() => this.activePage = { ...this.children[page] });
|
|
5051
5176
|
this.activeIndex = page;
|
|
5052
5177
|
if (content)
|
|
5053
5178
|
return content;
|
|
@@ -5404,6 +5529,15 @@ let CrudFieldComponent = class CrudFieldComponent extends NgxFormFieldDirective
|
|
|
5404
5529
|
* @memberOf CrudFieldComponent
|
|
5405
5530
|
*/
|
|
5406
5531
|
this.hidden = false;
|
|
5532
|
+
/**
|
|
5533
|
+
* @description Whether the field is read-only.
|
|
5534
|
+
* @summary When true, the field will be rendered in a read-only state. Unlike disabled fields,
|
|
5535
|
+
* read-only fields are still focusable but cannot be modified by the user.
|
|
5536
|
+
*
|
|
5537
|
+
* @type {boolean}
|
|
5538
|
+
* @memberOf CrudFieldComponent
|
|
5539
|
+
*/
|
|
5540
|
+
this.readonly = false;
|
|
5407
5541
|
/**
|
|
5408
5542
|
* @description Interface style for select inputs.
|
|
5409
5543
|
* @summary Specifies the interface style for select inputs, such as 'alert', 'action-sheet', or 'popover'.
|
|
@@ -5561,8 +5695,11 @@ let CrudFieldComponent = class CrudFieldComponent extends NgxFormFieldDirective
|
|
|
5561
5695
|
this.options = this.options();
|
|
5562
5696
|
}
|
|
5563
5697
|
else {
|
|
5564
|
-
const repo =
|
|
5565
|
-
|
|
5698
|
+
const repo = getModelAndRepository(this.options?.['name']);
|
|
5699
|
+
if (repo) {
|
|
5700
|
+
const { repository } = repo;
|
|
5701
|
+
this.options = await repository.select().execute();
|
|
5702
|
+
}
|
|
5566
5703
|
}
|
|
5567
5704
|
}
|
|
5568
5705
|
}
|
|
@@ -5607,11 +5744,10 @@ let CrudFieldComponent = class CrudFieldComponent extends NgxFormFieldDirective
|
|
|
5607
5744
|
* This ensures proper initialization of read-only fields that don't require
|
|
5608
5745
|
* form functionality but still need view setup.
|
|
5609
5746
|
*
|
|
5610
|
-
* @returns {void}
|
|
5747
|
+
* @returns {Promise<void>}
|
|
5611
5748
|
* @memberOf CrudFieldComponent
|
|
5612
5749
|
*/
|
|
5613
|
-
ngAfterViewInit() {
|
|
5614
|
-
super.afterViewInit();
|
|
5750
|
+
async ngAfterViewInit() {
|
|
5615
5751
|
if (this.type === HTML5InputTypes.RADIO && !this.value)
|
|
5616
5752
|
this.setValue(this.options[0].value); // TODO: migrate to RenderingEngine
|
|
5617
5753
|
}
|
|
@@ -5665,7 +5801,7 @@ let CrudFieldComponent = class CrudFieldComponent extends NgxFormFieldDirective
|
|
|
5665
5801
|
this.value = this.formControl.value;
|
|
5666
5802
|
}
|
|
5667
5803
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: CrudFieldComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
5668
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: CrudFieldComponent, isStandalone: true, selector: "ngx-decaf-crud-field", inputs: { operation: "operation", name: "name", className: "className", path: "path", childOf: "childOf", type: "type", value: "value", disabled: "disabled", label: "label", placeholder: "placeholder", format: "format", hidden: "hidden", max: "max", maxlength: "maxlength", min: "min", minlength: "minlength", pattern: "pattern", readonly: "readonly", required: "required", step: "step", equals: "equals", different: "different", lessThan: "lessThan", lessThanOrEqual: "lessThanOrEqual", greaterThan: "greaterThan", greaterThanOrEqual: "greaterThanOrEqual", alignment: "alignment", checked: "checked", justify: "justify", cancelText: "cancelText", interface: "interface", options: "options", mode: "mode", spellcheck: "spellcheck", inputmode: "inputmode", autocomplete: "autocomplete", fill: "fill", labelPlacement: "labelPlacement", updateOn: "updateOn", formGroup: "formGroup", formControl: "formControl", multiple: "multiple", uid: "uid", page: "page", translatable: "translatable" }, host: { listeners: { "window:fieldsetUpdateGroupEvent": "handleFieldsetUpdateGroupEvent($event)" }, properties: { "attr.id": "uid", "attr.class": "className" } }, viewQueries: [{ propertyName: "component", first: true, predicate: ["component"], descendants: true, read: ElementRef }], usesInheritance: true, ngImport: i0, template: "@if (operation === 'read' || operation === 'delete') {\n <ng-container>\n <div>\n <ion-item [class]=\"'dcf-input-item ' + operation\" #component>\n <ion-label>\n {{ label | translate }}<br />\n @if (value) {\n <ion-text [innerHTML]=\"type === 'password' ? '********' : value\"></ion-text>\n } @else {\n @if (['checkbox'].includes(type)) {\n <ion-icon aria-hidden=\"true\" class=\"dcf-margin-small-top\" [color]=\"!isDarkMode ? 'primary' : 'light'\" size=\"large\" name=\"checkmark-circle-outline\"></ion-icon>\n } @else {\n <br />\n }\n }\n </ion-label>\n </ion-item>\n </div>\n </ng-container>\n} @else {\n @if (formControl) {\n <ng-container [formGroup]=\"multiple ? activeFormGroup : formControl.parent\">\n <div\n\n [id]=\"uid\" #container\n [class]=\"'dcf-input-item ' + (operation || 'create')\"\n [class.dcf-field-required]=\"required\"\n >\n @if (type === 'textarea') {\n <ion-textarea\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [autoGrow]=\"true\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [inputmode]=\"inputmode\"\n [spellcheck]=\"spellcheck\"\n [rows]=\"rows\"\n [labelPlacement]=\"labelPlacement\"\n [value]=\"value\"\n [fill]=\"fill\"\n [errorText]=\"getErrors(container)\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [label]=\"label | translate\"\n #component>\n </ion-textarea>\n }\n @else if (type === 'checkbox') {\n @if (!options?.length) {\n <ion-item class=\"dcf-width-1-1\" [hidden]=\"hidden\">\n <ion-checkbox\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n [mode]=\"'md'\"\n [errorText]=\"getErrors(container)\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify || 'start'\"\n [value]=\"value\"\n [checked]=\"checked\"\n [readonly]=\"readonly\"\n (ionChange)=\"checked = !checked\"\n [formControlName]=\"name\"\n #component>\n <span>{{label | translate}}</span>\n </ion-checkbox>\n\n </ion-item>\n } @else {\n <div class=\"dcf-checkbox-group\">\n <label class=\"dcf-label\" [for]=\"path\">{{ label | translate }}</label>\n @for(option of options; track trackItemFn($index, option.text)) {\n <ion-item class=\"dcf-width-1-1\" [button]=\"true\">\n <ion-checkbox\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"option.text\"\n [mode]=\"'md'\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify\"\n [value]=\"option.value\"\n [readonly]=\"readonly\"\n [checked]=\"isOptionChecked(option.value)\"\n (ionChange)=\"toggleOptionSelection(option.value, $event)\"\n #component>\n <span>{{ $index + 1 }}. {{ option?.text | translate }}</span>\n </ion-checkbox>\n </ion-item>\n }\n <span class=\"dcf-error\" [innerHTML]=\"getErrors(container)\"></span>\n </div>\n }\n\n }\n @else if (type === 'radio' && options?.length) {\n <ion-radio-group class=\"dcf-width-1-1\" [formControlName]=\"name\" [value]=\"value\" #component>\n <label class=\"dcf-radio-group-label\" [for]=\"path\">{{label | translate}}</label>\n @for(option of options; track $index) {\n <ion-item>\n <ion-radio\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n [errorText]=\"getErrors(container)\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [alignment]=\"alignment\"\n [justify]=\"justify\"\n [readonly]=\"readonly\"\n [value]=\"option.value\"\n >{{ option?.text | translate }}</ion-radio>\n </ion-item>\n }\n </ion-radio-group>\n }\n @else if (type === 'select') {\n <div>\n <ion-select\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n [interface]=\"interface\"\n [mode]=\"'md'\"\n [hidden]=\"hidden || !options?.length\"\n [labelPlacement]=\"labelPlacement\"\n [label]=\"label | translate\"\n [value]=\"value\"\n (click)=\"openSelectOptions($event, interface)\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [interface]=\"interface\" #component>\n @if (options?.length) {\n @for(option of options; track trackItemFn($index, option.text)) {\n <ion-select-option [value]=\"option.value\">\n {{ option.text | translate }}\n </ion-select-option>\n }\n }\n </ion-select>\n <div class=\"dcf-error\" [innerHTML]=\"getErrors(container)\"></div>\n @if (!options?.length) {\n <ion-text color=\"danger\">\n * {{ 'errors.empty_options' | translate:{'0': name} }}\n </ion-text>\n }\n </div>\n }\n @else {\n <ion-input\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n [type]=\"type\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [inputmode]=\"inputmode\"\n [labelPlacement]=\"labelPlacement\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [max]=\"max !== undefined ? max : null\"\n [min]=\"min !== undefined ? min : null\"\n [pattern]=\"pattern !== undefined ? pattern : null\"\n [step]=\"step !== undefined ? step : null\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [label]=\"label | translate\" #component />\n }\n </div>\n </ng-container>\n } @else {\n <div>\n <p class=\"dcf-error\">\n {{ 'errors.form.control' | translate:{'0': name} }}\n </p>\n </div>\n }\n\n}\n\n", styles: ["ion-item{--border-color: transparent}ion-item:not(.dcf-input-item){--inner-padding-start: 0rem;--padding-start: 0rem;--background: transparent}ion-item.dcf-input-item{--padding-end: 0rem;--padding-start: 0px !important;--padding-top: 0px !important;--inner-padding-start: .75rem;--background: transparent;--background-hover-opacity: .1;--background-activated-opacity: .15;--background-focused-opacity: .15;--background-hover: var(--dcf-color-primary);--background-focused: var(--dcf-color-primary);--border-color: var(--dcf-color-gray-2)}ion-item.dcf-input-item.dcf-palette-dark{--border-color: var(--dcf-color-gray-6) !important}ion-item.dcf-input-item.read,ion-item.dcf-input-item.delete{--min-height: 30px;padding:unset;margin:unset!important;margin-bottom:var(--dcf-margin-xsmall)!important}ion-item.dcf-input-item.read ion-label,ion-item.dcf-input-item.delete ion-label{font-weight:600;margin-top:0!important;margin-bottom:.25rem!important;font-size:.925rem}ion-item.dcf-input-item.read ion-label:not(:first-of-type),ion-item.dcf-input-item.delete ion-label:not(:first-of-type){margin:100rem}ion-item.dcf-input-item.read span,ion-item.dcf-input-item.read ion-text,ion-item.dcf-input-item.delete span,ion-item.dcf-input-item.delete ion-text{font-weight:400!important;font-size:.825rem;min-height:.5rem!important}ion-item.dcf-input-item.read span:not(.dcf-display-block),ion-item.dcf-input-item.read ion-text:not(.dcf-display-block),ion-item.dcf-input-item.delete span:not(.dcf-display-block),ion-item.dcf-input-item.delete ion-text:not(.dcf-display-block){display:inline-block}ion-item.dcf-input-item.read span.dcf-display-block,ion-item.dcf-input-item.read ion-text.dcf-display-block,ion-item.dcf-input-item.delete span.dcf-display-block,ion-item.dcf-input-item.delete ion-text.dcf-display-block{display:block!important}ion-item.dcf-input-item>*,ion-item.dcf-input-item ion-select{width:100%!important}ion-item.dcf-input-item.create.checkbox+.checkbox,ion-item.dcf-input-item.update.checkbox+.checkbox{margin-top:-.25rem!important}ion-item.dcf-input-item.create ion-item,ion-item.dcf-input-item.update ion-item{--border-color: transparent}ion-item.dcf-input-item.create ion-item.dcf-text-wrap ion-label>*,ion-item.dcf-input-item.update ion-item.dcf-text-wrap ion-label>*{white-space:wrap!important;word-break:break-all!important}ion-textarea textarea{scrollbar-width:thin!important;margin-bottom:.5rem!important}ion-select.dcf-select-label-placement-floating::part(label){line-height:1.2rem!important}.dcf-proccessing,.dcf-proccessing *{pointer-events:none;touch-action:none;cursor:text}ion-checkbox::part(container){border:2px solid var(--dcf-color-primary);margin-left:.5rem;margin-right:.5rem;border-radius:var(--dcf-border-radius-small);padding:3px}ion-checkbox{--size: 1.5rem;--checkbox-background-checked: var(--dcf-color-primary);--checkmark-width: 2px}ion-radio-group .dcf-radio-group-label{font-weight:600}ion-radio-group .dcf-radio-group-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}ion-radio-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-checkbox-group{width:100%}.dcf-checkbox-group .dcf-label{font-weight:600}.dcf-checkbox-group .dcf-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}.dcf-checkbox-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-error{position:absolute;color:var(--dcf-color-danger)!important;font-size:.8rem!important;font-weight:500!important;line-height:1.1rem;z-index:9999}.dcf-error .ti,.dcf-error ion-icon{position:relative;top:2px!important;min-width:20px;font-size:1rem!important;text-align:left}.dcf-helper{font-size:.875rem!important;font-weight:500;margin-top:.25rem;margin-bottom:-.75rem}.dcf-helper.dcf-has-action{cursor:pointer;text-decoration:underline}.dcf-error+.dcf-helper{padding-top:1rem}::ng-deep ion-textarea{min-height:80px!important;scrollbar-color:#888 #f0f0f0;scrollbar-width:thin}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonRadioGroup, selector: "ion-radio-group", inputs: ["allowEmptySelection", "compareWith", "errorText", "helperText", "name", "value"] }, { kind: "component", type: IonRadio, selector: "ion-radio", inputs: ["alignment", "color", "disabled", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonTextarea, selector: "ion-textarea", inputs: ["autoGrow", "autocapitalize", "autofocus", "clearOnEdit", "color", "cols", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "maxlength", "minlength", "mode", "name", "placeholder", "readonly", "required", "rows", "shape", "spellcheck", "value", "wrap"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
5804
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: CrudFieldComponent, isStandalone: true, selector: "ngx-decaf-crud-field", inputs: { operation: "operation", name: "name", className: "className", path: "path", childOf: "childOf", type: "type", value: "value", disabled: "disabled", label: "label", placeholder: "placeholder", format: "format", hidden: "hidden", max: "max", maxlength: "maxlength", min: "min", minlength: "minlength", pattern: "pattern", readonly: "readonly", required: "required", step: "step", equals: "equals", different: "different", lessThan: "lessThan", lessThanOrEqual: "lessThanOrEqual", greaterThan: "greaterThan", greaterThanOrEqual: "greaterThanOrEqual", alignment: "alignment", checked: "checked", justify: "justify", cancelText: "cancelText", interface: "interface", options: "options", mode: "mode", spellcheck: "spellcheck", inputmode: "inputmode", autocomplete: "autocomplete", fill: "fill", labelPlacement: "labelPlacement", updateOn: "updateOn", formGroup: "formGroup", formControl: "formControl", multiple: "multiple", uid: "uid", page: "page", translatable: "translatable" }, host: { listeners: { "window:fieldsetUpdateGroupEvent": "handleFieldsetUpdateGroupEvent($event)" }, properties: { "attr.id": "uid", "attr.class": "className" } }, viewQueries: [{ propertyName: "component", first: true, predicate: ["component"], descendants: true, read: ElementRef }], usesInheritance: true, ngImport: i0, template: "@if (operation === 'read' || operation === 'delete') {\n <ng-container>\n <div>\n <ion-item [class]=\"'dcf-input-item ' + operation\" #component>\n <ion-label>\n {{ label | translate }}<br />\n @if (value) {\n <ion-text [innerHTML]=\"type === 'password' ? '********' : value\"></ion-text>\n } @else {\n @if (['checkbox'].includes(type)) {\n <ion-icon aria-hidden=\"true\" class=\"dcf-margin-small-top\" [color]=\"!isDarkMode ? 'primary' : 'light'\" size=\"large\" name=\"checkmark-circle-outline\"></ion-icon>\n } @else {\n <br />\n }\n }\n </ion-label>\n </ion-item>\n </div>\n </ng-container>\n} @else {\n @if (formControl) {\n <ng-container [formGroup]=\"multiple ? activeFormGroup : formControl.parent\">\n <div\n [id]=\"uid\" #container\n [class]=\"'dcf-input-item ' + (operation || 'create')\"\n [class.dcf-field-required]=\"required\"\n [class.dcf-field-readonly]=\"readonly\"\n >\n @if (type === 'textarea') {\n <ion-textarea\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [autoGrow]=\"true\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [inputmode]=\"inputmode\"\n [spellcheck]=\"spellcheck\"\n [rows]=\"rows\"\n [labelPlacement]=\"labelPlacement\"\n [value]=\"value\"\n [fill]=\"fill\"\n [errorText]=\"getErrors(container)\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [label]=\"label | translate\"\n #component>\n </ion-textarea>\n }\n @else if (type === 'checkbox') {\n @if (!options?.length) {\n <ion-item class=\"dcf-width-1-1\" [hidden]=\"hidden\">\n <ion-checkbox\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n [mode]=\"'md'\"\n [errorText]=\"getErrors(container)\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify || 'start'\"\n [value]=\"value\"\n [checked]=\"checked\"\n [readonly]=\"readonly\"\n (ionChange)=\"checked = !checked\"\n [formControlName]=\"name\"\n #component>\n <span>{{label | translate}}</span>\n </ion-checkbox>\n\n </ion-item>\n } @else {\n <div class=\"dcf-checkbox-group\">\n <label class=\"dcf-label\" [for]=\"path\">{{ label | translate }}</label>\n @for(option of options; track trackItemFn($index, option.text)) {\n <ion-item class=\"dcf-width-1-1\" [button]=\"true\">\n <ion-checkbox\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"option.text\"\n [mode]=\"'md'\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify\"\n [value]=\"option.value\"\n [readonly]=\"readonly\"\n [checked]=\"isOptionChecked(option.value)\"\n (ionChange)=\"toggleOptionSelection(option.value, $event)\"\n #component>\n <span>{{ $index + 1 }}. {{ option?.text | translate }}</span>\n </ion-checkbox>\n </ion-item>\n }\n <span class=\"dcf-error\" [innerHTML]=\"getErrors(container)\"></span>\n </div>\n }\n\n }\n @else if (type === 'radio' && options?.length) {\n <ion-radio-group class=\"dcf-width-1-1\" [formControlName]=\"name\" [value]=\"value\" #component>\n <label class=\"dcf-radio-group-label\" [for]=\"path\">{{label | translate}}</label>\n @for(option of options; track $index) {\n <ion-item>\n <ion-radio\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n [errorText]=\"getErrors(container)\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [alignment]=\"alignment\"\n [justify]=\"justify\"\n [readonly]=\"readonly\"\n [value]=\"option.value\"\n >{{ option?.text | translate }}</ion-radio>\n </ion-item>\n }\n </ion-radio-group>\n }\n @else if (type === 'select') {\n <div>\n <ion-select\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n [interface]=\"interface\"\n [mode]=\"'md'\"\n [hidden]=\"hidden || !options?.length\"\n [labelPlacement]=\"labelPlacement\"\n [label]=\"label | translate\"\n [value]=\"value\"\n (click)=\"openSelectOptions($event, interface)\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [interface]=\"interface\" #component>\n @if (options?.length) {\n @for(option of options; track trackItemFn($index, option.text)) {\n <ion-select-option [value]=\"option.value\">\n {{ option.text | translate }}\n </ion-select-option>\n }\n }\n </ion-select>\n <div class=\"dcf-error\" [innerHTML]=\"getErrors(container)\"></div>\n @if (!options?.length) {\n <ion-text color=\"danger\">\n * {{ 'errors.empty_options' | translate:{'0': name} }}\n </ion-text>\n }\n </div>\n }\n @else {\n <ion-input\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n [type]=\"type\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [inputmode]=\"inputmode\"\n [labelPlacement]=\"labelPlacement\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [max]=\"max !== undefined ? max : null\"\n [min]=\"min !== undefined ? min : null\"\n [pattern]=\"pattern !== undefined ? pattern : null\"\n [step]=\"step !== undefined ? step : null\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [label]=\"label | translate\" #component />\n }\n </div>\n </ng-container>\n } @else {\n <div>\n <p class=\"dcf-error\">\n {{ 'errors.form.control' | translate:{'0': name} }}\n </p>\n </div>\n }\n\n}\n\n", styles: ["ion-item{--border-color: transparent}ion-item:not(.dcf-input-item){--inner-padding-start: 0rem;--padding-start: 0rem;--background: transparent}ion-item.dcf-input-item{--padding-end: 0rem;--padding-start: 0px !important;--padding-top: 0px !important;--inner-padding-start: .75rem;--background: transparent;--background-hover-opacity: .1;--background-activated-opacity: .15;--background-focused-opacity: .15;--background-hover: var(--dcf-color-primary);--background-focused: var(--dcf-color-primary);--border-color: var(--dcf-color-gray-2)}ion-item.dcf-input-item.dcf-palette-dark{--border-color: var(--dcf-color-gray-6) !important}ion-item.dcf-input-item.read,ion-item.dcf-input-item.delete{--min-height: 30px;padding:unset;margin:unset!important;margin-bottom:var(--dcf-margin-xsmall)!important}ion-item.dcf-input-item.read ion-label,ion-item.dcf-input-item.delete ion-label{font-weight:600;margin-top:0!important;margin-bottom:.25rem!important;font-size:.925rem}ion-item.dcf-input-item.read ion-label:not(:first-of-type),ion-item.dcf-input-item.delete ion-label:not(:first-of-type){margin:100rem}ion-item.dcf-input-item.read span,ion-item.dcf-input-item.read ion-text,ion-item.dcf-input-item.delete span,ion-item.dcf-input-item.delete ion-text{font-weight:400!important;font-size:.825rem;min-height:.5rem!important}ion-item.dcf-input-item.read span:not(.dcf-display-block),ion-item.dcf-input-item.read ion-text:not(.dcf-display-block),ion-item.dcf-input-item.delete span:not(.dcf-display-block),ion-item.dcf-input-item.delete ion-text:not(.dcf-display-block){display:inline-block}ion-item.dcf-input-item.read span.dcf-display-block,ion-item.dcf-input-item.read ion-text.dcf-display-block,ion-item.dcf-input-item.delete span.dcf-display-block,ion-item.dcf-input-item.delete ion-text.dcf-display-block{display:block!important}ion-item.dcf-input-item>*,ion-item.dcf-input-item ion-select{width:100%!important}ion-item.dcf-input-item.create.checkbox+.checkbox,ion-item.dcf-input-item.update.checkbox+.checkbox{margin-top:-.25rem!important}ion-item.dcf-input-item.create ion-item,ion-item.dcf-input-item.update ion-item{--border-color: transparent}ion-item.dcf-input-item.create ion-item.dcf-text-wrap ion-label>*,ion-item.dcf-input-item.update ion-item.dcf-text-wrap ion-label>*{white-space:wrap!important;word-break:break-all!important}ion-textarea textarea{scrollbar-width:thin!important;margin-bottom:.5rem!important}ion-select.dcf-select-label-placement-floating::part(label){line-height:1.2rem!important}.dcf-proccessing,.dcf-proccessing *{pointer-events:none;touch-action:none;cursor:text}ion-checkbox::part(container){border:2px solid var(--dcf-color-primary);margin-left:.5rem;margin-right:.5rem;border-radius:var(--dcf-border-radius-small);padding:3px}ion-checkbox{--size: 1.5rem;--checkbox-background-checked: var(--dcf-color-primary);--checkmark-width: 2px}ion-radio-group .dcf-radio-group-label{font-weight:600}ion-radio-group .dcf-radio-group-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}ion-radio-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-checkbox-group{width:100%}.dcf-checkbox-group .dcf-label{font-weight:600}.dcf-checkbox-group .dcf-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}.dcf-checkbox-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-error{position:absolute;color:var(--dcf-color-danger)!important;font-size:.8rem!important;font-weight:500!important;line-height:1.1rem;z-index:9999}.dcf-error .ti,.dcf-error ion-icon{position:relative;top:2px!important;min-width:20px;font-size:1rem!important;text-align:left}.dcf-helper{font-size:.875rem!important;font-weight:500;margin-top:.25rem;margin-bottom:-.75rem}.dcf-helper.dcf-has-action{cursor:pointer;text-decoration:underline}.dcf-error+.dcf-helper{padding-top:1rem}::ng-deep ion-textarea{min-height:80px!important;scrollbar-color:#888 #f0f0f0;scrollbar-width:thin}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonRadioGroup, selector: "ion-radio-group", inputs: ["allowEmptySelection", "compareWith", "errorText", "helperText", "name", "value"] }, { kind: "component", type: IonRadio, selector: "ion-radio", inputs: ["alignment", "color", "disabled", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonTextarea, selector: "ion-textarea", inputs: ["autoGrow", "autocapitalize", "autofocus", "clearOnEdit", "color", "cols", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "maxlength", "minlength", "mode", "name", "placeholder", "readonly", "required", "rows", "shape", "spellcheck", "value", "wrap"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
5669
5805
|
};
|
|
5670
5806
|
CrudFieldComponent = __decorate([
|
|
5671
5807
|
Dynamic()
|
|
@@ -5685,7 +5821,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
|
|
|
5685
5821
|
IonLabel,
|
|
5686
5822
|
IonText,
|
|
5687
5823
|
IonTextarea
|
|
5688
|
-
], selector: 'ngx-decaf-crud-field', schemas: [CUSTOM_ELEMENTS_SCHEMA], host: { '[attr.id]': 'uid', '[attr.class]': 'className' }, template: "@if (operation === 'read' || operation === 'delete') {\n <ng-container>\n <div>\n <ion-item [class]=\"'dcf-input-item ' + operation\" #component>\n <ion-label>\n {{ label | translate }}<br />\n @if (value) {\n <ion-text [innerHTML]=\"type === 'password' ? '********' : value\"></ion-text>\n } @else {\n @if (['checkbox'].includes(type)) {\n <ion-icon aria-hidden=\"true\" class=\"dcf-margin-small-top\" [color]=\"!isDarkMode ? 'primary' : 'light'\" size=\"large\" name=\"checkmark-circle-outline\"></ion-icon>\n } @else {\n <br />\n }\n }\n </ion-label>\n </ion-item>\n </div>\n </ng-container>\n} @else {\n @if (formControl) {\n <ng-container [formGroup]=\"multiple ? activeFormGroup : formControl.parent\">\n <div\n\n [id]=\"uid\" #container\n [class]=\"'dcf-input-item ' + (operation || 'create')\"\n [class.dcf-field-required]=\"required\"\n >\n @if (type === 'textarea') {\n <ion-textarea\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [autoGrow]=\"true\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [inputmode]=\"inputmode\"\n [spellcheck]=\"spellcheck\"\n [rows]=\"rows\"\n [labelPlacement]=\"labelPlacement\"\n [value]=\"value\"\n [fill]=\"fill\"\n [errorText]=\"getErrors(container)\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [label]=\"label | translate\"\n #component>\n </ion-textarea>\n }\n @else if (type === 'checkbox') {\n @if (!options?.length) {\n <ion-item class=\"dcf-width-1-1\" [hidden]=\"hidden\">\n <ion-checkbox\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n [mode]=\"'md'\"\n [errorText]=\"getErrors(container)\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify || 'start'\"\n [value]=\"value\"\n [checked]=\"checked\"\n [readonly]=\"readonly\"\n (ionChange)=\"checked = !checked\"\n [formControlName]=\"name\"\n #component>\n <span>{{label | translate}}</span>\n </ion-checkbox>\n\n </ion-item>\n } @else {\n <div class=\"dcf-checkbox-group\">\n <label class=\"dcf-label\" [for]=\"path\">{{ label | translate }}</label>\n @for(option of options; track trackItemFn($index, option.text)) {\n <ion-item class=\"dcf-width-1-1\" [button]=\"true\">\n <ion-checkbox\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"option.text\"\n [mode]=\"'md'\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify\"\n [value]=\"option.value\"\n [readonly]=\"readonly\"\n [checked]=\"isOptionChecked(option.value)\"\n (ionChange)=\"toggleOptionSelection(option.value, $event)\"\n #component>\n <span>{{ $index + 1 }}. {{ option?.text | translate }}</span>\n </ion-checkbox>\n </ion-item>\n }\n <span class=\"dcf-error\" [innerHTML]=\"getErrors(container)\"></span>\n </div>\n }\n\n }\n @else if (type === 'radio' && options?.length) {\n <ion-radio-group class=\"dcf-width-1-1\" [formControlName]=\"name\" [value]=\"value\" #component>\n <label class=\"dcf-radio-group-label\" [for]=\"path\">{{label | translate}}</label>\n @for(option of options; track $index) {\n <ion-item>\n <ion-radio\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n [errorText]=\"getErrors(container)\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [alignment]=\"alignment\"\n [justify]=\"justify\"\n [readonly]=\"readonly\"\n [value]=\"option.value\"\n >{{ option?.text | translate }}</ion-radio>\n </ion-item>\n }\n </ion-radio-group>\n }\n @else if (type === 'select') {\n <div>\n <ion-select\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n [interface]=\"interface\"\n [mode]=\"'md'\"\n [hidden]=\"hidden || !options?.length\"\n [labelPlacement]=\"labelPlacement\"\n [label]=\"label | translate\"\n [value]=\"value\"\n (click)=\"openSelectOptions($event, interface)\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [interface]=\"interface\" #component>\n @if (options?.length) {\n @for(option of options; track trackItemFn($index, option.text)) {\n <ion-select-option [value]=\"option.value\">\n {{ option.text | translate }}\n </ion-select-option>\n }\n }\n </ion-select>\n <div class=\"dcf-error\" [innerHTML]=\"getErrors(container)\"></div>\n @if (!options?.length) {\n <ion-text color=\"danger\">\n * {{ 'errors.empty_options' | translate:{'0': name} }}\n </ion-text>\n }\n </div>\n }\n @else {\n <ion-input\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n [type]=\"type\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [inputmode]=\"inputmode\"\n [labelPlacement]=\"labelPlacement\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [max]=\"max !== undefined ? max : null\"\n [min]=\"min !== undefined ? min : null\"\n [pattern]=\"pattern !== undefined ? pattern : null\"\n [step]=\"step !== undefined ? step : null\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [label]=\"label | translate\" #component />\n }\n </div>\n </ng-container>\n } @else {\n <div>\n <p class=\"dcf-error\">\n {{ 'errors.form.control' | translate:{'0': name} }}\n </p>\n </div>\n }\n\n}\n\n", styles: ["ion-item{--border-color: transparent}ion-item:not(.dcf-input-item){--inner-padding-start: 0rem;--padding-start: 0rem;--background: transparent}ion-item.dcf-input-item{--padding-end: 0rem;--padding-start: 0px !important;--padding-top: 0px !important;--inner-padding-start: .75rem;--background: transparent;--background-hover-opacity: .1;--background-activated-opacity: .15;--background-focused-opacity: .15;--background-hover: var(--dcf-color-primary);--background-focused: var(--dcf-color-primary);--border-color: var(--dcf-color-gray-2)}ion-item.dcf-input-item.dcf-palette-dark{--border-color: var(--dcf-color-gray-6) !important}ion-item.dcf-input-item.read,ion-item.dcf-input-item.delete{--min-height: 30px;padding:unset;margin:unset!important;margin-bottom:var(--dcf-margin-xsmall)!important}ion-item.dcf-input-item.read ion-label,ion-item.dcf-input-item.delete ion-label{font-weight:600;margin-top:0!important;margin-bottom:.25rem!important;font-size:.925rem}ion-item.dcf-input-item.read ion-label:not(:first-of-type),ion-item.dcf-input-item.delete ion-label:not(:first-of-type){margin:100rem}ion-item.dcf-input-item.read span,ion-item.dcf-input-item.read ion-text,ion-item.dcf-input-item.delete span,ion-item.dcf-input-item.delete ion-text{font-weight:400!important;font-size:.825rem;min-height:.5rem!important}ion-item.dcf-input-item.read span:not(.dcf-display-block),ion-item.dcf-input-item.read ion-text:not(.dcf-display-block),ion-item.dcf-input-item.delete span:not(.dcf-display-block),ion-item.dcf-input-item.delete ion-text:not(.dcf-display-block){display:inline-block}ion-item.dcf-input-item.read span.dcf-display-block,ion-item.dcf-input-item.read ion-text.dcf-display-block,ion-item.dcf-input-item.delete span.dcf-display-block,ion-item.dcf-input-item.delete ion-text.dcf-display-block{display:block!important}ion-item.dcf-input-item>*,ion-item.dcf-input-item ion-select{width:100%!important}ion-item.dcf-input-item.create.checkbox+.checkbox,ion-item.dcf-input-item.update.checkbox+.checkbox{margin-top:-.25rem!important}ion-item.dcf-input-item.create ion-item,ion-item.dcf-input-item.update ion-item{--border-color: transparent}ion-item.dcf-input-item.create ion-item.dcf-text-wrap ion-label>*,ion-item.dcf-input-item.update ion-item.dcf-text-wrap ion-label>*{white-space:wrap!important;word-break:break-all!important}ion-textarea textarea{scrollbar-width:thin!important;margin-bottom:.5rem!important}ion-select.dcf-select-label-placement-floating::part(label){line-height:1.2rem!important}.dcf-proccessing,.dcf-proccessing *{pointer-events:none;touch-action:none;cursor:text}ion-checkbox::part(container){border:2px solid var(--dcf-color-primary);margin-left:.5rem;margin-right:.5rem;border-radius:var(--dcf-border-radius-small);padding:3px}ion-checkbox{--size: 1.5rem;--checkbox-background-checked: var(--dcf-color-primary);--checkmark-width: 2px}ion-radio-group .dcf-radio-group-label{font-weight:600}ion-radio-group .dcf-radio-group-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}ion-radio-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-checkbox-group{width:100%}.dcf-checkbox-group .dcf-label{font-weight:600}.dcf-checkbox-group .dcf-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}.dcf-checkbox-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-error{position:absolute;color:var(--dcf-color-danger)!important;font-size:.8rem!important;font-weight:500!important;line-height:1.1rem;z-index:9999}.dcf-error .ti,.dcf-error ion-icon{position:relative;top:2px!important;min-width:20px;font-size:1rem!important;text-align:left}.dcf-helper{font-size:.875rem!important;font-weight:500;margin-top:.25rem;margin-bottom:-.75rem}.dcf-helper.dcf-has-action{cursor:pointer;text-decoration:underline}.dcf-error+.dcf-helper{padding-top:1rem}::ng-deep ion-textarea{min-height:80px!important;scrollbar-color:#888 #f0f0f0;scrollbar-width:thin}\n"] }]
|
|
5824
|
+
], selector: 'ngx-decaf-crud-field', schemas: [CUSTOM_ELEMENTS_SCHEMA], host: { '[attr.id]': 'uid', '[attr.class]': 'className' }, template: "@if (operation === 'read' || operation === 'delete') {\n <ng-container>\n <div>\n <ion-item [class]=\"'dcf-input-item ' + operation\" #component>\n <ion-label>\n {{ label | translate }}<br />\n @if (value) {\n <ion-text [innerHTML]=\"type === 'password' ? '********' : value\"></ion-text>\n } @else {\n @if (['checkbox'].includes(type)) {\n <ion-icon aria-hidden=\"true\" class=\"dcf-margin-small-top\" [color]=\"!isDarkMode ? 'primary' : 'light'\" size=\"large\" name=\"checkmark-circle-outline\"></ion-icon>\n } @else {\n <br />\n }\n }\n </ion-label>\n </ion-item>\n </div>\n </ng-container>\n} @else {\n @if (formControl) {\n <ng-container [formGroup]=\"multiple ? activeFormGroup : formControl.parent\">\n <div\n [id]=\"uid\" #container\n [class]=\"'dcf-input-item ' + (operation || 'create')\"\n [class.dcf-field-required]=\"required\"\n [class.dcf-field-readonly]=\"readonly\"\n >\n @if (type === 'textarea') {\n <ion-textarea\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [autoGrow]=\"true\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [inputmode]=\"inputmode\"\n [spellcheck]=\"spellcheck\"\n [rows]=\"rows\"\n [labelPlacement]=\"labelPlacement\"\n [value]=\"value\"\n [fill]=\"fill\"\n [errorText]=\"getErrors(container)\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [label]=\"label | translate\"\n #component>\n </ion-textarea>\n }\n @else if (type === 'checkbox') {\n @if (!options?.length) {\n <ion-item class=\"dcf-width-1-1\" [hidden]=\"hidden\">\n <ion-checkbox\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n [mode]=\"'md'\"\n [errorText]=\"getErrors(container)\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify || 'start'\"\n [value]=\"value\"\n [checked]=\"checked\"\n [readonly]=\"readonly\"\n (ionChange)=\"checked = !checked\"\n [formControlName]=\"name\"\n #component>\n <span>{{label | translate}}</span>\n </ion-checkbox>\n\n </ion-item>\n } @else {\n <div class=\"dcf-checkbox-group\">\n <label class=\"dcf-label\" [for]=\"path\">{{ label | translate }}</label>\n @for(option of options; track trackItemFn($index, option.text)) {\n <ion-item class=\"dcf-width-1-1\" [button]=\"true\">\n <ion-checkbox\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"option.text\"\n [mode]=\"'md'\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify\"\n [value]=\"option.value\"\n [readonly]=\"readonly\"\n [checked]=\"isOptionChecked(option.value)\"\n (ionChange)=\"toggleOptionSelection(option.value, $event)\"\n #component>\n <span>{{ $index + 1 }}. {{ option?.text | translate }}</span>\n </ion-checkbox>\n </ion-item>\n }\n <span class=\"dcf-error\" [innerHTML]=\"getErrors(container)\"></span>\n </div>\n }\n\n }\n @else if (type === 'radio' && options?.length) {\n <ion-radio-group class=\"dcf-width-1-1\" [formControlName]=\"name\" [value]=\"value\" #component>\n <label class=\"dcf-radio-group-label\" [for]=\"path\">{{label | translate}}</label>\n @for(option of options; track $index) {\n <ion-item>\n <ion-radio\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n [errorText]=\"getErrors(container)\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [alignment]=\"alignment\"\n [justify]=\"justify\"\n [readonly]=\"readonly\"\n [value]=\"option.value\"\n >{{ option?.text | translate }}</ion-radio>\n </ion-item>\n }\n </ion-radio-group>\n }\n @else if (type === 'select') {\n <div>\n <ion-select\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n [interface]=\"interface\"\n [mode]=\"'md'\"\n [hidden]=\"hidden || !options?.length\"\n [labelPlacement]=\"labelPlacement\"\n [label]=\"label | translate\"\n [value]=\"value\"\n (click)=\"openSelectOptions($event, interface)\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [interface]=\"interface\" #component>\n @if (options?.length) {\n @for(option of options; track trackItemFn($index, option.text)) {\n <ion-select-option [value]=\"option.value\">\n {{ option.text | translate }}\n </ion-select-option>\n }\n }\n </ion-select>\n <div class=\"dcf-error\" [innerHTML]=\"getErrors(container)\"></div>\n @if (!options?.length) {\n <ion-text color=\"danger\">\n * {{ 'errors.empty_options' | translate:{'0': name} }}\n </ion-text>\n }\n </div>\n }\n @else {\n <ion-input\n (ionInput)=\"handleModalChildChanges()\"\n (ionChange)=\"handleModalChildChanges()\"\n [id]=\"name\"\n [type]=\"type\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [inputmode]=\"inputmode\"\n [labelPlacement]=\"labelPlacement\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [max]=\"max !== undefined ? max : null\"\n [min]=\"min !== undefined ? min : null\"\n [pattern]=\"pattern !== undefined ? pattern : null\"\n [step]=\"step !== undefined ? step : null\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [label]=\"label | translate\" #component />\n }\n </div>\n </ng-container>\n } @else {\n <div>\n <p class=\"dcf-error\">\n {{ 'errors.form.control' | translate:{'0': name} }}\n </p>\n </div>\n }\n\n}\n\n", styles: ["ion-item{--border-color: transparent}ion-item:not(.dcf-input-item){--inner-padding-start: 0rem;--padding-start: 0rem;--background: transparent}ion-item.dcf-input-item{--padding-end: 0rem;--padding-start: 0px !important;--padding-top: 0px !important;--inner-padding-start: .75rem;--background: transparent;--background-hover-opacity: .1;--background-activated-opacity: .15;--background-focused-opacity: .15;--background-hover: var(--dcf-color-primary);--background-focused: var(--dcf-color-primary);--border-color: var(--dcf-color-gray-2)}ion-item.dcf-input-item.dcf-palette-dark{--border-color: var(--dcf-color-gray-6) !important}ion-item.dcf-input-item.read,ion-item.dcf-input-item.delete{--min-height: 30px;padding:unset;margin:unset!important;margin-bottom:var(--dcf-margin-xsmall)!important}ion-item.dcf-input-item.read ion-label,ion-item.dcf-input-item.delete ion-label{font-weight:600;margin-top:0!important;margin-bottom:.25rem!important;font-size:.925rem}ion-item.dcf-input-item.read ion-label:not(:first-of-type),ion-item.dcf-input-item.delete ion-label:not(:first-of-type){margin:100rem}ion-item.dcf-input-item.read span,ion-item.dcf-input-item.read ion-text,ion-item.dcf-input-item.delete span,ion-item.dcf-input-item.delete ion-text{font-weight:400!important;font-size:.825rem;min-height:.5rem!important}ion-item.dcf-input-item.read span:not(.dcf-display-block),ion-item.dcf-input-item.read ion-text:not(.dcf-display-block),ion-item.dcf-input-item.delete span:not(.dcf-display-block),ion-item.dcf-input-item.delete ion-text:not(.dcf-display-block){display:inline-block}ion-item.dcf-input-item.read span.dcf-display-block,ion-item.dcf-input-item.read ion-text.dcf-display-block,ion-item.dcf-input-item.delete span.dcf-display-block,ion-item.dcf-input-item.delete ion-text.dcf-display-block{display:block!important}ion-item.dcf-input-item>*,ion-item.dcf-input-item ion-select{width:100%!important}ion-item.dcf-input-item.create.checkbox+.checkbox,ion-item.dcf-input-item.update.checkbox+.checkbox{margin-top:-.25rem!important}ion-item.dcf-input-item.create ion-item,ion-item.dcf-input-item.update ion-item{--border-color: transparent}ion-item.dcf-input-item.create ion-item.dcf-text-wrap ion-label>*,ion-item.dcf-input-item.update ion-item.dcf-text-wrap ion-label>*{white-space:wrap!important;word-break:break-all!important}ion-textarea textarea{scrollbar-width:thin!important;margin-bottom:.5rem!important}ion-select.dcf-select-label-placement-floating::part(label){line-height:1.2rem!important}.dcf-proccessing,.dcf-proccessing *{pointer-events:none;touch-action:none;cursor:text}ion-checkbox::part(container){border:2px solid var(--dcf-color-primary);margin-left:.5rem;margin-right:.5rem;border-radius:var(--dcf-border-radius-small);padding:3px}ion-checkbox{--size: 1.5rem;--checkbox-background-checked: var(--dcf-color-primary);--checkmark-width: 2px}ion-radio-group .dcf-radio-group-label{font-weight:600}ion-radio-group .dcf-radio-group-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}ion-radio-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-checkbox-group{width:100%}.dcf-checkbox-group .dcf-label{font-weight:600}.dcf-checkbox-group .dcf-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}.dcf-checkbox-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-error{position:absolute;color:var(--dcf-color-danger)!important;font-size:.8rem!important;font-weight:500!important;line-height:1.1rem;z-index:9999}.dcf-error .ti,.dcf-error ion-icon{position:relative;top:2px!important;min-width:20px;font-size:1rem!important;text-align:left}.dcf-helper{font-size:.875rem!important;font-weight:500;margin-top:.25rem;margin-bottom:-.75rem}.dcf-helper.dcf-has-action{cursor:pointer;text-decoration:underline}.dcf-error+.dcf-helper{padding-top:1rem}::ng-deep ion-textarea{min-height:80px!important;scrollbar-color:#888 #f0f0f0;scrollbar-width:thin}\n"] }]
|
|
5689
5825
|
}], propDecorators: { operation: [{
|
|
5690
5826
|
type: Input,
|
|
5691
5827
|
args: [{ required: true }]
|
|
@@ -5934,7 +6070,7 @@ class NgxFormDirective extends NgxParentComponentDirective {
|
|
|
5934
6070
|
this.formGroup = undefined;
|
|
5935
6071
|
this.initialized = true;
|
|
5936
6072
|
}
|
|
5937
|
-
ngAfterViewInit() {
|
|
6073
|
+
async ngAfterViewInit() {
|
|
5938
6074
|
if (this.isModalChild)
|
|
5939
6075
|
this.changeDetectorRef.detectChanges();
|
|
5940
6076
|
}
|
|
@@ -6002,7 +6138,7 @@ class NgxFormDirective extends NgxParentComponentDirective {
|
|
|
6002
6138
|
return NgxFormService.reset(this.formGroup);
|
|
6003
6139
|
this.location.back();
|
|
6004
6140
|
}
|
|
6005
|
-
async
|
|
6141
|
+
async submit(event, eventName, componentName) {
|
|
6006
6142
|
if (event) {
|
|
6007
6143
|
event.preventDefault();
|
|
6008
6144
|
event.stopImmediatePropagation();
|
|
@@ -6108,10 +6244,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
|
|
|
6108
6244
|
* @param {string} title - Primary title text displayed in the card header.
|
|
6109
6245
|
* @param {('small'|'default'|'blank')} body - Body size preset controlling padding/typography; defaults to 'default'.
|
|
6110
6246
|
* @param {string} subtitle - Optional subtitle rendered under the title.
|
|
6111
|
-
* @param {
|
|
6247
|
+
* @param {Color} color - Ionic color token applied to the card header/title.
|
|
6112
6248
|
* @param {boolean} separator - When true, renders a divider between header and body.
|
|
6113
6249
|
* @param {boolean} borders - Controls whether borders are rendered; defaults to true.
|
|
6114
|
-
* @param {string|
|
|
6250
|
+
* @param {string|SafeHtml} inlineContent - Inline HTML/SafeHtml to render inside the body.
|
|
6115
6251
|
* @param {('top'|'bottom')} inlineContentPosition - Where to render `inlineContent` relative to the body; defaults to 'bottom'.
|
|
6116
6252
|
* @return {void}
|
|
6117
6253
|
* @class CardComponent
|
|
@@ -6173,7 +6309,7 @@ let CardComponent = class CardComponent extends NgxComponentDirective {
|
|
|
6173
6309
|
/**
|
|
6174
6310
|
* @description Ionic color token applied to the card.
|
|
6175
6311
|
* @summary When provided, the color token (for example 'primary' or 'tertiary') is applied to title/header elements where supported.
|
|
6176
|
-
* @type {
|
|
6312
|
+
* @type {Color}
|
|
6177
6313
|
* @default ''
|
|
6178
6314
|
*/
|
|
6179
6315
|
this.color = '';
|
|
@@ -6215,7 +6351,6 @@ let CardComponent = class CardComponent extends NgxComponentDirective {
|
|
|
6215
6351
|
* @return {void}
|
|
6216
6352
|
*/
|
|
6217
6353
|
ngOnInit() {
|
|
6218
|
-
console.log(this.componentName, this.borders);
|
|
6219
6354
|
this.mediaService.isDarkMode().subscribe(isDark => {
|
|
6220
6355
|
this.isDarkMode = isDark;
|
|
6221
6356
|
this.mediaService.toggleClass([this.component], AngularEngineKeys.DARK_PALETTE_CLASS, this.isDarkMode);
|
|
@@ -6473,7 +6608,7 @@ let LayoutComponent = class LayoutComponent extends NgxParentComponentDirective
|
|
|
6473
6608
|
this.changeDetectorRef.detectChanges();
|
|
6474
6609
|
}
|
|
6475
6610
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6476
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: LayoutComponent, isStandalone: true, selector: "ngx-decaf-layout", inputs: { gap: "gap", grid: "grid", flexMode: "flexMode", rowCard: "rowCard", maxColsLength: "maxColsLength" }, usesInheritance: true, ngImport: i0, template: "<section class=\"dcf-layout-container\">\n @if (initialized) {\n @for (row of rows; track trackItemFn($index, row); let rowIndex = $index) {\n @if (row?.cols?.length) {\n <div\n [id]=\"uid\"\n [class]=\"\n (!grid\n ? 'dcf-layout-row '\n : 'dcf-layout-row dcf-grid ' + 'dcf-grid-' + gap) +\n ' ' +\n (className || '')\n \"\n [class.dcf-grid-match]=\"match\"\n [class.dcf-grid-bordered]=\"borders\"\n >\n @if (row?.title?.length) {\n <div class=\"dcf-width-1-1 dcf-grid-title\">\n <h3 class=\"\">{{ row.title | translate }}</h3>\n </div>\n }\n @for (\n child of row.cols;\n track trackItemFn($index, child.col);\n let colIndex = $index\n ) {\n\n <div\n [class]=\"'dcf-grid-col ' + child.colClass\"\n [class.dcf-first-column]=\"$index === 0\"\n [class.dcf-layout-separator]=\"child.props?.separator ?? false\"\n >\n <div>\n\n @if (child.tag === \"ngx-decaf-crud-form\") {\n\n <ngx-decaf-card\n [className]=\"\n (match ? 'dcf-height-1-1 dcf-card-layout' : '') +\n className\n \"\n [body]=\"cardBody\"\n [type]=\"cardType\"\n >\n <ngx-decaf-model-renderer\n [model]=\"child.props.name\"\n (listenEvent)=\"handleEvent($event)\"\n />\n </ngx-decaf-card>\n } @else {\n\n <ngx-decaf-component-renderer\n [tag]=\"child.tag\"\n [className]=\"\n (match ? 'dcf-height-1-1 dcf-card-layout' : '') +\n className\n \"\n [parentForm]=\"parentForm || child.parentForm || child?.formGroup\"\n [children]=\"child?.children || []\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]=\"{ props: child.props }\"\n />\n }\n </div>\n </div>\n }\n </div>\n }\n }\n }\n</section>\n", styles: [".dcf-grid.dcf-grid-bordered>div>div{padding:var(--dcf-padding-small) var(--dcf-padding);border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-2);background:var(--dcf-card-background)!important}.dcf-grid .dcf-grid-title{padding:unset;margin:unset}.dcf-grid .dcf-grid-title>*{padding:unset;margin:unset;padding-left:var(--dcf-padding-small);font-size:1.05rem!important;font-weight:600;background:none;box-shadow:none;display:flex;align-items:center;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.dcf-grid.dcf-grid-match ::ng-deep ngx-decaf-component-renderer>*>*{height:100%!important}.dcf-grid.dcf-grid-small.dcf-grid-nested{padding:0 .5rem!important}.dcf-grid.dcf-grid-small>div{margin-bottom:1.75rem}.dcf-grid.dcf-grid-small>div.dcf-layout-separator{margin-bottom:1rem}.dcf-grid.dcf-grid-small>div.dcf-grid-bordered:last-child{margin-bottom:0}.dcf-grid.dcf-grid-small+.dcf-grid-small{margin-bottom:1.75rem}.dcf-grid.dcf-grid-small+.dcf-grid-small.dcf-layout-separator{margin-bottom:1rem}::ng-deep ngx-decaf-component-renderer>*>div{margin-bottom:0!important}\n"], dependencies: [{ kind: "component", type: CardComponent, selector: "ngx-decaf-card", inputs: ["type", "title", "body", "subtitle", "color", "separator", "borders", "inlineContent", "inlineContentPosition"] }, { kind: "component", type: ModelRendererComponent, selector: "ngx-decaf-model-renderer", inputs: ["projectable"] }, { kind: "component", type: ComponentRendererComponent, selector: "ngx-decaf-component-renderer", inputs: ["tag", "children", "projectable", "parent"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
6611
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: LayoutComponent, isStandalone: true, selector: "ngx-decaf-layout", inputs: { gap: "gap", grid: "grid", flexMode: "flexMode", rowCard: "rowCard", maxColsLength: "maxColsLength" }, usesInheritance: true, ngImport: i0, template: "<section class=\"dcf-layout-container\">\n @if (initialized) {\n @for (row of rows; track trackItemFn($index, row); let rowIndex = $index) {\n @if (row?.cols?.length) {\n <div\n [id]=\"uid\"\n [class]=\"\n (!grid\n ? 'dcf-layout-row '\n : 'dcf-layout-row dcf-grid ' + 'dcf-grid-' + gap) +\n ' ' +\n (className || '')\n \"\n [class.dcf-grid-match]=\"match\"\n [class.dcf-grid-bordered]=\"borders\"\n >\n @if (row?.title?.length) {\n <div class=\"dcf-width-1-1 dcf-grid-title\">\n <h3 class=\"\">{{ row.title | translate }}</h3>\n </div>\n }\n @for (\n child of row.cols;\n track trackItemFn($index, child.col);\n let colIndex = $index\n ) {\n\n <div\n [class]=\"'dcf-grid-col ' + child.colClass\"\n [class.dcf-first-column]=\"$index === 0\"\n [class.dcf-layout-separator]=\"child.props?.separator ?? false\"\n >\n <div>\n\n @if (child.tag === \"ngx-decaf-crud-form\") {\n\n <ngx-decaf-card\n [className]=\"\n (match ? 'dcf-height-1-1 dcf-card-layout' : '') +\n className\n \"\n [body]=\"cardBody\"\n [type]=\"cardType\"\n >\n <ngx-decaf-model-renderer\n [model]=\"child.props.name\"\n (listenEvent)=\"handleEvent($event)\"\n />\n </ngx-decaf-card>\n } @else {\n\n <ngx-decaf-component-renderer\n [tag]=\"child.tag\"\n [className]=\"\n (match ? 'dcf-height-1-1 dcf-card-layout' : '') +\n className\n \"\n [parentForm]=\"parentForm || child.parentForm || child?.formGroup\"\n [children]=\"child?.children || []\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]=\"{ props: child.props }\"\n />\n }\n </div>\n </div>\n }\n </div>\n }\n }\n }\n</section>\n", styles: [".dcf-grid.dcf-grid-collapse.read>div{margin:var(--dcf-margin-small) 0!important}.dcf-grid.dcf-grid-bordered>div>div{padding:var(--dcf-padding-small) var(--dcf-padding);border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-2);background:var(--dcf-card-background)!important}.dcf-grid .dcf-grid-title{padding:unset;margin:unset}.dcf-grid .dcf-grid-title>*{padding:unset;margin:unset;padding-left:var(--dcf-padding-small);font-size:1.05rem!important;font-weight:600;background:none;box-shadow:none;display:flex;align-items:center;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.dcf-grid.dcf-grid-match ::ng-deep ngx-decaf-component-renderer>*>*{height:100%!important}.dcf-grid.dcf-grid-small.dcf-grid-nested{padding:0 .5rem!important}.dcf-grid.dcf-grid-small>div{margin-bottom:1.75rem}.dcf-grid.dcf-grid-small>div.dcf-layout-separator{margin-bottom:1rem}.dcf-grid.dcf-grid-small>div.dcf-grid-bordered:last-child{margin-bottom:0}.dcf-grid.dcf-grid-small+.dcf-grid-small{margin-bottom:1.75rem}.dcf-grid.dcf-grid-small+.dcf-grid-small.dcf-layout-separator{margin-bottom:1rem}::ng-deep ngx-decaf-component-renderer>*>div{margin-bottom:0!important}\n"], dependencies: [{ kind: "component", type: CardComponent, selector: "ngx-decaf-card", inputs: ["type", "title", "body", "subtitle", "color", "separator", "borders", "inlineContent", "inlineContentPosition"] }, { kind: "component", type: ModelRendererComponent, selector: "ngx-decaf-model-renderer", inputs: ["projectable"] }, { kind: "component", type: ComponentRendererComponent, selector: "ngx-decaf-component-renderer", inputs: ["tag", "children", "projectable", "parent"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
6477
6612
|
};
|
|
6478
6613
|
LayoutComponent = __decorate([
|
|
6479
6614
|
Dynamic(),
|
|
@@ -6481,7 +6616,7 @@ LayoutComponent = __decorate([
|
|
|
6481
6616
|
], LayoutComponent);
|
|
6482
6617
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LayoutComponent, decorators: [{
|
|
6483
6618
|
type: Component,
|
|
6484
|
-
args: [{ selector: 'ngx-decaf-layout', imports: [TranslatePipe, CardComponent, ModelRendererComponent, ComponentRendererComponent], standalone: true, template: "<section class=\"dcf-layout-container\">\n @if (initialized) {\n @for (row of rows; track trackItemFn($index, row); let rowIndex = $index) {\n @if (row?.cols?.length) {\n <div\n [id]=\"uid\"\n [class]=\"\n (!grid\n ? 'dcf-layout-row '\n : 'dcf-layout-row dcf-grid ' + 'dcf-grid-' + gap) +\n ' ' +\n (className || '')\n \"\n [class.dcf-grid-match]=\"match\"\n [class.dcf-grid-bordered]=\"borders\"\n >\n @if (row?.title?.length) {\n <div class=\"dcf-width-1-1 dcf-grid-title\">\n <h3 class=\"\">{{ row.title | translate }}</h3>\n </div>\n }\n @for (\n child of row.cols;\n track trackItemFn($index, child.col);\n let colIndex = $index\n ) {\n\n <div\n [class]=\"'dcf-grid-col ' + child.colClass\"\n [class.dcf-first-column]=\"$index === 0\"\n [class.dcf-layout-separator]=\"child.props?.separator ?? false\"\n >\n <div>\n\n @if (child.tag === \"ngx-decaf-crud-form\") {\n\n <ngx-decaf-card\n [className]=\"\n (match ? 'dcf-height-1-1 dcf-card-layout' : '') +\n className\n \"\n [body]=\"cardBody\"\n [type]=\"cardType\"\n >\n <ngx-decaf-model-renderer\n [model]=\"child.props.name\"\n (listenEvent)=\"handleEvent($event)\"\n />\n </ngx-decaf-card>\n } @else {\n\n <ngx-decaf-component-renderer\n [tag]=\"child.tag\"\n [className]=\"\n (match ? 'dcf-height-1-1 dcf-card-layout' : '') +\n className\n \"\n [parentForm]=\"parentForm || child.parentForm || child?.formGroup\"\n [children]=\"child?.children || []\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]=\"{ props: child.props }\"\n />\n }\n </div>\n </div>\n }\n </div>\n }\n }\n }\n</section>\n", styles: [".dcf-grid.dcf-grid-bordered>div>div{padding:var(--dcf-padding-small) var(--dcf-padding);border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-2);background:var(--dcf-card-background)!important}.dcf-grid .dcf-grid-title{padding:unset;margin:unset}.dcf-grid .dcf-grid-title>*{padding:unset;margin:unset;padding-left:var(--dcf-padding-small);font-size:1.05rem!important;font-weight:600;background:none;box-shadow:none;display:flex;align-items:center;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.dcf-grid.dcf-grid-match ::ng-deep ngx-decaf-component-renderer>*>*{height:100%!important}.dcf-grid.dcf-grid-small.dcf-grid-nested{padding:0 .5rem!important}.dcf-grid.dcf-grid-small>div{margin-bottom:1.75rem}.dcf-grid.dcf-grid-small>div.dcf-layout-separator{margin-bottom:1rem}.dcf-grid.dcf-grid-small>div.dcf-grid-bordered:last-child{margin-bottom:0}.dcf-grid.dcf-grid-small+.dcf-grid-small{margin-bottom:1.75rem}.dcf-grid.dcf-grid-small+.dcf-grid-small.dcf-layout-separator{margin-bottom:1rem}::ng-deep ngx-decaf-component-renderer>*>div{margin-bottom:0!important}\n"] }]
|
|
6619
|
+
args: [{ selector: 'ngx-decaf-layout', imports: [TranslatePipe, CardComponent, ModelRendererComponent, ComponentRendererComponent], standalone: true, template: "<section class=\"dcf-layout-container\">\n @if (initialized) {\n @for (row of rows; track trackItemFn($index, row); let rowIndex = $index) {\n @if (row?.cols?.length) {\n <div\n [id]=\"uid\"\n [class]=\"\n (!grid\n ? 'dcf-layout-row '\n : 'dcf-layout-row dcf-grid ' + 'dcf-grid-' + gap) +\n ' ' +\n (className || '')\n \"\n [class.dcf-grid-match]=\"match\"\n [class.dcf-grid-bordered]=\"borders\"\n >\n @if (row?.title?.length) {\n <div class=\"dcf-width-1-1 dcf-grid-title\">\n <h3 class=\"\">{{ row.title | translate }}</h3>\n </div>\n }\n @for (\n child of row.cols;\n track trackItemFn($index, child.col);\n let colIndex = $index\n ) {\n\n <div\n [class]=\"'dcf-grid-col ' + child.colClass\"\n [class.dcf-first-column]=\"$index === 0\"\n [class.dcf-layout-separator]=\"child.props?.separator ?? false\"\n >\n <div>\n\n @if (child.tag === \"ngx-decaf-crud-form\") {\n\n <ngx-decaf-card\n [className]=\"\n (match ? 'dcf-height-1-1 dcf-card-layout' : '') +\n className\n \"\n [body]=\"cardBody\"\n [type]=\"cardType\"\n >\n <ngx-decaf-model-renderer\n [model]=\"child.props.name\"\n (listenEvent)=\"handleEvent($event)\"\n />\n </ngx-decaf-card>\n } @else {\n\n <ngx-decaf-component-renderer\n [tag]=\"child.tag\"\n [className]=\"\n (match ? 'dcf-height-1-1 dcf-card-layout' : '') +\n className\n \"\n [parentForm]=\"parentForm || child.parentForm || child?.formGroup\"\n [children]=\"child?.children || []\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]=\"{ props: child.props }\"\n />\n }\n </div>\n </div>\n }\n </div>\n }\n }\n }\n</section>\n", styles: [".dcf-grid.dcf-grid-collapse.read>div{margin:var(--dcf-margin-small) 0!important}.dcf-grid.dcf-grid-bordered>div>div{padding:var(--dcf-padding-small) var(--dcf-padding);border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-2);background:var(--dcf-card-background)!important}.dcf-grid .dcf-grid-title{padding:unset;margin:unset}.dcf-grid .dcf-grid-title>*{padding:unset;margin:unset;padding-left:var(--dcf-padding-small);font-size:1.05rem!important;font-weight:600;background:none;box-shadow:none;display:flex;align-items:center;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.dcf-grid.dcf-grid-match ::ng-deep ngx-decaf-component-renderer>*>*{height:100%!important}.dcf-grid.dcf-grid-small.dcf-grid-nested{padding:0 .5rem!important}.dcf-grid.dcf-grid-small>div{margin-bottom:1.75rem}.dcf-grid.dcf-grid-small>div.dcf-layout-separator{margin-bottom:1rem}.dcf-grid.dcf-grid-small>div.dcf-grid-bordered:last-child{margin-bottom:0}.dcf-grid.dcf-grid-small+.dcf-grid-small{margin-bottom:1.75rem}.dcf-grid.dcf-grid-small+.dcf-grid-small.dcf-layout-separator{margin-bottom:1rem}::ng-deep ngx-decaf-component-renderer>*>div{margin-bottom:0!important}\n"] }]
|
|
6485
6620
|
}], ctorParameters: () => [], propDecorators: { gap: [{
|
|
6486
6621
|
type: Input
|
|
6487
6622
|
}], grid: [{
|
|
@@ -6530,7 +6665,7 @@ let CrudFormComponent = class CrudFormComponent extends NgxFormDirective {
|
|
|
6530
6665
|
});
|
|
6531
6666
|
}
|
|
6532
6667
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: CrudFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6533
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: CrudFormComponent, isStandalone: true, selector: "ngx-decaf-crud-form", host: { properties: { "attr.id": "uid" } }, usesInheritance: true, ngImport: i0, template: "@if (operation !== 'read' && operation !== 'delete') {\n <form\n [class]=\"'dcf-form-grid ' + operation\" #component\n [id]=\"rendererId\"\n [formGroup]=\"formGroup\"\n (ngSubmit)=\"
|
|
6668
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: CrudFormComponent, isStandalone: true, selector: "ngx-decaf-crud-form", host: { properties: { "attr.id": "uid" } }, usesInheritance: true, ngImport: i0, template: "@if (operation !== 'read' && operation !== 'delete') {\n <form\n [class]=\"'dcf-form-grid ' + operation\" #component\n [id]=\"rendererId\"\n [formGroup]=\"formGroup\"\n (ngSubmit)=\"submit($event)\"\n novalidate\n [target]=\"target\">\n @if (!children?.length) {\n <ng-content #formContent></ng-content>\n } @else {\n <ngx-decaf-layout\n [className]=\"'dcf-crud-form-grid dcf-grid-nested '\"\n [children]=\"children || []\"\n [parentForm]=\"formGroup || parentForm\"\n [match]=\"match ?? false\"\n [gap]=\"'small'\"\n [flexMode]=\"props.flexMode || false\"\n [rows]=\"rows\"\n [borders]=\"borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [cols]=\"cols\" />\n }\n @if (initialized) {\n <div class=\"dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-left\">\n <div>\n <ion-button type=\"submit\" [expand]=\"action ? 'block' : 'default'\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{ action ? action : options.buttons.submit.text}}\n </ion-button>\n </div>\n @if (!action) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if (options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n Back\n </ion-button>\n </div>\n }\n </div>\n }\n\n </form>\n} @else {\n <section [class]=\"'dcf-grid dcf-grid-small dcf-child-width-1-1 dcf-form-grid ' + operation\" #component [id]=\"uid\">\n @if (!children?.length) {\n <ng-content #formContent></ng-content>\n } @else {\n @for (child of children; track $index) {\n <div class=\"dcf-form-item\">\n <ngx-decaf-component-renderer\n [tag]=\"child?.tag\"\n [projectable]=\"false\"\n [children]=\"child?.children || []\"\n [globals]=\"{props: child.props}\"\n />\n </div>\n }\n }\n </section>\n <section [class]=\"'dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-left ' + operation\" [id]=\"uid\">\n @if ([OperationKeys.READ, OperationKeys.DELETE].includes(operation) && modelId) {\n <div>\n <ion-button\n (click)=\"handleDelete()\"\n color=\"danger\"\n type=\"button\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n Delete\n </ion-button>\n </div>\n\n }\n @if (operation === OperationKeys.CREATE || operation === OperationKeys.UPDATE) {\n\n <div>\n <ion-button\n type=\"submit\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{options.buttons.submit.text}}\n </ion-button>\n </div>\n }\n\n @if (options.buttons.clear) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if (options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n {{ [OperationKeys.DELETE, OperationKeys.READ, OperationKeys.UPDATE].includes(operation) ? 'Back' : options.buttons.clear?.text}}\n </ion-button>\n </div>\n\n }\n </section>\n}\n\n", styles: [".dcf-buttons-grid{margin-top:var(--dcf-margin-medium);margin-bottom:var(--dcf-margin)}@media (min-width: 577px){.dcf-buttons-grid.dcf-flex{flex-direction:row-reverse}}@media (max-width: 576px){.dcf-buttons-grid.dcf-flex>div{width:100%}.dcf-buttons-grid.dcf-flex>div+div{margin-top:1rem}.dcf-buttons-grid.dcf-flex ion-button{width:100%}}.dcf-form-grid.create,.dcf-form-grid.update{margin-top:var(--dcf-margin-small)}.dcf-form-grid .dcf-form-item{margin-top:0!important}.dcf-form-grid.read .dcf-form-item{margin-bottom:var(--dcf-margin-small)}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: LayoutComponent, selector: "ngx-decaf-layout", inputs: ["gap", "grid", "flexMode", "rowCard", "maxColsLength"] }, { kind: "component", type: ComponentRendererComponent, selector: "ngx-decaf-component-renderer", inputs: ["tag", "children", "projectable", "parent"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
|
|
6534
6669
|
};
|
|
6535
6670
|
CrudFormComponent = __decorate([
|
|
6536
6671
|
Dynamic(),
|
|
@@ -6538,7 +6673,7 @@ CrudFormComponent = __decorate([
|
|
|
6538
6673
|
], CrudFormComponent);
|
|
6539
6674
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: CrudFormComponent, decorators: [{
|
|
6540
6675
|
type: Component,
|
|
6541
|
-
args: [{ standalone: true, selector: 'ngx-decaf-crud-form', imports: [ReactiveFormsModule, LayoutComponent, ComponentRendererComponent, IonButton, IonIcon], host: { '[attr.id]': 'uid' }, template: "@if (operation !== 'read' && operation !== 'delete') {\n <form\n [class]=\"'dcf-form-grid ' + operation\" #component\n [id]=\"rendererId\"\n [formGroup]=\"formGroup\"\n (ngSubmit)=\"
|
|
6676
|
+
args: [{ standalone: true, selector: 'ngx-decaf-crud-form', imports: [ReactiveFormsModule, LayoutComponent, ComponentRendererComponent, IonButton, IonIcon], host: { '[attr.id]': 'uid' }, template: "@if (operation !== 'read' && operation !== 'delete') {\n <form\n [class]=\"'dcf-form-grid ' + operation\" #component\n [id]=\"rendererId\"\n [formGroup]=\"formGroup\"\n (ngSubmit)=\"submit($event)\"\n novalidate\n [target]=\"target\">\n @if (!children?.length) {\n <ng-content #formContent></ng-content>\n } @else {\n <ngx-decaf-layout\n [className]=\"'dcf-crud-form-grid dcf-grid-nested '\"\n [children]=\"children || []\"\n [parentForm]=\"formGroup || parentForm\"\n [match]=\"match ?? false\"\n [gap]=\"'small'\"\n [flexMode]=\"props.flexMode || false\"\n [rows]=\"rows\"\n [borders]=\"borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [cols]=\"cols\" />\n }\n @if (initialized) {\n <div class=\"dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-left\">\n <div>\n <ion-button type=\"submit\" [expand]=\"action ? 'block' : 'default'\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{ action ? action : options.buttons.submit.text}}\n </ion-button>\n </div>\n @if (!action) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if (options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n Back\n </ion-button>\n </div>\n }\n </div>\n }\n\n </form>\n} @else {\n <section [class]=\"'dcf-grid dcf-grid-small dcf-child-width-1-1 dcf-form-grid ' + operation\" #component [id]=\"uid\">\n @if (!children?.length) {\n <ng-content #formContent></ng-content>\n } @else {\n @for (child of children; track $index) {\n <div class=\"dcf-form-item\">\n <ngx-decaf-component-renderer\n [tag]=\"child?.tag\"\n [projectable]=\"false\"\n [children]=\"child?.children || []\"\n [globals]=\"{props: child.props}\"\n />\n </div>\n }\n }\n </section>\n <section [class]=\"'dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-left ' + operation\" [id]=\"uid\">\n @if ([OperationKeys.READ, OperationKeys.DELETE].includes(operation) && modelId) {\n <div>\n <ion-button\n (click)=\"handleDelete()\"\n color=\"danger\"\n type=\"button\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n Delete\n </ion-button>\n </div>\n\n }\n @if (operation === OperationKeys.CREATE || operation === OperationKeys.UPDATE) {\n\n <div>\n <ion-button\n type=\"submit\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{options.buttons.submit.text}}\n </ion-button>\n </div>\n }\n\n @if (options.buttons.clear) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if (options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n {{ [OperationKeys.DELETE, OperationKeys.READ, OperationKeys.UPDATE].includes(operation) ? 'Back' : options.buttons.clear?.text}}\n </ion-button>\n </div>\n\n }\n </section>\n}\n\n", styles: [".dcf-buttons-grid{margin-top:var(--dcf-margin-medium);margin-bottom:var(--dcf-margin)}@media (min-width: 577px){.dcf-buttons-grid.dcf-flex{flex-direction:row-reverse}}@media (max-width: 576px){.dcf-buttons-grid.dcf-flex>div{width:100%}.dcf-buttons-grid.dcf-flex>div+div{margin-top:1rem}.dcf-buttons-grid.dcf-flex ion-button{width:100%}}.dcf-form-grid.create,.dcf-form-grid.update{margin-top:var(--dcf-margin-small)}.dcf-form-grid .dcf-form-item{margin-top:0!important}.dcf-form-grid.read .dcf-form-item{margin-bottom:var(--dcf-margin-small)}\n"] }]
|
|
6542
6677
|
}], ctorParameters: () => [] });
|
|
6543
6678
|
|
|
6544
6679
|
class NgxSvgDirective {
|
|
@@ -6589,12 +6724,10 @@ let IconComponent = class IconComponent {
|
|
|
6589
6724
|
this.type = 'image';
|
|
6590
6725
|
this.isSvg = this.name.endsWith('.svg');
|
|
6591
6726
|
}
|
|
6592
|
-
this.initialized = true;
|
|
6593
|
-
}
|
|
6594
|
-
ngAfterViewInit() {
|
|
6595
6727
|
this.mediaService.isDarkMode().subscribe(isDark => {
|
|
6596
6728
|
this.isDarkMode = isDark;
|
|
6597
6729
|
});
|
|
6730
|
+
this.initialized = true;
|
|
6598
6731
|
}
|
|
6599
6732
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: IconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6600
6733
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: IconComponent, isStandalone: true, selector: "ngx-decaf-icon", inputs: { name: "name", color: "color", slot: "slot", button: "button", buttonFill: "buttonFill", buttonShape: "buttonShape", width: "width", size: "size", inline: "inline" }, host: { properties: { "attr.id": "uid", "attr.aria-hidden": "!button" } }, viewQueries: [{ propertyName: "component", first: true, predicate: ["component"], descendants: true, read: ElementRef }], ngImport: i0, template: "<div class=\"dcf-icon\" #component>\n @if (initialized) {\n @if (button) {\n <ion-button [fill]=\"buttonFill\" [shape]=\"buttonShape\" [color]=\"isDarkMode ? 'light' : color\" [size]=\"size\">\n @if (type === \"image\") {\n @if (isSvg) {\n <span\n aria-hidden=\"true\"\n [slot]=\"slot\"\n [class]=\"color ? 'dcf-color-' + color : ''\"\n [style.width]=\"width\"\n [ngx-decaf-svg]=\"name\"\n >\n ></span\n >\n } @else {\n <img\n aria-hidden=\"true\"\n [alt]=\"name\"\n [title]=\"name\"\n [slot]=\"slot\"\n [src]=\"name\"\n [style.width]=\"width\"\n title=\"icon\"\n />\n }\n } @else {\n <ion-icon\n aria-hidden=\"true\"\n [slot]=\"slot\"\n [ios]=\"name\"\n [md]=\"name\"\n [color]=\"isDarkMode ? 'light' : color\"\n [name]=\"name\"\n />\n }\n </ion-button>\n } @else {\n @if (type === \"image\") {\n @if (isSvg) {\n <span\n aria-hidden=\"true\"\n [slot]=\"slot\"\n [class]=\"color ? 'dcf-color-' + color : ''\"\n [style.width]=\"width\"\n [ngx-decaf-svg]=\"name\"\n >\n </span>\n } @else {\n <img\n aria-hidden=\"true\"\n [alt]=\"name\"\n [title]=\"name\"\n [slot]=\"slot\"\n [src]=\"name\"\n [style.width]=\"width\"\n title=\"icon\"\n />\n }\n }\n @if (type === \"ionic\") {\n <ion-icon\n aria-hidden=\"true\"\n [slot]=\"slot\"\n [ios]=\"name\"\n [md]=\"name\"\n [size]=\"size\"\n [color]=\"isDarkMode ? 'light' : color\"\n [name]=\"name\"\n />\n }\n }\n }\n</div>\n", styles: ["::ng-deep .dcf-icon.dcf-palette-dark ion-icon{color:var(--dcf-text-color)!important}::ng-deep .dcf-icon.dcf-palette-dark svg{fill:var(--dcf-text-color);fill-opacity:.25!important;stroke:var(--dcf-text-color)!important}::ng-deep .dcf-icon.dcf-palette-dark svg *{fill:var(--dcf-color-primary)!important;stroke:var(--dcf-color-gray-1)!important}ion-button{cursor:pointer!important}.dcf-icon ion-icon:not([size]){font-size:1.35rem!important}\n"], dependencies: [{ kind: "directive", type: NgxSvgDirective, selector: "[ngx-decaf-svg]", inputs: ["ngx-decaf-svg"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }] }); }
|
|
@@ -7021,7 +7154,7 @@ let FieldsetComponent = class FieldsetComponent extends NgxFormDirective {
|
|
|
7021
7154
|
* @memberOf FieldsetComponent
|
|
7022
7155
|
*/
|
|
7023
7156
|
constructor() {
|
|
7024
|
-
super(
|
|
7157
|
+
super('FieldsetComponent');
|
|
7025
7158
|
/**
|
|
7026
7159
|
* @description The parent component identifier for hierarchical fieldset relationships.
|
|
7027
7160
|
* @summary Specifies the parent component name that this fieldset belongs to in a hierarchical
|
|
@@ -7175,6 +7308,7 @@ let FieldsetComponent = class FieldsetComponent extends NgxFormDirective {
|
|
|
7175
7308
|
* @memberOf FieldsetComponent
|
|
7176
7309
|
*/
|
|
7177
7310
|
async ngOnInit() {
|
|
7311
|
+
console.log(this.title);
|
|
7178
7312
|
await super.ngOnInit(this.model);
|
|
7179
7313
|
if (this.max && this.max === 1)
|
|
7180
7314
|
this.multiple = false;
|
|
@@ -7196,8 +7330,10 @@ let FieldsetComponent = class FieldsetComponent extends NgxFormDirective {
|
|
|
7196
7330
|
}
|
|
7197
7331
|
if (!this.formGroup && this.parentForm instanceof FormArray)
|
|
7198
7332
|
this.formGroup = this.parentForm;
|
|
7199
|
-
if (!this.formGroup &&
|
|
7200
|
-
this.
|
|
7333
|
+
if (!this.formGroup &&
|
|
7334
|
+
this.children[0]?.['formGroup'] instanceof FormGroup)
|
|
7335
|
+
this.formGroup = this.children[0]?.['formGroup']
|
|
7336
|
+
.parent;
|
|
7201
7337
|
if (this.formGroup && !(this.formGroup instanceof FormArray))
|
|
7202
7338
|
this.formGroup = this.formGroup?.parent;
|
|
7203
7339
|
}
|
|
@@ -7216,36 +7352,36 @@ let FieldsetComponent = class FieldsetComponent extends NgxFormDirective {
|
|
|
7216
7352
|
this.initialized = true;
|
|
7217
7353
|
}
|
|
7218
7354
|
/**
|
|
7219
|
-
|
|
7220
|
-
|
|
7221
|
-
|
|
7222
|
-
|
|
7223
|
-
|
|
7224
|
-
|
|
7225
|
-
|
|
7226
|
-
|
|
7227
|
-
|
|
7228
|
-
|
|
7229
|
-
|
|
7230
|
-
|
|
7231
|
-
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
|
|
7235
|
-
|
|
7236
|
-
|
|
7237
|
-
|
|
7238
|
-
|
|
7239
|
-
|
|
7240
|
-
|
|
7241
|
-
|
|
7242
|
-
|
|
7243
|
-
|
|
7244
|
-
|
|
7245
|
-
|
|
7246
|
-
|
|
7247
|
-
ngAfterViewInit() {
|
|
7248
|
-
super.ngAfterViewInit();
|
|
7355
|
+
* @description Initializes the component state after view and child components are rendered.
|
|
7356
|
+
* @summary This lifecycle hook implements intelligent auto-state management based on the current
|
|
7357
|
+
* CRUD operation. For READ and DELETE operations, the fieldset automatically opens to provide
|
|
7358
|
+
* immediate access to information, while CREATE and UPDATE operations keep it closed to maintain
|
|
7359
|
+
* a clean initial interface. The method directly manipulates the DOM to ensure proper accordion
|
|
7360
|
+
* synchronization and triggers change detection to reflect the programmatic state changes.
|
|
7361
|
+
*
|
|
7362
|
+
* @mermaid
|
|
7363
|
+
* sequenceDiagram
|
|
7364
|
+
* participant A as Angular Lifecycle
|
|
7365
|
+
* participant F as FieldsetComponent
|
|
7366
|
+
* participant D as DOM
|
|
7367
|
+
* participant C as ChangeDetector
|
|
7368
|
+
*
|
|
7369
|
+
* A->>F: ngAfterViewInit()
|
|
7370
|
+
* alt operation is READ or DELETE
|
|
7371
|
+
* F->>F: Set isOpen = true
|
|
7372
|
+
* F->>D: Query ion-accordion-group element
|
|
7373
|
+
* alt accordion element exists
|
|
7374
|
+
* F->>D: Set value attribute to 'open'
|
|
7375
|
+
* end
|
|
7376
|
+
* end
|
|
7377
|
+
* F->>C: detectChanges()
|
|
7378
|
+
* C->>F: Update view with new state
|
|
7379
|
+
*
|
|
7380
|
+
* @returns {Promise<void>}
|
|
7381
|
+
* @memberOf FieldsetComponent
|
|
7382
|
+
*/
|
|
7383
|
+
async ngAfterViewInit() {
|
|
7384
|
+
await super.ngAfterViewInit();
|
|
7249
7385
|
// if (!this.collapsable)
|
|
7250
7386
|
// this.isOpen = true;
|
|
7251
7387
|
// if (this.operation === OperationKeys.READ || this.operation === OperationKeys.DELETE) {
|
|
@@ -7266,6 +7402,29 @@ let FieldsetComponent = class FieldsetComponent extends NgxFormDirective {
|
|
|
7266
7402
|
// this.formGroup = (this.formGroup as FormGroup)
|
|
7267
7403
|
// this.changeDetectorRef.detectChanges();
|
|
7268
7404
|
}
|
|
7405
|
+
async refresh() {
|
|
7406
|
+
this.refreshing = true;
|
|
7407
|
+
this.changeDetectorRef.detectChanges();
|
|
7408
|
+
if ([OperationKeys.READ, OperationKeys.DELETE].includes(this.operation)) {
|
|
7409
|
+
// if(!this.multiple) {
|
|
7410
|
+
// this.required = this.collapsable = false;
|
|
7411
|
+
// }
|
|
7412
|
+
this.items = [...this.value.map((v) => {
|
|
7413
|
+
return this.children.map((child) => {
|
|
7414
|
+
const { props, tag } = child;
|
|
7415
|
+
return {
|
|
7416
|
+
tag,
|
|
7417
|
+
props: {
|
|
7418
|
+
...props,
|
|
7419
|
+
value: v[props.name] || ""
|
|
7420
|
+
}
|
|
7421
|
+
};
|
|
7422
|
+
});
|
|
7423
|
+
})];
|
|
7424
|
+
}
|
|
7425
|
+
this.refreshing = false;
|
|
7426
|
+
this.changeDetectorRef.detectChanges();
|
|
7427
|
+
}
|
|
7269
7428
|
/**
|
|
7270
7429
|
* @description Handles removal of the fieldset with slide animation.
|
|
7271
7430
|
* @summary Initiates the removal process for the fieldset with a smooth slide-up animation.
|
|
@@ -7326,7 +7485,9 @@ let FieldsetComponent = class FieldsetComponent extends NgxFormDirective {
|
|
|
7326
7485
|
const value = formGroup.value;
|
|
7327
7486
|
const hasSomeValue = this.hasValue(value);
|
|
7328
7487
|
if (hasSomeValue) {
|
|
7329
|
-
const action = this.updatingItem
|
|
7488
|
+
const action = this.updatingItem
|
|
7489
|
+
? OperationKeys.UPDATE
|
|
7490
|
+
: OperationKeys.CREATE;
|
|
7330
7491
|
const isValid = NgxFormService.validateFields(formGroup);
|
|
7331
7492
|
// must pass correct pk here
|
|
7332
7493
|
const isUnique = NgxFormService.isUniqueOnGroup(formGroup, action, action === OperationKeys.UPDATE ? this.updatingItem?.index : undefined);
|
|
@@ -7336,12 +7497,15 @@ let FieldsetComponent = class FieldsetComponent extends NgxFormDirective {
|
|
|
7336
7497
|
this.isUniqueError = this.updatingItem = undefined;
|
|
7337
7498
|
this.setValue();
|
|
7338
7499
|
NgxFormService.addGroupToParent(formGroup.parent);
|
|
7339
|
-
this.activeFormGroupIndex =
|
|
7500
|
+
this.activeFormGroupIndex =
|
|
7501
|
+
formGroup.parent.length - 1;
|
|
7340
7502
|
this.activePage = this.getActivePage();
|
|
7341
7503
|
}
|
|
7342
7504
|
else {
|
|
7343
|
-
this.isUniqueError =
|
|
7344
|
-
value
|
|
7505
|
+
this.isUniqueError =
|
|
7506
|
+
typeof value === ReservedModels.OBJECT.name.toLowerCase()
|
|
7507
|
+
? value?.[this.pk] || undefined
|
|
7508
|
+
: value;
|
|
7345
7509
|
}
|
|
7346
7510
|
}
|
|
7347
7511
|
}
|
|
@@ -7387,7 +7551,7 @@ let FieldsetComponent = class FieldsetComponent extends NgxFormDirective {
|
|
|
7387
7551
|
const formArray = this.formGroup;
|
|
7388
7552
|
if (formArray.length === 1) {
|
|
7389
7553
|
const currentGroup = formArray.at(0);
|
|
7390
|
-
Object.keys(currentGroup?.controls).forEach(controlName => {
|
|
7554
|
+
Object.keys(currentGroup?.controls).forEach((controlName) => {
|
|
7391
7555
|
currentGroup.get(controlName)?.setValue(null);
|
|
7392
7556
|
});
|
|
7393
7557
|
}
|
|
@@ -7430,7 +7594,7 @@ let FieldsetComponent = class FieldsetComponent extends NgxFormDirective {
|
|
|
7430
7594
|
// reorder visual data
|
|
7431
7595
|
const itemToMove = items.splice(fromIndex, 1)[0];
|
|
7432
7596
|
items.splice(toIndex, 0, itemToMove);
|
|
7433
|
-
items.forEach((item, index) => item['index'] = index + 1);
|
|
7597
|
+
items.forEach((item, index) => (item['index'] = index + 1));
|
|
7434
7598
|
// reorder FormArray controls
|
|
7435
7599
|
const controlToMove = formArray.at(fromIndex);
|
|
7436
7600
|
formArray.removeAt(fromIndex);
|
|
@@ -7514,14 +7678,17 @@ let FieldsetComponent = class FieldsetComponent extends NgxFormDirective {
|
|
|
7514
7678
|
this.accordionComponent.value = 'open';
|
|
7515
7679
|
this.changeDetectorRef.detectChanges();
|
|
7516
7680
|
this.timerSubscription = timer(10).subscribe(() => {
|
|
7517
|
-
this.children = this.children.map(child => {
|
|
7681
|
+
this.children = this.children.map((child) => {
|
|
7518
7682
|
if (!child.props)
|
|
7519
7683
|
child.props = {};
|
|
7520
|
-
child.props = Object.assign(child.props, {
|
|
7684
|
+
child.props = Object.assign(child.props, {
|
|
7685
|
+
activeFormGroup: this.activeFormGroupIndex,
|
|
7686
|
+
multiple: this.multiple,
|
|
7687
|
+
});
|
|
7521
7688
|
return child;
|
|
7522
7689
|
});
|
|
7523
7690
|
});
|
|
7524
|
-
if (this.multiple)
|
|
7691
|
+
if (this.multiple && [OperationKeys.CREATE, OperationKeys.UPDATE].includes(this.operation))
|
|
7525
7692
|
this.getFormArrayIndex(this.activeFormGroupIndex);
|
|
7526
7693
|
return this.children;
|
|
7527
7694
|
}
|
|
@@ -7538,11 +7705,11 @@ let FieldsetComponent = class FieldsetComponent extends NgxFormDirective {
|
|
|
7538
7705
|
setValue() {
|
|
7539
7706
|
this.value = this.formGroup.controls.map(({ value }) => value);
|
|
7540
7707
|
this.items = this.value
|
|
7541
|
-
.filter(v => (v[this.pk] ||
|
|
7708
|
+
.filter((v) => (v[this.pk] || '').trim().length)
|
|
7542
7709
|
.map((v, index) => {
|
|
7543
7710
|
return {
|
|
7544
7711
|
...itemMapper(Object.assign({}, v), this.mapper),
|
|
7545
|
-
index: index + 1
|
|
7712
|
+
index: index + 1,
|
|
7546
7713
|
};
|
|
7547
7714
|
});
|
|
7548
7715
|
this.updatingItem = undefined;
|
|
@@ -7563,9 +7730,10 @@ let FieldsetComponent = class FieldsetComponent extends NgxFormDirective {
|
|
|
7563
7730
|
this.pk = Object.keys(value)[0];
|
|
7564
7731
|
if (!Object.keys(this.mapper).length)
|
|
7565
7732
|
this.mapper['title'] = this.pk;
|
|
7566
|
-
this.mapper['index'] =
|
|
7733
|
+
this.mapper['index'] = 'index';
|
|
7567
7734
|
for (const key in value) {
|
|
7568
|
-
if (Object.keys(this.mapper).length >= 2 ||
|
|
7735
|
+
if (Object.keys(this.mapper).length >= 2 ||
|
|
7736
|
+
Object.keys(this.mapper).length === Object.keys(value).length)
|
|
7569
7737
|
break;
|
|
7570
7738
|
if (!this.mapper['title']) {
|
|
7571
7739
|
this.mapper['title'] = key;
|
|
@@ -7577,7 +7745,7 @@ let FieldsetComponent = class FieldsetComponent extends NgxFormDirective {
|
|
|
7577
7745
|
return this.mapper;
|
|
7578
7746
|
}
|
|
7579
7747
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: FieldsetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7580
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: FieldsetComponent, isStandalone: true, selector: "ngx-decaf-fieldset", inputs: { formControl: "formControl", collapsable: "collapsable", customTypes: "customTypes", title: "title", description: "description", multiple: "multiple", value: "value", borders: "borders", max: "max", required: "required", ordenable: "ordenable", editable: "editable" }, viewQueries: [{ propertyName: "accordionComponent", first: true, predicate: ["accordionComponent"], descendants: true }], usesInheritance: true, ngImport: i0, template: "\n\n<fieldset\n (fieldsetAddGroupEvent)=\"handleCreateItem($event)\"\n [class]=\"'dcf-fieldset-component ' + operation\"\n [class.dcf-blank]=\"!borders\"\n [class.open]=\"isOpen\"\n [class.dcf-not-collapsable]=\"!collapsable\"\n #component>\n <div class=\"dcf-width-1-1\">\n @if (!collapsable || required) {\n <legend class=\"dcf-title\">{{ (title ? title : name) | translate }}</legend>\n }\n <ion-accordion-group class=\"dcf-width-1-1\" [class.open]=\"isOpen\" [class.hasValidationErrors]=\"hasValidationErrors\" [value]=\"(operation === 'read' || !collapsable) ? 'open' : ''\" #accordionComponent>\n <ion-accordion\n value=\"open\"\n [class.dcf-disabled]=\"!activePage\"\n [class.dcf-empty]=\"!items?.length\"\n >\n @if (collapsable && !required) {\n <ion-item slot=\"header\" [button]=\"collapsable\" (click)=\"handleAccordionToggle($event)\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-width-1-1\">\n <div class=\"dcf-width-expand\">\n <legend>{{ (title ? title : name) | translate }}</legend>\n </div>\n @if (!isRequired && ['create', 'update'].includes(operation) && collapsable && multiple) {\n <div class=\"dcf-width-auto dcf-delete\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleClear($event)\">\n <ion-icon aria-hidden=\"true\" name=\"trash-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n }\n </div>\n </ion-item>\n }\n\n <div slot=\"content\" [attr.aria-hidden]=\"!isOpen\">\n @if (activePage) {\n <div>\n <ngx-decaf-layout\n [className]=\"'dcf-fieldset-grid dcf-grid-nested'\"\n [flexMode]=\"props.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'small'\"\n [children]=\"activePage || []\"\n [parentForm]=\"formGroup || parentForm\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"activePage?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [hidden]=\"items.length === max && !updatingItem\"\n />\n </div>\n }\n </div>\n </ion-accordion>\n </ion-accordion-group>\n\n @if (multiple && items.length) {\n <ion-list class=\"dcf-fields-list\">\n <ion-reorder-group [formGroup]=\"formGroup.parent\" [disabled]=\"updatingItem\" (ionItemReorder)=\"handleReorderItems($any($event))\" #accordionComponent>\n @for(item of items; track item.index) {\n <ion-item [class.not-unique]=\"item.title === isUniqueError\" [class.updating]=\"updatingItem?.[pk] === item.title\" lines=\"full\" [button]=\"false\">\n @if(ordenable) {\n @if (items?.length > 1 && !updatingItem) {\n <ion-reorder slot=\"start\">\n <ion-icon aria-hidden=\"true\" name=\"swap-vertical-outline\"></ion-icon>\n </ion-reorder>\n } @else {\n <div slot=\"start\">\n <ion-icon aria-hidden=\"true\" class=\"dcf-reorder-disabled\" size=\"small\" name=\"swap-vertical-outline\" disabled></ion-icon>\n </div>\n }\n }\n\n <ion-label [color]=\"(item.title === isUniqueError && !updatingItem?.[pk] === item.title) ? 'danger' : ''\">{{ item.index }}. {{ item.title }}\n @if (item.description?.length > 0) {\n <br />\n <ion-text class=\"dcf-subtitle\">{{item.description}}</ion-text>\n }\n </ion-label>\n\n @if(editable) {\n @if (!updatingItem || updatingItem?.[pk] !== item.title) {\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleUpdateItem($index)\">\n <ion-icon aria-hidden=\"true\" name=\"create-outline\" color=\"dark\" ></ion-icon>\n </ion-button>\n }\n }\n\n\n @if (!updatingItem) {\n <ion-button fill=\"clear\" size=\"small\" color=\"danger\" (click)=\"handleRemoveItem($index)\">\n <ion-icon aria-hidden=\"true\" name=\"close-outline\" color=\"dark\"></ion-icon>\n </ion-button>\n }\n </ion-item>\n }\n </ion-reorder-group>\n </ion-list>\n }\n\n @if (multiple && ['create', 'update'].includes(operation)) {\n @if (isUniqueError) {\n <div class=\"dcf-not-unique-container dcf-animation dcf-animation-bottom-small dcf-animation-fast\">\n <div class=\" dcf-grid dcf-grid-collapse dcf-width-1-1 \">\n <div class=\"dcf-auto\" [attr.style]=\"'max-width: 50px'\">\n <ion-icon aria-hidden=\"true\" name=\"alert-circle-outline\"></ion-icon>\n </div>\n <div class=\"dcf-width-expand\">\n <ion-text color=\"danger\" class=\"dcf-text-small\">{{ locale + '.not_unique' | translate : { value: isUniqueError } }}</ion-text>\n </div>\n </div>\n </div>\n }\n @if(max) {\n <div class=\"dcf-width-1-1 dcf-max-message-container\">\n <ion-text class=\"dcf-text-small\"\n [color]=\"items.length !== max ? (!isDarkMode ? 'medium' : '') : 'primary'\"\n >\n {{ locale + (items.length !== max ? '.max_items' : '.max_items_reached') | translate : { '0': max } }}\n </ion-text>\n </div>\n }\n\n <div class=\"dcf-grid dcf-grid-small dcf-flex dcf-buttons-container\" [class.dcf-not-collapsable]=\"!collapsable\" [class.dcf-empty]=\"!activePage\" [class.dcf-blank]=\"!borders\">\n @if (updatingItem) {\n <div>\n <ion-button size=\"small\" fill=\"clear\" color=\"danger\" (click)=\"handleCancelUpdateItem()\">\n {{ locale + '.cancel' | translate }}\n </ion-button>\n </div>\n <div>\n <ion-button size=\"small\" fill=\"clear\" (click)=\"handleCreateItem()\">\n <ion-icon aria-hidden=\"true\" name=\"refresh-outline\" slot=\"start\"></ion-icon>\n {{ locale + '.update' | translate }}\n </ion-button>\n </div>\n } @else {\n\n @if (items.length < max || !max) {\n <div>\n <ion-button size=\"small\" fill=\"clear\" class=\"dcf-button-add\" [color]=\"isDarkMode ? 'light' : 'dark'\" (click)=\"handleCreateItem()\">\n <ion-icon aria-hidden=\"true\" name=\"add-outline\" slot=\"start\"></ion-icon>\n {{ locale + '.add' | translate }}\n </ion-button>\n </div>\n }\n }\n </div>\n }\n </div>\n</fieldset>\n\n", styles: ["ion-accordion ion-item[slot=header] .dcf-delete{width:30px}ion-accordion ion-item[slot=header] .dcf-delete ion-button{transform:translateY(-2px)}ion-accordion ion-item[slot=header] .dcf-delete ion-icon{font-size:1.15rem}ion-accordion.dcf-disabled [slot=content]{padding-bottom:0rem!important}ion-accordion.dcf-empty,ion-accordion.dcf-disabled{opacity:1!important}ion-accordion.dcf-empty ::ng-deep .ion-accordion-toggle-icon,ion-accordion.dcf-disabled ::ng-deep .ion-accordion-toggle-icon{display:none!important}ion-accordion.dcf-empty .dcf-delete,ion-accordion.dcf-disabled .dcf-delete{display:none!important}ion-accordion.dcf-empty ion-item[slot=header],ion-accordion.dcf-disabled ion-item[slot=header]{pointer-events:none;cursor:default!important}.dcf-not-collapsable .dcf-max-message-container{margin:.75rem;margin-top:0rem!important}.dcf-not-collapsable .dcf-max-message-container+.dcf-buttons-container{margin-top:var(--dcf-margin-small)!important}.dcf-fieldset-component{border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-3)}.dcf-fieldset-component.dcf-blank{border-color:transparent;padding:0rem!important;margin:0!important}.dcf-fieldset-component *{overflow-x:hidden!important}.dcf-fieldset-component ion-accordion:not(.dcf-empty){background:var(--dcf-card-background)!important}.dcf-fieldset-component ion-accordion ion-item{--background-hover: transparent !important}.dcf-fieldset-component.read,.dcf-fieldset-component.delete{margin:var(--dcf-margin-small) 0rem!important}.dcf-fieldset-component.read [slot=header],.dcf-fieldset-component.delete [slot=header]{margin-bottom:0rem!important}.dcf-fieldset-component [slot=header]{--border-color: transparent;--border-radius: 6px;--inner-border-width: 0;--padding-start: .65rem;--color: var(--ion-color-text) !important;margin:unset}.dcf-fieldset-component legend,.dcf-fieldset-component .dcf-title{font-weight:500;font-size:1rem;line-height:1.5rem;font-weight:600;margin:0;color:var(--ion-color-text)!important}.dcf-fieldset-component .dcf-title{padding:.8rem!important}.dcf-fieldset-component [slot=content]{padding:var(--dcf-padding-small) .25rem!important}.dcf-fieldset-component [slot=content]>div{padding-top:.25rem!important}.dcf-fieldset-component:not(.dcf-blank) ion-accordion [slot=header]{margin-top:.125rem}.dcf-fieldset-component .dcf-max-message-container{margin:var(--dcf-padding-small) .75rem}.dcf-not-unique-container{display:flex;justify-content:center;align-items:center;margin-bottom:var(--dcf-spacement);flex:1 1 auto}.dcf-not-unique-container>div{display:flex;justify-content:center;align-items:center}.dcf-not-unique-container ion-icon{transform:translatey(2px);margin-right:5px}.dcf-fields-list{padding:.25rem var(--dcf-margin-small);margin-bottom:var(--dcf-margin-small)!important}.dcf-fields-list ion-item{--min-height: 50px;--padding-top: .25rem;--padding-bottom: .25rem;--padding-start: .75rem;--padding-end: .75rem;--inner-padding-start: 0px !important;--inner-padding-end: 0px !important;--border-color: var(--dcf-color-gray-2) !important}.dcf-fields-list ion-item ion-icon.dcf-reorder-disabled{width:var(--dcf-spacement);transform:translatey(2px);color:var(--dcf-color-gray-4)}.dcf-fields-list ion-item.updating{--background: rgba(var(--dcf-color-primary-rgb), .1) !important}.dcf-fields-list ion-item.not-unique{--background: rgba(var(--dcf-color-danger-rgb), .05) !important}.dcf-fields-list ion-item .dcf-subtitle{font-size:.925rem;color:var(--ion-color-gray-4)}.dcf-buttons-container{margin-bottom:0!important;margin-top:-.5rem;padding:0rem .125rem}.dcf-buttons-container:not(.dcf-blank){padding-bottom:var(--dcf-padding-small)!important}.dcf-buttons-container.dcf-not-collapsable.dcf-empty{position:relative;top:-1rem!important}@media (max-width: 480px){.dcf-buttons-container{flex-direction:column-reverse;gap:.5rem;align-items:stretch}.dcf-buttons-container ion-button{width:100%;justify-content:center;height:40px}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: IonAccordionGroup, selector: "ion-accordion-group", inputs: ["animated", "disabled", "expand", "mode", "multiple", "readonly", "value"] }, { kind: "component", type: IonAccordion, selector: "ion-accordion", inputs: ["disabled", "mode", "readonly", "toggleIcon", "toggleIconSlot", "value"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonReorder, selector: "ion-reorder" }, { kind: "component", type: IonReorderGroup, selector: "ion-reorder-group", inputs: ["disabled"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: LayoutComponent, selector: "ngx-decaf-layout", inputs: ["gap", "grid", "flexMode", "rowCard", "maxColsLength"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
7748
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: FieldsetComponent, isStandalone: true, selector: "ngx-decaf-fieldset", inputs: { formControl: "formControl", collapsable: "collapsable", customTypes: "customTypes", title: "title", description: "description", multiple: "multiple", value: "value", borders: "borders", max: "max", required: "required", ordenable: "ordenable", editable: "editable" }, viewQueries: [{ propertyName: "accordionComponent", first: true, predicate: ["accordionComponent"], descendants: true }], usesInheritance: true, ngImport: i0, template: "\n\n <fieldset\n (fieldsetAddGroupEvent)=\"handleCreateItem($event)\"\n [class]=\"'dcf-fieldset-component ' + operation\"\n [class.dcf-blank]=\"!borders\"\n [class.open]=\"isOpen\"\n [class.dcf-not-collapsable]=\"!collapsable\"\n #component>\n <div class=\"dcf-width-1-1\">\n @if (!collapsable || required) {\n <legend class=\"dcf-title\">{{ (title ? title : name) | translate }}</legend>\n }\n <ion-accordion-group class=\"dcf-width-1-1\" [class.open]=\"isOpen\" [class.hasValidationErrors]=\"hasValidationErrors\" [value]=\"(operation === 'read' || !collapsable) ? 'open' : ''\" #accordionComponent>\n <ion-accordion\n value=\"open\"\n [class.dcf-disabled]=\"!activePage\"\n [class.dcf-empty]=\"!items?.length\"\n >\n @if (collapsable && !required) {\n <ion-item slot=\"header\" [button]=\"collapsable\" (click)=\"handleAccordionToggle($event)\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-width-1-1\">\n <div class=\"dcf-width-expand\">\n <legend>{{ (title ? title : name) | translate }}</legend>\n </div>\n @if (!isRequired && ['create', 'update'].includes(operation) && collapsable && multiple) {\n <div class=\"dcf-width-auto dcf-delete\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleClear($event)\">\n <ion-icon aria-hidden=\"true\" name=\"trash-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n }\n </div>\n </ion-item>\n }\n\n <div slot=\"content\" [attr.aria-hidden]=\"!isOpen\">\n @if (['create', 'update'].includes(operation) || !multiple) {\n @if(activePage) {\n <div>\n <ngx-decaf-layout\n [className]=\"'dcf-fieldset-grid dcf-grid-nested'\"\n [flexMode]=\"props.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'small'\"\n [children]=\"activePage || []\"\n [parentForm]=\"formGroup || parentForm\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"activePage?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [hidden]=\"items.length === max && !updatingItem\"\n />\n </div>\n }\n } @else {\n @if(refreshing) {\n <div class=\"dcf-loading-container\">\n <ion-spinner name=\"crescent\" color=\"primary\"></ion-spinner>\n </div>\n } @else {\n @if(!items.length) {\n <div class=\"dcf-padding-xsmall\">\n <ion-text class=\"dcf-text-small\">{{ locale + '.empty' | translate }}</ion-text>\n </div>\n } @else {\n @for(item of items; track trackItemFn($index, item)) {\n <div class=\"dcf-fieldset-item\">\n <div>\n <ngx-decaf-layout\n [className]=\"'dcf-fieldset-grid dcf-grid-nested ' + operation\"\n [flexMode]=\"item?.props?.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'collapse'\"\n [children]=\"item || []\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"item?.props?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n />\n </div>\n </div>\n }\n }\n }\n }\n </div>\n </ion-accordion>\n </ion-accordion-group>\n @if (multiple && ['create', 'update'].includes(operation)) {\n @if (multiple && items.length) {\n <ion-list class=\"dcf-fields-list\">\n <ion-reorder-group [formGroup]=\"formGroup.parent\" [disabled]=\"updatingItem\" (ionItemReorder)=\"handleReorderItems($any($event))\" #accordionComponent>\n @for(item of items; track item.index) {\n <ion-item [class.not-unique]=\"item.title === isUniqueError\" [class.updating]=\"updatingItem?.[pk] === item.title\" lines=\"full\" [button]=\"false\">\n @if(ordenable) {\n @if (items?.length > 1 && !updatingItem) {\n <ion-reorder slot=\"start\">\n <ion-icon aria-hidden=\"true\" name=\"swap-vertical-outline\"></ion-icon>\n </ion-reorder>\n } @else {\n <div slot=\"start\">\n <ion-icon aria-hidden=\"true\" class=\"dcf-reorder-disabled\" size=\"small\" name=\"swap-vertical-outline\" disabled></ion-icon>\n </div>\n }\n }\n\n <ion-label [color]=\"(item.title === isUniqueError && !updatingItem?.[pk] === item.title) ? 'danger' : ''\">{{ item.index }}. {{ item.title }}\n @if (item.description?.length > 0) {\n <br />\n <ion-text class=\"dcf-subtitle\">{{item.description}}</ion-text>\n }\n </ion-label>\n\n @if(editable) {\n @if (!updatingItem || updatingItem?.[pk] !== item.title) {\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleUpdateItem($index)\">\n <ion-icon aria-hidden=\"true\" name=\"create-outline\" color=\"dark\" ></ion-icon>\n </ion-button>\n }\n }\n\n\n @if (!updatingItem) {\n <ion-button fill=\"clear\" size=\"small\" color=\"danger\" (click)=\"handleRemoveItem($index)\">\n <ion-icon aria-hidden=\"true\" name=\"close-outline\" color=\"dark\"></ion-icon>\n </ion-button>\n }\n </ion-item>\n }\n </ion-reorder-group>\n </ion-list>\n }\n\n @if (isUniqueError) {\n <div class=\"dcf-not-unique-container dcf-animation dcf-animation-bottom-small dcf-animation-fast\">\n <div class=\" dcf-grid dcf-grid-collapse dcf-width-1-1 \">\n <div class=\"dcf-auto\" [attr.style]=\"'max-width: 50px'\">\n <ion-icon aria-hidden=\"true\" name=\"alert-circle-outline\"></ion-icon>\n </div>\n <div class=\"dcf-width-expand\">\n <ion-text color=\"danger\" class=\"dcf-text-small\">{{ locale + '.not_unique' | translate : { value: isUniqueError } }}</ion-text>\n </div>\n </div>\n </div>\n }\n\n @if(max) {\n <div class=\"dcf-width-1-1 dcf-max-message-container\">\n <ion-text class=\"dcf-text-small\"\n [color]=\"items.length !== max ? (!isDarkMode ? 'medium' : '') : 'primary'\"\n >\n {{ locale + (items.length !== max ? '.max_items' : '.max_items_reached') | translate : { '0': max } }}\n </ion-text>\n </div>\n }\n\n <div class=\"dcf-grid dcf-grid-small dcf-flex dcf-buttons-container\" [class.dcf-not-collapsable]=\"!collapsable\" [class.dcf-empty]=\"!activePage\" [class.dcf-blank]=\"!borders\">\n @if (updatingItem) {\n <div>\n <ion-button size=\"small\" fill=\"clear\" color=\"danger\" (click)=\"handleCancelUpdateItem()\">\n {{ locale + '.cancel' | translate }}\n </ion-button>\n </div>\n <div>\n <ion-button size=\"small\" fill=\"clear\" (click)=\"handleCreateItem()\">\n <ion-icon aria-hidden=\"true\" name=\"refresh-outline\" slot=\"start\"></ion-icon>\n {{ locale + '.update' | translate }}\n </ion-button>\n </div>\n } @else {\n @if (items.length < max || !max) {\n <div>\n <ion-button size=\"small\" fill=\"clear\" class=\"dcf-button-add\" [color]=\"isDarkMode ? 'light' : 'dark'\" (click)=\"handleCreateItem()\">\n <ion-icon aria-hidden=\"true\" name=\"add-outline\" slot=\"start\"></ion-icon>\n {{ locale + '.add' | translate }}\n </ion-button>\n </div>\n }\n }\n </div>\n }\n </div>\n </fieldset>\n\n\n", styles: [".dcf-fieldset-item{border:1px solid var(--dcf-color-gray-3);border-radius:var(--dcf-border-radius-small);padding:var(--dcf-padding-small) var(--dcf-padding-xsmall);padding-bottom:0;margin-bottom:var(--dcf-margin-small)}.dcf-loading-container{height:50%;display:flex;justify-content:center;align-items:center}.dcf-loading-container ion-spinner{width:30px;height:30px}ion-accordion{background:transparent!important;--background: transparent !important}ion-accordion ion-item[slot=header] .dcf-delete{width:30px}ion-accordion ion-item[slot=header] .dcf-delete ion-button{transform:translateY(-2px)}ion-accordion ion-item[slot=header] .dcf-delete ion-icon{font-size:1.15rem}ion-accordion.dcf-disabled [slot=content]{padding-bottom:0rem!important}ion-accordion.dcf-empty,ion-accordion.dcf-disabled{opacity:1!important}ion-accordion.dcf-empty ::ng-deep .ion-accordion-toggle-icon,ion-accordion.dcf-disabled ::ng-deep .ion-accordion-toggle-icon{display:none!important}ion-accordion.dcf-empty .dcf-delete,ion-accordion.dcf-disabled .dcf-delete{display:none!important}ion-accordion.dcf-empty ion-item[slot=header],ion-accordion.dcf-disabled ion-item[slot=header]{pointer-events:none;cursor:default!important}.dcf-not-collapsable .dcf-max-message-container{margin:.75rem;margin-top:0rem!important}.dcf-not-collapsable .dcf-max-message-container+.dcf-buttons-container{margin-top:var(--dcf-margin-small)!important}.dcf-fieldset-component{border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-3)}.dcf-fieldset-component.dcf-blank{border-color:transparent;padding:0rem!important;margin:0!important}.dcf-fieldset-component *{overflow-x:hidden!important}.dcf-fieldset-component ion-accordion ion-item{--background-hover: transparent !important}.dcf-fieldset-component.read,.dcf-fieldset-component.delete{margin:var(--dcf-margin-small) 0rem!important}.dcf-fieldset-component.read [slot=header],.dcf-fieldset-component.delete [slot=header]{margin-bottom:0rem!important}.dcf-fieldset-component [slot=header]{--border-color: transparent;--border-radius: 6px;--inner-border-width: 0;--padding-start: .65rem;--color: var(--ion-color-text) !important;margin:unset}.dcf-fieldset-component legend,.dcf-fieldset-component .dcf-title{font-weight:500;font-size:1rem;line-height:1.5rem;font-weight:600;margin:0;color:var(--ion-color-text)!important}.dcf-fieldset-component .dcf-title{padding:.8rem!important}.dcf-fieldset-component [slot=content]{padding:var(--dcf-padding-small) .25rem!important;background:transparent!important;--background: transparent !important}.dcf-fieldset-component [slot=content]>div{padding-top:.25rem!important}.dcf-fieldset-component:not(.dcf-blank) ion-accordion [slot=header]{margin-top:.125rem}.dcf-fieldset-component .dcf-max-message-container{margin:var(--dcf-padding-small) .75rem}.dcf-not-unique-container{display:flex;justify-content:center;align-items:center;margin-bottom:var(--dcf-spacement);flex:1 1 auto}.dcf-not-unique-container>div{display:flex;justify-content:center;align-items:center}.dcf-not-unique-container ion-icon{transform:translatey(2px);margin-right:5px}.dcf-fields-list{padding:.25rem var(--dcf-margin-small);margin-bottom:var(--dcf-margin-small)!important}.dcf-fields-list ion-item{--min-height: 50px;--padding-top: .25rem;--padding-bottom: .25rem;--padding-start: .75rem;--padding-end: .75rem;--inner-padding-start: 0px !important;--inner-padding-end: 0px !important;--border-color: var(--dcf-color-gray-2) !important}.dcf-fields-list ion-item ion-icon.dcf-reorder-disabled{width:var(--dcf-spacement);transform:translatey(2px);color:var(--dcf-color-gray-4)}.dcf-fields-list ion-item.updating{--background: rgba(var(--dcf-color-primary-rgb), .1) !important}.dcf-fields-list ion-item.not-unique{--background: rgba(var(--dcf-color-danger-rgb), .05) !important}.dcf-fields-list ion-item .dcf-subtitle{font-size:.925rem;color:var(--ion-color-gray-4)}.dcf-buttons-container{margin-bottom:0!important;margin-top:-.5rem;padding:0rem .125rem}.dcf-buttons-container:not(.dcf-blank){padding-bottom:var(--dcf-padding-small)!important}.dcf-buttons-container.dcf-not-collapsable.dcf-empty{position:relative;top:-1rem!important}@media (max-width: 480px){.dcf-buttons-container{flex-direction:column-reverse;gap:.5rem;align-items:stretch}.dcf-buttons-container ion-button{width:100%;justify-content:center;height:40px}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: IonAccordionGroup, selector: "ion-accordion-group", inputs: ["animated", "disabled", "expand", "mode", "multiple", "readonly", "value"] }, { kind: "component", type: IonAccordion, selector: "ion-accordion", inputs: ["disabled", "mode", "readonly", "toggleIcon", "toggleIconSlot", "value"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonReorder, selector: "ion-reorder" }, { kind: "component", type: IonReorderGroup, selector: "ion-reorder-group", inputs: ["disabled"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: LayoutComponent, selector: "ngx-decaf-layout", inputs: ["gap", "grid", "flexMode", "rowCard", "maxColsLength"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
7581
7749
|
};
|
|
7582
7750
|
FieldsetComponent = __decorate([
|
|
7583
7751
|
Dynamic(),
|
|
@@ -7598,8 +7766,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
|
|
|
7598
7766
|
IonReorderGroup,
|
|
7599
7767
|
IonButton,
|
|
7600
7768
|
IonIcon,
|
|
7601
|
-
LayoutComponent
|
|
7602
|
-
], template: "\n\n<fieldset\n (fieldsetAddGroupEvent)=\"handleCreateItem($event)\"\n [class]=\"'dcf-fieldset-component ' + operation\"\n [class.dcf-blank]=\"!borders\"\n [class.open]=\"isOpen\"\n [class.dcf-not-collapsable]=\"!collapsable\"\n #component>\n <div class=\"dcf-width-1-1\">\n @if (!collapsable || required) {\n <legend class=\"dcf-title\">{{ (title ? title : name) | translate }}</legend>\n }\n <ion-accordion-group class=\"dcf-width-1-1\" [class.open]=\"isOpen\" [class.hasValidationErrors]=\"hasValidationErrors\" [value]=\"(operation === 'read' || !collapsable) ? 'open' : ''\" #accordionComponent>\n <ion-accordion\n value=\"open\"\n [class.dcf-disabled]=\"!activePage\"\n [class.dcf-empty]=\"!items?.length\"\n >\n @if (collapsable && !required) {\n <ion-item slot=\"header\" [button]=\"collapsable\" (click)=\"handleAccordionToggle($event)\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-width-1-1\">\n <div class=\"dcf-width-expand\">\n <legend>{{ (title ? title : name) | translate }}</legend>\n </div>\n @if (!isRequired && ['create', 'update'].includes(operation) && collapsable && multiple) {\n <div class=\"dcf-width-auto dcf-delete\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleClear($event)\">\n <ion-icon aria-hidden=\"true\" name=\"trash-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n }\n </div>\n </ion-item>\n }\n\n <div slot=\"content\" [attr.aria-hidden]=\"!isOpen\">\n @if (activePage) {\n <div>\n <ngx-decaf-layout\n [className]=\"'dcf-fieldset-grid dcf-grid-nested'\"\n [flexMode]=\"props.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'small'\"\n [children]=\"activePage || []\"\n [parentForm]=\"formGroup || parentForm\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"activePage?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [hidden]=\"items.length === max && !updatingItem\"\n />\n </div>\n }\n </div>\n </ion-accordion>\n </ion-accordion-group>\n\n @if (multiple && items.length) {\n <ion-list class=\"dcf-fields-list\">\n <ion-reorder-group [formGroup]=\"formGroup.parent\" [disabled]=\"updatingItem\" (ionItemReorder)=\"handleReorderItems($any($event))\" #accordionComponent>\n @for(item of items; track item.index) {\n <ion-item [class.not-unique]=\"item.title === isUniqueError\" [class.updating]=\"updatingItem?.[pk] === item.title\" lines=\"full\" [button]=\"false\">\n @if(ordenable) {\n @if (items?.length > 1 && !updatingItem) {\n <ion-reorder slot=\"start\">\n <ion-icon aria-hidden=\"true\" name=\"swap-vertical-outline\"></ion-icon>\n </ion-reorder>\n } @else {\n <div slot=\"start\">\n <ion-icon aria-hidden=\"true\" class=\"dcf-reorder-disabled\" size=\"small\" name=\"swap-vertical-outline\" disabled></ion-icon>\n </div>\n }\n }\n\n <ion-label [color]=\"(item.title === isUniqueError && !updatingItem?.[pk] === item.title) ? 'danger' : ''\">{{ item.index }}. {{ item.title }}\n @if (item.description?.length > 0) {\n <br />\n <ion-text class=\"dcf-subtitle\">{{item.description}}</ion-text>\n }\n </ion-label>\n\n @if(editable) {\n @if (!updatingItem || updatingItem?.[pk] !== item.title) {\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleUpdateItem($index)\">\n <ion-icon aria-hidden=\"true\" name=\"create-outline\" color=\"dark\" ></ion-icon>\n </ion-button>\n }\n }\n\n\n @if (!updatingItem) {\n <ion-button fill=\"clear\" size=\"small\" color=\"danger\" (click)=\"handleRemoveItem($index)\">\n <ion-icon aria-hidden=\"true\" name=\"close-outline\" color=\"dark\"></ion-icon>\n </ion-button>\n }\n </ion-item>\n }\n </ion-reorder-group>\n </ion-list>\n }\n\n @if (multiple && ['create', 'update'].includes(operation)) {\n @if (isUniqueError) {\n <div class=\"dcf-not-unique-container dcf-animation dcf-animation-bottom-small dcf-animation-fast\">\n <div class=\" dcf-grid dcf-grid-collapse dcf-width-1-1 \">\n <div class=\"dcf-auto\" [attr.style]=\"'max-width: 50px'\">\n <ion-icon aria-hidden=\"true\" name=\"alert-circle-outline\"></ion-icon>\n </div>\n <div class=\"dcf-width-expand\">\n <ion-text color=\"danger\" class=\"dcf-text-small\">{{ locale + '.not_unique' | translate : { value: isUniqueError } }}</ion-text>\n </div>\n </div>\n </div>\n }\n @if(max) {\n <div class=\"dcf-width-1-1 dcf-max-message-container\">\n <ion-text class=\"dcf-text-small\"\n [color]=\"items.length !== max ? (!isDarkMode ? 'medium' : '') : 'primary'\"\n >\n {{ locale + (items.length !== max ? '.max_items' : '.max_items_reached') | translate : { '0': max } }}\n </ion-text>\n </div>\n }\n\n <div class=\"dcf-grid dcf-grid-small dcf-flex dcf-buttons-container\" [class.dcf-not-collapsable]=\"!collapsable\" [class.dcf-empty]=\"!activePage\" [class.dcf-blank]=\"!borders\">\n @if (updatingItem) {\n <div>\n <ion-button size=\"small\" fill=\"clear\" color=\"danger\" (click)=\"handleCancelUpdateItem()\">\n {{ locale + '.cancel' | translate }}\n </ion-button>\n </div>\n <div>\n <ion-button size=\"small\" fill=\"clear\" (click)=\"handleCreateItem()\">\n <ion-icon aria-hidden=\"true\" name=\"refresh-outline\" slot=\"start\"></ion-icon>\n {{ locale + '.update' | translate }}\n </ion-button>\n </div>\n } @else {\n\n @if (items.length < max || !max) {\n <div>\n <ion-button size=\"small\" fill=\"clear\" class=\"dcf-button-add\" [color]=\"isDarkMode ? 'light' : 'dark'\" (click)=\"handleCreateItem()\">\n <ion-icon aria-hidden=\"true\" name=\"add-outline\" slot=\"start\"></ion-icon>\n {{ locale + '.add' | translate }}\n </ion-button>\n </div>\n }\n }\n </div>\n }\n </div>\n</fieldset>\n\n", styles: ["ion-accordion ion-item[slot=header] .dcf-delete{width:30px}ion-accordion ion-item[slot=header] .dcf-delete ion-button{transform:translateY(-2px)}ion-accordion ion-item[slot=header] .dcf-delete ion-icon{font-size:1.15rem}ion-accordion.dcf-disabled [slot=content]{padding-bottom:0rem!important}ion-accordion.dcf-empty,ion-accordion.dcf-disabled{opacity:1!important}ion-accordion.dcf-empty ::ng-deep .ion-accordion-toggle-icon,ion-accordion.dcf-disabled ::ng-deep .ion-accordion-toggle-icon{display:none!important}ion-accordion.dcf-empty .dcf-delete,ion-accordion.dcf-disabled .dcf-delete{display:none!important}ion-accordion.dcf-empty ion-item[slot=header],ion-accordion.dcf-disabled ion-item[slot=header]{pointer-events:none;cursor:default!important}.dcf-not-collapsable .dcf-max-message-container{margin:.75rem;margin-top:0rem!important}.dcf-not-collapsable .dcf-max-message-container+.dcf-buttons-container{margin-top:var(--dcf-margin-small)!important}.dcf-fieldset-component{border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-3)}.dcf-fieldset-component.dcf-blank{border-color:transparent;padding:0rem!important;margin:0!important}.dcf-fieldset-component *{overflow-x:hidden!important}.dcf-fieldset-component ion-accordion:not(.dcf-empty){background:var(--dcf-card-background)!important}.dcf-fieldset-component ion-accordion ion-item{--background-hover: transparent !important}.dcf-fieldset-component.read,.dcf-fieldset-component.delete{margin:var(--dcf-margin-small) 0rem!important}.dcf-fieldset-component.read [slot=header],.dcf-fieldset-component.delete [slot=header]{margin-bottom:0rem!important}.dcf-fieldset-component [slot=header]{--border-color: transparent;--border-radius: 6px;--inner-border-width: 0;--padding-start: .65rem;--color: var(--ion-color-text) !important;margin:unset}.dcf-fieldset-component legend,.dcf-fieldset-component .dcf-title{font-weight:500;font-size:1rem;line-height:1.5rem;font-weight:600;margin:0;color:var(--ion-color-text)!important}.dcf-fieldset-component .dcf-title{padding:.8rem!important}.dcf-fieldset-component [slot=content]{padding:var(--dcf-padding-small) .25rem!important}.dcf-fieldset-component [slot=content]>div{padding-top:.25rem!important}.dcf-fieldset-component:not(.dcf-blank) ion-accordion [slot=header]{margin-top:.125rem}.dcf-fieldset-component .dcf-max-message-container{margin:var(--dcf-padding-small) .75rem}.dcf-not-unique-container{display:flex;justify-content:center;align-items:center;margin-bottom:var(--dcf-spacement);flex:1 1 auto}.dcf-not-unique-container>div{display:flex;justify-content:center;align-items:center}.dcf-not-unique-container ion-icon{transform:translatey(2px);margin-right:5px}.dcf-fields-list{padding:.25rem var(--dcf-margin-small);margin-bottom:var(--dcf-margin-small)!important}.dcf-fields-list ion-item{--min-height: 50px;--padding-top: .25rem;--padding-bottom: .25rem;--padding-start: .75rem;--padding-end: .75rem;--inner-padding-start: 0px !important;--inner-padding-end: 0px !important;--border-color: var(--dcf-color-gray-2) !important}.dcf-fields-list ion-item ion-icon.dcf-reorder-disabled{width:var(--dcf-spacement);transform:translatey(2px);color:var(--dcf-color-gray-4)}.dcf-fields-list ion-item.updating{--background: rgba(var(--dcf-color-primary-rgb), .1) !important}.dcf-fields-list ion-item.not-unique{--background: rgba(var(--dcf-color-danger-rgb), .05) !important}.dcf-fields-list ion-item .dcf-subtitle{font-size:.925rem;color:var(--ion-color-gray-4)}.dcf-buttons-container{margin-bottom:0!important;margin-top:-.5rem;padding:0rem .125rem}.dcf-buttons-container:not(.dcf-blank){padding-bottom:var(--dcf-padding-small)!important}.dcf-buttons-container.dcf-not-collapsable.dcf-empty{position:relative;top:-1rem!important}@media (max-width: 480px){.dcf-buttons-container{flex-direction:column-reverse;gap:.5rem;align-items:stretch}.dcf-buttons-container ion-button{width:100%;justify-content:center;height:40px}}\n"] }]
|
|
7769
|
+
LayoutComponent,
|
|
7770
|
+
IonSpinner
|
|
7771
|
+
], template: "\n\n <fieldset\n (fieldsetAddGroupEvent)=\"handleCreateItem($event)\"\n [class]=\"'dcf-fieldset-component ' + operation\"\n [class.dcf-blank]=\"!borders\"\n [class.open]=\"isOpen\"\n [class.dcf-not-collapsable]=\"!collapsable\"\n #component>\n <div class=\"dcf-width-1-1\">\n @if (!collapsable || required) {\n <legend class=\"dcf-title\">{{ (title ? title : name) | translate }}</legend>\n }\n <ion-accordion-group class=\"dcf-width-1-1\" [class.open]=\"isOpen\" [class.hasValidationErrors]=\"hasValidationErrors\" [value]=\"(operation === 'read' || !collapsable) ? 'open' : ''\" #accordionComponent>\n <ion-accordion\n value=\"open\"\n [class.dcf-disabled]=\"!activePage\"\n [class.dcf-empty]=\"!items?.length\"\n >\n @if (collapsable && !required) {\n <ion-item slot=\"header\" [button]=\"collapsable\" (click)=\"handleAccordionToggle($event)\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-width-1-1\">\n <div class=\"dcf-width-expand\">\n <legend>{{ (title ? title : name) | translate }}</legend>\n </div>\n @if (!isRequired && ['create', 'update'].includes(operation) && collapsable && multiple) {\n <div class=\"dcf-width-auto dcf-delete\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleClear($event)\">\n <ion-icon aria-hidden=\"true\" name=\"trash-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n }\n </div>\n </ion-item>\n }\n\n <div slot=\"content\" [attr.aria-hidden]=\"!isOpen\">\n @if (['create', 'update'].includes(operation) || !multiple) {\n @if(activePage) {\n <div>\n <ngx-decaf-layout\n [className]=\"'dcf-fieldset-grid dcf-grid-nested'\"\n [flexMode]=\"props.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'small'\"\n [children]=\"activePage || []\"\n [parentForm]=\"formGroup || parentForm\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"activePage?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [hidden]=\"items.length === max && !updatingItem\"\n />\n </div>\n }\n } @else {\n @if(refreshing) {\n <div class=\"dcf-loading-container\">\n <ion-spinner name=\"crescent\" color=\"primary\"></ion-spinner>\n </div>\n } @else {\n @if(!items.length) {\n <div class=\"dcf-padding-xsmall\">\n <ion-text class=\"dcf-text-small\">{{ locale + '.empty' | translate }}</ion-text>\n </div>\n } @else {\n @for(item of items; track trackItemFn($index, item)) {\n <div class=\"dcf-fieldset-item\">\n <div>\n <ngx-decaf-layout\n [className]=\"'dcf-fieldset-grid dcf-grid-nested ' + operation\"\n [flexMode]=\"item?.props?.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'collapse'\"\n [children]=\"item || []\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"item?.props?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n />\n </div>\n </div>\n }\n }\n }\n }\n </div>\n </ion-accordion>\n </ion-accordion-group>\n @if (multiple && ['create', 'update'].includes(operation)) {\n @if (multiple && items.length) {\n <ion-list class=\"dcf-fields-list\">\n <ion-reorder-group [formGroup]=\"formGroup.parent\" [disabled]=\"updatingItem\" (ionItemReorder)=\"handleReorderItems($any($event))\" #accordionComponent>\n @for(item of items; track item.index) {\n <ion-item [class.not-unique]=\"item.title === isUniqueError\" [class.updating]=\"updatingItem?.[pk] === item.title\" lines=\"full\" [button]=\"false\">\n @if(ordenable) {\n @if (items?.length > 1 && !updatingItem) {\n <ion-reorder slot=\"start\">\n <ion-icon aria-hidden=\"true\" name=\"swap-vertical-outline\"></ion-icon>\n </ion-reorder>\n } @else {\n <div slot=\"start\">\n <ion-icon aria-hidden=\"true\" class=\"dcf-reorder-disabled\" size=\"small\" name=\"swap-vertical-outline\" disabled></ion-icon>\n </div>\n }\n }\n\n <ion-label [color]=\"(item.title === isUniqueError && !updatingItem?.[pk] === item.title) ? 'danger' : ''\">{{ item.index }}. {{ item.title }}\n @if (item.description?.length > 0) {\n <br />\n <ion-text class=\"dcf-subtitle\">{{item.description}}</ion-text>\n }\n </ion-label>\n\n @if(editable) {\n @if (!updatingItem || updatingItem?.[pk] !== item.title) {\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleUpdateItem($index)\">\n <ion-icon aria-hidden=\"true\" name=\"create-outline\" color=\"dark\" ></ion-icon>\n </ion-button>\n }\n }\n\n\n @if (!updatingItem) {\n <ion-button fill=\"clear\" size=\"small\" color=\"danger\" (click)=\"handleRemoveItem($index)\">\n <ion-icon aria-hidden=\"true\" name=\"close-outline\" color=\"dark\"></ion-icon>\n </ion-button>\n }\n </ion-item>\n }\n </ion-reorder-group>\n </ion-list>\n }\n\n @if (isUniqueError) {\n <div class=\"dcf-not-unique-container dcf-animation dcf-animation-bottom-small dcf-animation-fast\">\n <div class=\" dcf-grid dcf-grid-collapse dcf-width-1-1 \">\n <div class=\"dcf-auto\" [attr.style]=\"'max-width: 50px'\">\n <ion-icon aria-hidden=\"true\" name=\"alert-circle-outline\"></ion-icon>\n </div>\n <div class=\"dcf-width-expand\">\n <ion-text color=\"danger\" class=\"dcf-text-small\">{{ locale + '.not_unique' | translate : { value: isUniqueError } }}</ion-text>\n </div>\n </div>\n </div>\n }\n\n @if(max) {\n <div class=\"dcf-width-1-1 dcf-max-message-container\">\n <ion-text class=\"dcf-text-small\"\n [color]=\"items.length !== max ? (!isDarkMode ? 'medium' : '') : 'primary'\"\n >\n {{ locale + (items.length !== max ? '.max_items' : '.max_items_reached') | translate : { '0': max } }}\n </ion-text>\n </div>\n }\n\n <div class=\"dcf-grid dcf-grid-small dcf-flex dcf-buttons-container\" [class.dcf-not-collapsable]=\"!collapsable\" [class.dcf-empty]=\"!activePage\" [class.dcf-blank]=\"!borders\">\n @if (updatingItem) {\n <div>\n <ion-button size=\"small\" fill=\"clear\" color=\"danger\" (click)=\"handleCancelUpdateItem()\">\n {{ locale + '.cancel' | translate }}\n </ion-button>\n </div>\n <div>\n <ion-button size=\"small\" fill=\"clear\" (click)=\"handleCreateItem()\">\n <ion-icon aria-hidden=\"true\" name=\"refresh-outline\" slot=\"start\"></ion-icon>\n {{ locale + '.update' | translate }}\n </ion-button>\n </div>\n } @else {\n @if (items.length < max || !max) {\n <div>\n <ion-button size=\"small\" fill=\"clear\" class=\"dcf-button-add\" [color]=\"isDarkMode ? 'light' : 'dark'\" (click)=\"handleCreateItem()\">\n <ion-icon aria-hidden=\"true\" name=\"add-outline\" slot=\"start\"></ion-icon>\n {{ locale + '.add' | translate }}\n </ion-button>\n </div>\n }\n }\n </div>\n }\n </div>\n </fieldset>\n\n\n", styles: [".dcf-fieldset-item{border:1px solid var(--dcf-color-gray-3);border-radius:var(--dcf-border-radius-small);padding:var(--dcf-padding-small) var(--dcf-padding-xsmall);padding-bottom:0;margin-bottom:var(--dcf-margin-small)}.dcf-loading-container{height:50%;display:flex;justify-content:center;align-items:center}.dcf-loading-container ion-spinner{width:30px;height:30px}ion-accordion{background:transparent!important;--background: transparent !important}ion-accordion ion-item[slot=header] .dcf-delete{width:30px}ion-accordion ion-item[slot=header] .dcf-delete ion-button{transform:translateY(-2px)}ion-accordion ion-item[slot=header] .dcf-delete ion-icon{font-size:1.15rem}ion-accordion.dcf-disabled [slot=content]{padding-bottom:0rem!important}ion-accordion.dcf-empty,ion-accordion.dcf-disabled{opacity:1!important}ion-accordion.dcf-empty ::ng-deep .ion-accordion-toggle-icon,ion-accordion.dcf-disabled ::ng-deep .ion-accordion-toggle-icon{display:none!important}ion-accordion.dcf-empty .dcf-delete,ion-accordion.dcf-disabled .dcf-delete{display:none!important}ion-accordion.dcf-empty ion-item[slot=header],ion-accordion.dcf-disabled ion-item[slot=header]{pointer-events:none;cursor:default!important}.dcf-not-collapsable .dcf-max-message-container{margin:.75rem;margin-top:0rem!important}.dcf-not-collapsable .dcf-max-message-container+.dcf-buttons-container{margin-top:var(--dcf-margin-small)!important}.dcf-fieldset-component{border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-3)}.dcf-fieldset-component.dcf-blank{border-color:transparent;padding:0rem!important;margin:0!important}.dcf-fieldset-component *{overflow-x:hidden!important}.dcf-fieldset-component ion-accordion ion-item{--background-hover: transparent !important}.dcf-fieldset-component.read,.dcf-fieldset-component.delete{margin:var(--dcf-margin-small) 0rem!important}.dcf-fieldset-component.read [slot=header],.dcf-fieldset-component.delete [slot=header]{margin-bottom:0rem!important}.dcf-fieldset-component [slot=header]{--border-color: transparent;--border-radius: 6px;--inner-border-width: 0;--padding-start: .65rem;--color: var(--ion-color-text) !important;margin:unset}.dcf-fieldset-component legend,.dcf-fieldset-component .dcf-title{font-weight:500;font-size:1rem;line-height:1.5rem;font-weight:600;margin:0;color:var(--ion-color-text)!important}.dcf-fieldset-component .dcf-title{padding:.8rem!important}.dcf-fieldset-component [slot=content]{padding:var(--dcf-padding-small) .25rem!important;background:transparent!important;--background: transparent !important}.dcf-fieldset-component [slot=content]>div{padding-top:.25rem!important}.dcf-fieldset-component:not(.dcf-blank) ion-accordion [slot=header]{margin-top:.125rem}.dcf-fieldset-component .dcf-max-message-container{margin:var(--dcf-padding-small) .75rem}.dcf-not-unique-container{display:flex;justify-content:center;align-items:center;margin-bottom:var(--dcf-spacement);flex:1 1 auto}.dcf-not-unique-container>div{display:flex;justify-content:center;align-items:center}.dcf-not-unique-container ion-icon{transform:translatey(2px);margin-right:5px}.dcf-fields-list{padding:.25rem var(--dcf-margin-small);margin-bottom:var(--dcf-margin-small)!important}.dcf-fields-list ion-item{--min-height: 50px;--padding-top: .25rem;--padding-bottom: .25rem;--padding-start: .75rem;--padding-end: .75rem;--inner-padding-start: 0px !important;--inner-padding-end: 0px !important;--border-color: var(--dcf-color-gray-2) !important}.dcf-fields-list ion-item ion-icon.dcf-reorder-disabled{width:var(--dcf-spacement);transform:translatey(2px);color:var(--dcf-color-gray-4)}.dcf-fields-list ion-item.updating{--background: rgba(var(--dcf-color-primary-rgb), .1) !important}.dcf-fields-list ion-item.not-unique{--background: rgba(var(--dcf-color-danger-rgb), .05) !important}.dcf-fields-list ion-item .dcf-subtitle{font-size:.925rem;color:var(--ion-color-gray-4)}.dcf-buttons-container{margin-bottom:0!important;margin-top:-.5rem;padding:0rem .125rem}.dcf-buttons-container:not(.dcf-blank){padding-bottom:var(--dcf-padding-small)!important}.dcf-buttons-container.dcf-not-collapsable.dcf-empty{position:relative;top:-1rem!important}@media (max-width: 480px){.dcf-buttons-container{flex-direction:column-reverse;gap:.5rem;align-items:stretch}.dcf-buttons-container ion-button{width:100%;justify-content:center;height:40px}}\n"] }]
|
|
7603
7772
|
}], ctorParameters: () => [], propDecorators: { accordionComponent: [{
|
|
7604
7773
|
type: ViewChild,
|
|
7605
7774
|
args: ['accordionComponent', { static: false }]
|
|
@@ -8172,7 +8341,7 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
|
|
|
8172
8341
|
* @memberOf FilterComponent
|
|
8173
8342
|
*/
|
|
8174
8343
|
constructor() {
|
|
8175
|
-
super(
|
|
8344
|
+
super('FilterComponent');
|
|
8176
8345
|
/**
|
|
8177
8346
|
* @description Available field indexes for filtering operations.
|
|
8178
8347
|
* @summary Defines the list of field names that users can filter by. These represent
|
|
@@ -8195,7 +8364,14 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
|
|
|
8195
8364
|
* @default []
|
|
8196
8365
|
* @memberOf FilterComponent
|
|
8197
8366
|
*/
|
|
8198
|
-
this.conditions = [
|
|
8367
|
+
this.conditions = [
|
|
8368
|
+
'Equal',
|
|
8369
|
+
'Contains',
|
|
8370
|
+
'Not Contains',
|
|
8371
|
+
'Greater Than',
|
|
8372
|
+
'Less Than',
|
|
8373
|
+
'Not Equal',
|
|
8374
|
+
];
|
|
8199
8375
|
/**
|
|
8200
8376
|
* @description Available sorting options for the filtered data.
|
|
8201
8377
|
* @summary Defines the list of field names that can be used for sorting the filtered results.
|
|
@@ -8328,7 +8504,15 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
|
|
|
8328
8504
|
* @memberOf FilterComponent
|
|
8329
8505
|
*/
|
|
8330
8506
|
this.searchEvent = new EventEmitter();
|
|
8331
|
-
addIcons({
|
|
8507
|
+
addIcons({
|
|
8508
|
+
chevronDownOutline,
|
|
8509
|
+
trashOutline,
|
|
8510
|
+
closeOutline,
|
|
8511
|
+
searchOutline,
|
|
8512
|
+
arrowDownOutline,
|
|
8513
|
+
arrowUpOutline,
|
|
8514
|
+
chevronUpOutline,
|
|
8515
|
+
});
|
|
8332
8516
|
}
|
|
8333
8517
|
/**
|
|
8334
8518
|
* @description Initializes the component after Angular first displays the data-bound properties.
|
|
@@ -8377,11 +8561,13 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
|
|
|
8377
8561
|
*/
|
|
8378
8562
|
getIndexes() {
|
|
8379
8563
|
if (this.model)
|
|
8380
|
-
this.indexes = Object.keys(
|
|
8564
|
+
this.indexes = Object.keys(Model.indexes(this.model) || {});
|
|
8381
8565
|
if (!this.disableSort) {
|
|
8382
8566
|
this.sortBy = [...this.sortBy, ...this.indexes];
|
|
8383
|
-
if (this.repository)
|
|
8384
|
-
|
|
8567
|
+
if (this.repository) {
|
|
8568
|
+
const pk = Model.pk(this.repository.class);
|
|
8569
|
+
this.sortValue = pk || this.sortValue;
|
|
8570
|
+
}
|
|
8385
8571
|
}
|
|
8386
8572
|
}
|
|
8387
8573
|
/**
|
|
@@ -8513,13 +8699,13 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
|
|
|
8513
8699
|
*
|
|
8514
8700
|
* @memberOf FilterComponent
|
|
8515
8701
|
*/
|
|
8516
|
-
addFilter(value, event) {
|
|
8702
|
+
async addFilter(value, event) {
|
|
8517
8703
|
value = value.trim();
|
|
8518
8704
|
if (event instanceof KeyboardEvent && !value) {
|
|
8519
8705
|
this.submit();
|
|
8520
8706
|
}
|
|
8521
8707
|
else {
|
|
8522
|
-
if ((value &&
|
|
8708
|
+
if ((value && !(event instanceof KeyboardEvent)) || this.step === 3) {
|
|
8523
8709
|
const filter = this.lastFilter;
|
|
8524
8710
|
switch (this.step) {
|
|
8525
8711
|
case 1:
|
|
@@ -8547,7 +8733,7 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
|
|
|
8547
8733
|
this.filterValue[this.filterValue.length - 1] = filter;
|
|
8548
8734
|
this.lastFilter = {};
|
|
8549
8735
|
if (!this.multiple)
|
|
8550
|
-
return this.submit();
|
|
8736
|
+
return await this.submit();
|
|
8551
8737
|
}
|
|
8552
8738
|
this.step++;
|
|
8553
8739
|
this.value = '';
|
|
@@ -8581,7 +8767,8 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
|
|
|
8581
8767
|
* @memberOf FilterComponent
|
|
8582
8768
|
*/
|
|
8583
8769
|
allowClear(option) {
|
|
8584
|
-
return this.indexes.indexOf(option) === -1 &&
|
|
8770
|
+
return (this.indexes.indexOf(option) === -1 &&
|
|
8771
|
+
this.conditions.indexOf(option) === -1);
|
|
8585
8772
|
}
|
|
8586
8773
|
/**
|
|
8587
8774
|
* @description Removes a complete filter from the collection based on filter value.
|
|
@@ -8610,11 +8797,11 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
|
|
|
8610
8797
|
function cleanString(filter) {
|
|
8611
8798
|
return filter
|
|
8612
8799
|
.toLowerCase() // convert all characters to lowercase
|
|
8613
|
-
.normalize(
|
|
8614
|
-
.replace(/[\u0300-\u036f]/g,
|
|
8615
|
-
.replace(/\s+/g,
|
|
8800
|
+
.normalize('NFD') // separate accent marks from characters
|
|
8801
|
+
.replace(/[\u0300-\u036f]/g, '') // remove accent marks
|
|
8802
|
+
.replace(/\s+/g, ''); // remove all whitespace
|
|
8616
8803
|
}
|
|
8617
|
-
this.value =
|
|
8804
|
+
this.value = '';
|
|
8618
8805
|
this.filterValue = this.filterValue.filter((item) => item?.['value'] && cleanString(item?.['value']) !== cleanString(filter));
|
|
8619
8806
|
if (this.filterValue.length === 0) {
|
|
8620
8807
|
this.step = 1;
|
|
@@ -8659,16 +8846,16 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
|
|
|
8659
8846
|
* @summary Emits the current filter array to parent components when filters are ready
|
|
8660
8847
|
* to be applied. Only emits if there are active filters. Clears options after submission.
|
|
8661
8848
|
*
|
|
8662
|
-
* @returns {void}
|
|
8849
|
+
* @returns {Promise<void>}
|
|
8663
8850
|
* @memberOf FilterComponent
|
|
8664
8851
|
*/
|
|
8665
|
-
submit() {
|
|
8852
|
+
async submit() {
|
|
8666
8853
|
this.filterEvent.emit({
|
|
8667
8854
|
query: this.filterValue.length > 0 ? this.filterValue : undefined,
|
|
8668
8855
|
sort: {
|
|
8669
8856
|
value: this.sortValue,
|
|
8670
|
-
direction: this.sortDirection
|
|
8671
|
-
}
|
|
8857
|
+
direction: this.sortDirection,
|
|
8858
|
+
},
|
|
8672
8859
|
});
|
|
8673
8860
|
if (this.filterValue.length === 0)
|
|
8674
8861
|
this.options = [];
|
|
@@ -8683,7 +8870,9 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
|
|
|
8683
8870
|
* @memberOf FilterComponent
|
|
8684
8871
|
*/
|
|
8685
8872
|
handleSortDirectionChange() {
|
|
8686
|
-
const direction = this.sortDirection === OrderDirection.ASC
|
|
8873
|
+
const direction = this.sortDirection === OrderDirection.ASC
|
|
8874
|
+
? OrderDirection.DSC
|
|
8875
|
+
: OrderDirection.ASC;
|
|
8687
8876
|
if (direction !== this.sortDirection) {
|
|
8688
8877
|
this.sortDirection = direction;
|
|
8689
8878
|
this.submit();
|
|
@@ -8745,7 +8934,9 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
|
|
|
8745
8934
|
}
|
|
8746
8935
|
const options = optionsElement.querySelectorAll('.dcf-item');
|
|
8747
8936
|
for (const option of options) {
|
|
8748
|
-
const isActive = option.textContent
|
|
8937
|
+
const isActive = option.textContent
|
|
8938
|
+
?.toLowerCase()
|
|
8939
|
+
.includes(value.toLowerCase());
|
|
8749
8940
|
if (isActive) {
|
|
8750
8941
|
option.classList.add('dcf-filtering-item');
|
|
8751
8942
|
break;
|
|
@@ -8784,7 +8975,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
|
|
|
8784
8975
|
IonSelect,
|
|
8785
8976
|
IonSelectOption,
|
|
8786
8977
|
IonIcon,
|
|
8787
|
-
SearchbarComponent
|
|
8978
|
+
SearchbarComponent,
|
|
8788
8979
|
], standalone: true, host: { '[attr.id]': 'uid' }, template: "\n@if (!indexes.length) {\n <ngx-decaf-searchbar [emitEventToWindow]=\"false\" [debounce]=\"500\" (searchEvent)=\"handleSearch($event)\" />\n}\n\n<div [id]=\"uid\" class=\"dcf-grid dcf-grid-small dcf-grid-match dcf-filter-component\" [class.dcf-hidden]=\"!indexes.length\" #component>\n <div class=\"dcf-width-expand\">\n <div class=\"dcf-filter\">\n <div class=\"dcf-input\">\n @for(filter of filterValue; track trackItemFn($index, filter?.['index'])) {\n @if (filter?.['index']) {\n <ion-chip [outline]=\"true\">{{ filter?.['index'] }}</ion-chip>\n }\n @if (filter?.['condition']) {\n <ion-chip [outline]=\"true\">{{ filter?.['condition'] }}</ion-chip>\n }\n @if (filter?.['value']) {\n <ion-chip [outline]=\"true\" class=\"dcf-filter-value\">\n {{ filter?.['value'] }}\n <ion-icon tabindex=\"0\" name=\"close-outline\" (click)=\"removeFilter(filter?.['value'])\" size=\"small\"></ion-icon>\n </ion-chip>\n }\n }\n <div class=\"dcf-width-1-1\">\n <!-- [readonly]=\"step !== 3\" -->\n <input\n fill=\"none\"\n [(ngModel)]=\"value\"\n (keydown.enter)=\"addFilter(value, $event)\"\n (keydown.backspace)=\"clear(value)\"\n (input)=\"handleInput($event)\"\n (click)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n type=\"text\"\n id=\"dcf-filter-field\"\n placeholder=\"{{ locale + (step === 3 ? '.type' : '.select') | translate }}\"\n\n />\n @if (windowWidth >= 768) {\n <div [class]=\"'dcf-dropdown ' + (options.length > 0 ? ' dcf-active' : '')\" #optionsFilterElement>\n <div>\n @if (filteredOptions.length > 0) {\n @for(key of filteredOptions; track key) {\n <div\n class=\"dcf-item\"\n tabindex=\"0\"\n (keydown.enter)=\"selectOption(key)\"\n (click)=\"selectOption(key)\">\n {{ key }}\n </div>\n }\n } @else {\n <div class=\"dcf-empty\"\n (click)=\"filteredOptions = options; value = ''\"\n tabindex=\"0\"\n (keydown.enter)=\"filteredOptions = options; value = ''\"\n >\n {{ locale + '.no_suggestions' | translate }}\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n @if (filterValue.length > 0) {\n <div class=\"dcf-icon-clear\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"clear()\">\n <ion-icon aria-hidden=\"true\" name=\"trash-outline\" [color]=\"!isDarkMode ? 'dark' : 'light'\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n }\n <div class=\"dcf-icon-search\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"submit()\">\n <ion-icon aria-hidden=\"true\" name=\"search-outline\" [color]=\"!isDarkMode ? 'dark' : 'light'\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n </div>\n @if (windowWidth < 768) {\n <div [class]=\"'dcf-dropdown ' + (options.length > 0 ? ' dcf-active' : '')\" #optionsFilterElement>\n <div>\n @if (filteredOptions.length > 0) {\n @for(key of filteredOptions; track key) {\n <div\n class=\"dcf-item\"\n tabindex=\"0\"\n (keydown.enter)=\"selectOption(key)\"\n (click)=\"selectOption(key)\">\n {{ key }}\n </div>\n }\n } @else {\n <div class=\"dcf-empty\"\n (click)=\"filteredOptions = options; value = ''\"\n tabindex=\"0\"\n (keydown.enter)=\"filteredOptions = options; value = ''\"\n >\n {{ locale + '.no_suggestions' | translate }}\n </div>\n }\n </div>\n </div>\n }\n </div>\n @if (!disableSort) {\n <div class=\"dcf-width-1-5@m dcf-width-1-1 dcf-sort-container\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-grid-match\">\n <div class=\"dcf-width-expand\">\n <ion-select\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n class=\"dcf-sort-select\"\n (ionChange)=\"handleSortChange($event)\"\n interface=\"popover\"\n [value]=\"sortValue\"\n label-placement=\"floating\"\n fill=\"outline\"\n [label]=\"locale + '.sort' | translate\"\n >\n @for(sort of sortBy; track sort) {\n\n <ion-select-option [value]=\"sort\">{{ sort | translate }}</ion-select-option>\n }\n </ion-select>\n </div>\n <div class=\"dcf-width-auto\">\n <ion-button (click)=\"handleSortDirectionChange()\" fill=\"clear\">\n <ion-icon aria-hidden=\"true\" slot=\"icon-only\" [color]=\"!isDarkMode ? 'primary' : 'light'\" [name]=\"sortDirection === 'desc' ? 'arrow-down-outline' : 'arrow-up-outline'\"></ion-icon>\n </ion-button>\n </div>\n </div>\n </div>\n }\n</div>\n\n\n", styles: [":host{position:relative;z-index:1000!important}:host *{z-index:1000!important}.dcf-filter-component{padding:0 .5rem;margin-top:.75rem;margin-bottom:.75rem}.dcf-filter-component:not(.dcf-palette-dark) .dcf-filter{border:1px solid var(--dcf-color-gray-3);background-color:#fff}.dcf-filter-component:not(.dcf-palette-dark) .dcf-filter:focus-within{border-color:var(--dcf-color-primary);background-color:#fff}.dcf-filter-component:not(.dcf-palette-dark) ion-chip{border:1px solid var(--dcf-color-gray-3);color:var(--dcf-color-gray-7)}.dcf-filter-component:not(.dcf-palette-dark) ion-chip.dcf-filter-value{background:var(--dcf-color-gray-2);border-color:var(--dcf-color-gray-4)!important;color:var(--dcf-color-gray-8)!important}.dcf-filter-component:not(.dcf-palette-dark) .dcf-input input{color:var(--dcf-color-gray-7)}.dcf-filter-component:not(.dcf-palette-dark) .dcf-dropdown{background-color:#fff}.dcf-filter-component:not(.dcf-palette-dark) .dcf-dropdown.dcf-active{border:1px solid var(--dcf-color-gray-2)}.dcf-filter-component:not(.dcf-palette-dark) .dcf-dropdown.dcf-active>div>div{color:var(--dcf-color-gray-8)}.dcf-filter-component:not(.dcf-palette-dark) .dcf-dropdown.dcf-active>div>div.dcf-filtering-item,.dcf-filter-component:not(.dcf-palette-dark) .dcf-dropdown.dcf-active>div>div:only-child{border-color:var(--dcf-color-gray-3)}.dcf-filter-component:not(.dcf-palette-dark) .dcf-dropdown.dcf-active>div>div.dcf-filtering-item.dcf-empty,.dcf-filter-component:not(.dcf-palette-dark) .dcf-dropdown.dcf-active>div>div:only-child.dcf-empty{pointer-events:none;touch-action:none;cursor:text!important;border-color:transparent!important}.dcf-filter-component:not(.dcf-palette-dark) .dcf-dropdown.dcf-active>div>div:hover{background-color:var(--dcf-color-gray-1)}.dcf-filter-component.dcf-palette-dark .dcf-filter{border:1px solid var(--dcf-color-step-500)}.dcf-filter-component.dcf-palette-dark .dcf-filter ::-webkit-input-placeholder,.dcf-filter-component.dcf-palette-dark .dcf-filter ::placeholder{color:var(--dcf-color-gray-4)!important}.dcf-filter-component.dcf-palette-dark .dcf-filter:hover{border-color:var(--dcf-color-gray-2)}.dcf-filter-component.dcf-palette-dark .dcf-filter:focus-within{border-color:var(--dcf-color-gray-2)}.dcf-filter-component.dcf-palette-dark ion-chip{border-color:var(--dcf-color-step-300);background:rgba(var(--dcf-color-medium-rgb),.1)}.dcf-filter-component.dcf-palette-dark ion-chip.dcf-filter-value{background:rgba(var(--dcf-color-medium-rgb),.3)!important;border-color:var(--dcf-color-step-500)}.dcf-filter-component.dcf-palette-dark .dcf-input input{color:var(--dcf-color-gray-1)}.dcf-filter-component.dcf-palette-dark .dcf-dropdown{background-color:var(--dcf-item-background)}.dcf-filter-component.dcf-palette-dark .dcf-dropdown.dcf-active{border:1px solid var(--dcf-color-step-600)}.dcf-filter-component.dcf-palette-dark .dcf-dropdown.dcf-active>div>div{color:var(--dcf-color-gray-1)}.dcf-filter-component.dcf-palette-dark .dcf-dropdown.dcf-active>div>div.dcf-filtering-item,.dcf-filter-component.dcf-palette-dark .dcf-dropdown.dcf-active>div>div:only-child{border-color:var(--dcf-color-gray-5)}.dcf-filter-component.dcf-palette-dark .dcf-dropdown.dcf-active>div>div.dcf-filtering-item.dcf-empty,.dcf-filter-component.dcf-palette-dark .dcf-dropdown.dcf-active>div>div:only-child.dcf-empty{cursor:text!important;pointer-events:none;touch-action:none;border-color:transparent!important}.dcf-filter-component.dcf-palette-dark .dcf-dropdown.dcf-active>div>div:hover{background-color:var(--dcf-color-gray-8)}ion-select{min-height:44px!important}.dcf-hidden{display:none!important}.dcf-filter{display:flex;width:100%;min-height:40px;box-shadow:0 1px 2px #0a0d120d;border-radius:var(--dcf-border-radius);box-sizing:border-box}.dcf-filter ion-chip{border-radius:6px;padding:0 8px!important;height:24px;min-height:24px;font-size:.75rem;font-style:normal;font-weight:500;flex-shrink:0;margin-right:2px;white-space:nowrap}.dcf-filter ion-chip.sc-ion-chip-md-h,.dcf-filter ion-chip.sc-ion-chip-ios-h{height:24px;min-height:24px}.dcf-filter ion-chip.sc-ion-chip-md-h .chip-native,.dcf-filter ion-chip.sc-ion-chip-ios-h .chip-native{padding:0 8px!important;height:24px;min-height:24px}.dcf-filter ion-chip ion-label{padding:0 4px;margin:0;font-size:.75rem;white-space:nowrap}.dcf-filter ion-chip ion-icon{margin:0 2px;font-size:.75rem}.dcf-filter .dcf-input{width:100%;display:flex;align-items:center;overflow-x:auto;overflow-y:hidden;white-space:nowrap;padding-left:.5rem}.dcf-filter .dcf-input input{min-height:40px;min-width:100px;width:100%;font-size:1rem;border:none;outline:none;background:transparent;border:0px!important;outline:none!important}.dcf-filter .dcf-input input:focus{border:0px!important;outline:none!important}.dcf-filter .dcf-icon-clear,.dcf-filter .dcf-icon-search{display:flex;justify-content:center;text-align:center;align-items:center;min-width:40px}.dcf-filter .dcf-icon-search ion-icon{font-size:1.25rem}.dcf-sort-container{min-width:200px!important;width:auto}@media (min-width: 990px){.dcf-sort-container{max-width:20%!important}}@media (max-width: 680px){.dcf-sort-container{min-width:100%!important;margin:.75rem 0rem}}.dcf-dropdown{position:absolute;max-height:200px;overflow-y:auto;border-radius:4px;z-index:1000!important;min-width:200px;max-width:300px;display:none}.dcf-dropdown.dcf-active{display:block;margin-top:-3px;box-shadow:0 12px 16px -4px #0a0d1214,0 4px 6px -2px #0a0d1208,0 2px 2px -1px #0a0d120a!important;border-radius:var(--dcf-border-radius);padding:.5rem .25rem}@media (max-width: 768px){.dcf-dropdown.dcf-active{margin-top:55px}}.dcf-dropdown.dcf-active>div>div{cursor:pointer;height:35px;padding:.5rem 1rem;border:1px solid transparent;font-size:1rem;display:flex;align-items:center;border-radius:6px}\n"] }]
|
|
8789
8980
|
}], ctorParameters: () => [], propDecorators: { optionsFilterElement: [{
|
|
8790
8981
|
type: ViewChild,
|
|
@@ -9203,7 +9394,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9203
9394
|
* @memberOf ListComponent
|
|
9204
9395
|
*/
|
|
9205
9396
|
constructor() {
|
|
9206
|
-
super(
|
|
9397
|
+
super('ListComponent');
|
|
9207
9398
|
/**
|
|
9208
9399
|
* @description The display mode for the list component.
|
|
9209
9400
|
* @summary Determines how the list data is loaded and displayed. Options include:
|
|
@@ -9279,7 +9470,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9279
9470
|
* @default "full"
|
|
9280
9471
|
* @memberOf ListComponent
|
|
9281
9472
|
*/
|
|
9282
|
-
this.lines =
|
|
9473
|
+
this.lines = 'full';
|
|
9283
9474
|
/**
|
|
9284
9475
|
* @description Controls whether the list has inset styling.
|
|
9285
9476
|
* @summary When set to true, the list will have inset styling with rounded corners
|
|
@@ -9300,7 +9491,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9300
9491
|
* @default "15%"
|
|
9301
9492
|
* @memberOf ListComponent
|
|
9302
9493
|
*/
|
|
9303
|
-
this.scrollThreshold =
|
|
9494
|
+
this.scrollThreshold = '15%';
|
|
9304
9495
|
/**
|
|
9305
9496
|
* @description The position where new items are added during infinite scrolling.
|
|
9306
9497
|
* @summary Determines whether new items are added to the top or bottom of the list
|
|
@@ -9310,7 +9501,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9310
9501
|
* @default "bottom"
|
|
9311
9502
|
* @memberOf ListComponent
|
|
9312
9503
|
*/
|
|
9313
|
-
this.scrollPosition =
|
|
9504
|
+
this.scrollPosition = 'bottom';
|
|
9314
9505
|
/**
|
|
9315
9506
|
* @description Controls the visibility of the pull-to-refresh feature.
|
|
9316
9507
|
* @summary When set to true, enables the pull-to-refresh functionality that allows
|
|
@@ -9339,7 +9530,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9339
9530
|
* @default "circular"
|
|
9340
9531
|
* @memberOf ListComponent
|
|
9341
9532
|
*/
|
|
9342
|
-
this.loadingSpinner =
|
|
9533
|
+
this.loadingSpinner = 'circular';
|
|
9343
9534
|
// /**
|
|
9344
9535
|
// * @description Query parameters for data fetching.
|
|
9345
9536
|
// * @summary Specifies additional query parameters to use when fetching data from
|
|
@@ -9408,17 +9599,6 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9408
9599
|
* @memberOf ListComponent
|
|
9409
9600
|
*/
|
|
9410
9601
|
this.page = 1;
|
|
9411
|
-
/**
|
|
9412
|
-
* @description Indicates whether a refresh operation is in progress.
|
|
9413
|
-
* @summary When true, the component is currently fetching new data. This is used
|
|
9414
|
-
* to control loading indicators and prevent duplicate refresh operations from
|
|
9415
|
-
* being triggered simultaneously.
|
|
9416
|
-
*
|
|
9417
|
-
* @type {boolean}
|
|
9418
|
-
* @default false
|
|
9419
|
-
* @memberOf ListComponent
|
|
9420
|
-
*/
|
|
9421
|
-
this.refreshing = false;
|
|
9422
9602
|
/**
|
|
9423
9603
|
* @description Array used for rendering skeleton loading placeholders.
|
|
9424
9604
|
* @summary Contains placeholder items that are displayed during data loading.
|
|
@@ -9440,15 +9620,6 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9440
9620
|
* @memberOf ListComponent
|
|
9441
9621
|
*/
|
|
9442
9622
|
this.lastPage = 1;
|
|
9443
|
-
/**
|
|
9444
|
-
* @description Event emitter for refresh operations.
|
|
9445
|
-
* @summary Emits an event when the list data is refreshed, either through pull-to-refresh
|
|
9446
|
-
* or programmatic refresh. The event includes the refreshed data and component information.
|
|
9447
|
-
*
|
|
9448
|
-
* @type {EventEmitter<IBaseCustomEvent>}
|
|
9449
|
-
* @memberOf ListComponent
|
|
9450
|
-
*/
|
|
9451
|
-
this.refreshEvent = new EventEmitter();
|
|
9452
9623
|
/**
|
|
9453
9624
|
* @description Event emitter for item click interactions.
|
|
9454
9625
|
* @summary Emits an event when a list item is clicked. The event includes the data
|
|
@@ -9509,9 +9680,15 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9509
9680
|
* @memberOf ListComponent
|
|
9510
9681
|
*/
|
|
9511
9682
|
async ngOnInit() {
|
|
9512
|
-
this.observer = {
|
|
9513
|
-
|
|
9514
|
-
|
|
9683
|
+
this.observer = {
|
|
9684
|
+
refresh: async (...args) => this.observeRepository(...args),
|
|
9685
|
+
};
|
|
9686
|
+
this.clickItemSubject
|
|
9687
|
+
.pipe(debounceTime(100))
|
|
9688
|
+
.subscribe((event) => this.clickEventEmit(event));
|
|
9689
|
+
this.observerSubjet
|
|
9690
|
+
.pipe(debounceTime(100))
|
|
9691
|
+
.subscribe((args) => this.handleObserveEvent(args[0], args[1], args[2]));
|
|
9515
9692
|
this.limit = Number(this.limit);
|
|
9516
9693
|
this.start = Number(this.start);
|
|
9517
9694
|
this.enableFilter = stringToBoolean(this.enableFilter);
|
|
@@ -9619,7 +9796,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9619
9796
|
async handleCreate(uid) {
|
|
9620
9797
|
const result = await this._repository?.read(uid);
|
|
9621
9798
|
const item = this.mapResults([result])[0];
|
|
9622
|
-
this.items = this.data = [item, ...this.items || []];
|
|
9799
|
+
this.items = this.data = [item, ...(this.items || [])];
|
|
9623
9800
|
}
|
|
9624
9801
|
/**
|
|
9625
9802
|
* @description Handles the update event from the repository.
|
|
@@ -9631,7 +9808,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9631
9808
|
* @memberOf ListComponent
|
|
9632
9809
|
*/
|
|
9633
9810
|
async handleUpdate(uid) {
|
|
9634
|
-
const item = this.itemMapper(await this._repository?.read(uid) || {}, this.mapper);
|
|
9811
|
+
const item = this.itemMapper((await this._repository?.read(uid)) || {}, this.mapper);
|
|
9635
9812
|
this.data = [];
|
|
9636
9813
|
for (const key in this.items) {
|
|
9637
9814
|
const child = this.items[key];
|
|
@@ -9658,7 +9835,8 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9658
9835
|
handleDelete(uid, pk) {
|
|
9659
9836
|
if (!pk)
|
|
9660
9837
|
pk = this.pk;
|
|
9661
|
-
this.items =
|
|
9838
|
+
this.items =
|
|
9839
|
+
this.data?.filter((item) => item['uid'] !== uid) || [];
|
|
9662
9840
|
}
|
|
9663
9841
|
/**
|
|
9664
9842
|
* @description Handles click events from list items.
|
|
@@ -9762,7 +9940,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9762
9940
|
this.refreshEvent.emit({
|
|
9763
9941
|
name: ComponentEventNames.REFRESH,
|
|
9764
9942
|
data: data || [],
|
|
9765
|
-
component: this.componentName
|
|
9943
|
+
component: this.componentName,
|
|
9766
9944
|
});
|
|
9767
9945
|
}
|
|
9768
9946
|
/**
|
|
@@ -9838,10 +10016,10 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9838
10016
|
// }
|
|
9839
10017
|
this.refreshing = true;
|
|
9840
10018
|
const start = this.page > 1 ? (this.page - 1) * this.limit : this.start;
|
|
9841
|
-
const limit =
|
|
9842
|
-
this.data = !this.model
|
|
9843
|
-
await this.getFromRequest(!!event, start, limit)
|
|
9844
|
-
: await this.getFromModel(!!event);
|
|
10019
|
+
const limit = this.page * (this.limit > 12 ? 12 : this.limit);
|
|
10020
|
+
this.data = !this.model
|
|
10021
|
+
? await this.getFromRequest(!!event, start, limit)
|
|
10022
|
+
: (await this.getFromModel(!!event));
|
|
9845
10023
|
if (this.type === ListComponentsTypes.INFINITE) {
|
|
9846
10024
|
if (this.page === this.pages) {
|
|
9847
10025
|
if (event?.target)
|
|
@@ -9852,7 +10030,9 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9852
10030
|
this.page += 1;
|
|
9853
10031
|
this.refreshing = false;
|
|
9854
10032
|
setTimeout(() => {
|
|
9855
|
-
if (event?.target &&
|
|
10033
|
+
if (event?.target &&
|
|
10034
|
+
event?.type !==
|
|
10035
|
+
ComponentEventNames.BACK_BUTTON_NAVIGATION)
|
|
9856
10036
|
event.target.complete();
|
|
9857
10037
|
}, 200);
|
|
9858
10038
|
}
|
|
@@ -9864,16 +10044,16 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9864
10044
|
}
|
|
9865
10045
|
}
|
|
9866
10046
|
/**
|
|
9867
|
-
|
|
9868
|
-
|
|
9869
|
-
|
|
9870
|
-
|
|
9871
|
-
|
|
9872
|
-
|
|
9873
|
-
|
|
9874
|
-
|
|
9875
|
-
|
|
9876
|
-
|
|
10047
|
+
* @description Handles pagination events from the pagination component.
|
|
10048
|
+
* @summary Processes pagination events by updating the current page number and
|
|
10049
|
+
* refreshing the list data to display the selected page. This method is called
|
|
10050
|
+
* when a user interacts with the pagination controls to navigate between pages.
|
|
10051
|
+
*
|
|
10052
|
+
* @param {IPaginationCustomEvent} event - The pagination event containing page information
|
|
10053
|
+
* @returns {void}
|
|
10054
|
+
*
|
|
10055
|
+
* @memberOf ListComponent
|
|
10056
|
+
*/
|
|
9877
10057
|
handlePaginate(event) {
|
|
9878
10058
|
const { page } = event.data;
|
|
9879
10059
|
this.page = page;
|
|
@@ -9911,8 +10091,11 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9911
10091
|
* @memberOf ListComponent
|
|
9912
10092
|
*/
|
|
9913
10093
|
parseSearchResults(results, search) {
|
|
9914
|
-
const filtered = results.filter((item) => Object.values(item).some(v => {
|
|
9915
|
-
if (v
|
|
10094
|
+
const filtered = results.filter((item) => Object.values(item).some((v) => {
|
|
10095
|
+
if (v
|
|
10096
|
+
.toString()
|
|
10097
|
+
.toLowerCase()
|
|
10098
|
+
.includes(search?.toLowerCase()))
|
|
9916
10099
|
return v;
|
|
9917
10100
|
}));
|
|
9918
10101
|
return filtered;
|
|
@@ -9931,25 +10114,31 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9931
10114
|
* @memberOf ListComponent
|
|
9932
10115
|
*/
|
|
9933
10116
|
async getFromRequest(force = false, start, limit) {
|
|
9934
|
-
let data = [...this.data || []];
|
|
9935
|
-
if (!this.data?.length ||
|
|
10117
|
+
let data = [...(this.data || [])];
|
|
10118
|
+
if (!this.data?.length ||
|
|
10119
|
+
force ||
|
|
10120
|
+
this.searchValue?.length ||
|
|
10121
|
+
!!this.searchValue) {
|
|
9936
10122
|
// (self.data as ListItem[]) = [];
|
|
9937
|
-
if (!this.searchValue?.length &&
|
|
10123
|
+
if (!this.searchValue?.length &&
|
|
10124
|
+
!this.searchValue) {
|
|
9938
10125
|
if (!this.source && !this.data?.length) {
|
|
9939
|
-
this.
|
|
10126
|
+
this.log.info('No data and source passed to infinite list');
|
|
9940
10127
|
return [];
|
|
9941
10128
|
}
|
|
9942
10129
|
if (this.source instanceof Function) {
|
|
9943
|
-
data = await this.source();
|
|
10130
|
+
data = (await this.source());
|
|
9944
10131
|
if (!Array.isArray(data))
|
|
9945
10132
|
data = data?.['response']?.['data'] || data?.['results'] || [];
|
|
9946
10133
|
}
|
|
9947
10134
|
if (!data?.length && this.data?.length)
|
|
9948
10135
|
data = this.data;
|
|
9949
|
-
this.data = [...await this.parseResult(data)];
|
|
10136
|
+
this.data = [...(await this.parseResult(data))];
|
|
9950
10137
|
if (this.data?.length)
|
|
9951
|
-
this.items =
|
|
9952
|
-
|
|
10138
|
+
this.items =
|
|
10139
|
+
this.type === ListComponentsTypes.INFINITE
|
|
10140
|
+
? (this.items || []).concat([...this.data.slice(start, limit)])
|
|
10141
|
+
: [...data.slice(start, limit)];
|
|
9953
10142
|
}
|
|
9954
10143
|
else {
|
|
9955
10144
|
const data = await this.parseResult(this.parseSearchResults(this.data, this.searchValue));
|
|
@@ -9959,8 +10148,11 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9959
10148
|
}
|
|
9960
10149
|
}
|
|
9961
10150
|
else {
|
|
9962
|
-
const data = [...await this.parseResult(this.data)];
|
|
9963
|
-
this.items =
|
|
10151
|
+
const data = [...(await this.parseResult(this.data))];
|
|
10152
|
+
this.items =
|
|
10153
|
+
this.type === ListComponentsTypes.INFINITE
|
|
10154
|
+
? [...(this.items || []), ...(data || [])]
|
|
10155
|
+
: [...(data || [])];
|
|
9964
10156
|
if (this.isModalChild)
|
|
9965
10157
|
this.changeDetectorRef.detectChanges();
|
|
9966
10158
|
}
|
|
@@ -9982,7 +10174,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9982
10174
|
* @memberOf ListComponent
|
|
9983
10175
|
*/
|
|
9984
10176
|
async getFromModel(force = false) {
|
|
9985
|
-
let data = [...this.data || []];
|
|
10177
|
+
let data = [...(this.data || [])];
|
|
9986
10178
|
let request = [];
|
|
9987
10179
|
// getting model repository
|
|
9988
10180
|
if (!this._repository) {
|
|
@@ -9991,9 +10183,13 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
9991
10183
|
this._repository.observe(this.observer);
|
|
9992
10184
|
}
|
|
9993
10185
|
const repo = this._repository;
|
|
9994
|
-
if (!this.data?.length ||
|
|
10186
|
+
if (!this.data?.length ||
|
|
10187
|
+
force ||
|
|
10188
|
+
this.searchValue?.length ||
|
|
10189
|
+
!!this.searchValue) {
|
|
9995
10190
|
try {
|
|
9996
|
-
if (!this.searchValue?.length &&
|
|
10191
|
+
if (!this.searchValue?.length &&
|
|
10192
|
+
!this.searchValue) {
|
|
9997
10193
|
this.data = [];
|
|
9998
10194
|
// const rawQuery = this.parseQuery(self.model as Repository<Model>, start, limit);
|
|
9999
10195
|
// request = this.parseResult(await (this.model as any)?.paginate(start, limit));
|
|
@@ -10007,17 +10203,21 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
10007
10203
|
}
|
|
10008
10204
|
else {
|
|
10009
10205
|
if (!this.indexes)
|
|
10010
|
-
this.indexes =
|
|
10206
|
+
this.indexes = Object.values(this.mapper) || [this.pk];
|
|
10011
10207
|
const condition = this.parseConditions(this.searchValue);
|
|
10012
10208
|
this.changeDetectorRef.detectChanges();
|
|
10013
10209
|
request = await this.parseResult(await repo.query(condition, (this.sortBy || this.pk), this.sortDirection));
|
|
10014
10210
|
data = [];
|
|
10015
10211
|
this.changeDetectorRef.detectChanges();
|
|
10016
10212
|
}
|
|
10017
|
-
data =
|
|
10213
|
+
data =
|
|
10214
|
+
this.type === ListComponentsTypes.INFINITE
|
|
10215
|
+
? [...data.concat(request)]
|
|
10216
|
+
: [...request];
|
|
10018
10217
|
}
|
|
10019
10218
|
catch (error) {
|
|
10020
|
-
this.
|
|
10219
|
+
this.log.error(error?.message ||
|
|
10220
|
+
`Unable to find ${this.model} on registry. Return empty array from component`);
|
|
10021
10221
|
}
|
|
10022
10222
|
}
|
|
10023
10223
|
if (data?.length) {
|
|
@@ -10057,7 +10257,8 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
10057
10257
|
*/
|
|
10058
10258
|
parseConditions(value) {
|
|
10059
10259
|
let _condition;
|
|
10060
|
-
if (typeof value === Primitives.STRING ||
|
|
10260
|
+
if (typeof value === Primitives.STRING ||
|
|
10261
|
+
typeof value === Primitives.NUMBER) {
|
|
10061
10262
|
_condition = Condition.attribute(this.pk).eq(!isNaN(value) ? Number(value) : value);
|
|
10062
10263
|
for (const index of this.indexes) {
|
|
10063
10264
|
if (index === this.pk)
|
|
@@ -10084,27 +10285,28 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
10084
10285
|
val = Number(val);
|
|
10085
10286
|
let orCondition;
|
|
10086
10287
|
switch (condition) {
|
|
10087
|
-
case
|
|
10288
|
+
case 'Equal':
|
|
10088
10289
|
orCondition = Condition.attribute(index).eq(val);
|
|
10089
10290
|
break;
|
|
10090
|
-
case
|
|
10291
|
+
case 'Not Equal':
|
|
10091
10292
|
orCondition = Condition.attribute(index).dif(val);
|
|
10092
10293
|
break;
|
|
10093
|
-
case
|
|
10294
|
+
case 'Not Contains':
|
|
10094
10295
|
orCondition = !Condition.attribute(index).regexp(new RegExp(`^(?!.*${val}).*$`));
|
|
10095
10296
|
break;
|
|
10096
|
-
case
|
|
10297
|
+
case 'Contains':
|
|
10097
10298
|
orCondition = Condition.attribute(index).regexp(val);
|
|
10098
10299
|
break;
|
|
10099
|
-
case
|
|
10300
|
+
case 'Greater Than':
|
|
10100
10301
|
orCondition = Condition.attribute(index).gte(val);
|
|
10101
10302
|
break;
|
|
10102
|
-
case
|
|
10303
|
+
case 'Less Than':
|
|
10103
10304
|
orCondition = Condition.attribute(index).lte(val);
|
|
10104
10305
|
break;
|
|
10105
10306
|
}
|
|
10106
|
-
_condition = (!_condition
|
|
10107
|
-
|
|
10307
|
+
_condition = (!_condition
|
|
10308
|
+
? orCondition
|
|
10309
|
+
: _condition.and(orCondition));
|
|
10108
10310
|
});
|
|
10109
10311
|
this.sortBy = sort?.value || this.pk;
|
|
10110
10312
|
this.sortDirection = sort?.direction || this.sortDirection;
|
|
@@ -10124,22 +10326,24 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
10124
10326
|
* @memberOf ListComponent
|
|
10125
10327
|
*/
|
|
10126
10328
|
async parseResult(result) {
|
|
10127
|
-
if (!Array.isArray(result) &&
|
|
10329
|
+
if (!Array.isArray(result) && 'page' in result && 'total' in result) {
|
|
10128
10330
|
const paginator = result;
|
|
10129
10331
|
try {
|
|
10130
10332
|
result = await paginator.page(this.page);
|
|
10131
10333
|
this.getMoreData(paginator.total);
|
|
10132
10334
|
}
|
|
10133
10335
|
catch (error) {
|
|
10134
|
-
this.
|
|
10336
|
+
this.log.info(error?.message ||
|
|
10337
|
+
'Unable to get page from paginator. Return empty array from component');
|
|
10135
10338
|
result = [];
|
|
10136
10339
|
}
|
|
10137
10340
|
}
|
|
10138
10341
|
else {
|
|
10139
10342
|
this.getMoreData(result?.length || 0);
|
|
10140
10343
|
}
|
|
10141
|
-
return
|
|
10142
|
-
this.mapResults(result)
|
|
10344
|
+
return Object.keys(this.mapper || {}).length
|
|
10345
|
+
? this.mapResults(result)
|
|
10346
|
+
: result;
|
|
10143
10347
|
}
|
|
10144
10348
|
/**
|
|
10145
10349
|
* @description Updates pagination state based on data length.
|
|
@@ -10161,7 +10365,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
10161
10365
|
}
|
|
10162
10366
|
else {
|
|
10163
10367
|
this.pages = Math.floor(length / this.limit);
|
|
10164
|
-
if (
|
|
10368
|
+
if (this.pages * this.limit < length)
|
|
10165
10369
|
this.pages += 1;
|
|
10166
10370
|
if (this.pages === 1)
|
|
10167
10371
|
this.loadMoreData = false;
|
|
@@ -10195,7 +10399,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
10195
10399
|
}
|
|
10196
10400
|
else {
|
|
10197
10401
|
if (arrayValue.length === 1) {
|
|
10198
|
-
value = item?.[value] ? item[value] :
|
|
10402
|
+
value = item?.[value] ? item[value] : '';
|
|
10199
10403
|
// value = item?.[value] ? item[value] : value !== key ? value : "";
|
|
10200
10404
|
if (isValidDate(value))
|
|
10201
10405
|
value = `${formatDate(value)}`;
|
|
@@ -10244,18 +10448,23 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
|
|
|
10244
10448
|
// }, {}))
|
|
10245
10449
|
});
|
|
10246
10450
|
return data.reduce((accum, curr) => {
|
|
10247
|
-
accum.push({
|
|
10451
|
+
accum.push({
|
|
10452
|
+
...this.itemMapper(curr, this.mapper, props),
|
|
10453
|
+
...{ pk: this.pk },
|
|
10454
|
+
});
|
|
10248
10455
|
return accum;
|
|
10249
10456
|
}, []);
|
|
10250
10457
|
}
|
|
10251
10458
|
parseSearchValue() {
|
|
10252
10459
|
if (typeof this.searchValue === Primitives.STRING)
|
|
10253
|
-
return this.searchValue ||
|
|
10460
|
+
return this.searchValue || '';
|
|
10254
10461
|
const searchValue = this.searchValue;
|
|
10255
|
-
return (searchValue?.query)
|
|
10462
|
+
return (searchValue?.query)
|
|
10463
|
+
.map((item) => `${item.index} ${item.condition} ${item.value}`)
|
|
10464
|
+
.join(', ');
|
|
10256
10465
|
}
|
|
10257
10466
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: ListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
10258
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: ListComponent, isStandalone: true, selector: "ngx-decaf-list", inputs: { type: "type", showSearchbar: "showSearchbar", data: "data", source: "source", start: "start", limit: "limit", loadMoreData: "loadMoreData", lines: "lines", inset: "inset", scrollThreshold: "scrollThreshold", scrollPosition: "scrollPosition", loadingText: "loadingText", showRefresher: "showRefresher", createButton: "createButton", loadingSpinner: "loadingSpinner", enableFilter: "enableFilter", sortDirection: "sortDirection", sortBy: "sortBy", disableSort: "disableSort", empty: "empty" }, outputs: {
|
|
10467
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: ListComponent, isStandalone: true, selector: "ngx-decaf-list", inputs: { type: "type", showSearchbar: "showSearchbar", data: "data", source: "source", start: "start", limit: "limit", loadMoreData: "loadMoreData", lines: "lines", inset: "inset", scrollThreshold: "scrollThreshold", scrollPosition: "scrollPosition", loadingText: "loadingText", showRefresher: "showRefresher", createButton: "createButton", loadingSpinner: "loadingSpinner", enableFilter: "enableFilter", sortDirection: "sortDirection", sortBy: "sortBy", disableSort: "disableSort", empty: "empty" }, outputs: { clickEvent: "clickEvent" }, host: { listeners: { "window:ListItemClickEvent": "handleClick($event)", "window:searchbarEvent": "handleSearch($event)", "window:BackButtonNavigationEndEvent": "refresh($event)" }, properties: { "attr.id": "uid" } }, usesInheritance: true, ngImport: i0, template: "\n@if (showRefresher) {\n <ion-refresher slot=\"fixed\" [pullFactor]=\"1\" [pullMin]=\"100\" [pullMax]=\"200\" (ionRefresh)=\"handleRefresh($event)\">\n <ion-refresher-content />\n </ion-refresher>\n}\n\n\n@if (showSearchbar) {\n <div [hidden]=\"!data?.length\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-grid-actions\">\n <div class=\"dcf-width-expand@m dcf-width-1-1\">\n @if (model && enableFilter) {\n @if (data?.length || searching) {\n <ngx-decaf-filter\n [model]=\"model\"\n [sortDirection]=\"sortDirection\"\n [disableSort]=\"disableSort\"\n (filterEvent)=\"handleFilter($event)\"\n (searchEvent)=\"handleSearch($event)\"\n />\n }\n } @else {\n <ngx-decaf-searchbar [emitEventToWindow]=\"false\" [debounce]=\"500\" (searchEvent)=\"handleSearch($event)\" />\n }\n </div>\n @if(createButton) {\n <div class=\"dcf-width-auto@m dcf-button-container dcf-width-1-1 dcf-flex-middle dcf-flex dcf-flex-center dcf-flex-right@m\">\n <div>\n <ion-button expand=\"block\" (click)=\"changeOperation(OperationKeys.CREATE)\">Create</ion-button>\n </div>\n </div>\n }\n </div>\n </div>\n}\n\n@if (initialized && data?.length) {\n <ion-list [id]=\"uid\" [inset]=\"inset\" [lines]=\"lines\">\n @if (item?.tag) {\n @for(child of items; track trackItemFn($index, child)) {\n <ngx-decaf-component-renderer\n [tag]=\"item.tag\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]='{\n item: child,\n mapper: mapper,\n route: route\n }'>\n </ngx-decaf-component-renderer>\n }\n } @else {\n <ng-content></ng-content>\n }\n </ion-list>\n\n @if (loadMoreData) {\n @if (pages > 0 && type === 'paginated' && !searchValue?.length) {\n <ngx-decaf-pagination\n [totalPages]=\"pages\"\n [current]=\"page\"\n (clickEvent)=\"handlePaginate($event)\"\n />\n\n } @else {\n <ion-infinite-scroll\n [class]=\"searchValue?.length ? 'dcf-hidden' : ''\"\n\n [position]=\"scrollPosition\"\n [threshold]=\"scrollThreshold\"\n (ionInfinite)=\"handleRefresh($event)\">\n <ion-infinite-scroll-content [loadingSpinner]=\"loadingSpinner\" [loadingText]=\"loadingText\" />\n </ion-infinite-scroll>\n }\n }\n} @else {\n @if (refreshing) {\n @for(skl of skeletonData; track $index) {\n <ion-item>\n <ion-thumbnail slot=\"start\">\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n </ion-thumbnail>\n <ion-label>\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n <ion-text class=\"date\" style=\"width: 20%;\"><ion-skeleton-text [animated]=\"true\"></ion-skeleton-text></ion-text>\n </ion-label>\n </ion-item>\n }\n\n } @else {\n @if (!searching) {\n <ngx-decaf-empty-state\n [title]=\"(locale + '.'+ empty.title) | translate\"\n [model]=\"model\"\n [route]=\"route\"\n [borders]=\"borders\"\n [icon]=\"empty.icon\"\n className=\"dcf-empty-data\"\n [subtitle]=\"(locale + '.'+ empty.subtitle) | translate\" />\n } @else {\n <ngx-decaf-empty-state\n icon=\"search-outline\"\n [model]=\"model\"\n [route]=\"route\"\n [borders]=\"borders\"\n className=\"empty-search\"\n [translatable]=\"true\"\n className=\"dcf-empty-data\"\n [title]=\"locale + '.search.title' | translate\"\n [subtitle]=\"locale + '.search.subtitle' | translate: {'0': parseSearchValue()}\"\n [searchValue]=\"searchValue\"\n />\n }\n }\n}\n\n", styles: ["ion-infinite-scroll{max-height:50px}ion-infinite-scroll:not(.infinite-scroll-loading) ::ng-deep{max-height:1.5rem}ion-infinite-scroll ::ng-deep ion-spinner{--color: var(--dcf-color-primary);padding-top:1rem}@media (max-width: 768px){#end,[slot=end]{display:none!important}}.dcf-grid-actions{padding:var(--dcf-padding-small);padding-bottom:0}@media (max-width: 768px){.dcf-grid-actions .dcf-button-container{width:100%!important}.dcf-grid-actions .dcf-button-container *{width:calc(100% - 5px)!important;display:inline-block;margin-top:0!important;margin-bottom:var(--dcf-margin-xsmall)!important}}.dcf-grid-actions>div:only-child{width:100%}\n"], dependencies: [{ kind: "component", type: IonRefresher, selector: "ion-refresher", inputs: ["closeDuration", "disabled", "mode", "pullFactor", "pullMax", "pullMin", "snapbackDuration"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: PaginationComponent, selector: "ngx-decaf-pagination", inputs: ["totalPages", "current"], outputs: ["clickEvent"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonThumbnail, selector: "ion-thumbnail" }, { kind: "component", type: IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonRefresherContent, selector: "ion-refresher-content", inputs: ["pullingIcon", "pullingText", "refreshingSpinner", "refreshingText"] }, { kind: "component", type: IonInfiniteScroll, selector: "ion-infinite-scroll", inputs: ["disabled", "position", "threshold"] }, { kind: "component", type: IonInfiniteScrollContent, selector: "ion-infinite-scroll-content", inputs: ["loadingSpinner", "loadingText"] }, { kind: "component", type: SearchbarComponent, selector: "ngx-decaf-searchbar", inputs: ["autocomplete", "autocorrect", "animated", "buttonCancelText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value", "queryKeys", "isVisible", "wrapper", "wrapperColor", "emitEventToWindow"], outputs: ["searchEvent"] }, { kind: "component", type: EmptyStateComponent, selector: "ngx-decaf-empty-state", inputs: ["title", "titleColor", "subtitle", "subtitleColor", "showIcon", "icon", "iconSize", "iconColor", "buttonLink", "buttonText", "buttonFill", "buttonColor", "buttonSize", "searchValue"] }, { kind: "component", type: FilterComponent, selector: "ngx-decaf-filter", inputs: ["indexes", "multiple", "conditions", "sortBy", "disableSort"], outputs: ["filterEvent", "searchEvent"] }, { kind: "component", type: ComponentRendererComponent, selector: "ngx-decaf-component-renderer", inputs: ["tag", "children", "projectable", "parent"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
10259
10468
|
};
|
|
10260
10469
|
ListComponent = __decorate([
|
|
10261
10470
|
Dynamic(),
|
|
@@ -10282,7 +10491,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
|
|
|
10282
10491
|
SearchbarComponent,
|
|
10283
10492
|
EmptyStateComponent,
|
|
10284
10493
|
FilterComponent,
|
|
10285
|
-
ComponentRendererComponent
|
|
10494
|
+
ComponentRendererComponent,
|
|
10286
10495
|
], host: { '[attr.id]': 'uid' }, template: "\n@if (showRefresher) {\n <ion-refresher slot=\"fixed\" [pullFactor]=\"1\" [pullMin]=\"100\" [pullMax]=\"200\" (ionRefresh)=\"handleRefresh($event)\">\n <ion-refresher-content />\n </ion-refresher>\n}\n\n\n@if (showSearchbar) {\n <div [hidden]=\"!data?.length\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-grid-actions\">\n <div class=\"dcf-width-expand@m dcf-width-1-1\">\n @if (model && enableFilter) {\n @if (data?.length || searching) {\n <ngx-decaf-filter\n [model]=\"model\"\n [sortDirection]=\"sortDirection\"\n [disableSort]=\"disableSort\"\n (filterEvent)=\"handleFilter($event)\"\n (searchEvent)=\"handleSearch($event)\"\n />\n }\n } @else {\n <ngx-decaf-searchbar [emitEventToWindow]=\"false\" [debounce]=\"500\" (searchEvent)=\"handleSearch($event)\" />\n }\n </div>\n @if(createButton) {\n <div class=\"dcf-width-auto@m dcf-button-container dcf-width-1-1 dcf-flex-middle dcf-flex dcf-flex-center dcf-flex-right@m\">\n <div>\n <ion-button expand=\"block\" (click)=\"changeOperation(OperationKeys.CREATE)\">Create</ion-button>\n </div>\n </div>\n }\n </div>\n </div>\n}\n\n@if (initialized && data?.length) {\n <ion-list [id]=\"uid\" [inset]=\"inset\" [lines]=\"lines\">\n @if (item?.tag) {\n @for(child of items; track trackItemFn($index, child)) {\n <ngx-decaf-component-renderer\n [tag]=\"item.tag\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]='{\n item: child,\n mapper: mapper,\n route: route\n }'>\n </ngx-decaf-component-renderer>\n }\n } @else {\n <ng-content></ng-content>\n }\n </ion-list>\n\n @if (loadMoreData) {\n @if (pages > 0 && type === 'paginated' && !searchValue?.length) {\n <ngx-decaf-pagination\n [totalPages]=\"pages\"\n [current]=\"page\"\n (clickEvent)=\"handlePaginate($event)\"\n />\n\n } @else {\n <ion-infinite-scroll\n [class]=\"searchValue?.length ? 'dcf-hidden' : ''\"\n\n [position]=\"scrollPosition\"\n [threshold]=\"scrollThreshold\"\n (ionInfinite)=\"handleRefresh($event)\">\n <ion-infinite-scroll-content [loadingSpinner]=\"loadingSpinner\" [loadingText]=\"loadingText\" />\n </ion-infinite-scroll>\n }\n }\n} @else {\n @if (refreshing) {\n @for(skl of skeletonData; track $index) {\n <ion-item>\n <ion-thumbnail slot=\"start\">\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n </ion-thumbnail>\n <ion-label>\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n <ion-text class=\"date\" style=\"width: 20%;\"><ion-skeleton-text [animated]=\"true\"></ion-skeleton-text></ion-text>\n </ion-label>\n </ion-item>\n }\n\n } @else {\n @if (!searching) {\n <ngx-decaf-empty-state\n [title]=\"(locale + '.'+ empty.title) | translate\"\n [model]=\"model\"\n [route]=\"route\"\n [borders]=\"borders\"\n [icon]=\"empty.icon\"\n className=\"dcf-empty-data\"\n [subtitle]=\"(locale + '.'+ empty.subtitle) | translate\" />\n } @else {\n <ngx-decaf-empty-state\n icon=\"search-outline\"\n [model]=\"model\"\n [route]=\"route\"\n [borders]=\"borders\"\n className=\"empty-search\"\n [translatable]=\"true\"\n className=\"dcf-empty-data\"\n [title]=\"locale + '.search.title' | translate\"\n [subtitle]=\"locale + '.search.subtitle' | translate: {'0': parseSearchValue()}\"\n [searchValue]=\"searchValue\"\n />\n }\n }\n}\n\n", styles: ["ion-infinite-scroll{max-height:50px}ion-infinite-scroll:not(.infinite-scroll-loading) ::ng-deep{max-height:1.5rem}ion-infinite-scroll ::ng-deep ion-spinner{--color: var(--dcf-color-primary);padding-top:1rem}@media (max-width: 768px){#end,[slot=end]{display:none!important}}.dcf-grid-actions{padding:var(--dcf-padding-small);padding-bottom:0}@media (max-width: 768px){.dcf-grid-actions .dcf-button-container{width:100%!important}.dcf-grid-actions .dcf-button-container *{width:calc(100% - 5px)!important;display:inline-block;margin-top:0!important;margin-bottom:var(--dcf-margin-xsmall)!important}}.dcf-grid-actions>div:only-child{width:100%}\n"] }]
|
|
10287
10496
|
}], ctorParameters: () => [], propDecorators: { type: [{
|
|
10288
10497
|
type: Input
|
|
@@ -10324,8 +10533,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
|
|
|
10324
10533
|
type: Input
|
|
10325
10534
|
}], empty: [{
|
|
10326
10535
|
type: Input
|
|
10327
|
-
}], refreshEvent: [{
|
|
10328
|
-
type: Output
|
|
10329
10536
|
}], clickEvent: [{
|
|
10330
10537
|
type: Output
|
|
10331
10538
|
}], handleClick: [{
|
|
@@ -10491,7 +10698,7 @@ let ListItemComponent = class ListItemComponent extends NgxComponentDirective {
|
|
|
10491
10698
|
this.className += ` action`;
|
|
10492
10699
|
this.windowWidth = getWindowWidth();
|
|
10493
10700
|
}
|
|
10494
|
-
ngAfterViewInit() {
|
|
10701
|
+
async ngAfterViewInit() {
|
|
10495
10702
|
this.checkDarkMode();
|
|
10496
10703
|
}
|
|
10497
10704
|
/**
|
|
@@ -11391,7 +11598,7 @@ let FileUploadComponent = class FileUploadComponent extends NgxFormFieldDirectiv
|
|
|
11391
11598
|
return xmlDoc.documentElement.innerHTML;
|
|
11392
11599
|
}
|
|
11393
11600
|
catch (error) {
|
|
11394
|
-
this.
|
|
11601
|
+
this.log.error(error?.message);
|
|
11395
11602
|
return undefined;
|
|
11396
11603
|
}
|
|
11397
11604
|
};
|
|
@@ -11705,15 +11912,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
|
|
|
11705
11912
|
class DynamicModule {
|
|
11706
11913
|
}
|
|
11707
11914
|
|
|
11708
|
-
|
|
11709
|
-
|
|
11710
|
-
|
|
11711
|
-
|
|
11712
|
-
* logging support for handlers that process custom events emitted by components.
|
|
11713
|
-
*
|
|
11714
|
-
* @link {@link NgxEventHandler}
|
|
11715
|
-
*/
|
|
11716
|
-
class NgxEventHandler extends LoggedClass {
|
|
11915
|
+
class NgxEventHandler extends DecafEventHandler {
|
|
11916
|
+
async refresh(args) {
|
|
11917
|
+
this.log.for(this.refresh).debug(`Refresh called with args: ${args}`);
|
|
11918
|
+
}
|
|
11717
11919
|
}
|
|
11718
11920
|
|
|
11719
11921
|
/**
|
|
@@ -11819,7 +12021,6 @@ class NgxPageDirective extends NgxComponentDirective {
|
|
|
11819
12021
|
this.mediaService.colorSchemeObserver(this.component);
|
|
11820
12022
|
this.currentRoute = this.router.url.replace('/', '');
|
|
11821
12023
|
this.setPageTitle(this.currentRoute);
|
|
11822
|
-
this.initialized = true;
|
|
11823
12024
|
}
|
|
11824
12025
|
/**
|
|
11825
12026
|
* @description Ionic lifecycle hook called when the page is about to enter view.
|
|
@@ -11909,17 +12110,20 @@ class NgxModelPageDirective extends NgxPageDirective {
|
|
|
11909
12110
|
* @default [OperationKeys.CREATE, OperationKeys.READ]
|
|
11910
12111
|
* @memberOf ModelPage
|
|
11911
12112
|
*/
|
|
11912
|
-
this.allowedOperations = [
|
|
11913
|
-
|
|
11914
|
-
|
|
11915
|
-
|
|
11916
|
-
|
|
11917
|
-
|
|
11918
|
-
|
|
11919
|
-
|
|
11920
|
-
|
|
11921
|
-
|
|
11922
|
-
|
|
12113
|
+
this.allowedOperations = [
|
|
12114
|
+
OperationKeys.CREATE,
|
|
12115
|
+
OperationKeys.READ,
|
|
12116
|
+
];
|
|
12117
|
+
/**
|
|
12118
|
+
* @description Current model data loaded from the repository.
|
|
12119
|
+
* @summary Stores the raw data object representing the current model instance retrieved
|
|
12120
|
+
* from the repository. This property holds the actual data values for the model being
|
|
12121
|
+
* displayed or edited, and is set to undefined when no data is available or when an
|
|
12122
|
+
* error occurs during data loading.
|
|
12123
|
+
* @type {KeyValue | undefined}
|
|
12124
|
+
* @default undefined
|
|
12125
|
+
* @memberOf NgxModelPageDirective
|
|
12126
|
+
*/
|
|
11923
12127
|
this.modelData = undefined;
|
|
11924
12128
|
/**
|
|
11925
12129
|
* @description Error message from failed operations.
|
|
@@ -11937,12 +12141,12 @@ class NgxModelPageDirective extends NgxPageDirective {
|
|
|
11937
12141
|
// }
|
|
11938
12142
|
get pageTitle() {
|
|
11939
12143
|
if (!this.modelName && this.model instanceof Model)
|
|
11940
|
-
this.modelName = this.model?.constructor?.name ||
|
|
12144
|
+
this.modelName = this.model?.constructor?.name || '';
|
|
11941
12145
|
if (!this.operation)
|
|
11942
12146
|
return this.title ? this.title : `Listing ${this.modelName}`;
|
|
11943
|
-
const operation = this.operation.charAt(0).toUpperCase() +
|
|
11944
|
-
|
|
11945
|
-
|
|
12147
|
+
const operation = this.operation.charAt(0).toUpperCase() +
|
|
12148
|
+
this.operation.slice(1).toLowerCase();
|
|
12149
|
+
return this.modelName ? `${operation} ${this.modelName}` : this.title;
|
|
11946
12150
|
}
|
|
11947
12151
|
/**
|
|
11948
12152
|
* @description Lazy-initialized repository getter with model resolution.
|
|
@@ -11956,14 +12160,21 @@ class NgxModelPageDirective extends NgxPageDirective {
|
|
|
11956
12160
|
* @throws {InternalError} When the model is not found in the registry
|
|
11957
12161
|
*/
|
|
11958
12162
|
get repository() {
|
|
11959
|
-
|
|
11960
|
-
|
|
11961
|
-
|
|
11962
|
-
|
|
11963
|
-
|
|
11964
|
-
|
|
11965
|
-
|
|
11966
|
-
|
|
12163
|
+
try {
|
|
12164
|
+
if (!this._repository) {
|
|
12165
|
+
const constructor = Model.get(this.modelName);
|
|
12166
|
+
if (!constructor)
|
|
12167
|
+
throw new InternalError('Cannot find model. was it registered with @model?');
|
|
12168
|
+
this._repository = Repository.forModel(constructor);
|
|
12169
|
+
if (!this.pk)
|
|
12170
|
+
this.pk = Model.pk(constructor);
|
|
12171
|
+
this.model = new constructor();
|
|
12172
|
+
}
|
|
12173
|
+
}
|
|
12174
|
+
catch (error) {
|
|
12175
|
+
this.log.warn(`Error getting repository for model: ${this.modelName}. ${error.message}`);
|
|
12176
|
+
this._repository = undefined;
|
|
12177
|
+
// throw new InternalError((error as Error)?.message || (error as string));
|
|
11967
12178
|
}
|
|
11968
12179
|
return this._repository;
|
|
11969
12180
|
}
|
|
@@ -11976,7 +12187,10 @@ class NgxModelPageDirective extends NgxPageDirective {
|
|
|
11976
12187
|
async ionViewWillEnter() {
|
|
11977
12188
|
// await super.ionViewWillEnter();
|
|
11978
12189
|
if (this.modelId)
|
|
11979
|
-
this.allowedOperations = this.allowedOperations.concat([
|
|
12190
|
+
this.allowedOperations = this.allowedOperations.concat([
|
|
12191
|
+
OperationKeys.UPDATE,
|
|
12192
|
+
OperationKeys.DELETE,
|
|
12193
|
+
]);
|
|
11980
12194
|
this.getLocale(this.modelName);
|
|
11981
12195
|
await this.refresh(this.modelId);
|
|
11982
12196
|
this.initialized = true;
|
|
@@ -11999,7 +12213,7 @@ class NgxModelPageDirective extends NgxPageDirective {
|
|
|
11999
12213
|
case OperationKeys.READ:
|
|
12000
12214
|
case OperationKeys.UPDATE:
|
|
12001
12215
|
case OperationKeys.DELETE:
|
|
12002
|
-
this.model = await this.handleGet(uid || this.modelId);
|
|
12216
|
+
this.model = (await this.handleGet(uid || this.modelId));
|
|
12003
12217
|
break;
|
|
12004
12218
|
}
|
|
12005
12219
|
}
|
|
@@ -12007,23 +12221,23 @@ class NgxModelPageDirective extends NgxPageDirective {
|
|
|
12007
12221
|
if (error instanceof NotFoundError) {
|
|
12008
12222
|
this.errorMessage = error.message;
|
|
12009
12223
|
}
|
|
12010
|
-
this.
|
|
12224
|
+
this.log.error(error);
|
|
12011
12225
|
}
|
|
12012
12226
|
}
|
|
12013
12227
|
/**
|
|
12014
12228
|
* @description Generic event handler for component events.
|
|
12015
12229
|
* @summary Processes incoming events from child components and routes them to appropriate
|
|
12016
12230
|
* handlers based on the event name. Currently handles SUBMIT events by delegating to
|
|
12017
|
-
* the
|
|
12231
|
+
* the submit method. This centralized event handling approach allows for easy
|
|
12018
12232
|
* extension and consistent event processing.
|
|
12019
12233
|
*
|
|
12020
12234
|
* @param {IBaseCustomEvent} event - The event object containing event data and metadata
|
|
12021
12235
|
*/
|
|
12022
|
-
async handleEvent(event) {
|
|
12236
|
+
async handleEvent(event, repository) {
|
|
12023
12237
|
const { name } = event;
|
|
12024
12238
|
switch (name) {
|
|
12025
12239
|
case ComponentEventNames.SUBMIT:
|
|
12026
|
-
await this.
|
|
12240
|
+
await this.submit(event, repository);
|
|
12027
12241
|
break;
|
|
12028
12242
|
}
|
|
12029
12243
|
}
|
|
@@ -12038,38 +12252,61 @@ class NgxModelPageDirective extends NgxPageDirective {
|
|
|
12038
12252
|
* @param {IBaseCustomEvent} event - The submit event containing form data
|
|
12039
12253
|
* @return {Promise<IModelPageCustomEvent|void>} Promise that resolves on success or throws on error
|
|
12040
12254
|
*/
|
|
12041
|
-
async
|
|
12255
|
+
async submit(event, repository, redirect = false) {
|
|
12042
12256
|
try {
|
|
12043
|
-
|
|
12044
|
-
|
|
12045
|
-
const
|
|
12046
|
-
const
|
|
12047
|
-
|
|
12048
|
-
|
|
12049
|
-
|
|
12050
|
-
|
|
12051
|
-
|
|
12052
|
-
|
|
12053
|
-
|
|
12054
|
-
|
|
12055
|
-
|
|
12056
|
-
|
|
12257
|
+
if (!repository)
|
|
12258
|
+
repository = this._repository;
|
|
12259
|
+
// const pk = this.pk || Model.pk(repository.class as Constructor<Model>);
|
|
12260
|
+
const operation = this.operation;
|
|
12261
|
+
const { data } = event;
|
|
12262
|
+
if (data) {
|
|
12263
|
+
const model = this.parseData(data || {}, operation, repository);
|
|
12264
|
+
let result;
|
|
12265
|
+
switch (operation) {
|
|
12266
|
+
case OperationKeys.CREATE:
|
|
12267
|
+
result = await (!Array.isArray(model)
|
|
12268
|
+
? repository.create(model)
|
|
12269
|
+
: repository.createAll(model));
|
|
12270
|
+
break;
|
|
12271
|
+
case OperationKeys.UPDATE:
|
|
12272
|
+
result = await (!Array.isArray(model)
|
|
12273
|
+
? repository.update(model)
|
|
12274
|
+
: repository.updateAll(model));
|
|
12275
|
+
break;
|
|
12276
|
+
case OperationKeys.DELETE:
|
|
12277
|
+
result = await (!Array.isArray(model)
|
|
12278
|
+
? repository.delete(model)
|
|
12279
|
+
: repository.deleteAll(model));
|
|
12280
|
+
break;
|
|
12281
|
+
}
|
|
12282
|
+
const message = await this.translate(!Array.isArray(result)
|
|
12283
|
+
? `operations.${operation}.${result ? 'success' : 'error'}`
|
|
12284
|
+
: `operations.multiple`);
|
|
12285
|
+
if (result) {
|
|
12286
|
+
// repository.refresh(this.modelName, this.operation, this.modelId as EventIds);
|
|
12287
|
+
if (redirect)
|
|
12288
|
+
this.location.back();
|
|
12289
|
+
}
|
|
12290
|
+
return {
|
|
12291
|
+
...event,
|
|
12292
|
+
success: result ? true : false,
|
|
12293
|
+
message,
|
|
12294
|
+
};
|
|
12057
12295
|
}
|
|
12058
|
-
return {
|
|
12059
|
-
...event,
|
|
12060
|
-
success: result ? true : false,
|
|
12061
|
-
message
|
|
12062
|
-
};
|
|
12063
12296
|
}
|
|
12064
12297
|
catch (error) {
|
|
12065
|
-
this.logger.error(error);
|
|
12066
12298
|
return {
|
|
12067
12299
|
...event,
|
|
12068
12300
|
success: false,
|
|
12069
|
-
message: error instanceof Error ? error.message : error
|
|
12301
|
+
message: error instanceof Error ? error.message : error,
|
|
12070
12302
|
};
|
|
12071
12303
|
}
|
|
12072
12304
|
}
|
|
12305
|
+
async create(data, repository) {
|
|
12306
|
+
alert('create');
|
|
12307
|
+
console.log(repository);
|
|
12308
|
+
console.log(data);
|
|
12309
|
+
}
|
|
12073
12310
|
/**
|
|
12074
12311
|
* @description Retrieves a model instance from the repository by unique identifier.
|
|
12075
12312
|
* @summary Fetches a specific model instance using the repository's read method.
|
|
@@ -12080,17 +12317,58 @@ class NgxModelPageDirective extends NgxPageDirective {
|
|
|
12080
12317
|
* @param {string} uid - The unique identifier of the model instance to retrieve
|
|
12081
12318
|
* @return {Promise<Model | undefined>} Promise resolving to the model instance or undefined
|
|
12082
12319
|
*/
|
|
12083
|
-
async handleGet(uid) {
|
|
12320
|
+
async handleGet(uid, repository, modelName) {
|
|
12084
12321
|
if (!uid) {
|
|
12085
|
-
this.
|
|
12322
|
+
this.log.info('No key passed to model page read operation, backing to last page');
|
|
12086
12323
|
this.location.back();
|
|
12087
12324
|
return undefined;
|
|
12088
12325
|
}
|
|
12089
|
-
|
|
12090
|
-
|
|
12091
|
-
|
|
12092
|
-
|
|
12093
|
-
|
|
12326
|
+
if (!modelName)
|
|
12327
|
+
modelName = this.modelName;
|
|
12328
|
+
const getRepository = async (modelName, parent, model) => {
|
|
12329
|
+
if (this._repository)
|
|
12330
|
+
return this._repository;
|
|
12331
|
+
const constructor = Model.get(modelName);
|
|
12332
|
+
if (constructor) {
|
|
12333
|
+
const properties = Metadata.properties(constructor);
|
|
12334
|
+
// if (!model) model = {} as KeyValue;
|
|
12335
|
+
for (const prop of properties) {
|
|
12336
|
+
const type = Metadata.type(constructor, prop).name;
|
|
12337
|
+
const context = getModelAndRepository(type);
|
|
12338
|
+
if (!context)
|
|
12339
|
+
return getRepository(type, prop, model);
|
|
12340
|
+
const { repository } = context;
|
|
12341
|
+
if (modelName === this.modelName) {
|
|
12342
|
+
const data = await this.handleGet(uid, repository, modelName);
|
|
12343
|
+
this.model = Model.build({ [prop]: data }, modelName);
|
|
12344
|
+
}
|
|
12345
|
+
// else {
|
|
12346
|
+
// model[prop as string] = Model.build({}, type);
|
|
12347
|
+
// }
|
|
12348
|
+
}
|
|
12349
|
+
// (this.model as KeyValue)[parent as string] = Model.build(
|
|
12350
|
+
// model,
|
|
12351
|
+
// modelName
|
|
12352
|
+
// );
|
|
12353
|
+
}
|
|
12354
|
+
};
|
|
12355
|
+
repository = (repository ||
|
|
12356
|
+
(await getRepository(modelName)));
|
|
12357
|
+
if (!repository)
|
|
12358
|
+
return this.model;
|
|
12359
|
+
const type = Metadata.type(repository.class, Model.pk(repository.class)).name;
|
|
12360
|
+
try {
|
|
12361
|
+
const result = await (repository).read(([Primitives.NUMBER, Primitives.BIGINT].includes(type.toLowerCase())
|
|
12362
|
+
? Number(uid)
|
|
12363
|
+
: uid));
|
|
12364
|
+
return result;
|
|
12365
|
+
}
|
|
12366
|
+
catch (error) {
|
|
12367
|
+
this.log
|
|
12368
|
+
.for(this.handleGet)
|
|
12369
|
+
.info(`Error getting model instance with id ${uid}: ${error.message}`);
|
|
12370
|
+
return undefined;
|
|
12371
|
+
}
|
|
12094
12372
|
}
|
|
12095
12373
|
/**
|
|
12096
12374
|
* @description Parses and transforms form data for repository operations.
|
|
@@ -12103,13 +12381,22 @@ class NgxModelPageDirective extends NgxPageDirective {
|
|
|
12103
12381
|
* @return {Model | string | number} Processed data ready for repository operations
|
|
12104
12382
|
* @private
|
|
12105
12383
|
*/
|
|
12106
|
-
parseData(data, operation) {
|
|
12107
|
-
|
|
12384
|
+
parseData(data, operation, repository) {
|
|
12385
|
+
operation = (operation === OperationKeys.READ
|
|
12386
|
+
? OperationKeys.DELETE
|
|
12387
|
+
: operation.toLowerCase());
|
|
12388
|
+
if (Array.isArray(data)) {
|
|
12389
|
+
data = data.map((item) => this.parseData(item, operation, repository));
|
|
12390
|
+
return data;
|
|
12391
|
+
}
|
|
12108
12392
|
let uid = this.modelId;
|
|
12109
|
-
|
|
12110
|
-
|
|
12393
|
+
const pk = Model.pk(repository.class);
|
|
12394
|
+
const type = Metadata.type(repository.class, pk).name;
|
|
12395
|
+
uid = [Primitives.NUMBER, Primitives.BIGINT].includes(type.toLowerCase())
|
|
12396
|
+
? Number(uid)
|
|
12397
|
+
: uid;
|
|
12111
12398
|
if (operation !== OperationKeys.DELETE)
|
|
12112
|
-
return Model.build(this.modelId ? Object.assign(data, { [
|
|
12399
|
+
return Model.build(this.modelId ? Object.assign(data, { [pk]: uid }) : data, repository.class.name);
|
|
12113
12400
|
return uid;
|
|
12114
12401
|
}
|
|
12115
12402
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgxModelPageDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
|
|
@@ -12156,5 +12443,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
|
|
|
12156
12443
|
* Generated bundle index. Do not edit.
|
|
12157
12444
|
*/
|
|
12158
12445
|
|
|
12159
|
-
export { ActionRoles, AngularEngineKeys, BaseComponentProps, CPTKN, CardComponent, ComponentEventNames, ComponentRendererComponent, ComponentsTagNames, CrudFieldComponent, CrudFormComponent, CssClasses, DB_ADAPTER_PROVIDER, DB_ADAPTER_PROVIDER_TOKEN, DecafFakerRepository, DefaultFormReactiveOptions, DefaultListEmptyOptions, DefaultModalOptions, Dynamic, DynamicModule, ElementPositions, ElementSizes, EmptyStateComponent, FieldsetComponent, FileUploadComponent, FilterComponent, ForAngularCommonModule, ForAngularComponentsModule, FormConstants, I18N_CONFIG_TOKEN, I18nLoader, I18nLoaderFactory, I18nParser, IconComponent, LOCALE_ROOT_TOKEN, LayoutComponent, LayoutGridGaps, ListComponent, ListComponentsTypes, ListItemComponent, ListItemPositions, LoggerLevels, ModalComponent, ModelRendererComponent, NgxComponentDirective, NgxEventHandler, NgxFormDirective, NgxFormFieldDirective, NgxFormService, NgxMediaService, NgxModelPageDirective, NgxPageDirective, NgxParentComponentDirective, NgxRenderingEngine, NgxSvgDirective, PaginationComponent, RouteDirections, SearchbarComponent, SteppedFormComponent, WindowColorSchemes, cleanSpaces, dataMapper, filterString, formatDate, generateRandomValue, getFakerData, getInjectablesRegistry, getLocaleContext, getLocaleContextByKey, getLocaleFromClassName, getLocaleLanguage, getLogger,
|
|
12446
|
+
export { ActionRoles, AngularEngineKeys, BaseComponentProps, CPTKN, CardComponent, ComponentEventNames, ComponentRendererComponent, ComponentsTagNames, CrudFieldComponent, CrudFormComponent, CssClasses, DB_ADAPTER_PROVIDER, DB_ADAPTER_PROVIDER_TOKEN, DecafFakerRepository, DefaultFormReactiveOptions, DefaultListEmptyOptions, DefaultModalOptions, Dynamic, DynamicModule, ElementPositions, ElementSizes, EmptyStateComponent, FieldsetComponent, FileUploadComponent, FilterComponent, ForAngularCommonModule, ForAngularComponentsModule, FormConstants, I18N_CONFIG_TOKEN, I18nLoader, I18nLoaderFactory, I18nParser, IconComponent, LOCALE_ROOT_TOKEN, LayoutComponent, LayoutGridGaps, ListComponent, ListComponentsTypes, ListItemComponent, ListItemPositions, LoggerLevels, ModalComponent, ModelRendererComponent, NgxComponentDirective, NgxEventHandler, NgxFormDirective, NgxFormFieldDirective, NgxFormService, NgxMediaService, NgxModelPageDirective, NgxPageDirective, NgxParentComponentDirective, NgxRenderingEngine, NgxSvgDirective, PaginationComponent, RouteDirections, SearchbarComponent, SteppedFormComponent, WindowColorSchemes, cleanSpaces, dataMapper, filterString, formatDate, generateRandomValue, getFakerData, getInjectablesRegistry, getLocaleContext, getLocaleContextByKey, getLocaleFromClassName, getLocaleLanguage, getLogger, getModelAndRepository, getNgxModalComponent, getNgxSelectOptionsModal, getOnWindow, getOnWindowDocument, getWindow, getWindowDocument, getWindowWidth, isDarkMode, isDevelopmentMode, isNotUndefined, isValidDate, itemMapper, parseToValidDate, presentNgxLightBoxModal, provideDbAdapter, provideDynamicComponents, provideI18n, provideI18nLoader, removeFocusTrap, setOnWindow, stringToBoolean, windowEventEmitter };
|
|
12160
12447
|
//# sourceMappingURL=decaf-ts-for-angular.mjs.map
|