@sd-angular/core 19.0.44 → 19.0.46
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 +6 -0
- package/assets/scss/core/form.scss +21 -11
- package/assets/scss/core/view.scss +24 -0
- package/assets/scss/sd-core.scss +1 -0
- package/assets/scss/themes/_material-tokens.scss +56 -0
- package/assets/scss/themes/default.scss +10 -0
- package/components/form-generic/src/components/form-builder/components/expression-builder/expression-builder.component.d.ts +1 -0
- package/components/form-generic/src/models/form-generic-expression.model.d.ts +10 -4
- package/components/form-generic/src/pipes/component-viewed.pipe.d.ts +1 -0
- package/components/import-excel/src/pipes/column-transform.pipe.d.ts +1 -0
- package/components/inform/src/inform.component.d.ts +12 -3
- package/components/table/src/services/table-export/table-export.service.d.ts +1 -1
- package/components/table/src/services/table-filter/table-filter.model.d.ts +7 -0
- package/components/table/src/services/table-local/table-local-sort.util.d.ts +8 -2
- package/components/table/src/services/table-local/table-local.util.d.ts +6 -1
- package/components/table/src/table.component.d.ts +1 -1
- package/components/timeline/pipes/view-date.pipe.d.ts +1 -0
- package/configurations/src/sd-core.configuration.d.ts +7 -0
- package/fesm2022/sd-angular-core-components-form-generic.mjs +44 -31
- package/fesm2022/sd-angular-core-components-form-generic.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-import-excel.mjs +19 -5
- package/fesm2022/sd-angular-core-components-import-excel.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-inform.mjs +16 -2
- package/fesm2022/sd-angular-core-components-inform.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-section.mjs +2 -2
- package/fesm2022/sd-angular-core-components-section.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-table.mjs +174 -66
- package/fesm2022/sd-angular-core-components-table.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-timeline.mjs +4 -1
- package/fesm2022/sd-angular-core-components-timeline.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-view.mjs +2 -2
- package/fesm2022/sd-angular-core-components-view.mjs.map +1 -1
- package/fesm2022/sd-angular-core-configurations.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-checkbox.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-checkbox.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-date-range.mjs +15 -2
- package/fesm2022/sd-angular-core-forms-date-range.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-date.mjs +11 -1
- package/fesm2022/sd-angular-core-forms-date.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-datetime.mjs +43 -9
- package/fesm2022/sd-angular-core-forms-datetime.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-models.mjs +6 -0
- package/fesm2022/sd-angular-core-forms-models.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-radio.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-radio.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-switch.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-switch.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-textarea.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-textarea.mjs.map +1 -1
- package/fesm2022/sd-angular-core-pipes.mjs +26 -10
- package/fesm2022/sd-angular-core-pipes.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-date-time.mjs +143 -0
- package/fesm2022/sd-angular-core-services-date-time.mjs.map +1 -0
- package/fesm2022/sd-angular-core-services.mjs +1 -0
- package/fesm2022/sd-angular-core-services.mjs.map +1 -1
- package/fesm2022/sd-angular-core-utilities-models.mjs.map +1 -1
- package/forms/datetime/src/datetime-time-zone.adapter.d.ts +15 -0
- package/forms/models/src/sd-strict-date-adapter.d.ts +3 -0
- package/package.json +17 -13
- package/pipes/src/time-different.pipe.d.ts +1 -0
- package/services/date-time/index.d.ts +1 -0
- package/services/date-time/src/date-time.service.d.ts +54 -0
- package/services/date-time/src/public-api.d.ts +1 -0
- package/services/index.d.ts +1 -0
- package/utilities/extensions/src/string.extension.d.ts +1 -0
- package/utilities/models/src/icon.model.d.ts +2 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { InjectionToken, inject, Injectable, Pipe, SecurityContext, Input, ChangeDetectionStrategy, Component, ViewChild, EventEmitter, Output, ViewChildren, QueryList, ChangeDetectorRef, input, effect, untracked, viewChild, signal, computed } from '@angular/core';
|
|
3
3
|
import { Utilities, StringUtilities as StringUtilities$1 } from '@sdcorejs/utils/fns';
|
|
4
|
+
import { ɵSD_LOCAL_DATE_TIME as _SD_LOCAL_DATE_TIME, ɵsdInjectDateTime as _sdInjectDateTime, SdDateTimeService } from '@sd-angular/core/services/date-time';
|
|
4
5
|
import { DateUtilities } from '@sd-angular/core/utilities';
|
|
5
6
|
import * as i3 from '@angular/cdk/drag-drop';
|
|
6
7
|
import { moveItemInArray, transferArrayItem, DragDropModule } from '@angular/cdk/drag-drop';
|
|
@@ -19,9 +20,9 @@ import { SdNotifyService, SdConfirmService } from '@sd-angular/core/services';
|
|
|
19
20
|
import { Subscription, Subject, filter, debounceTime, startWith, combineLatest } from 'rxjs';
|
|
20
21
|
import { SdSection } from '@sd-angular/core/components/section';
|
|
21
22
|
import { startWith as startWith$1, debounceTime as debounceTime$1 } from 'rxjs/operators';
|
|
22
|
-
import { DateUtilities as DateUtilities$1, StringUtilities, ArrayUtilities, NumberUtilities } from '@sd-angular/core/utilities/extensions';
|
|
23
23
|
import { EMPTY_STR } from '@sdcorejs/utils/constants';
|
|
24
24
|
import * as i1 from '@sd-angular/core/pipes';
|
|
25
|
+
import { StringUtilities, ArrayUtilities, NumberUtilities } from '@sd-angular/core/utilities/extensions';
|
|
25
26
|
import * as i1$1 from '@angular/platform-browser';
|
|
26
27
|
import { SdInput, SdChip, SdChipCalendar, SdSelect, SdAutocomplete, SdRadio, SdInputNumber as SdInputNumber$1 } from '@sd-angular/core/forms';
|
|
27
28
|
import { SdInputNumber } from '@sd-angular/core/forms/input-number';
|
|
@@ -262,23 +263,25 @@ const DayInfoPreviouses = [
|
|
|
262
263
|
// { value: 'LASTMONTH', display: 'Tháng trước', format: (n: number) => `${n || 1}LastMonth` },
|
|
263
264
|
// { value: 'NEXTMONTH', display: 'Tháng tới', format: (n: number) => `${n || 1}NextMonth` },
|
|
264
265
|
];
|
|
265
|
-
|
|
266
|
+
// why: a relative value is the current instant shifted by whole days, formatted once in the zone; formatting
|
|
267
|
+
// a wall-clock carrier such as now() in the zone would shift it a second time.
|
|
268
|
+
const GetDatetimeValue = (value, dateTime = _SD_LOCAL_DATE_TIME) => {
|
|
266
269
|
if (!value || typeof value !== 'string') {
|
|
267
270
|
return undefined;
|
|
268
271
|
}
|
|
269
272
|
if (value === 'now') {
|
|
270
|
-
return
|
|
273
|
+
return dateTime.toFormat(new Date(), 'yyyy/MM/dd HH:mm:ss');
|
|
271
274
|
}
|
|
272
275
|
if (value?.endsWith('LastDay')) {
|
|
273
276
|
const relatedValue = +value.replace('LastDay', '');
|
|
274
277
|
if (relatedValue) {
|
|
275
|
-
return
|
|
278
|
+
return dateTime.toFormat(DateUtilities.addDays(new Date(), -relatedValue), 'yyyy/MM/dd HH:mm:ss');
|
|
276
279
|
}
|
|
277
280
|
}
|
|
278
281
|
if (value?.endsWith('NextDay')) {
|
|
279
282
|
const relatedValue = +value.replace('LastDay', '');
|
|
280
283
|
if (relatedValue) {
|
|
281
|
-
return
|
|
284
|
+
return dateTime.toFormat(DateUtilities.addDays(new Date(), relatedValue), 'yyyy/MM/dd HH:mm:ss');
|
|
282
285
|
}
|
|
283
286
|
}
|
|
284
287
|
return undefined;
|
|
@@ -405,7 +408,7 @@ const GetAttributes = (components) => {
|
|
|
405
408
|
}
|
|
406
409
|
return attributes;
|
|
407
410
|
};
|
|
408
|
-
const TemplateToCondition = (template, entity) => {
|
|
411
|
+
const TemplateToCondition = (template, entity, dateTime = _SD_LOCAL_DATE_TIME) => {
|
|
409
412
|
if (!template) {
|
|
410
413
|
return undefined;
|
|
411
414
|
}
|
|
@@ -423,7 +426,7 @@ const TemplateToCondition = (template, entity) => {
|
|
|
423
426
|
if (typeof val === 'string') {
|
|
424
427
|
// Xử lý đối với trường hợp string là 'datetime' thì cần format thành string đồng nhất để compare chính xác
|
|
425
428
|
if (DateUtilities.isDate(val)) {
|
|
426
|
-
template = template.replace(match, `'${
|
|
429
|
+
template = template.replace(match, `'${dateTime.toFormat(val, 'yyyy/MM/dd HH:mm:ss')}'`);
|
|
427
430
|
}
|
|
428
431
|
else {
|
|
429
432
|
// Nếu là chuỗi thì thêm dấu nháy khi replace giá trị để so sánh, ví dụ 'a' === 'a'
|
|
@@ -448,14 +451,14 @@ const GetEntityValue = (entity, key) => {
|
|
|
448
451
|
}
|
|
449
452
|
return value;
|
|
450
453
|
};
|
|
451
|
-
const NormalizeExpressionValue = (value) => {
|
|
454
|
+
const NormalizeExpressionValue = (value, dateTime) => {
|
|
452
455
|
if (typeof value === 'string' && DateUtilities.isDate(value)) {
|
|
453
|
-
return
|
|
456
|
+
return dateTime.toFormat(value, 'yyyy/MM/dd HH:mm:ss');
|
|
454
457
|
}
|
|
455
458
|
return value;
|
|
456
459
|
};
|
|
457
|
-
const EvaluateExpressionCondition = (condition, entity) => {
|
|
458
|
-
const actualValue = NormalizeExpressionValue(GetEntityValue(entity, condition.field));
|
|
460
|
+
const EvaluateExpressionCondition = (condition, entity, dateTime) => {
|
|
461
|
+
const actualValue = NormalizeExpressionValue(GetEntityValue(entity, condition.field), dateTime);
|
|
459
462
|
const { operator } = condition;
|
|
460
463
|
if (!operator) {
|
|
461
464
|
return undefined;
|
|
@@ -466,11 +469,11 @@ const EvaluateExpressionCondition = (condition, entity) => {
|
|
|
466
469
|
if (operator === 'NOT_NULL') {
|
|
467
470
|
return !!actualValue;
|
|
468
471
|
}
|
|
469
|
-
const expectedValue = typeof condition.value === 'string' ? GetDatetimeValue(condition.value) || condition.value : condition.value;
|
|
472
|
+
const expectedValue = typeof condition.value === 'string' ? GetDatetimeValue(condition.value, dateTime) || condition.value : condition.value;
|
|
470
473
|
if (expectedValue === undefined || expectedValue === null || expectedValue === '') {
|
|
471
474
|
return undefined;
|
|
472
475
|
}
|
|
473
|
-
const normalizedExpectedValue = NormalizeExpressionValue(expectedValue);
|
|
476
|
+
const normalizedExpectedValue = NormalizeExpressionValue(expectedValue, dateTime);
|
|
474
477
|
if (operator === 'EQUAL') {
|
|
475
478
|
return actualValue === normalizedExpectedValue;
|
|
476
479
|
}
|
|
@@ -491,12 +494,12 @@ const EvaluateExpressionCondition = (condition, entity) => {
|
|
|
491
494
|
}
|
|
492
495
|
return undefined;
|
|
493
496
|
};
|
|
494
|
-
const EvaluateExpression = (condition, entity) => {
|
|
497
|
+
const EvaluateExpression = (condition, entity, dateTime = _SD_LOCAL_DATE_TIME) => {
|
|
495
498
|
if (condition.type === 'combinator') {
|
|
496
499
|
if (!condition.conditions?.length) {
|
|
497
500
|
return undefined;
|
|
498
501
|
}
|
|
499
|
-
const results = condition.conditions.map(child => EvaluateExpression(child, entity));
|
|
502
|
+
const results = condition.conditions.map(child => EvaluateExpression(child, entity, dateTime));
|
|
500
503
|
if (results.some(result => typeof result !== 'boolean')) {
|
|
501
504
|
return undefined;
|
|
502
505
|
}
|
|
@@ -505,14 +508,14 @@ const EvaluateExpression = (condition, entity) => {
|
|
|
505
508
|
}
|
|
506
509
|
return results.some(result => result === true);
|
|
507
510
|
}
|
|
508
|
-
return EvaluateExpressionCondition(condition, entity);
|
|
511
|
+
return EvaluateExpressionCondition(condition, entity, dateTime);
|
|
509
512
|
};
|
|
510
|
-
const ExpressionToJavascriptExpression = (condition) => {
|
|
513
|
+
const ExpressionToJavascriptExpression = (condition, dateTime = _SD_LOCAL_DATE_TIME) => {
|
|
511
514
|
const queries = [];
|
|
512
515
|
if (condition.type === 'combinator') {
|
|
513
516
|
if (condition.conditions?.length) {
|
|
514
517
|
for (const child of condition.conditions) {
|
|
515
|
-
queries.push(`(${ExpressionToJavascriptExpression(child)})`);
|
|
518
|
+
queries.push(`(${ExpressionToJavascriptExpression(child, dateTime)})`);
|
|
516
519
|
}
|
|
517
520
|
}
|
|
518
521
|
// Nếu nhiều hơn 1 điều kiện, bọc điều kiện bằng cặp ngoặc ()
|
|
@@ -525,10 +528,10 @@ const ExpressionToJavascriptExpression = (condition) => {
|
|
|
525
528
|
}
|
|
526
529
|
}
|
|
527
530
|
else {
|
|
528
|
-
return ConvertToJavascriptExpression(condition);
|
|
531
|
+
return ConvertToJavascriptExpression(condition, dateTime);
|
|
529
532
|
}
|
|
530
533
|
};
|
|
531
|
-
const ConvertToJavascriptExpression = (condition) => {
|
|
534
|
+
const ConvertToJavascriptExpression = (condition, dateTime) => {
|
|
532
535
|
const { value } = condition;
|
|
533
536
|
// Convert thành syntax ${field}
|
|
534
537
|
const field = '${' + condition.field + '}';
|
|
@@ -546,7 +549,7 @@ const ConvertToJavascriptExpression = (condition) => {
|
|
|
546
549
|
return undefined;
|
|
547
550
|
}
|
|
548
551
|
// Xử lý đối với trường hợp string là 'datetime' thì value sẽ có thể là 'now', '1LastDay' ....
|
|
549
|
-
const datetimeValue = GetDatetimeValue(value);
|
|
552
|
+
const datetimeValue = GetDatetimeValue(value, dateTime);
|
|
550
553
|
if (operator === 'EQUAL') {
|
|
551
554
|
// Nếu là chuỗi thì thêm dấu nháy, nếu không thì bỏ qua
|
|
552
555
|
if (typeof value === 'string') {
|
|
@@ -789,6 +792,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
|
|
|
789
792
|
class ComponentViewedPipe {
|
|
790
793
|
formatNumberPipe;
|
|
791
794
|
formGenericService;
|
|
795
|
+
// why: datetime values show as the wall clock of ISdCoreConfiguration.timeZone; outside DI it stays local.
|
|
796
|
+
#dateTime = _sdInjectDateTime() ?? _SD_LOCAL_DATE_TIME;
|
|
792
797
|
constructor(formatNumberPipe, formGenericService) {
|
|
793
798
|
this.formatNumberPipe = formatNumberPipe;
|
|
794
799
|
this.formGenericService = formGenericService;
|
|
@@ -809,10 +814,10 @@ class ComponentViewedPipe {
|
|
|
809
814
|
}
|
|
810
815
|
if (component.type === 'datetime') {
|
|
811
816
|
if (component.subtype === 'datetime') {
|
|
812
|
-
return
|
|
817
|
+
return this.#dateTime.toFormat(val, 'dd/MM/yyyy HH:mm') || EMPTY_STR;
|
|
813
818
|
}
|
|
814
819
|
else {
|
|
815
|
-
return
|
|
820
|
+
return this.#dateTime.toFormat(val, 'dd/MM/yyyy') || EMPTY_STR;
|
|
816
821
|
}
|
|
817
822
|
}
|
|
818
823
|
if (component.type === 'select' || component.type === 'radio' || component.type === 'checklist') {
|
|
@@ -876,13 +881,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
|
|
|
876
881
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
877
882
|
// Xử lý thông tin required, disabled, hidden của component
|
|
878
883
|
class WhenExpressionPipe {
|
|
884
|
+
// why: date conditions compare in ISdCoreConfiguration.timeZone; `new WhenExpressionPipe()` outside DI stays local.
|
|
885
|
+
#dateTime = _sdInjectDateTime() ?? _SD_LOCAL_DATE_TIME;
|
|
879
886
|
#hidden = (component, variables) => {
|
|
880
887
|
if (component.properties?.hidden) {
|
|
881
888
|
return true;
|
|
882
889
|
}
|
|
883
890
|
const hiddenWhenExpression = component.properties?.hiddenWhenExpression;
|
|
884
891
|
if (hiddenWhenExpression) {
|
|
885
|
-
const result = EvaluateExpression(hiddenWhenExpression, variables);
|
|
892
|
+
const result = EvaluateExpression(hiddenWhenExpression, variables, this.#dateTime);
|
|
886
893
|
if (typeof result === 'boolean') {
|
|
887
894
|
return result;
|
|
888
895
|
}
|
|
@@ -890,7 +897,7 @@ class WhenExpressionPipe {
|
|
|
890
897
|
}
|
|
891
898
|
const visibleWhenExpression = component.properties?.visibleWhenExpression;
|
|
892
899
|
if (visibleWhenExpression) {
|
|
893
|
-
const result = EvaluateExpression(visibleWhenExpression, variables);
|
|
900
|
+
const result = EvaluateExpression(visibleWhenExpression, variables, this.#dateTime);
|
|
894
901
|
if (typeof result === 'boolean') {
|
|
895
902
|
return !result;
|
|
896
903
|
}
|
|
@@ -901,7 +908,7 @@ class WhenExpressionPipe {
|
|
|
901
908
|
#disabled = (component, variables) => {
|
|
902
909
|
const disabledWhenExpression = component.properties?.disabledWhenExpression;
|
|
903
910
|
if (disabledWhenExpression) {
|
|
904
|
-
const result = EvaluateExpression(disabledWhenExpression, variables);
|
|
911
|
+
const result = EvaluateExpression(disabledWhenExpression, variables, this.#dateTime);
|
|
905
912
|
if (typeof result === 'boolean') {
|
|
906
913
|
return result;
|
|
907
914
|
}
|
|
@@ -912,7 +919,7 @@ class WhenExpressionPipe {
|
|
|
912
919
|
#required = (component, variables) => {
|
|
913
920
|
const requiredWhenExpression = component.properties?.requiredWhenExpression;
|
|
914
921
|
if (requiredWhenExpression) {
|
|
915
|
-
const result = EvaluateExpression(requiredWhenExpression, variables);
|
|
922
|
+
const result = EvaluateExpression(requiredWhenExpression, variables, this.#dateTime);
|
|
916
923
|
if (typeof result === 'boolean') {
|
|
917
924
|
return result;
|
|
918
925
|
}
|
|
@@ -2969,6 +2976,8 @@ class SdFormRender {
|
|
|
2969
2976
|
setVariables = new Subject();
|
|
2970
2977
|
ref = inject(ChangeDetectorRef);
|
|
2971
2978
|
formGenericConfiguration = inject(SD_FORM_GENERIC_CONFIGURATION, { optional: true });
|
|
2979
|
+
// why: validation expressions compare dates in ISdCoreConfiguration.timeZone.
|
|
2980
|
+
#dateTime = inject(SdDateTimeService);
|
|
2972
2981
|
ngAfterViewInit() {
|
|
2973
2982
|
this.#subscription.add(combineLatest([this.#configurationChanges, this.#entityChanges])
|
|
2974
2983
|
.pipe(startWith$1([]))
|
|
@@ -3032,7 +3041,7 @@ class SdFormRender {
|
|
|
3032
3041
|
const messages = [];
|
|
3033
3042
|
for (const validation of this.configuration?.validations?.filter(e => e.alert === alert) || []) {
|
|
3034
3043
|
if (validation.type === 'expression') {
|
|
3035
|
-
const result = EvaluateExpression(validation.expression, this.entity);
|
|
3044
|
+
const result = EvaluateExpression(validation.expression, this.entity, this.#dateTime);
|
|
3036
3045
|
if (result) {
|
|
3037
3046
|
messages.push(validation.message);
|
|
3038
3047
|
}
|
|
@@ -3148,6 +3157,8 @@ class ExpressionBuilderComponent {
|
|
|
3148
3157
|
modelChange = new EventEmitter();
|
|
3149
3158
|
sdChange = new EventEmitter();
|
|
3150
3159
|
edit = new EventEmitter();
|
|
3160
|
+
// why: a picked datetime is a model value; keep it in ISdCoreConfiguration.timeZone like the expressions that read it.
|
|
3161
|
+
#dateTime = inject(SdDateTimeService);
|
|
3151
3162
|
constructor(ref) {
|
|
3152
3163
|
this.ref = ref;
|
|
3153
3164
|
}
|
|
@@ -3210,7 +3221,7 @@ class ExpressionBuilderComponent {
|
|
|
3210
3221
|
condition.value = DayInfoPreviouses.find(e => e.value === condition.dayInfo.related)?.format(condition.dayInfo.relatedValue) ?? null;
|
|
3211
3222
|
}
|
|
3212
3223
|
else if (condition.value?.type === 'DATETIME' && condition.value) {
|
|
3213
|
-
condition.value =
|
|
3224
|
+
condition.value = this.#dateTime.toFormat(condition.value, 'yyyy/MM/dd HH:mm:00');
|
|
3214
3225
|
}
|
|
3215
3226
|
};
|
|
3216
3227
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ExpressionBuilderComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -4141,8 +4152,10 @@ class DatetimeControl {
|
|
|
4141
4152
|
set _component(component) {
|
|
4142
4153
|
this.component = component;
|
|
4143
4154
|
}
|
|
4144
|
-
|
|
4145
|
-
|
|
4155
|
+
// why: the builder preview shows today as the app does, in ISdCoreConfiguration.timeZone.
|
|
4156
|
+
#dateTime = inject(SdDateTimeService);
|
|
4157
|
+
date = this.#dateTime.toFormat(new Date(), 'dd/MM/yyyy');
|
|
4158
|
+
datetime = this.#dateTime.toFormat(new Date(), 'dd/MM/yyyy HH:mm');
|
|
4146
4159
|
#subscription = new Subscription();
|
|
4147
4160
|
constructor(ref, builderService) {
|
|
4148
4161
|
this.ref = ref;
|