@sd-angular/core 19.0.0-beta.103 → 19.0.0-beta.105
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/assets/scss/README.md +433 -353
- package/assets/scss/core/form.scss +43 -1
- package/assets/scss/core/utilities/_base.scss +6 -6
- package/assets/scss/core/utilities/_grid.scss +4 -3
- package/assets/scss/core/utilities/_index.scss +1 -1
- package/assets/scss/core/utilities/_sizing.scss +2 -2
- package/assets/scss/sd-core.scss +0 -2
- package/components/badge/src/badge.component.d.ts +20 -3
- package/components/button/src/button.component.d.ts +2 -1
- package/components/ckeditor-styles/index.d.ts +1 -0
- package/components/ckeditor-styles/src/ckeditor-styles.component.d.ts +25 -0
- package/components/form-generic/src/models/form-generic-component.model.d.ts +5 -6
- package/components/form-generic/src/models/form-generic-expression.model.d.ts +1 -1
- package/components/history/models/history.model.d.ts +2 -2
- package/components/inform/index.d.ts +2 -0
- package/components/inform/src/inform-action.directive.d.ts +9 -0
- package/components/inform/src/inform.component.d.ts +59 -0
- package/components/modal/src/modal.component.d.ts +3 -2
- package/components/query-bar/src/{actions-bar.component.d.ts → components/actions-bar/actions-bar.component.d.ts} +8 -11
- package/components/query-bar/src/{build-chip.component.d.ts → components/build-chip/build-chip.component.d.ts} +2 -2
- package/components/query-bar/src/{chip-popover.component.d.ts → components/chip-popover/chip-popover.component.d.ts} +2 -2
- package/components/query-bar/src/{field-picker.component.d.ts → components/field-picker/field-picker.component.d.ts} +1 -1
- package/components/query-bar/src/{inline-chip.component.d.ts → components/inline-chip/inline-chip.component.d.ts} +2 -2
- package/components/query-bar/src/{inline-value-chip.component.d.ts → components/inline-value-chip/inline-value-chip.component.d.ts} +2 -2
- package/components/query-bar/src/{popover-chip.component.d.ts → components/popover-chip/popover-chip.component.d.ts} +2 -2
- package/components/query-bar/src/{saved-filters-menu.component.d.ts → components/saved-filters-menu/saved-filters-menu.component.d.ts} +1 -1
- package/components/query-bar/src/query-bar.component.d.ts +3 -3
- package/components/query-bar/src/query-bar.model.d.ts +1 -1
- package/components/section/src/section.component.d.ts +2 -1
- package/components/stepper/index.d.ts +2 -0
- package/components/stepper/src/step.component.d.ts +17 -0
- package/components/stepper/src/stepper.component.d.ts +33 -0
- package/components/tab/index.d.ts +2 -0
- package/components/tab/src/tab-group.component.d.ts +37 -0
- package/components/tab/src/tab.component.d.ts +13 -0
- package/components/tab-router/src/decorators/tab.decorator.d.ts +2 -2
- package/components/tab-router/src/models/tab-router.model.d.ts +2 -2
- package/components/table/index.d.ts +1 -0
- package/components/table/src/configurations/table.configuration.d.ts +3 -3
- package/components/table/src/directives/index.d.ts +1 -0
- package/components/table/src/directives/sd-table-group-def.directive.d.ts +44 -0
- package/components/table/src/models/index.d.ts +1 -0
- package/components/table/src/models/table-column.model.d.ts +13 -13
- package/components/table/src/models/table-command.model.d.ts +3 -2
- package/components/table/src/models/table-item.model.d.ts +19 -4
- package/components/table/src/models/table-option-export.model.d.ts +3 -3
- package/components/table/src/models/table-option-group.model.d.ts +19 -2
- package/components/table/src/models/table-option-selector.model.d.ts +17 -1
- package/components/table/src/models/table-option.model.d.ts +11 -2
- package/components/table/src/pipes/sd-group.pipe.d.ts +15 -1
- package/components/table/src/services/table-filter/table-filter.model.d.ts +9 -9
- package/components/table/src/services/table-filter/table-filter.service.d.ts +2 -2
- package/components/table/src/table.component.d.ts +29 -4
- package/fesm2022/sd-angular-core-components-anchor.mjs +2 -2
- package/fesm2022/sd-angular-core-components-anchor.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-badge.mjs +18 -3
- package/fesm2022/sd-angular-core-components-badge.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-button.mjs +2 -2
- package/fesm2022/sd-angular-core-components-button.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-ckeditor-styles.mjs +38 -0
- package/fesm2022/sd-angular-core-components-ckeditor-styles.mjs.map +1 -0
- package/fesm2022/sd-angular-core-components-document-builder.mjs +10 -8
- package/fesm2022/sd-angular-core-components-document-builder.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-editor.mjs +3 -2
- package/fesm2022/sd-angular-core-components-editor.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-form-generic.mjs +49 -48
- package/fesm2022/sd-angular-core-components-form-generic.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-history.mjs +3 -2
- package/fesm2022/sd-angular-core-components-history.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-inform.mjs +190 -0
- package/fesm2022/sd-angular-core-components-inform.mjs.map +1 -0
- package/fesm2022/sd-angular-core-components-mini-editor.mjs +4 -3
- package/fesm2022/sd-angular-core-components-mini-editor.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-modal.mjs +2 -2
- package/fesm2022/sd-angular-core-components-modal.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-operator.mjs +1 -1
- package/fesm2022/sd-angular-core-components-operator.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-query-bar.mjs +15 -22
- package/fesm2022/sd-angular-core-components-query-bar.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-section.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-splitter.mjs +5 -2
- package/fesm2022/sd-angular-core-components-splitter.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-stepper.mjs +140 -0
- package/fesm2022/sd-angular-core-components-stepper.mjs.map +1 -0
- package/fesm2022/sd-angular-core-components-tab-router.mjs +3 -3
- package/fesm2022/sd-angular-core-components-tab-router.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-tab.mjs +145 -0
- package/fesm2022/sd-angular-core-components-tab.mjs.map +1 -0
- package/fesm2022/sd-angular-core-components-table.mjs +284 -95
- package/fesm2022/sd-angular-core-components-table.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-upload-file.mjs +5 -6
- package/fesm2022/sd-angular-core-components-upload-file.mjs.map +1 -1
- package/fesm2022/sd-angular-core-directives.mjs +4 -4
- package/fesm2022/sd-angular-core-directives.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-autocomplete.mjs +5 -4
- package/fesm2022/sd-angular-core-forms-autocomplete.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-checkbox.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-chip-calendar.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-chip.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-date-range.mjs +3 -2
- package/fesm2022/sd-angular-core-forms-date-range.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-date.mjs +5 -4
- package/fesm2022/sd-angular-core-forms-date.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-datetime.mjs +5 -4
- package/fesm2022/sd-angular-core-forms-datetime.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-input-color.mjs +117 -0
- package/fesm2022/sd-angular-core-forms-input-color.mjs.map +1 -0
- package/fesm2022/sd-angular-core-forms-input-number.mjs +24 -2
- package/fesm2022/sd-angular-core-forms-input-number.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-input.mjs +26 -2
- package/fesm2022/sd-angular-core-forms-input.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-radio.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-select.mjs +10 -10
- package/fesm2022/sd-angular-core-forms-select.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-switch.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-textarea.mjs.map +1 -1
- package/fesm2022/sd-angular-core-i18n.mjs +10 -0
- package/fesm2022/sd-angular-core-i18n.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-auth.mjs +4 -4
- package/fesm2022/sd-angular-core-modules-auth.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-authom.mjs +1 -1
- package/fesm2022/sd-angular-core-modules-authom.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-layout.mjs +14 -14
- package/fesm2022/sd-angular-core-modules-layout.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-permission.mjs +3 -3
- package/fesm2022/sd-angular-core-modules-permission.mjs.map +1 -1
- package/fesm2022/sd-angular-core-pipes.mjs +2 -2
- package/fesm2022/sd-angular-core-pipes.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-api.mjs +3 -3
- package/fesm2022/sd-angular-core-services-api.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-cache.mjs +3 -2
- package/fesm2022/sd-angular-core-services-cache.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-confirm.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-excel.mjs +6 -5
- package/fesm2022/sd-angular-core-services-excel.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-notify.mjs +3 -3
- package/fesm2022/sd-angular-core-services-notify.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-storage.mjs +2 -2
- package/fesm2022/sd-angular-core-services-storage.mjs.map +1 -1
- package/fesm2022/sd-angular-core-utilities-models.mjs.map +1 -1
- package/forms/autocomplete/src/autocomplete.component.d.ts +2 -1
- package/forms/checkbox/src/checkbox.component.d.ts +1 -1
- package/forms/chip/src/chip.component.d.ts +1 -1
- package/forms/chip-calendar/src/chip-calendar.component.d.ts +1 -1
- package/forms/date/src/date.component.d.ts +2 -1
- package/forms/date-range/src/date-range.component.d.ts +2 -1
- package/forms/datetime/src/datetime.component.d.ts +2 -1
- package/forms/input/src/input.component.d.ts +6 -2
- package/forms/input-color/index.d.ts +1 -0
- package/forms/input-color/src/input-color.component.d.ts +32 -0
- package/forms/input-number/src/input-number.component.d.ts +6 -2
- package/forms/radio/src/radio.component.d.ts +1 -1
- package/forms/select/src/select.component.d.ts +5 -5
- package/forms/switch/src/switch.component.d.ts +1 -1
- package/forms/textarea/src/textarea.component.d.ts +2 -1
- package/i18n/src/en.d.ts +2 -0
- package/modules/auth/configurations/auth.configuration.d.ts +4 -4
- package/modules/layout/configurations/layout.configuration.d.ts +3 -3
- package/modules/permission/src/configurations/permission.configuration.d.ts +3 -3
- package/package.json +123 -103
- package/sd-angular-core-19.0.0-beta.105.tgz +0 -0
- package/services/confirm/src/lib/components/dialog-confirm/dialog-confirm.component.d.ts +3 -3
- package/services/confirm/src/lib/confirm.service.d.ts +9 -9
- package/utilities/models/src/icon.model.d.ts +1 -1
- package/assets/scss/bootstrap-4.6.2/_alert.scss +0 -52
- package/assets/scss/bootstrap-4.6.2/_badge.scss +0 -54
- package/assets/scss/bootstrap-4.6.2/_breadcrumb.scss +0 -42
- package/assets/scss/bootstrap-4.6.2/_button-group.scss +0 -163
- package/assets/scss/bootstrap-4.6.2/_buttons.scss +0 -142
- package/assets/scss/bootstrap-4.6.2/_card.scss +0 -286
- package/assets/scss/bootstrap-4.6.2/_carousel.scss +0 -200
- package/assets/scss/bootstrap-4.6.2/_close.scss +0 -40
- package/assets/scss/bootstrap-4.6.2/_code.scss +0 -48
- package/assets/scss/bootstrap-4.6.2/_custom-forms.scss +0 -526
- package/assets/scss/bootstrap-4.6.2/_dropdown.scss +0 -192
- package/assets/scss/bootstrap-4.6.2/_forms.scss +0 -347
- package/assets/scss/bootstrap-4.6.2/_functions.scss +0 -190
- package/assets/scss/bootstrap-4.6.2/_grid.scss +0 -73
- package/assets/scss/bootstrap-4.6.2/_images.scss +0 -42
- package/assets/scss/bootstrap-4.6.2/_input-group.scss +0 -211
- package/assets/scss/bootstrap-4.6.2/_jumbotron.scss +0 -17
- package/assets/scss/bootstrap-4.6.2/_list-group.scss +0 -154
- package/assets/scss/bootstrap-4.6.2/_media.scss +0 -8
- package/assets/scss/bootstrap-4.6.2/_mixins.scss +0 -47
- package/assets/scss/bootstrap-4.6.2/_modal.scss +0 -240
- package/assets/scss/bootstrap-4.6.2/_nav.scss +0 -125
- package/assets/scss/bootstrap-4.6.2/_navbar.scss +0 -332
- package/assets/scss/bootstrap-4.6.2/_pagination.scss +0 -74
- package/assets/scss/bootstrap-4.6.2/_popover.scss +0 -170
- package/assets/scss/bootstrap-4.6.2/_print.scss +0 -132
- package/assets/scss/bootstrap-4.6.2/_progress.scss +0 -47
- package/assets/scss/bootstrap-4.6.2/_reboot.scss +0 -484
- package/assets/scss/bootstrap-4.6.2/_root.scss +0 -19
- package/assets/scss/bootstrap-4.6.2/_spinners.scss +0 -65
- package/assets/scss/bootstrap-4.6.2/_tables.scss +0 -185
- package/assets/scss/bootstrap-4.6.2/_toasts.scss +0 -46
- package/assets/scss/bootstrap-4.6.2/_tooltip.scss +0 -115
- package/assets/scss/bootstrap-4.6.2/_transitions.scss +0 -26
- package/assets/scss/bootstrap-4.6.2/_type.scss +0 -125
- package/assets/scss/bootstrap-4.6.2/_utilities.scss +0 -18
- package/assets/scss/bootstrap-4.6.2/_variables.scss +0 -1150
- package/assets/scss/bootstrap-4.6.2/bootstrap-grid.scss +0 -30
- package/assets/scss/bootstrap-4.6.2/bootstrap-reboot.scss +0 -12
- package/assets/scss/bootstrap-4.6.2/bootstrap.scss +0 -44
- package/assets/scss/bootstrap-4.6.2/mixins/_alert.scss +0 -13
- package/assets/scss/bootstrap-4.6.2/mixins/_background-variant.scss +0 -23
- package/assets/scss/bootstrap-4.6.2/mixins/_badge.scss +0 -17
- package/assets/scss/bootstrap-4.6.2/mixins/_border-radius.scss +0 -76
- package/assets/scss/bootstrap-4.6.2/mixins/_box-shadow.scss +0 -20
- package/assets/scss/bootstrap-4.6.2/mixins/_breakpoints.scss +0 -123
- package/assets/scss/bootstrap-4.6.2/mixins/_buttons.scss +0 -110
- package/assets/scss/bootstrap-4.6.2/mixins/_caret.scss +0 -62
- package/assets/scss/bootstrap-4.6.2/mixins/_clearfix.scss +0 -7
- package/assets/scss/bootstrap-4.6.2/mixins/_deprecate.scss +0 -10
- package/assets/scss/bootstrap-4.6.2/mixins/_float.scss +0 -14
- package/assets/scss/bootstrap-4.6.2/mixins/_forms.scss +0 -195
- package/assets/scss/bootstrap-4.6.2/mixins/_gradients.scss +0 -45
- package/assets/scss/bootstrap-4.6.2/mixins/_grid-framework.scss +0 -80
- package/assets/scss/bootstrap-4.6.2/mixins/_grid.scss +0 -69
- package/assets/scss/bootstrap-4.6.2/mixins/_hover.scss +0 -37
- package/assets/scss/bootstrap-4.6.2/mixins/_image.scss +0 -36
- package/assets/scss/bootstrap-4.6.2/mixins/_list-group.scss +0 -21
- package/assets/scss/bootstrap-4.6.2/mixins/_lists.scss +0 -7
- package/assets/scss/bootstrap-4.6.2/mixins/_nav-divider.scss +0 -11
- package/assets/scss/bootstrap-4.6.2/mixins/_pagination.scss +0 -22
- package/assets/scss/bootstrap-4.6.2/mixins/_reset-text.scss +0 -17
- package/assets/scss/bootstrap-4.6.2/mixins/_resize.scss +0 -6
- package/assets/scss/bootstrap-4.6.2/mixins/_screen-reader.scss +0 -34
- package/assets/scss/bootstrap-4.6.2/mixins/_size.scss +0 -7
- package/assets/scss/bootstrap-4.6.2/mixins/_table-row.scss +0 -39
- package/assets/scss/bootstrap-4.6.2/mixins/_text-emphasis.scss +0 -17
- package/assets/scss/bootstrap-4.6.2/mixins/_text-hide.scss +0 -11
- package/assets/scss/bootstrap-4.6.2/mixins/_text-truncate.scss +0 -8
- package/assets/scss/bootstrap-4.6.2/mixins/_transition.scss +0 -26
- package/assets/scss/bootstrap-4.6.2/mixins/_visibility.scss +0 -8
- package/assets/scss/bootstrap-4.6.2/utilities/_align.scss +0 -8
- package/assets/scss/bootstrap-4.6.2/utilities/_background.scss +0 -19
- package/assets/scss/bootstrap-4.6.2/utilities/_borders.scss +0 -75
- package/assets/scss/bootstrap-4.6.2/utilities/_clearfix.scss +0 -3
- package/assets/scss/bootstrap-4.6.2/utilities/_display.scss +0 -26
- package/assets/scss/bootstrap-4.6.2/utilities/_embed.scss +0 -39
- package/assets/scss/bootstrap-4.6.2/utilities/_flex.scss +0 -51
- package/assets/scss/bootstrap-4.6.2/utilities/_float.scss +0 -11
- package/assets/scss/bootstrap-4.6.2/utilities/_interactions.scss +0 -5
- package/assets/scss/bootstrap-4.6.2/utilities/_overflow.scss +0 -5
- package/assets/scss/bootstrap-4.6.2/utilities/_position.scss +0 -32
- package/assets/scss/bootstrap-4.6.2/utilities/_screenreaders.scss +0 -11
- package/assets/scss/bootstrap-4.6.2/utilities/_shadows.scss +0 -6
- package/assets/scss/bootstrap-4.6.2/utilities/_sizing.scss +0 -20
- package/assets/scss/bootstrap-4.6.2/utilities/_spacing.scss +0 -73
- package/assets/scss/bootstrap-4.6.2/utilities/_stretched-link.scss +0 -19
- package/assets/scss/bootstrap-4.6.2/utilities/_text.scss +0 -72
- package/assets/scss/bootstrap-4.6.2/utilities/_visibility.scss +0 -13
- package/assets/scss/bootstrap-4.6.2/vendor/_rfs.scss +0 -228
- package/assets/scss/core/bootstrap.scss +0 -13
- package/sd-angular-core-19.0.0-beta.103.tgz +0 -0
|
@@ -34,17 +34,16 @@ import { SdButton } from '@sd-angular/core/components/button';
|
|
|
34
34
|
import { SdQuickAction } from '@sd-angular/core/components/quick-action';
|
|
35
35
|
import { SdTooltipDirective, SdScrollDirective, SdDesktopDirective, SdMobileDirective, SdHoverCopyDirective } from '@sd-angular/core/directives';
|
|
36
36
|
import { SdSafeHtmlPipe, SdFormatNumberPipe } from '@sd-angular/core/pipes';
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
37
|
+
import { BrowserUtilities, Utilities } from '@sdcorejs/utils/fns';
|
|
38
|
+
import { DateUtilities, ArrayUtilities, NumberUtilities } from '@sd-angular/core/utilities/extensions';
|
|
39
39
|
import { SdBadge } from '@sd-angular/core/components/badge';
|
|
40
40
|
import { SdOperator } from '@sd-angular/core/components/operator';
|
|
41
41
|
import { SdInput, SdInputNumber, SdSelect, SdDate, SdDatetime, SdDateRange as SdDateRange$1, SdCheckbox, SdSwitch } from '@sd-angular/core/forms';
|
|
42
42
|
import { SdDateRange } from '@sd-angular/core/forms/date-range';
|
|
43
|
-
import { OPERATORS } from '@sdcorejs/utils/constants';
|
|
43
|
+
import { OPERATORS, EMPTY_STR } from '@sdcorejs/utils/constants';
|
|
44
44
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
45
45
|
import { SdSection } from '@sd-angular/core/components/section';
|
|
46
46
|
import { TranslatePipe, I18nService } from '@sd-angular/core/i18n';
|
|
47
|
-
import { BrowserUtilities } from '@sdcorejs/utils/fns';
|
|
48
47
|
import { SdSideDrawer } from '@sd-angular/core/components/side-drawer';
|
|
49
48
|
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
|
50
49
|
import { SdModal } from '@sd-angular/core/components/modal';
|
|
@@ -53,6 +52,7 @@ import * as i4 from '@angular/material/button';
|
|
|
53
52
|
import { MatButtonModule } from '@angular/material/button';
|
|
54
53
|
import * as i2$1 from '@angular/material/tooltip';
|
|
55
54
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
55
|
+
import { StringUtilities, DateUtilities as DateUtilities$1 } from '@sd-angular/core/utilities';
|
|
56
56
|
import * as i5$1 from '@angular/material/chips';
|
|
57
57
|
import { MatChipsModule } from '@angular/material/chips';
|
|
58
58
|
|
|
@@ -120,6 +120,34 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
|
|
|
120
120
|
}]
|
|
121
121
|
}] });
|
|
122
122
|
|
|
123
|
+
/**
|
|
124
|
+
* Directive cung cấp custom template render group header row trong sd-table.
|
|
125
|
+
* Thay thế cho htmlTemplate callback cũ — cho phép Angular template binding,
|
|
126
|
+
* pipes, components con (sd-badge, sd-button, …) bên trong.
|
|
127
|
+
*
|
|
128
|
+
* Ví dụ:
|
|
129
|
+
* ```html
|
|
130
|
+
* <sd-table [option]="opt">
|
|
131
|
+
* <ng-template sdTableGroupDef let-values="values" let-items="items" let-indeterminate="indeterminate">
|
|
132
|
+
* <b>Khách hàng: {{ values.customerName }}</b>
|
|
133
|
+
* <span>{{ items.length }} đơn hàng</span>
|
|
134
|
+
* </ng-template>
|
|
135
|
+
* </sd-table>
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
class SdTableGroupDefDirective {
|
|
139
|
+
static ngTemplateContextGuard(_dir, _ctx) {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
templateRef = inject(TemplateRef);
|
|
143
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdTableGroupDefDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
144
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.21", type: SdTableGroupDefDirective, isStandalone: true, selector: "[sdTableGroupDef]", ngImport: i0 });
|
|
145
|
+
}
|
|
146
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdTableGroupDefDirective, decorators: [{
|
|
147
|
+
type: Directive,
|
|
148
|
+
args: [{ selector: '[sdTableGroupDef]' }]
|
|
149
|
+
}] });
|
|
150
|
+
|
|
123
151
|
class SdTableTitleDefDirective {
|
|
124
152
|
static ngTemplateContextGuard(_dir, _ctx) {
|
|
125
153
|
return true;
|
|
@@ -252,11 +280,11 @@ class ColumnFilterComponent {
|
|
|
252
280
|
// Blur input: commit giá trị KHÔNG trigger reload.
|
|
253
281
|
onFilterCommit = () => this.filterCommit.emit();
|
|
254
282
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ColumnFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
255
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ColumnFilterComponent, isStandalone: true, selector: "column-filter", inputs: { autoIdInput: { classPropertyName: "autoIdInput", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null }, column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, columnFilter: { classPropertyName: "columnFilter", publicName: "columnFilter", isSignal: true, isRequired: false, transformFunction: null }, cacheValues: { classPropertyName: "cacheValues", publicName: "cacheValues", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, operator: { classPropertyName: "operator", publicName: "operator", isSignal: true, isRequired: false, transformFunction: null }, isMobile: { classPropertyName: "isMobile", publicName: "isMobile", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { operator: "operatorChange", filterChange: "filterChange", filterCommit: "filterCommit" }, ngImport: i0, template: "@let _column = column();\r\n@let _columnFilter = columnFilter();\r\n@let _autoId = autoId();\r\n@let _templateRef = templateRef();\r\n@let _operators = operators();\r\n@let _items = items();\r\n@let _label = label();\r\n@let _context = { columnFilter: _columnFilter, autoId: _autoId };\r\n\r\n<div class=\"d-flex c-inline-column align-items-end\" style=\"width: 100%; max-width: 100%\">\r\n @if (\r\n _column.type === 'string' ||\r\n _column.type === 'number' ||\r\n _column.type === 'boolean' ||\r\n _column.type === 'values' ||\r\n _column.type === 'lazy-values' ||\r\n _column.type === 'date' ||\r\n _column.type === 'datetime' ||\r\n _column.type === 'time'\r\n ) {\r\n <!-- Operator filter -->\r\n @if (_operators.length) {\r\n <div class=\"d-flex align-items-center\" [ngClass]=\"operatorWrapperClass()\">\r\n <sd-operator [(model)]=\"operator\" [operators]=\"operatorValues()\" />\r\n </div>\r\n }\r\n\r\n <!-- N\u1EBFu filter nh\u1EADn v\u00E0o template -->\r\n @if (_templateRef) {\r\n <ng-container *ngTemplateOutlet=\"_templateRef; context: _context\"></ng-container>\r\n }\r\n <!-- M\u1EB7c \u0111\u1ECBnh theo type v\u00E0 gi\u00E1 tr\u1ECB values defined c\u1EE7a column -->\r\n @else {\r\n @if (_column.type === 'string') {\r\n <sd-input\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n type=\"text\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (keyupEnter)=\"onFilterChange()\"\r\n (sdBlur)=\"onFilterCommit()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n </sd-input>\r\n } @else if (_column.type === 'number') {\r\n @if (!_column.filter?.type) {\r\n <sd-input-number\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (keyupEnter)=\"onFilterChange()\"\r\n (sdBlur)=\"onFilterCommit()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n </sd-input-number>\r\n } @else if (_column.filter?.type === 'split-number') {\r\n <ng-container\r\n *ngTemplateOutlet=\"splitNumberTpl; context: { field: _column.field, disabled: _column.filter?.disabled }\">\r\n </ng-container>\r\n }\r\n } @else if (_column.type === 'boolean') {\r\n <sd-select\r\n minWidthPanel=\"200px\"\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n [style.width]=\"'100%'\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [items]=\"[\r\n { value: '1', display: _column.option?.displayOnTrue || 'True' },\r\n { value: '0', display: _column.option?.displayOnFalse || 'False' },\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n <ng-template sdItemDef let-item=\"item\">\r\n @if (item.value === '1') {\r\n <sd-badge color=\"success\" [title]=\"_column.option?.displayOnTrue || 'True'\"> </sd-badge>\r\n } @else {\r\n <sd-badge color=\"error\" [title]=\"_column.option?.displayOnFalse || 'False'\"> </sd-badge>\r\n }\r\n </ng-template>\r\n </sd-select>\r\n } @else if (_column.type === 'values') {\r\n <sd-select\r\n minWidthPanel=\"200px\"\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n [style.width]=\"'100%'\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [items]=\"_items\"\r\n [valueField]=\"_column.option.valueField\"\r\n [displayField]=\"_column.option.displayField\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n [multiple]=\"_column.option.selection === 'MULTIPLE'\"\r\n hideInlineError>\r\n </sd-select>\r\n } @else if (_column.type === 'lazy-values') {\r\n <sd-select\r\n minWidthPanel=\"200px\"\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n [style.width]=\"'100%'\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [items]=\"_items\"\r\n [valueField]=\"_column.option.valueField\"\r\n [displayField]=\"_column.option.displayField\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n [multiple]=\"_column.option.selection === 'MULTIPLE'\"\r\n hideInlineError>\r\n </sd-select>\r\n } @else if (_column.type === 'date' || _column.type === 'datetime' || _column.type === 'time') {\r\n @if (!_column.filter?.type || _column.filter?.type === 'daterange') {\r\n <sd-date-range\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n </sd-date-range>\r\n } @else if (_column.filter?.type === 'date') {\r\n <sd-date\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n type=\"date\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n </sd-date>\r\n } @else if (_column.filter?.type === 'split-date') {\r\n <ng-container\r\n *ngTemplateOutlet=\"splitDateTpl; context: { field: _column.field, disabled: _column.filter?.disabled }\">\r\n </ng-container>\r\n }\r\n }\r\n }\r\n } @else {\r\n <sd-input [autoId]=\"_autoId\" style=\"flex: 1 1 0%; min-width: 0\" type=\"text\" size=\"sm\" disabled></sd-input>\r\n }\r\n</div>\r\n\r\n<!-- ================================================ -->\r\n<!-- Split from/to templates (\u0111\u01B0a xu\u1ED1ng cu\u1ED1i file) -->\r\n<!-- ================================================ -->\r\n<ng-template #splitNumberTpl let-field=\"field\" let-disabled=\"disabled\">\r\n <div class=\"d-flex align-items-center\" style=\"flex: 1 1 0%; min-width: 0\">\r\n <sd-input-number\r\n [autoId]=\"_autoId + '-from'\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[field].from\"\r\n (sdChange)=\"onFilterChange()\"\r\n (sdBlur)=\"onFilterCommit()\"\r\n [disabled]=\"disabled\"\r\n hideInlineError>\r\n </sd-input-number>\r\n <div class=\"mx-4\">-</div>\r\n <sd-input-number\r\n [autoId]=\"_autoId + '-to'\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n [(model)]=\"_columnFilter[field].to\"\r\n (sdChange)=\"onFilterChange()\"\r\n (sdBlur)=\"onFilterCommit()\"\r\n [disabled]=\"disabled\"\r\n hideInlineError>\r\n </sd-input-number>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #splitDateTpl let-field=\"field\" let-disabled=\"disabled\">\r\n <div class=\"d-flex align-items-center\" style=\"flex: 1 1 0%; min-width: 0\">\r\n <sd-date\r\n [autoId]=\"_autoId + '-from'\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n type=\"date\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[field].from\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"disabled\"\r\n hideInlineError>\r\n </sd-date>\r\n <div class=\"mx-4\">-</div>\r\n <sd-date\r\n [autoId]=\"_autoId + '-to'\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n type=\"date\"\r\n size=\"sm\"\r\n [(model)]=\"_columnFilter[field].to\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"disabled\"\r\n hideInlineError>\r\n </sd-date>\r\n </div>\r\n</ng-template>\r\n", styles: [":host ::ng-deep .c-inline-column .mat-mdc-text-field-wrapper{background-color:#fff}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: SdOperator, selector: "sd-operator", inputs: ["model", "operators", "disabled", "autoId"], outputs: ["modelChange"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "bare", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdDate, selector: "sd-date", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDateRange, selector: "sd-date-range", inputs: ["autoId", "name", "size", "form", "label", "helperText", "hideInlineError", "required", "disabled", "bare", "viewed", "appearance", "floatLabel", "min", "max", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: SdBadge, selector: "sd-badge", inputs: ["type", "color", "primary", "secondary", "success", "info", "warning", "error", "fontSet", "title", "description", "tooltip", "icon", "size"], outputs: ["click"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
283
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ColumnFilterComponent, isStandalone: true, selector: "column-filter", inputs: { autoIdInput: { classPropertyName: "autoIdInput", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null }, column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, columnFilter: { classPropertyName: "columnFilter", publicName: "columnFilter", isSignal: true, isRequired: false, transformFunction: null }, cacheValues: { classPropertyName: "cacheValues", publicName: "cacheValues", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, operator: { classPropertyName: "operator", publicName: "operator", isSignal: true, isRequired: false, transformFunction: null }, isMobile: { classPropertyName: "isMobile", publicName: "isMobile", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { operator: "operatorChange", filterChange: "filterChange", filterCommit: "filterCommit" }, ngImport: i0, template: "@let _column = column();\r\n@let _columnFilter = columnFilter();\r\n@let _autoId = autoId();\r\n@let _templateRef = templateRef();\r\n@let _operators = operators();\r\n@let _items = items();\r\n@let _label = label();\r\n@let _context = { columnFilter: _columnFilter, autoId: _autoId };\r\n\r\n<div class=\"d-flex c-inline-column align-items-end\" style=\"width: 100%; max-width: 100%\">\r\n @if (\r\n _column.type === 'string' ||\r\n _column.type === 'number' ||\r\n _column.type === 'boolean' ||\r\n _column.type === 'values' ||\r\n _column.type === 'lazy-values' ||\r\n _column.type === 'date' ||\r\n _column.type === 'datetime' ||\r\n _column.type === 'time'\r\n ) {\r\n <!-- Operator filter -->\r\n @if (_operators.length) {\r\n <div class=\"d-flex align-items-center\" [ngClass]=\"operatorWrapperClass()\">\r\n <sd-operator [(model)]=\"operator\" [operators]=\"operatorValues()\" />\r\n </div>\r\n }\r\n\r\n <!-- N\u1EBFu filter nh\u1EADn v\u00E0o template -->\r\n @if (_templateRef) {\r\n <ng-container *ngTemplateOutlet=\"_templateRef; context: _context\"></ng-container>\r\n }\r\n <!-- M\u1EB7c \u0111\u1ECBnh theo type v\u00E0 gi\u00E1 tr\u1ECB values defined c\u1EE7a column -->\r\n @else {\r\n @if (_column.type === 'string') {\r\n <sd-input\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n type=\"text\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (keyupEnter)=\"onFilterChange()\"\r\n (sdBlur)=\"onFilterCommit()\"\r\n (cleared)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n </sd-input>\r\n } @else if (_column.type === 'number') {\r\n @if (!_column.filter?.type) {\r\n <sd-input-number\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (keyupEnter)=\"onFilterChange()\"\r\n (sdBlur)=\"onFilterCommit()\"\r\n (cleared)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n </sd-input-number>\r\n } @else if (_column.filter?.type === 'split-number') {\r\n <ng-container\r\n *ngTemplateOutlet=\"splitNumberTpl; context: { field: _column.field, disabled: _column.filter?.disabled }\">\r\n </ng-container>\r\n }\r\n } @else if (_column.type === 'boolean') {\r\n <sd-select\r\n minWidthPanel=\"200px\"\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n [style.width]=\"'100%'\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [items]=\"[\r\n { value: '1', display: _column.option?.displayOnTrue || 'True' },\r\n { value: '0', display: _column.option?.displayOnFalse || 'False' },\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n <ng-template sdItemDef let-item=\"item\">\r\n @if (item.value === '1') {\r\n <sd-badge color=\"success\" [title]=\"_column.option?.displayOnTrue || 'True'\"> </sd-badge>\r\n } @else {\r\n <sd-badge color=\"error\" [title]=\"_column.option?.displayOnFalse || 'False'\"> </sd-badge>\r\n }\r\n </ng-template>\r\n </sd-select>\r\n } @else if (_column.type === 'values') {\r\n <sd-select\r\n minWidthPanel=\"200px\"\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n [style.width]=\"'100%'\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [items]=\"_items\"\r\n [valueField]=\"_column.option.valueField\"\r\n [displayField]=\"_column.option.displayField\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n [multiple]=\"_column.option.selection === 'MULTIPLE'\"\r\n hideInlineError>\r\n </sd-select>\r\n } @else if (_column.type === 'lazy-values') {\r\n <sd-select\r\n minWidthPanel=\"200px\"\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n [style.width]=\"'100%'\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [items]=\"_items\"\r\n [valueField]=\"_column.option.valueField\"\r\n [displayField]=\"_column.option.displayField\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n [multiple]=\"_column.option.selection === 'MULTIPLE'\"\r\n hideInlineError>\r\n </sd-select>\r\n } @else if (_column.type === 'date' || _column.type === 'datetime' || _column.type === 'time') {\r\n @if (!_column.filter?.type || _column.filter?.type === 'daterange') {\r\n <sd-date-range\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n </sd-date-range>\r\n } @else if (_column.filter?.type === 'date') {\r\n <sd-date\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n type=\"date\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n </sd-date>\r\n } @else if (_column.filter?.type === 'split-date') {\r\n <ng-container\r\n *ngTemplateOutlet=\"splitDateTpl; context: { field: _column.field, disabled: _column.filter?.disabled }\">\r\n </ng-container>\r\n }\r\n }\r\n }\r\n } @else {\r\n <sd-input [autoId]=\"_autoId\" style=\"flex: 1 1 0%; min-width: 0\" type=\"text\" size=\"sm\" disabled></sd-input>\r\n }\r\n</div>\r\n\r\n<!-- ================================================ -->\r\n<!-- Split from/to templates (\u0111\u01B0a xu\u1ED1ng cu\u1ED1i file) -->\r\n<!-- ================================================ -->\r\n<ng-template #splitNumberTpl let-field=\"field\" let-disabled=\"disabled\">\r\n <div class=\"d-flex align-items-center\" style=\"flex: 1 1 0%; min-width: 0\">\r\n <sd-input-number\r\n [autoId]=\"_autoId + '-from'\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[field].from\"\r\n (sdChange)=\"onFilterChange()\"\r\n (sdBlur)=\"onFilterCommit()\"\r\n (cleared)=\"onFilterChange()\"\r\n [disabled]=\"disabled\"\r\n hideInlineError>\r\n </sd-input-number>\r\n <div class=\"mx-4\">-</div>\r\n <sd-input-number\r\n [autoId]=\"_autoId + '-to'\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n [(model)]=\"_columnFilter[field].to\"\r\n (sdChange)=\"onFilterChange()\"\r\n (sdBlur)=\"onFilterCommit()\"\r\n (cleared)=\"onFilterChange()\"\r\n [disabled]=\"disabled\"\r\n hideInlineError>\r\n </sd-input-number>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #splitDateTpl let-field=\"field\" let-disabled=\"disabled\">\r\n <div class=\"d-flex align-items-center\" style=\"flex: 1 1 0%; min-width: 0\">\r\n <sd-date\r\n [autoId]=\"_autoId + '-from'\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n type=\"date\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[field].from\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"disabled\"\r\n hideInlineError>\r\n </sd-date>\r\n <div class=\"mx-4\">-</div>\r\n <sd-date\r\n [autoId]=\"_autoId + '-to'\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n type=\"date\"\r\n size=\"sm\"\r\n [(model)]=\"_columnFilter[field].to\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"disabled\"\r\n hideInlineError>\r\n </sd-date>\r\n </div>\r\n</ng-template>\r\n", styles: [":host ::ng-deep .c-inline-column .mat-mdc-text-field-wrapper{background-color:#fff}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: SdOperator, selector: "sd-operator", inputs: ["model", "operators", "disabled", "autoId"], outputs: ["modelChange"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "bare", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdDate, selector: "sd-date", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDateRange, selector: "sd-date-range", inputs: ["autoId", "name", "size", "form", "label", "helperText", "hideInlineError", "required", "disabled", "bare", "viewed", "appearance", "floatLabel", "min", "max", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: SdBadge, selector: "sd-badge", inputs: ["type", "color", "primary", "secondary", "success", "info", "warning", "error", "fontSet", "title", "description", "tooltip", "icon", "size"], outputs: ["click"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
256
284
|
}
|
|
257
285
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ColumnFilterComponent, decorators: [{
|
|
258
286
|
type: Component,
|
|
259
|
-
args: [{ selector: 'column-filter', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, SdOperator, SdInput, SdInputNumber, SdSelect, SdDate, SdDateRange, SdBadge], template: "@let _column = column();\r\n@let _columnFilter = columnFilter();\r\n@let _autoId = autoId();\r\n@let _templateRef = templateRef();\r\n@let _operators = operators();\r\n@let _items = items();\r\n@let _label = label();\r\n@let _context = { columnFilter: _columnFilter, autoId: _autoId };\r\n\r\n<div class=\"d-flex c-inline-column align-items-end\" style=\"width: 100%; max-width: 100%\">\r\n @if (\r\n _column.type === 'string' ||\r\n _column.type === 'number' ||\r\n _column.type === 'boolean' ||\r\n _column.type === 'values' ||\r\n _column.type === 'lazy-values' ||\r\n _column.type === 'date' ||\r\n _column.type === 'datetime' ||\r\n _column.type === 'time'\r\n ) {\r\n <!-- Operator filter -->\r\n @if (_operators.length) {\r\n <div class=\"d-flex align-items-center\" [ngClass]=\"operatorWrapperClass()\">\r\n <sd-operator [(model)]=\"operator\" [operators]=\"operatorValues()\" />\r\n </div>\r\n }\r\n\r\n <!-- N\u1EBFu filter nh\u1EADn v\u00E0o template -->\r\n @if (_templateRef) {\r\n <ng-container *ngTemplateOutlet=\"_templateRef; context: _context\"></ng-container>\r\n }\r\n <!-- M\u1EB7c \u0111\u1ECBnh theo type v\u00E0 gi\u00E1 tr\u1ECB values defined c\u1EE7a column -->\r\n @else {\r\n @if (_column.type === 'string') {\r\n <sd-input\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n type=\"text\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (keyupEnter)=\"onFilterChange()\"\r\n (sdBlur)=\"onFilterCommit()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n </sd-input>\r\n } @else if (_column.type === 'number') {\r\n @if (!_column.filter?.type) {\r\n <sd-input-number\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (keyupEnter)=\"onFilterChange()\"\r\n (sdBlur)=\"onFilterCommit()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n </sd-input-number>\r\n } @else if (_column.filter?.type === 'split-number') {\r\n <ng-container\r\n *ngTemplateOutlet=\"splitNumberTpl; context: { field: _column.field, disabled: _column.filter?.disabled }\">\r\n </ng-container>\r\n }\r\n } @else if (_column.type === 'boolean') {\r\n <sd-select\r\n minWidthPanel=\"200px\"\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n [style.width]=\"'100%'\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [items]=\"[\r\n { value: '1', display: _column.option?.displayOnTrue || 'True' },\r\n { value: '0', display: _column.option?.displayOnFalse || 'False' },\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n <ng-template sdItemDef let-item=\"item\">\r\n @if (item.value === '1') {\r\n <sd-badge color=\"success\" [title]=\"_column.option?.displayOnTrue || 'True'\"> </sd-badge>\r\n } @else {\r\n <sd-badge color=\"error\" [title]=\"_column.option?.displayOnFalse || 'False'\"> </sd-badge>\r\n }\r\n </ng-template>\r\n </sd-select>\r\n } @else if (_column.type === 'values') {\r\n <sd-select\r\n minWidthPanel=\"200px\"\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n [style.width]=\"'100%'\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [items]=\"_items\"\r\n [valueField]=\"_column.option.valueField\"\r\n [displayField]=\"_column.option.displayField\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n [multiple]=\"_column.option.selection === 'MULTIPLE'\"\r\n hideInlineError>\r\n </sd-select>\r\n } @else if (_column.type === 'lazy-values') {\r\n <sd-select\r\n minWidthPanel=\"200px\"\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n [style.width]=\"'100%'\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [items]=\"_items\"\r\n [valueField]=\"_column.option.valueField\"\r\n [displayField]=\"_column.option.displayField\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n [multiple]=\"_column.option.selection === 'MULTIPLE'\"\r\n hideInlineError>\r\n </sd-select>\r\n } @else if (_column.type === 'date' || _column.type === 'datetime' || _column.type === 'time') {\r\n @if (!_column.filter?.type || _column.filter?.type === 'daterange') {\r\n <sd-date-range\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n </sd-date-range>\r\n } @else if (_column.filter?.type === 'date') {\r\n <sd-date\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n type=\"date\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n </sd-date>\r\n } @else if (_column.filter?.type === 'split-date') {\r\n <ng-container\r\n *ngTemplateOutlet=\"splitDateTpl; context: { field: _column.field, disabled: _column.filter?.disabled }\">\r\n </ng-container>\r\n }\r\n }\r\n }\r\n } @else {\r\n <sd-input [autoId]=\"_autoId\" style=\"flex: 1 1 0%; min-width: 0\" type=\"text\" size=\"sm\" disabled></sd-input>\r\n }\r\n</div>\r\n\r\n<!-- ================================================ -->\r\n<!-- Split from/to templates (\u0111\u01B0a xu\u1ED1ng cu\u1ED1i file) -->\r\n<!-- ================================================ -->\r\n<ng-template #splitNumberTpl let-field=\"field\" let-disabled=\"disabled\">\r\n <div class=\"d-flex align-items-center\" style=\"flex: 1 1 0%; min-width: 0\">\r\n <sd-input-number\r\n [autoId]=\"_autoId + '-from'\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[field].from\"\r\n (sdChange)=\"onFilterChange()\"\r\n (sdBlur)=\"onFilterCommit()\"\r\n [disabled]=\"disabled\"\r\n hideInlineError>\r\n </sd-input-number>\r\n <div class=\"mx-4\">-</div>\r\n <sd-input-number\r\n [autoId]=\"_autoId + '-to'\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n [(model)]=\"_columnFilter[field].to\"\r\n (sdChange)=\"onFilterChange()\"\r\n (sdBlur)=\"onFilterCommit()\"\r\n [disabled]=\"disabled\"\r\n hideInlineError>\r\n </sd-input-number>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #splitDateTpl let-field=\"field\" let-disabled=\"disabled\">\r\n <div class=\"d-flex align-items-center\" style=\"flex: 1 1 0%; min-width: 0\">\r\n <sd-date\r\n [autoId]=\"_autoId + '-from'\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n type=\"date\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[field].from\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"disabled\"\r\n hideInlineError>\r\n </sd-date>\r\n <div class=\"mx-4\">-</div>\r\n <sd-date\r\n [autoId]=\"_autoId + '-to'\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n type=\"date\"\r\n size=\"sm\"\r\n [(model)]=\"_columnFilter[field].to\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"disabled\"\r\n hideInlineError>\r\n </sd-date>\r\n </div>\r\n</ng-template>\r\n", styles: [":host ::ng-deep .c-inline-column .mat-mdc-text-field-wrapper{background-color:#fff}\n"] }]
|
|
287
|
+
args: [{ selector: 'column-filter', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, SdOperator, SdInput, SdInputNumber, SdSelect, SdDate, SdDateRange, SdBadge], template: "@let _column = column();\r\n@let _columnFilter = columnFilter();\r\n@let _autoId = autoId();\r\n@let _templateRef = templateRef();\r\n@let _operators = operators();\r\n@let _items = items();\r\n@let _label = label();\r\n@let _context = { columnFilter: _columnFilter, autoId: _autoId };\r\n\r\n<div class=\"d-flex c-inline-column align-items-end\" style=\"width: 100%; max-width: 100%\">\r\n @if (\r\n _column.type === 'string' ||\r\n _column.type === 'number' ||\r\n _column.type === 'boolean' ||\r\n _column.type === 'values' ||\r\n _column.type === 'lazy-values' ||\r\n _column.type === 'date' ||\r\n _column.type === 'datetime' ||\r\n _column.type === 'time'\r\n ) {\r\n <!-- Operator filter -->\r\n @if (_operators.length) {\r\n <div class=\"d-flex align-items-center\" [ngClass]=\"operatorWrapperClass()\">\r\n <sd-operator [(model)]=\"operator\" [operators]=\"operatorValues()\" />\r\n </div>\r\n }\r\n\r\n <!-- N\u1EBFu filter nh\u1EADn v\u00E0o template -->\r\n @if (_templateRef) {\r\n <ng-container *ngTemplateOutlet=\"_templateRef; context: _context\"></ng-container>\r\n }\r\n <!-- M\u1EB7c \u0111\u1ECBnh theo type v\u00E0 gi\u00E1 tr\u1ECB values defined c\u1EE7a column -->\r\n @else {\r\n @if (_column.type === 'string') {\r\n <sd-input\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n type=\"text\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (keyupEnter)=\"onFilterChange()\"\r\n (sdBlur)=\"onFilterCommit()\"\r\n (cleared)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n </sd-input>\r\n } @else if (_column.type === 'number') {\r\n @if (!_column.filter?.type) {\r\n <sd-input-number\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (keyupEnter)=\"onFilterChange()\"\r\n (sdBlur)=\"onFilterCommit()\"\r\n (cleared)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n </sd-input-number>\r\n } @else if (_column.filter?.type === 'split-number') {\r\n <ng-container\r\n *ngTemplateOutlet=\"splitNumberTpl; context: { field: _column.field, disabled: _column.filter?.disabled }\">\r\n </ng-container>\r\n }\r\n } @else if (_column.type === 'boolean') {\r\n <sd-select\r\n minWidthPanel=\"200px\"\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n [style.width]=\"'100%'\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [items]=\"[\r\n { value: '1', display: _column.option?.displayOnTrue || 'True' },\r\n { value: '0', display: _column.option?.displayOnFalse || 'False' },\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n <ng-template sdItemDef let-item=\"item\">\r\n @if (item.value === '1') {\r\n <sd-badge color=\"success\" [title]=\"_column.option?.displayOnTrue || 'True'\"> </sd-badge>\r\n } @else {\r\n <sd-badge color=\"error\" [title]=\"_column.option?.displayOnFalse || 'False'\"> </sd-badge>\r\n }\r\n </ng-template>\r\n </sd-select>\r\n } @else if (_column.type === 'values') {\r\n <sd-select\r\n minWidthPanel=\"200px\"\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n [style.width]=\"'100%'\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [items]=\"_items\"\r\n [valueField]=\"_column.option.valueField\"\r\n [displayField]=\"_column.option.displayField\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n [multiple]=\"_column.option.selection === 'MULTIPLE'\"\r\n hideInlineError>\r\n </sd-select>\r\n } @else if (_column.type === 'lazy-values') {\r\n <sd-select\r\n minWidthPanel=\"200px\"\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n [style.width]=\"'100%'\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [items]=\"_items\"\r\n [valueField]=\"_column.option.valueField\"\r\n [displayField]=\"_column.option.displayField\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n [multiple]=\"_column.option.selection === 'MULTIPLE'\"\r\n hideInlineError>\r\n </sd-select>\r\n } @else if (_column.type === 'date' || _column.type === 'datetime' || _column.type === 'time') {\r\n @if (!_column.filter?.type || _column.filter?.type === 'daterange') {\r\n <sd-date-range\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n </sd-date-range>\r\n } @else if (_column.filter?.type === 'date') {\r\n <sd-date\r\n [autoId]=\"_autoId\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n type=\"date\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[_column.field]\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"_column.filter?.disabled\"\r\n hideInlineError>\r\n </sd-date>\r\n } @else if (_column.filter?.type === 'split-date') {\r\n <ng-container\r\n *ngTemplateOutlet=\"splitDateTpl; context: { field: _column.field, disabled: _column.filter?.disabled }\">\r\n </ng-container>\r\n }\r\n }\r\n }\r\n } @else {\r\n <sd-input [autoId]=\"_autoId\" style=\"flex: 1 1 0%; min-width: 0\" type=\"text\" size=\"sm\" disabled></sd-input>\r\n }\r\n</div>\r\n\r\n<!-- ================================================ -->\r\n<!-- Split from/to templates (\u0111\u01B0a xu\u1ED1ng cu\u1ED1i file) -->\r\n<!-- ================================================ -->\r\n<ng-template #splitNumberTpl let-field=\"field\" let-disabled=\"disabled\">\r\n <div class=\"d-flex align-items-center\" style=\"flex: 1 1 0%; min-width: 0\">\r\n <sd-input-number\r\n [autoId]=\"_autoId + '-from'\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[field].from\"\r\n (sdChange)=\"onFilterChange()\"\r\n (sdBlur)=\"onFilterCommit()\"\r\n (cleared)=\"onFilterChange()\"\r\n [disabled]=\"disabled\"\r\n hideInlineError>\r\n </sd-input-number>\r\n <div class=\"mx-4\">-</div>\r\n <sd-input-number\r\n [autoId]=\"_autoId + '-to'\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n size=\"sm\"\r\n [(model)]=\"_columnFilter[field].to\"\r\n (sdChange)=\"onFilterChange()\"\r\n (sdBlur)=\"onFilterCommit()\"\r\n (cleared)=\"onFilterChange()\"\r\n [disabled]=\"disabled\"\r\n hideInlineError>\r\n </sd-input-number>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #splitDateTpl let-field=\"field\" let-disabled=\"disabled\">\r\n <div class=\"d-flex align-items-center\" style=\"flex: 1 1 0%; min-width: 0\">\r\n <sd-date\r\n [autoId]=\"_autoId + '-from'\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n type=\"date\"\r\n size=\"sm\"\r\n [label]=\"_label\"\r\n [(model)]=\"_columnFilter[field].from\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"disabled\"\r\n hideInlineError>\r\n </sd-date>\r\n <div class=\"mx-4\">-</div>\r\n <sd-date\r\n [autoId]=\"_autoId + '-to'\"\r\n style=\"flex: 1 1 0%; min-width: 0\"\r\n type=\"date\"\r\n size=\"sm\"\r\n [(model)]=\"_columnFilter[field].to\"\r\n (sdChange)=\"onFilterChange()\"\r\n [disabled]=\"disabled\"\r\n hideInlineError>\r\n </sd-date>\r\n </div>\r\n</ng-template>\r\n", styles: [":host ::ng-deep .c-inline-column .mat-mdc-text-field-wrapper{background-color:#fff}\n"] }]
|
|
260
288
|
}], ctorParameters: () => [] });
|
|
261
289
|
|
|
262
290
|
// Đối với filter loại values, items có thể là 1 mảng, có thể là 1 hàm, do đó cần xử lý nếu là hàm có thể xử lý gọi API
|
|
@@ -316,23 +344,26 @@ const flattenTree = (roots, option, visited = new Set()) => {
|
|
|
316
344
|
return roots;
|
|
317
345
|
const maxDepth = option.maxDepth;
|
|
318
346
|
const result = [];
|
|
319
|
-
const walk = (rows, level) => {
|
|
320
|
-
|
|
347
|
+
const walk = (rows, level, parentPath) => {
|
|
348
|
+
rows.forEach((row, siblingIdx) => {
|
|
321
349
|
if (visited.has(row.meta.id))
|
|
322
|
-
|
|
350
|
+
return;
|
|
323
351
|
visited.add(row.meta.id);
|
|
324
352
|
row.meta.tree ??= { level, hasChildren: false, isExpanded: false };
|
|
325
353
|
row.meta.tree.level = level;
|
|
354
|
+
// why: hierarchical numbering (1, 1.2, 1.2.1, ...) — STT template join('.').
|
|
355
|
+
const indexPath = [...parentPath, siblingIdx + 1];
|
|
356
|
+
row.meta.tree.indexPath = indexPath;
|
|
326
357
|
result.push(row);
|
|
327
358
|
const canDescend = row.meta.tree.isExpanded && row.meta.tree.hasChildren;
|
|
328
359
|
const depthOk = maxDepth === undefined || level < maxDepth;
|
|
329
360
|
if (!canDescend || !depthOk)
|
|
330
|
-
|
|
361
|
+
return;
|
|
331
362
|
const children = row.meta.tree.childItems ?? [];
|
|
332
|
-
walk(children, level + 1);
|
|
333
|
-
}
|
|
363
|
+
walk(children, level + 1, indexPath);
|
|
364
|
+
});
|
|
334
365
|
};
|
|
335
|
-
walk(roots, 0);
|
|
366
|
+
walk(roots, 0, []);
|
|
336
367
|
return result;
|
|
337
368
|
};
|
|
338
369
|
/** Thu thập mọi SdTableItem đã format trong cây (kể cả node đang collapse). */
|
|
@@ -534,7 +565,7 @@ class ExternalFilterComponent {
|
|
|
534
565
|
});
|
|
535
566
|
};
|
|
536
567
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ExternalFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
537
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ExternalFilterComponent, isStandalone: true, selector: "external-filter", inputs: { autoIdInput: { classPropertyName: "autoIdInput", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, externalFilters: { classPropertyName: "externalFilters", publicName: "externalFilters", isSignal: true, isRequired: false, transformFunction: null }, filterRegister: { classPropertyName: "filterRegister", publicName: "filterRegister", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@let _filter = filter();\n@let _autoId = autoId();\n@let _items = filterItems();\n@let _externalFilter = externalFilter();\n@let _inlineExternal = inlineExternal();\n@let _filtered = filtered();\n@let _col = col();\n\n@if (!_filter?.disabled) {\n @if (!isMobileOrTablet && _items.length) {\n <sd-section\n [hideHeader]=\"_filter?.hideExternalFilterToolbar\"\n icon=\"filter_alt\"\n iconColor=\"secondary\"\n [title]=\"'core.component.table.filter' | translate\"\n collapsable>\n <div class=\"d-flex mr-4\" sdHeaderRight>\n <sd-button\n [autoId]=\"_autoId + 'clear'\"\n [disabled]=\"!_filtered\"\n type=\"link\"\n prefixIcon=\"cleaning_services\"\n [tooltip]=\"'core.component.table.clear-selection' | translate\"\n (click)=\"$event.stopPropagation(); clearFilter($event)\"></sd-button>\n <sd-button\n [autoId]=\"_autoId + 'setting'\"\n type=\"link\"\n prefixIcon=\"settings\"\n [tooltip]=\"'core.component.table.customize' | translate\"\n [matMenuTriggerFor]=\"menu\"\n (click)=\"$event.stopPropagation()\"></sd-button>\n <mat-menu #menu=\"matMenu\" class=\"sd-custom-panel-filter-configuration\" [attr.data-autoid]=\"_autoId + 'setting-menu'\">\n @for (externalFilter of _items; track externalFilter.field) {\n <button\n [attr.data-autoid]=\"_autoId + 'setting-' + externalFilter.field\"\n mat-menu-item\n (click)=\"onCheckboxChange($event, externalFilter)\"\n [disabled]=\"externalFilter.required\">\n <sd-checkbox\n [autoId]=\"_autoId + 'setting-' + externalFilter.field + '-checkbox'\"\n [label]=\"externalFilter.title\"\n [model]=\"_inlineExternal[externalFilter.field]\"\n [disabled]=\"externalFilter.required\" />\n </button>\n }\n </mat-menu>\n </div>\n <div class=\"row mx-0\" style=\"row-gap: 16px\">\n @for (item of _items; track item.field) {\n @if (_inlineExternal[item.field]) {\n <div class=\"col-md-3 col-sm-6 px-8\" [class.col-lg-2]=\"_col === 2\" [class.col-lg-3]=\"_col === 3\">\n @if (item.type === 'string') {\n <sd-input\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n type=\"text\"\n [(model)]=\"_externalFilter[item.field]\"\n (keyupEnter)=\"onKeyupEnter()\"\n appearance=\"outline\"\n [form]=\"form\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-input>\n } @else if (item.type === 'number') {\n <sd-input-number\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [(model)]=\"_externalFilter[item.field]\"\n (keyupEnter)=\"onKeyupEnter()\"\n appearance=\"outline\"\n [form]=\"form\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-input-number>\n } @else if (item.type === 'boolean') {\n <sd-select\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [items]=\"[\n { value: true, display: item.option?.displayOnTrue || 'True' },\n { value: false, display: item.option?.displayOnFalse || 'False' },\n ]\"\n valueField=\"value\"\n displayField=\"display\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n appearance=\"outline\"\n [form]=\"form\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n } @else if (item.type === 'date') {\n <sd-date\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n appearance=\"outline\"\n [form]=\"form\"\n [required]=\"item.required\"\n [min]=\"item.minDate\"\n [max]=\"item.maxDate\"\n hideInlineError>\n </sd-date>\n } @else if (item.type === 'datetime') {\n <sd-datetime\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n appearance=\"outline\"\n [form]=\"form\"\n [required]=\"item.required\"\n [min]=\"item.minDate\"\n [max]=\"item.maxDate\"\n hideInlineError>\n </sd-datetime>\n } @else if (item.type === 'daterange') {\n <sd-date-range\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n [form]=\"form\"\n [required]=\"item.required\"\n [min]=\"item.minDate\"\n [max]=\"item.maxDate\"\n appearance=\"outline\"\n hideInlineError>\n </sd-date-range>\n } @else if (item.type === 'values') {\n @if (item.option.selection === 'MULTIPLE') {\n <sd-select\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [items]=\"item.option.items | filterValues | async\"\n [valueField]=\"item.option.valueField\"\n [displayField]=\"item.option.displayField\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n appearance=\"outline\"\n multiple\n [form]=\"form\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n } @else if (item.option.selection === 'AUTOCOMPLETE') {\n <sd-select\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [items]=\"item.option.items | filterValues | async\"\n [valueField]=\"item.option.valueField\"\n [displayField]=\"item.option.displayField\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n appearance=\"outline\"\n [form]=\"form\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n } @else if (item.option.selection === 'MULTIPLEAUTOCOMPLETE') {\n <sd-select\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [items]=\"item.option.items | filterValues | async\"\n [valueField]=\"item.option.valueField\"\n [displayField]=\"item.option.displayField\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n appearance=\"outline\"\n multiple\n [form]=\"form\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n } @else {\n <sd-select\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [items]=\"item.option.items | filterValues | async\"\n [valueField]=\"item.option.valueField\"\n [displayField]=\"item.option.displayField\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n appearance=\"outline\"\n [form]=\"form\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n }\n } @else if (item.type === 'lazy-values') {\n @if (item.option.selection === 'MULTIPLE') {\n <sd-select\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [items]=\"item.option.items\"\n [valueField]=\"item.option.valueField\"\n [displayField]=\"item.option.displayField\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n appearance=\"outline\"\n multiple\n [form]=\"form\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n } @else {\n <sd-select\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [items]=\"item.option.items\"\n [valueField]=\"item.option.valueField\"\n [displayField]=\"item.option.displayField\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n appearance=\"outline\"\n [form]=\"form\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n }\n } @else if (item.type === 'custom' && item.filterDef) {\n <ng-container\n *ngTemplateOutlet=\"\n item.filterDef;\n context: { form: form, externalFilter: _externalFilter, autoId: _autoId + item.field }\n \">\n </ng-container>\n }\n </div>\n }\n }\n </div>\n @if (_filter?.manualFilter) {\n <div class=\"d-flex justify-content-end mt-16 px-8\">\n <sd-button\n [autoId]=\"_autoId + 'submit'\"\n [disabled]=\"form.invalid\"\n type=\"fill\"\n color=\"primary\"\n [title]=\"'core.component.table.search' | translate\"\n prefixIcon=\"filter_alt\"\n (click)=\"onSubmit()\">\n </sd-button>\n </div>\n }\n </sd-section>\n }\n}\n", styles: [":host{display:block;padding-left:0;padding-right:0}::ng-deep .sd-custom-panel-filter-configuration{width:240px;max-height:550px;overflow-y:auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i2.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "bare", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdDate, selector: "sd-date", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDatetime, selector: "sd-datetime", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "showSeconds", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDateRange$1, selector: "sd-date-range", inputs: ["autoId", "name", "size", "form", "label", "helperText", "hideInlineError", "required", "disabled", "bare", "viewed", "appearance", "floatLabel", "min", "max", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "pipe", type: FilterValuesPipe, name: "filterValues" }, { kind: "component", type: SdCheckbox, selector: "sd-checkbox", inputs: ["autoId", "name", "form", "label", "color", "disabled", "viewed", "inlineError", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
568
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ExternalFilterComponent, isStandalone: true, selector: "external-filter", inputs: { autoIdInput: { classPropertyName: "autoIdInput", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, externalFilters: { classPropertyName: "externalFilters", publicName: "externalFilters", isSignal: true, isRequired: false, transformFunction: null }, filterRegister: { classPropertyName: "filterRegister", publicName: "filterRegister", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@let _filter = filter();\n@let _autoId = autoId();\n@let _items = filterItems();\n@let _externalFilter = externalFilter();\n@let _inlineExternal = inlineExternal();\n@let _filtered = filtered();\n@let _col = col();\n\n@if (!_filter?.disabled) {\n @if (!isMobileOrTablet && _items.length) {\n <sd-section\n [hideHeader]=\"_filter?.hideExternalFilterToolbar\"\n icon=\"filter_alt\"\n iconColor=\"secondary\"\n [title]=\"'core.component.table.filter' | translate\"\n collapsable>\n <div class=\"d-flex mr-4\" sdHeaderRight>\n <sd-button\n [autoId]=\"_autoId + 'clear'\"\n [disabled]=\"!_filtered\"\n type=\"link\"\n prefixIcon=\"cleaning_services\"\n [tooltip]=\"'core.component.table.clear-selection' | translate\"\n (click)=\"$event.stopPropagation(); clearFilter($event)\"></sd-button>\n <sd-button\n [autoId]=\"_autoId + 'setting'\"\n type=\"link\"\n prefixIcon=\"settings\"\n [tooltip]=\"'core.component.table.customize' | translate\"\n [matMenuTriggerFor]=\"menu\"\n (click)=\"$event.stopPropagation()\"></sd-button>\n <mat-menu #menu=\"matMenu\" class=\"sd-custom-panel-filter-configuration\" [attr.data-autoid]=\"_autoId + 'setting-menu'\">\n @for (externalFilter of _items; track externalFilter.field) {\n <button\n [attr.data-autoid]=\"_autoId + 'setting-' + externalFilter.field\"\n mat-menu-item\n (click)=\"onCheckboxChange($event, externalFilter)\"\n [disabled]=\"externalFilter.required\">\n <sd-checkbox\n [autoId]=\"_autoId + 'setting-' + externalFilter.field + '-checkbox'\"\n [label]=\"externalFilter.title\"\n [model]=\"_inlineExternal[externalFilter.field]\"\n [disabled]=\"externalFilter.required\" />\n </button>\n }\n </mat-menu>\n </div>\n <div class=\"row mx-0\" style=\"row-gap: 16px\">\n @for (item of _items; track item.field) {\n @if (_inlineExternal[item.field]) {\n <div class=\"col-md-3 col-sm-6 px-8\" [class.col-lg-2]=\"_col === 2\" [class.col-lg-3]=\"_col === 3\">\n @if (item.type === 'string') {\n <sd-input\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n type=\"text\"\n [(model)]=\"_externalFilter[item.field]\"\n (keyupEnter)=\"onKeyupEnter()\"\n appearance=\"outline\"\n [form]=\"form\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-input>\n } @else if (item.type === 'number') {\n <sd-input-number\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [(model)]=\"_externalFilter[item.field]\"\n (keyupEnter)=\"onKeyupEnter()\"\n appearance=\"outline\"\n [form]=\"form\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-input-number>\n } @else if (item.type === 'boolean') {\n <sd-select\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [items]=\"[\n { value: true, display: item.option?.displayOnTrue || 'True' },\n { value: false, display: item.option?.displayOnFalse || 'False' },\n ]\"\n valueField=\"value\"\n displayField=\"display\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n appearance=\"outline\"\n [form]=\"form\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n } @else if (item.type === 'date') {\n <sd-date\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n appearance=\"outline\"\n [form]=\"form\"\n [required]=\"item.required\"\n [min]=\"item.minDate\"\n [max]=\"item.maxDate\"\n hideInlineError>\n </sd-date>\n } @else if (item.type === 'datetime') {\n <sd-datetime\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n appearance=\"outline\"\n [form]=\"form\"\n [required]=\"item.required\"\n [min]=\"item.minDate\"\n [max]=\"item.maxDate\"\n hideInlineError>\n </sd-datetime>\n } @else if (item.type === 'daterange') {\n <sd-date-range\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n [form]=\"form\"\n [required]=\"item.required\"\n [min]=\"item.minDate\"\n [max]=\"item.maxDate\"\n appearance=\"outline\"\n hideInlineError>\n </sd-date-range>\n } @else if (item.type === 'values') {\n @if (item.option.selection === 'MULTIPLE') {\n <sd-select\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [items]=\"item.option.items | filterValues | async\"\n [valueField]=\"item.option.valueField\"\n [displayField]=\"item.option.displayField\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n appearance=\"outline\"\n multiple\n [form]=\"form\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n } @else if (item.option.selection === 'AUTOCOMPLETE') {\n <sd-select\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [items]=\"item.option.items | filterValues | async\"\n [valueField]=\"item.option.valueField\"\n [displayField]=\"item.option.displayField\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n appearance=\"outline\"\n [form]=\"form\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n } @else if (item.option.selection === 'MULTIPLEAUTOCOMPLETE') {\n <sd-select\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [items]=\"item.option.items | filterValues | async\"\n [valueField]=\"item.option.valueField\"\n [displayField]=\"item.option.displayField\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n appearance=\"outline\"\n multiple\n [form]=\"form\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n } @else {\n <sd-select\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [items]=\"item.option.items | filterValues | async\"\n [valueField]=\"item.option.valueField\"\n [displayField]=\"item.option.displayField\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n appearance=\"outline\"\n [form]=\"form\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n }\n } @else if (item.type === 'lazy-values') {\n @if (item.option.selection === 'MULTIPLE') {\n <sd-select\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [items]=\"item.option.items\"\n [valueField]=\"item.option.valueField\"\n [displayField]=\"item.option.displayField\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n appearance=\"outline\"\n multiple\n [form]=\"form\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n } @else {\n <sd-select\n [autoId]=\"_autoId + item.field\"\n [label]=\"item.title\"\n [items]=\"item.option.items\"\n [valueField]=\"item.option.valueField\"\n [displayField]=\"item.option.displayField\"\n [(model)]=\"_externalFilter[item.field]\"\n (sdChange)=\"onFilter(item)\"\n appearance=\"outline\"\n [form]=\"form\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n }\n } @else if (item.type === 'custom' && item.filterDef) {\n <ng-container\n *ngTemplateOutlet=\"\n item.filterDef;\n context: { form: form, externalFilter: _externalFilter, autoId: _autoId + item.field }\n \">\n </ng-container>\n }\n </div>\n }\n }\n </div>\n @if (_filter?.manualFilter) {\n <div class=\"d-flex justify-content-end mt-16 px-8\">\n <sd-button\n [autoId]=\"_autoId + 'submit'\"\n [disabled]=\"form.invalid\"\n type=\"fill\"\n color=\"primary\"\n [title]=\"'core.component.table.search' | translate\"\n prefixIcon=\"filter_alt\"\n (click)=\"onSubmit()\">\n </sd-button>\n </div>\n }\n </sd-section>\n }\n}\n", styles: [":host{display:block;padding-left:0;padding-right:0}::ng-deep .sd-custom-panel-filter-configuration{width:240px;max-height:550px;overflow-y:auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i2.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "bare", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdDate, selector: "sd-date", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDatetime, selector: "sd-datetime", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "showSeconds", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDateRange$1, selector: "sd-date-range", inputs: ["autoId", "name", "size", "form", "label", "helperText", "hideInlineError", "required", "disabled", "bare", "viewed", "appearance", "floatLabel", "min", "max", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "pipe", type: FilterValuesPipe, name: "filterValues" }, { kind: "component", type: SdCheckbox, selector: "sd-checkbox", inputs: ["autoId", "name", "form", "label", "color", "disabled", "viewed", "inlineError", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
538
569
|
}
|
|
539
570
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ExternalFilterComponent, decorators: [{
|
|
540
571
|
type: Component,
|
|
@@ -630,7 +661,7 @@ class MobileFilterComponent {
|
|
|
630
661
|
this.drawer().close();
|
|
631
662
|
};
|
|
632
663
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: MobileFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
633
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: MobileFilterComponent, isStandalone: true, selector: "mobile-filter", inputs: { autoIdInput: { classPropertyName: "autoIdInput", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, externalFilters: { classPropertyName: "externalFilters", publicName: "externalFilters", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, filterDefs: { classPropertyName: "filterDefs", publicName: "filterDefs", isSignal: true, isRequired: false, transformFunction: null }, filterRegister: { classPropertyName: "filterRegister", publicName: "filterRegister", isSignal: true, isRequired: false, transformFunction: null }, cacheValues: { classPropertyName: "cacheValues", publicName: "cacheValues", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "drawer", first: true, predicate: SdSideDrawer, descendants: true, isSignal: true }], ngImport: i0, template: "@let _autoId = autoId();\n@let _externalFilters = externalFilterItems();\n@let _columns = columnItems();\n@let _filterDefs = filterDefItems();\n@let _workingColumnFilter = workingColumnFilter();\n@let _workingColumnOperator = workingColumnOperator();\n@let _workingExternalFilter = workingExternalFilter();\n@let _cacheValues = cacheValues();\n\n<sd-side-drawer\n #drawer\n [title]=\"'core.component.table.filter' | translate\"\n width=\"90vw\">\n <div class=\"mobile-filter-body\">\n <!-- ============================ -->\n <!-- 1. External filters (inline) -->\n <!-- ============================ -->\n @if (_externalFilters.length) {\n <section class=\"mobile-filter-section\">\n @for (item of _externalFilters; track item.field) {\n <div class=\"mobile-filter-row\">\n @if (item.type === 'string') {\n <sd-input\n [autoId]=\"_autoId + 'ext-' + item.field\"\n size=\"sm\"\n [label]=\"item.title\"\n type=\"text\"\n [(model)]=\"_workingExternalFilter[item.field]\"\n appearance=\"outline\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-input>\n } @else if (item.type === 'number') {\n <sd-input-number\n [autoId]=\"_autoId + 'ext-' + item.field\"\n size=\"sm\"\n [label]=\"item.title\"\n [(model)]=\"_workingExternalFilter[item.field]\"\n appearance=\"outline\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-input-number>\n } @else if (item.type === 'boolean') {\n <sd-select\n [autoId]=\"_autoId + 'ext-' + item.field\"\n size=\"sm\"\n [label]=\"item.title\"\n [items]=\"[\n { value: true, display: item.option?.displayOnTrue || 'True' },\n { value: false, display: item.option?.displayOnFalse || 'False' },\n ]\"\n valueField=\"value\"\n displayField=\"display\"\n [(model)]=\"_workingExternalFilter[item.field]\"\n appearance=\"outline\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n } @else if (item.type === 'date') {\n <sd-date\n [autoId]=\"_autoId + 'ext-' + item.field\"\n size=\"sm\"\n [label]=\"item.title\"\n [(model)]=\"_workingExternalFilter[item.field]\"\n appearance=\"outline\"\n [required]=\"item.required\"\n [min]=\"item.minDate\"\n [max]=\"item.maxDate\"\n hideInlineError>\n </sd-date>\n } @else if (item.type === 'datetime') {\n <sd-datetime\n [autoId]=\"_autoId + 'ext-' + item.field\"\n size=\"sm\"\n [label]=\"item.title\"\n [(model)]=\"_workingExternalFilter[item.field]\"\n appearance=\"outline\"\n [required]=\"item.required\"\n [min]=\"item.minDate\"\n [max]=\"item.maxDate\"\n hideInlineError>\n </sd-datetime>\n } @else if (item.type === 'daterange') {\n <sd-date-range\n [autoId]=\"_autoId + 'ext-' + item.field\"\n size=\"sm\"\n [label]=\"item.title\"\n [(model)]=\"_workingExternalFilter[item.field]\"\n [required]=\"item.required\"\n [min]=\"item.minDate\"\n [max]=\"item.maxDate\"\n appearance=\"outline\"\n hideInlineError>\n </sd-date-range>\n } @else if (item.type === 'values') {\n <sd-select\n [autoId]=\"_autoId + 'ext-' + item.field\"\n size=\"sm\"\n [label]=\"item.title\"\n [items]=\"item.option.items | filterValues | async\"\n [valueField]=\"item.option.valueField\"\n [displayField]=\"item.option.displayField\"\n [(model)]=\"_workingExternalFilter[item.field]\"\n appearance=\"outline\"\n [multiple]=\"item.option.selection === 'MULTIPLE' || item.option.selection === 'MULTIPLEAUTOCOMPLETE'\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n } @else if (item.type === 'lazy-values') {\n <sd-select\n [autoId]=\"_autoId + 'ext-' + item.field\"\n size=\"sm\"\n [label]=\"item.title\"\n [items]=\"item.option.items\"\n [valueField]=\"item.option.valueField\"\n [displayField]=\"item.option.displayField\"\n [(model)]=\"_workingExternalFilter[item.field]\"\n appearance=\"outline\"\n [multiple]=\"item.option.selection === 'MULTIPLE'\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n } @else if (item.type === 'custom' && item.filterDef) {\n <ng-container\n *ngTemplateOutlet=\"\n item.filterDef;\n context: { externalFilter: _workingExternalFilter, autoId: _autoId + 'ext-' + item.field }\n \">\n </ng-container>\n }\n </div>\n }\n </section>\n }\n\n <!-- ============================ -->\n <!-- 2. Custom filterDef templates -->\n <!-- ============================ -->\n @if (_filterDefs.length) {\n <section class=\"mobile-filter-section\">\n @for (def of _filterDefs; track def.sdTableFilterDef()) {\n <div class=\"mobile-filter-row\" [attr.data-autoid]=\"_autoId + 'def-' + def.sdTableFilterDef()\">\n <ng-container\n *ngTemplateOutlet=\"def.templateRef!; context: { externalFilter: _workingExternalFilter }\">\n </ng-container>\n </div>\n }\n </section>\n }\n\n <!-- ============================ -->\n <!-- 3. Column filters -->\n <!-- ============================ -->\n @if (_columns.length) {\n <section class=\"mobile-filter-section\">\n @for (column of _columns; track column.field) {\n <div class=\"mobile-filter-row\" [attr.data-autoid]=\"_autoId + 'col-' + column.field\">\n <column-filter\n [autoId]=\"_autoId + 'col'\"\n [column]=\"column\"\n [columnFilter]=\"_workingColumnFilter\"\n [operator]=\"$any(_workingColumnOperator[column.field])\"\n (operatorChange)=\"_workingColumnOperator[column.field] = $event!\"\n [cacheValues]=\"_cacheValues\"\n isMobile>\n </column-filter>\n </div>\n }\n </section>\n }\n </div>\n\n <ng-container sdFooter>\n <div class=\"mobile-filter-footer\">\n <sd-button\n [autoId]=\"_autoId + 'cancel'\"\n class=\"mobile-filter-action\"\n (click)=\"onCancel()\"\n [title]=\"'core.confirm.no' | translate\"\n type=\"link\"\n color=\"secondary\">\n </sd-button>\n <sd-button\n [autoId]=\"_autoId + 'apply'\"\n class=\"mobile-filter-action\"\n (click)=\"onApply()\"\n [title]=\"'core.confirm.yes' | translate\"\n type=\"fill\"\n color=\"primary\">\n </sd-button>\n </div>\n </ng-container>\n</sd-side-drawer>\n", styles: [".mobile-filter-body{display:flex;flex-direction:column;gap:16px;padding:8px 0}.mobile-filter-section{display:flex;flex-direction:column;gap:12px}.mobile-filter-row{display:flex;flex-direction:column}.mobile-filter-footer{display:flex;gap:8px;width:100%}.mobile-filter-action{flex:1 1 50%}.mobile-filter-action ::ng-deep button{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "component", type: SdSideDrawer, selector: "sd-side-drawer", inputs: ["title", "width", "hideClose", "disableBackdropClose", "drawerClass", "autoId"], outputs: ["sdClosed"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: ColumnFilterComponent, selector: "column-filter", inputs: ["autoId", "column", "columnFilter", "cacheValues", "value", "operator", "isMobile"], outputs: ["operatorChange", "filterChange", "filterCommit"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "bare", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdDate, selector: "sd-date", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDatetime, selector: "sd-datetime", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "showSeconds", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDateRange$1, selector: "sd-date-range", inputs: ["autoId", "name", "size", "form", "label", "helperText", "hideInlineError", "required", "disabled", "bare", "viewed", "appearance", "floatLabel", "min", "max", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: FilterValuesPipe, name: "filterValues" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
664
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: MobileFilterComponent, isStandalone: true, selector: "mobile-filter", inputs: { autoIdInput: { classPropertyName: "autoIdInput", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, externalFilters: { classPropertyName: "externalFilters", publicName: "externalFilters", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, filterDefs: { classPropertyName: "filterDefs", publicName: "filterDefs", isSignal: true, isRequired: false, transformFunction: null }, filterRegister: { classPropertyName: "filterRegister", publicName: "filterRegister", isSignal: true, isRequired: false, transformFunction: null }, cacheValues: { classPropertyName: "cacheValues", publicName: "cacheValues", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "drawer", first: true, predicate: SdSideDrawer, descendants: true, isSignal: true }], ngImport: i0, template: "@let _autoId = autoId();\n@let _externalFilters = externalFilterItems();\n@let _columns = columnItems();\n@let _filterDefs = filterDefItems();\n@let _workingColumnFilter = workingColumnFilter();\n@let _workingColumnOperator = workingColumnOperator();\n@let _workingExternalFilter = workingExternalFilter();\n@let _cacheValues = cacheValues();\n\n<sd-side-drawer\n #drawer\n [title]=\"'core.component.table.filter' | translate\"\n width=\"90vw\">\n <div class=\"mobile-filter-body\">\n <!-- ============================ -->\n <!-- 1. External filters (inline) -->\n <!-- ============================ -->\n @if (_externalFilters.length) {\n <section class=\"mobile-filter-section\">\n @for (item of _externalFilters; track item.field) {\n <div class=\"mobile-filter-row\">\n @if (item.type === 'string') {\n <sd-input\n [autoId]=\"_autoId + 'ext-' + item.field\"\n size=\"sm\"\n [label]=\"item.title\"\n type=\"text\"\n [(model)]=\"_workingExternalFilter[item.field]\"\n appearance=\"outline\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-input>\n } @else if (item.type === 'number') {\n <sd-input-number\n [autoId]=\"_autoId + 'ext-' + item.field\"\n size=\"sm\"\n [label]=\"item.title\"\n [(model)]=\"_workingExternalFilter[item.field]\"\n appearance=\"outline\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-input-number>\n } @else if (item.type === 'boolean') {\n <sd-select\n [autoId]=\"_autoId + 'ext-' + item.field\"\n size=\"sm\"\n [label]=\"item.title\"\n [items]=\"[\n { value: true, display: item.option?.displayOnTrue || 'True' },\n { value: false, display: item.option?.displayOnFalse || 'False' },\n ]\"\n valueField=\"value\"\n displayField=\"display\"\n [(model)]=\"_workingExternalFilter[item.field]\"\n appearance=\"outline\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n } @else if (item.type === 'date') {\n <sd-date\n [autoId]=\"_autoId + 'ext-' + item.field\"\n size=\"sm\"\n [label]=\"item.title\"\n [(model)]=\"_workingExternalFilter[item.field]\"\n appearance=\"outline\"\n [required]=\"item.required\"\n [min]=\"item.minDate\"\n [max]=\"item.maxDate\"\n hideInlineError>\n </sd-date>\n } @else if (item.type === 'datetime') {\n <sd-datetime\n [autoId]=\"_autoId + 'ext-' + item.field\"\n size=\"sm\"\n [label]=\"item.title\"\n [(model)]=\"_workingExternalFilter[item.field]\"\n appearance=\"outline\"\n [required]=\"item.required\"\n [min]=\"item.minDate\"\n [max]=\"item.maxDate\"\n hideInlineError>\n </sd-datetime>\n } @else if (item.type === 'daterange') {\n <sd-date-range\n [autoId]=\"_autoId + 'ext-' + item.field\"\n size=\"sm\"\n [label]=\"item.title\"\n [(model)]=\"_workingExternalFilter[item.field]\"\n [required]=\"item.required\"\n [min]=\"item.minDate\"\n [max]=\"item.maxDate\"\n appearance=\"outline\"\n hideInlineError>\n </sd-date-range>\n } @else if (item.type === 'values') {\n <sd-select\n [autoId]=\"_autoId + 'ext-' + item.field\"\n size=\"sm\"\n [label]=\"item.title\"\n [items]=\"item.option.items | filterValues | async\"\n [valueField]=\"item.option.valueField\"\n [displayField]=\"item.option.displayField\"\n [(model)]=\"_workingExternalFilter[item.field]\"\n appearance=\"outline\"\n [multiple]=\"item.option.selection === 'MULTIPLE' || item.option.selection === 'MULTIPLEAUTOCOMPLETE'\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n } @else if (item.type === 'lazy-values') {\n <sd-select\n [autoId]=\"_autoId + 'ext-' + item.field\"\n size=\"sm\"\n [label]=\"item.title\"\n [items]=\"item.option.items\"\n [valueField]=\"item.option.valueField\"\n [displayField]=\"item.option.displayField\"\n [(model)]=\"_workingExternalFilter[item.field]\"\n appearance=\"outline\"\n [multiple]=\"item.option.selection === 'MULTIPLE'\"\n [required]=\"item.required\"\n hideInlineError>\n </sd-select>\n } @else if (item.type === 'custom' && item.filterDef) {\n <ng-container\n *ngTemplateOutlet=\"\n item.filterDef;\n context: { externalFilter: _workingExternalFilter, autoId: _autoId + 'ext-' + item.field }\n \">\n </ng-container>\n }\n </div>\n }\n </section>\n }\n\n <!-- ============================ -->\n <!-- 2. Custom filterDef templates -->\n <!-- ============================ -->\n @if (_filterDefs.length) {\n <section class=\"mobile-filter-section\">\n @for (def of _filterDefs; track def.sdTableFilterDef()) {\n <div class=\"mobile-filter-row\" [attr.data-autoid]=\"_autoId + 'def-' + def.sdTableFilterDef()\">\n <ng-container\n *ngTemplateOutlet=\"def.templateRef!; context: { externalFilter: _workingExternalFilter }\">\n </ng-container>\n </div>\n }\n </section>\n }\n\n <!-- ============================ -->\n <!-- 3. Column filters -->\n <!-- ============================ -->\n @if (_columns.length) {\n <section class=\"mobile-filter-section\">\n @for (column of _columns; track column.field) {\n <div class=\"mobile-filter-row\" [attr.data-autoid]=\"_autoId + 'col-' + column.field\">\n <column-filter\n [autoId]=\"_autoId + 'col'\"\n [column]=\"column\"\n [columnFilter]=\"_workingColumnFilter\"\n [operator]=\"$any(_workingColumnOperator[column.field])\"\n (operatorChange)=\"_workingColumnOperator[column.field] = $event!\"\n [cacheValues]=\"_cacheValues\"\n isMobile>\n </column-filter>\n </div>\n }\n </section>\n }\n </div>\n\n <ng-container sdFooter>\n <div class=\"mobile-filter-footer\">\n <sd-button\n [autoId]=\"_autoId + 'cancel'\"\n class=\"mobile-filter-action\"\n (click)=\"onCancel()\"\n [title]=\"'core.confirm.no' | translate\"\n type=\"link\"\n color=\"secondary\">\n </sd-button>\n <sd-button\n [autoId]=\"_autoId + 'apply'\"\n class=\"mobile-filter-action\"\n (click)=\"onApply()\"\n [title]=\"'core.confirm.yes' | translate\"\n type=\"fill\"\n color=\"primary\">\n </sd-button>\n </div>\n </ng-container>\n</sd-side-drawer>\n", styles: [".mobile-filter-body{display:flex;flex-direction:column;gap:16px;padding:8px 0}.mobile-filter-section{display:flex;flex-direction:column;gap:12px}.mobile-filter-row{display:flex;flex-direction:column}.mobile-filter-footer{display:flex;gap:8px;width:100%}.mobile-filter-action{flex:1 1 50%}.mobile-filter-action ::ng-deep button{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "component", type: SdSideDrawer, selector: "sd-side-drawer", inputs: ["title", "width", "hideClose", "disableBackdropClose", "drawerClass", "autoId"], outputs: ["sdClosed"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: ColumnFilterComponent, selector: "column-filter", inputs: ["autoId", "column", "columnFilter", "cacheValues", "value", "operator", "isMobile"], outputs: ["operatorChange", "filterChange", "filterCommit"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "bare", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdDate, selector: "sd-date", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDatetime, selector: "sd-datetime", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "showSeconds", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDateRange$1, selector: "sd-date-range", inputs: ["autoId", "name", "size", "form", "label", "helperText", "hideInlineError", "required", "disabled", "bare", "viewed", "appearance", "floatLabel", "min", "max", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: FilterValuesPipe, name: "filterValues" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
634
665
|
}
|
|
635
666
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: MobileFilterComponent, decorators: [{
|
|
636
667
|
type: Component,
|
|
@@ -693,7 +724,7 @@ class ActionFilterPipe {
|
|
|
693
724
|
if ('children' in action) {
|
|
694
725
|
const children = [];
|
|
695
726
|
for (const childAction of action.children) {
|
|
696
|
-
const key =
|
|
727
|
+
const key = Utilities.hash(childAction);
|
|
697
728
|
if (selectedItems.every(e => e?.meta?.selector?.actions?.includes(key))) {
|
|
698
729
|
children.push(childAction);
|
|
699
730
|
}
|
|
@@ -703,7 +734,7 @@ class ActionFilterPipe {
|
|
|
703
734
|
}
|
|
704
735
|
}
|
|
705
736
|
else {
|
|
706
|
-
const key =
|
|
737
|
+
const key = Utilities.hash(action);
|
|
707
738
|
if (selectedItems.every(e => e?.meta?.selector?.actions?.includes(key))) {
|
|
708
739
|
results.push(action);
|
|
709
740
|
}
|
|
@@ -781,6 +812,7 @@ class ConfigService {
|
|
|
781
812
|
REORDER: 'sdReorder',
|
|
782
813
|
INDEX: 'sdIndex',
|
|
783
814
|
TREE_TOGGLE: 'sdTreeToggle',
|
|
815
|
+
FILLER: 'sdFiller',
|
|
784
816
|
};
|
|
785
817
|
#prefix = 'TABLE_CONFIG';
|
|
786
818
|
#storage;
|
|
@@ -793,7 +825,7 @@ class ConfigService {
|
|
|
793
825
|
#loadConfiguredTable = (option) => {
|
|
794
826
|
// Nếu không có key thì không lấy được setting
|
|
795
827
|
if (!option?.key) {
|
|
796
|
-
return this.storageService.create(
|
|
828
|
+
return this.storageService.create(Utilities.hash(option), {
|
|
797
829
|
type: 'session', // Nếu không có key thì lưu theo session
|
|
798
830
|
default: this.#default(option),
|
|
799
831
|
});
|
|
@@ -840,10 +872,10 @@ class ConfigService {
|
|
|
840
872
|
result.firstHeaders.push(this.#COLUMNS.COMMAND);
|
|
841
873
|
result.displayedColumns.push(this.#COLUMNS.COMMAND);
|
|
842
874
|
}
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
875
|
+
// why: group header row dùng matRowDef RIÊNG với column list ['sdGroupHeader'] qua predicate
|
|
876
|
+
// when:isGroupHeader — KHÔNG inject vào displayedColumns/firstHeaders để tránh colspan trick
|
|
877
|
+
// (TDs khác vẫn render gây overflow row). Data row dùng displayedColumns nguyên vẹn.
|
|
878
|
+
// group option vẫn cần khai báo (qua option.group) để SdGroupPipe biết bucket items.
|
|
847
879
|
// sdIndex đặt sau selector / tree / command-left / group, ngay trước data columns
|
|
848
880
|
if (option.index?.enabled) {
|
|
849
881
|
result.firstHeaders.push(this.#COLUMNS.INDEX);
|
|
@@ -919,9 +951,19 @@ class ConfigService {
|
|
|
919
951
|
result.firstHeaders.push(this.#COLUMNS.COMMAND);
|
|
920
952
|
result.displayedColumns.push(this.#COLUMNS.COMMAND);
|
|
921
953
|
}
|
|
954
|
+
// why: filler column ở cuối hấp thụ leftover space — opt-in qua option.filler.enabled.
|
|
955
|
+
// Khi bật, ngăn các cột utility (selection, index, command) bị table-layout auto stretch trên màn rộng.
|
|
956
|
+
if (option.filler?.enabled) {
|
|
957
|
+
result.firstHeaders.push(this.#COLUMNS.FILLER);
|
|
958
|
+
result.displayedColumns.push(this.#COLUMNS.FILLER);
|
|
959
|
+
}
|
|
922
960
|
result.multipleHeader = result.secondHeaders.length > 0;
|
|
923
|
-
// Sub infomation không thể có footer
|
|
924
|
-
result.displayedFooters = result.displayedColumns.filter(val => val !== this.#COLUMNS.SUBINFORMATION && val !== this.#COLUMNS.TREE_TOGGLE);
|
|
961
|
+
// Sub infomation không thể có footer; filler cũng không cần footer cell.
|
|
962
|
+
result.displayedFooters = result.displayedColumns.filter(val => val !== this.#COLUMNS.SUBINFORMATION && val !== this.#COLUMNS.TREE_TOGGLE && val !== this.#COLUMNS.FILLER);
|
|
963
|
+
if (option.filler?.enabled) {
|
|
964
|
+
// Footer cũng cần filler cuối để giữ width đồng bộ với data row
|
|
965
|
+
result.displayedFooters.push(this.#COLUMNS.FILLER);
|
|
966
|
+
}
|
|
925
967
|
if (option?.rowReorder?.enabled) {
|
|
926
968
|
result.displayedColumns.unshift(this.#COLUMNS.REORDER);
|
|
927
969
|
result.firstHeaders.unshift(this.#COLUMNS.REORDER);
|
|
@@ -1061,7 +1103,7 @@ class ConfigComponent {
|
|
|
1061
1103
|
this.dragDisabled = true;
|
|
1062
1104
|
}
|
|
1063
1105
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ConfigComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1064
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ConfigComponent, isStandalone: true, selector: "config", inputs: { tableOption: { classPropertyName: "tableOption", publicName: "tableOption", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { changes: "changes" }, providers: [ConfigService], viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true, isSignal: true }, { propertyName: "table", first: true, predicate: MatTable, descendants: true, isSignal: true }], ngImport: i0, template: "@let _configuration = configuration();\r\n\r\n<sd-modal width=\"sm\" [title]=\"'core.component.table.setup' | translate\" #modal>\r\n @if (_configuration) {\r\n <div class=\"c-container\">\r\n <div class=\"c-table\" style=\"max-height: 70vh\">\r\n <table\r\n mat-table\r\n [dataSource]=\"_configuration.columns!\"\r\n cdkDropList\r\n [cdkDropListData]=\"_configuration.columns\"\r\n (cdkDropListDropped)=\"dropTable($event)\">\r\n <ng-container matColumnDef=\"invisible\">\r\n <th mat-header-cell class=\"c-th text-center px-4\" *matHeaderCellDef style=\"width: 96px\">\r\n {{ 'core.component.form-builder.display' | translate }}\r\n </th>\r\n <td class=\"text-center px-4\" mat-cell *matCellDef=\"let item\">\r\n <div class=\"d-flex\" style=\"gap: 8px\">\r\n <div class=\"c-handle\" (mousedown)=\"handleMouseDown()\" (mouseup)=\"handleMouseUp()\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 0 24 24\" width=\"24px\" fill=\"#5f6368\">\r\n <path d=\"M0 0h24v24H0V0z\" fill=\"none\" />\r\n <path\r\n d=\"M11 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm-2-8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z\" />\r\n </svg>\r\n </div>\r\n <sd-switch [model]=\"!item.invisible\" (modelChange)=\"item.invisible = !item.invisible\" />\r\n </div>\r\n </td>\r\n </ng-container>\r\n <ng-container matColumnDef=\"title\">\r\n <th mat-header-cell class=\"c-th px-4\" *matHeaderCellDef>\r\n {{ 'core.component.table.column-header' | translate }}\r\n </th>\r\n <td class=\"px-4\" mat-cell *matCellDef=\"let item\">\r\n <sd-input class=\"pb-4\" [placeholder]=\"item?.origin?.title\" [(model)]=\"item.title\" hideInlineError></sd-input>\r\n </td>\r\n </ng-container>\r\n <ng-container matColumnDef=\"width\">\r\n <th mat-header-cell class=\"c-th px-4\" *matHeaderCellDef style=\"width: 80px\">\r\n {{ 'core.component.table.width' | translate }}\r\n </th>\r\n <td class=\"px-4\" mat-cell *matCellDef=\"let item\">\r\n <sd-input class=\"pb-4\" [placeholder]=\"item?.origin?.width\" [(model)]=\"item.width\" hideInlineError></sd-input>\r\n </td>\r\n </ng-container>\r\n <ng-container matColumnDef=\"fixed\">\r\n <th mat-header-cell class=\"c-th text-center px-4\" *matHeaderCellDef style=\"width: 80px\">\r\n {{ 'core.component.table.fixed' | translate }}\r\n </th>\r\n <td class=\"text-center px-4\" mat-cell *matCellDef=\"let item\">\r\n <sd-switch [(model)]=\"item.fixed\" />\r\n </td>\r\n </ng-container>\r\n\r\n <ng-container matColumnDef=\"truncate\">\r\n <th mat-header-cell class=\"c-th text-center px-4\" *matHeaderCellDef style=\"width: 100px\">\r\n {{ 'core.component.table.char-limit' | translate }}\r\n </th>\r\n <td class=\"text-center px-4\" mat-cell *matCellDef=\"let item\">\r\n <sd-switch [(model)]=\"item.truncate\" />\r\n </td>\r\n </ng-container>\r\n\r\n <tr mat-header-row *matHeaderRowDef=\"['invisible', 'title', 'width', 'fixed', 'truncate']; sticky: true\"></tr>\r\n <tr\r\n mat-row\r\n *matRowDef=\"let row; columns: ['invisible', 'title', 'width', 'fixed', 'truncate']\"\r\n cdkDrag\r\n [cdkDragData]=\"row\"\r\n cdkDragLockAxis=\"y\"\r\n [cdkDragDisabled]=\"dragDisabled\">\r\n </tr>\r\n </table>\r\n </div>\r\n </div>\r\n }\r\n <ng-container sdFooter>\r\n <sd-button class=\"mr-8\" (click)=\"close()\" [title]=\"'core.component.table.skip' | translate\" color=\"secondary\"> </sd-button>\r\n <sd-button class=\"mr-8\" (click)=\"onReset()\" [title]=\"'core.component.form-builder.default' | translate\" color=\"primary\"> </sd-button>\r\n <sd-button (click)=\"onSave()\" [title]=\"'core.component.table.apply' | translate\" type=\"fill\" color=\"primary\"> </sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n", styles: [".c-table{position:relative;overflow:auto}.c-table table{width:100%}.c-table .c-th{font-weight:500;font-size:14px;line-height:20px;color:#000}.c-container{position:relative;min-height:200px}.c-handle{color:#ccc;cursor:move}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i6.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "ngmodule", type: CdkTableModule }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i11.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i11.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "component", type: SdSwitch, selector: "sd-switch", inputs: ["autoId", "name", "form", "label", "color", "disabled", "viewed", "hideInlineError", "required", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
1106
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ConfigComponent, isStandalone: true, selector: "config", inputs: { tableOption: { classPropertyName: "tableOption", publicName: "tableOption", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { changes: "changes" }, providers: [ConfigService], viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true, isSignal: true }, { propertyName: "table", first: true, predicate: MatTable, descendants: true, isSignal: true }], ngImport: i0, template: "@let _configuration = configuration();\r\n\r\n<sd-modal width=\"sm\" [title]=\"'core.component.table.setup' | translate\" #modal>\r\n @if (_configuration) {\r\n <div class=\"c-container\">\r\n <div class=\"c-table\" style=\"max-height: 70vh\">\r\n <table\r\n mat-table\r\n [dataSource]=\"_configuration.columns!\"\r\n cdkDropList\r\n [cdkDropListData]=\"_configuration.columns\"\r\n (cdkDropListDropped)=\"dropTable($event)\">\r\n <ng-container matColumnDef=\"invisible\">\r\n <th mat-header-cell class=\"c-th text-center px-4\" *matHeaderCellDef style=\"width: 96px\">\r\n {{ 'core.component.form-builder.display' | translate }}\r\n </th>\r\n <td class=\"text-center px-4\" mat-cell *matCellDef=\"let item\">\r\n <div class=\"d-flex\" style=\"gap: 8px\">\r\n <div class=\"c-handle\" (mousedown)=\"handleMouseDown()\" (mouseup)=\"handleMouseUp()\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 0 24 24\" width=\"24px\" fill=\"#5f6368\">\r\n <path d=\"M0 0h24v24H0V0z\" fill=\"none\" />\r\n <path\r\n d=\"M11 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm-2-8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z\" />\r\n </svg>\r\n </div>\r\n <sd-switch [model]=\"!item.invisible\" (modelChange)=\"item.invisible = !item.invisible\" />\r\n </div>\r\n </td>\r\n </ng-container>\r\n <ng-container matColumnDef=\"title\">\r\n <th mat-header-cell class=\"c-th px-4\" *matHeaderCellDef>\r\n {{ 'core.component.table.column-header' | translate }}\r\n </th>\r\n <td class=\"px-4\" mat-cell *matCellDef=\"let item\">\r\n <sd-input class=\"pb-4\" [placeholder]=\"item?.origin?.title\" [(model)]=\"item.title\" hideInlineError></sd-input>\r\n </td>\r\n </ng-container>\r\n <ng-container matColumnDef=\"width\">\r\n <th mat-header-cell class=\"c-th px-4\" *matHeaderCellDef style=\"width: 80px\">\r\n {{ 'core.component.table.width' | translate }}\r\n </th>\r\n <td class=\"px-4\" mat-cell *matCellDef=\"let item\">\r\n <sd-input class=\"pb-4\" [placeholder]=\"item?.origin?.width\" [(model)]=\"item.width\" hideInlineError></sd-input>\r\n </td>\r\n </ng-container>\r\n <ng-container matColumnDef=\"fixed\">\r\n <th mat-header-cell class=\"c-th text-center px-4\" *matHeaderCellDef style=\"width: 80px\">\r\n {{ 'core.component.table.fixed' | translate }}\r\n </th>\r\n <td class=\"text-center px-4\" mat-cell *matCellDef=\"let item\">\r\n <sd-switch [(model)]=\"item.fixed\" />\r\n </td>\r\n </ng-container>\r\n\r\n <ng-container matColumnDef=\"truncate\">\r\n <th mat-header-cell class=\"c-th text-center px-4\" *matHeaderCellDef style=\"width: 100px\">\r\n {{ 'core.component.table.char-limit' | translate }}\r\n </th>\r\n <td class=\"text-center px-4\" mat-cell *matCellDef=\"let item\">\r\n <sd-switch [(model)]=\"item.truncate\" />\r\n </td>\r\n </ng-container>\r\n\r\n <tr mat-header-row *matHeaderRowDef=\"['invisible', 'title', 'width', 'fixed', 'truncate']; sticky: true\"></tr>\r\n <tr\r\n mat-row\r\n *matRowDef=\"let row; columns: ['invisible', 'title', 'width', 'fixed', 'truncate']\"\r\n cdkDrag\r\n [cdkDragData]=\"row\"\r\n cdkDragLockAxis=\"y\"\r\n [cdkDragDisabled]=\"dragDisabled\">\r\n </tr>\r\n </table>\r\n </div>\r\n </div>\r\n }\r\n <ng-container sdFooter>\r\n <sd-button class=\"mr-8\" (click)=\"close()\" [title]=\"'core.component.table.skip' | translate\" color=\"secondary\"> </sd-button>\r\n <sd-button class=\"mr-8\" (click)=\"onReset()\" [title]=\"'core.component.form-builder.default' | translate\" color=\"primary\"> </sd-button>\r\n <sd-button (click)=\"onSave()\" [title]=\"'core.component.table.apply' | translate\" type=\"fill\" color=\"primary\"> </sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n", styles: [".c-table{position:relative;overflow:auto}.c-table table{width:100%}.c-table .c-th{font-weight:500;font-size:14px;line-height:20px;color:#000}.c-container{position:relative;min-height:200px}.c-handle{color:#ccc;cursor:move}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i6.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "ngmodule", type: CdkTableModule }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i11.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i11.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "component", type: SdSwitch, selector: "sd-switch", inputs: ["autoId", "name", "form", "label", "color", "disabled", "viewed", "hideInlineError", "required", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
1065
1107
|
}
|
|
1066
1108
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ConfigComponent, decorators: [{
|
|
1067
1109
|
type: Component,
|
|
@@ -1150,7 +1192,7 @@ class DesktopCellComponent {
|
|
|
1150
1192
|
item = input.required();
|
|
1151
1193
|
cellDef = input.required({});
|
|
1152
1194
|
value = computed(() => {
|
|
1153
|
-
return
|
|
1195
|
+
return Utilities.getNestedValue(this.item()?.data, this.column()?.field);
|
|
1154
1196
|
});
|
|
1155
1197
|
key = computed(() => {
|
|
1156
1198
|
const data = this.item()?.data;
|
|
@@ -1415,7 +1457,7 @@ class SdPopupExport {
|
|
|
1415
1457
|
if (!this.exportOption?.key) {
|
|
1416
1458
|
return null;
|
|
1417
1459
|
}
|
|
1418
|
-
return
|
|
1460
|
+
return Utilities.hash({
|
|
1419
1461
|
prefix,
|
|
1420
1462
|
key: this.exportOption?.key,
|
|
1421
1463
|
});
|
|
@@ -1666,7 +1708,7 @@ class SdPopupExport {
|
|
|
1666
1708
|
return '';
|
|
1667
1709
|
};
|
|
1668
1710
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdPopupExport, deps: [{ token: i0.ChangeDetectorRef }, { token: i1$1.SdLoadingService }, { token: i1$1.SdExcelService }, { token: i1$1.SdNotifyService }, { token: i1$1.SdConfirmService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1669
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.21", type: SdPopupExport, isStandalone: true, selector: "sd-popup-export", inputs: { _tableOption: ["tableOption", "_tableOption"], configuration: "configuration" }, outputs: { export: "export" }, viewQueries: [{ propertyName: "modal", first: true, predicate: ["modal"], descendants: true }, { propertyName: "listGroups", first: true, predicate: ["listGroups"], descendants: true }], ngImport: i0, template: "<sd-modal width=\"907px\" [title]=\"'Exported template'\" #modal>\r\n <div class=\"row\">\r\n <div *ngIf=\"!files?.length\" class=\"col-12\">\r\n <div class=\"c-empty\">\r\n <img class=\"sd-image-data-empty\" alt=\"empty-image\" />\r\n <div class=\"T14R\">{{ 'There are no exported templates' }}</div>\r\n </div>\r\n </div>\r\n <ng-container *ngIf=\"files?.length\">\r\n <div class=\"col-12\">\r\n <div class=\"c-table\" style=\"max-height: 50vh\">\r\n <table mat-table [dataSource]=\"files\">\r\n <ng-container matColumnDef=\"stt\">\r\n <th mat-header-cell class=\"c-th text-center px-5\" *matHeaderCellDef style=\"width: 50px\">#</th>\r\n <td class=\"text-center px-5\" mat-cell *matCellDef=\"let item; let idx = index\">\r\n {{ idx + 1 }}\r\n </td>\r\n </ng-container>\r\n <ng-container matColumnDef=\"fileName\">\r\n <th mat-header-cell class=\"c-th px-5\" *matHeaderCellDef>\r\n {{ 'File name' }}\r\n </th>\r\n <td class=\"px-5\" mat-cell *matCellDef=\"let item\">\r\n {{ item.fileName }}\r\n </td>\r\n </ng-container>\r\n <ng-container matColumnDef=\"action\">\r\n <th mat-header-cell class=\"c-th px-5\" *matHeaderCellDef style=\"width: 80px\"></th>\r\n <td class=\"px-5\" mat-cell *matCellDef=\"let item\">\r\n <div class=\"d-flex\">\r\n <button mat-icon-button aria-label=\"delete\" (click)=\"removeFile(item)\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n <button mat-icon-button aria-label=\"download\" (click)=\"onExport(item)\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n </div>\r\n </td>\r\n </ng-container>\r\n <tr mat-header-row *matHeaderRowDef=\"['stt', 'fileName', 'action']; sticky: true\"></tr>\r\n <tr mat-row *matRowDef=\"let row; columns: ['stt', 'fileName', 'action']\"></tr>\r\n </table>\r\n </div>\r\n </div>\r\n <div *ngIf=\"files.length < 5\" class=\"col-12 mt-10\">\r\n <sd-button class=\"mr-4\" [title]=\"'New template'\" (click)=\"enableCreating = true\" color=\"info\" [disabled]=\"enableCreating\">\r\n </sd-button>\r\n <sd-button *ngIf=\"exportOption?.enableUpload\" [title]=\"'Upload template'\" (click)=\"uploadTemplate()\" type=\"outline\">\r\n </sd-button>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"enableCreating || !files?.length\">\r\n <div class=\"col-12 mt-20\">\r\n <div class=\"T14R\">{{ 'Select columns for creating template' }}:</div>\r\n </div>\r\n <div class=\"col-12\">\r\n <mat-chip-listbox selectable=\"true\" multiple=\"true\">\r\n <ng-container *ngFor=\"let column of columns\">\r\n <mat-chip-option [selected]=\"selected[column.field]\" (click)=\"selected[column.field] = !selected[column.field]\">\r\n {{ column.title }}\r\n </mat-chip-option>\r\n </ng-container>\r\n </mat-chip-listbox>\r\n </div>\r\n <div class=\"col-12 row\">\r\n <div class=\"col-10\">\r\n <sd-input [form]=\"form\" [label]=\"'Template name'\" [(model)]=\"templateName\" [validator]=\"templateNameValidator\"></sd-input>\r\n </div>\r\n <div class=\"col-2 mt-8\">\r\n <sd-button width=\"100%\" [title]=\"'Save'\" color=\"info\" (click)=\"createTemplate()\"> </sd-button>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n</sd-modal>\r\n", styles: [".c-radio-group{display:flex;flex-direction:column;margin:15px 0}.c-radio-button{margin:5px}.c-empty{display:flex;flex-direction:column;justify-content:center;align-items:center;position:static;height:116px;background:#f6f6f6;border-radius:4px}.c-table{position:relative;overflow:auto}.c-table table{width:100%}.c-table .c-th{font-weight:500;font-size:14px;line-height:20px;color:#000}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i6.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i5$1.MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { kind: "component", type: i5$1.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1711
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.21", type: SdPopupExport, isStandalone: true, selector: "sd-popup-export", inputs: { _tableOption: ["tableOption", "_tableOption"], configuration: "configuration" }, outputs: { export: "export" }, viewQueries: [{ propertyName: "modal", first: true, predicate: ["modal"], descendants: true }, { propertyName: "listGroups", first: true, predicate: ["listGroups"], descendants: true }], ngImport: i0, template: "<sd-modal width=\"907px\" [title]=\"'Exported template'\" #modal>\r\n <div class=\"row\">\r\n <div *ngIf=\"!files?.length\" class=\"col-12\">\r\n <div class=\"c-empty\">\r\n <img class=\"sd-image-data-empty\" alt=\"empty-image\" />\r\n <div class=\"T14R\">{{ 'There are no exported templates' }}</div>\r\n </div>\r\n </div>\r\n <ng-container *ngIf=\"files?.length\">\r\n <div class=\"col-12\">\r\n <div class=\"c-table\" style=\"max-height: 50vh\">\r\n <table mat-table [dataSource]=\"files\">\r\n <ng-container matColumnDef=\"stt\">\r\n <th mat-header-cell class=\"c-th text-center px-5\" *matHeaderCellDef style=\"width: 50px\">#</th>\r\n <td class=\"text-center px-5\" mat-cell *matCellDef=\"let item; let idx = index\">\r\n {{ idx + 1 }}\r\n </td>\r\n </ng-container>\r\n <ng-container matColumnDef=\"fileName\">\r\n <th mat-header-cell class=\"c-th px-5\" *matHeaderCellDef>\r\n {{ 'File name' }}\r\n </th>\r\n <td class=\"px-5\" mat-cell *matCellDef=\"let item\">\r\n {{ item.fileName }}\r\n </td>\r\n </ng-container>\r\n <ng-container matColumnDef=\"action\">\r\n <th mat-header-cell class=\"c-th px-5\" *matHeaderCellDef style=\"width: 80px\"></th>\r\n <td class=\"px-5\" mat-cell *matCellDef=\"let item\">\r\n <div class=\"d-flex\">\r\n <button mat-icon-button aria-label=\"delete\" (click)=\"removeFile(item)\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n <button mat-icon-button aria-label=\"download\" (click)=\"onExport(item)\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n </div>\r\n </td>\r\n </ng-container>\r\n <tr mat-header-row *matHeaderRowDef=\"['stt', 'fileName', 'action']; sticky: true\"></tr>\r\n <tr mat-row *matRowDef=\"let row; columns: ['stt', 'fileName', 'action']\"></tr>\r\n </table>\r\n </div>\r\n </div>\r\n <div *ngIf=\"files.length < 5\" class=\"col-12 mt-10\">\r\n <sd-button class=\"mr-4\" [title]=\"'New template'\" (click)=\"enableCreating = true\" color=\"info\" [disabled]=\"enableCreating\">\r\n </sd-button>\r\n <sd-button *ngIf=\"exportOption?.enableUpload\" [title]=\"'Upload template'\" (click)=\"uploadTemplate()\" type=\"outline\">\r\n </sd-button>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"enableCreating || !files?.length\">\r\n <div class=\"col-12 mt-20\">\r\n <div class=\"T14R\">{{ 'Select columns for creating template' }}:</div>\r\n </div>\r\n <div class=\"col-12\">\r\n <mat-chip-listbox selectable=\"true\" multiple=\"true\">\r\n <ng-container *ngFor=\"let column of columns\">\r\n <mat-chip-option [selected]=\"selected[column.field]\" (click)=\"selected[column.field] = !selected[column.field]\">\r\n {{ column.title }}\r\n </mat-chip-option>\r\n </ng-container>\r\n </mat-chip-listbox>\r\n </div>\r\n <div class=\"col-12 row\">\r\n <div class=\"col-10\">\r\n <sd-input [form]=\"form\" [label]=\"'Template name'\" [(model)]=\"templateName\" [validator]=\"templateNameValidator\"></sd-input>\r\n </div>\r\n <div class=\"col-2 mt-8\">\r\n <sd-button width=\"100%\" [title]=\"'Save'\" color=\"info\" (click)=\"createTemplate()\"> </sd-button>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n</sd-modal>\r\n", styles: [".c-radio-group{display:flex;flex-direction:column;margin:15px 0}.c-radio-button{margin:5px}.c-empty{display:flex;flex-direction:column;justify-content:center;align-items:center;position:static;height:116px;background:#f6f6f6;border-radius:4px}.c-table{position:relative;overflow:auto}.c-table table{width:100%}.c-table .c-th{font-weight:500;font-size:14px;line-height:20px;color:#000}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i6.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i5$1.MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { kind: "component", type: i5$1.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1670
1712
|
}
|
|
1671
1713
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdPopupExport, decorators: [{
|
|
1672
1714
|
type: Component,
|
|
@@ -1933,7 +1975,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
|
|
|
1933
1975
|
const MapToSdTableItem = (item) => ({
|
|
1934
1976
|
data: item,
|
|
1935
1977
|
meta: {
|
|
1936
|
-
id:
|
|
1978
|
+
id: Utilities.hash({ data: item }),
|
|
1937
1979
|
display: {},
|
|
1938
1980
|
expand: {
|
|
1939
1981
|
isExpanding: false,
|
|
@@ -1946,56 +1988,76 @@ const MapToSdTableItem = (item) => ({
|
|
|
1946
1988
|
});
|
|
1947
1989
|
|
|
1948
1990
|
class SdGroupPipe {
|
|
1949
|
-
|
|
1950
|
-
|
|
1991
|
+
/**
|
|
1992
|
+
* Nhóm items theo `option.group.fields`. Mỗi group sinh ra 1 synthetic SdTableItem
|
|
1993
|
+
* (group header) đặt trước children. Header có `meta.group.isGroupHeader = true` + `key`
|
|
1994
|
+
* + `values` + `items` + `isExpanded` để template + table consume.
|
|
1995
|
+
*
|
|
1996
|
+
* Khi `option.group.collapsible = true` + group đang collapse → children bị lọc khỏi output.
|
|
1997
|
+
*
|
|
1998
|
+
* `expandState` (optional, owned by component) — Map<key, expanded> giữ trạng thái
|
|
1999
|
+
* expand/collapse qua các lần transform. Pipe đọc state từ Map; nếu key chưa tồn tại,
|
|
2000
|
+
* dùng `!option.group.defaultCollapsed`. Pipe ghi state về Map cho lần read sau.
|
|
2001
|
+
*
|
|
2002
|
+
* @example
|
|
2003
|
+
* `_items | sdGroup: _tableOption : groupExpandState`
|
|
2004
|
+
*/
|
|
2005
|
+
transform(items, gridOption, expandState) {
|
|
2006
|
+
if (gridOption?.tree) {
|
|
1951
2007
|
if (typeof ngDevMode !== 'undefined' && ngDevMode && gridOption.group) {
|
|
1952
2008
|
console.warn('[sd-table] option.tree and option.group cannot be used together. group is ignored.');
|
|
1953
2009
|
}
|
|
1954
2010
|
return items;
|
|
1955
2011
|
}
|
|
1956
|
-
const
|
|
1957
|
-
if (!group)
|
|
2012
|
+
const group = gridOption?.group;
|
|
2013
|
+
if (!group?.fields?.length)
|
|
1958
2014
|
return items;
|
|
1959
|
-
|
|
1960
|
-
const
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
const
|
|
2015
|
+
const fields = group.fields;
|
|
2016
|
+
const collapsible = !!group.collapsible;
|
|
2017
|
+
const defaultExpanded = !group.defaultCollapsed;
|
|
2018
|
+
// Bucket items theo combined field-value hash.
|
|
2019
|
+
// Field hỗ trợ dot-notation (vd 'customer.id') — resolve qua getNestedValue.
|
|
2020
|
+
const buckets = new Map();
|
|
1965
2021
|
for (const item of items) {
|
|
1966
|
-
|
|
1967
|
-
for (const
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
2022
|
+
const values = {};
|
|
2023
|
+
for (const f of fields)
|
|
2024
|
+
values[f] = Utilities.getNestedValue(item.data, f);
|
|
2025
|
+
const key = Utilities.hash(values);
|
|
2026
|
+
let bucket = buckets.get(key);
|
|
2027
|
+
if (!bucket) {
|
|
2028
|
+
bucket = { values, items: [] };
|
|
2029
|
+
buckets.set(key, bucket);
|
|
1972
2030
|
}
|
|
1973
|
-
|
|
1974
|
-
if (!groupItem[key]) {
|
|
1975
|
-
groupItem[key] = [];
|
|
1976
|
-
}
|
|
1977
|
-
groupItem[key].push(item);
|
|
2031
|
+
bucket.items.push(item);
|
|
1978
2032
|
}
|
|
1979
|
-
const
|
|
1980
|
-
|
|
1981
|
-
const
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
2033
|
+
const result = [];
|
|
2034
|
+
buckets.forEach((bucket, key) => {
|
|
2035
|
+
const isExpanded = expandState?.has(key) ? !!expandState.get(key) : defaultExpanded;
|
|
2036
|
+
if (collapsible && expandState)
|
|
2037
|
+
expandState.set(key, isExpanded);
|
|
2038
|
+
const header = MapToSdTableItem({});
|
|
2039
|
+
header.meta.group = {
|
|
2040
|
+
isGroupHeader: true,
|
|
2041
|
+
key,
|
|
2042
|
+
values: bucket.values,
|
|
2043
|
+
items: bucket.items,
|
|
2044
|
+
isExpanded,
|
|
2045
|
+
};
|
|
2046
|
+
header.meta.selector.selectable = false;
|
|
2047
|
+
result.push(header);
|
|
2048
|
+
if (!collapsible || isExpanded) {
|
|
2049
|
+
for (const child of bucket.items)
|
|
2050
|
+
result.push(child);
|
|
1987
2051
|
}
|
|
1988
|
-
}
|
|
1989
|
-
return
|
|
2052
|
+
});
|
|
2053
|
+
return result;
|
|
1990
2054
|
}
|
|
1991
2055
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdGroupPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
1992
2056
|
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.21", ngImport: i0, type: SdGroupPipe, isStandalone: true, name: "sdGroup" });
|
|
1993
2057
|
}
|
|
1994
2058
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdGroupPipe, decorators: [{
|
|
1995
2059
|
type: Pipe,
|
|
1996
|
-
args: [{
|
|
1997
|
-
name: 'sdGroup',
|
|
1998
|
-
}]
|
|
2060
|
+
args: [{ name: 'sdGroup' }]
|
|
1999
2061
|
}] });
|
|
2000
2062
|
|
|
2001
2063
|
class SdSelectionDisabledPipe {
|
|
@@ -2021,7 +2083,7 @@ class SdSelectionDisabledPipe {
|
|
|
2021
2083
|
const availableActions = actions.filter(action => {
|
|
2022
2084
|
if ('children' in action) {
|
|
2023
2085
|
for (const childAction of action.children) {
|
|
2024
|
-
const key =
|
|
2086
|
+
const key = Utilities.hash(childAction);
|
|
2025
2087
|
if (selectedItems.every(e => e.meta.selector?.actions?.includes(key))) {
|
|
2026
2088
|
return true;
|
|
2027
2089
|
}
|
|
@@ -2029,7 +2091,7 @@ class SdSelectionDisabledPipe {
|
|
|
2029
2091
|
return false;
|
|
2030
2092
|
}
|
|
2031
2093
|
else {
|
|
2032
|
-
const key =
|
|
2094
|
+
const key = Utilities.hash(action);
|
|
2033
2095
|
return selectedItems.every(e => e.meta.selector?.actions?.includes(key));
|
|
2034
2096
|
}
|
|
2035
2097
|
});
|
|
@@ -2037,13 +2099,13 @@ class SdSelectionDisabledPipe {
|
|
|
2037
2099
|
for (const action of availableActions) {
|
|
2038
2100
|
if ('children' in action) {
|
|
2039
2101
|
for (const childAction of action.children) {
|
|
2040
|
-
if (rowData.meta.selector?.actions?.includes(
|
|
2102
|
+
if (rowData.meta.selector?.actions?.includes(Utilities.hash(childAction))) {
|
|
2041
2103
|
return false;
|
|
2042
2104
|
}
|
|
2043
2105
|
}
|
|
2044
2106
|
}
|
|
2045
2107
|
else {
|
|
2046
|
-
if (rowData.meta.selector?.actions?.includes(
|
|
2108
|
+
if (rowData.meta.selector?.actions?.includes(Utilities.hash(action))) {
|
|
2047
2109
|
return false;
|
|
2048
2110
|
}
|
|
2049
2111
|
}
|
|
@@ -2110,7 +2172,7 @@ class SdSelectionVisiblePipe {
|
|
|
2110
2172
|
let hasGroup = false;
|
|
2111
2173
|
for (const child of action.children) {
|
|
2112
2174
|
const { hidden, isGrouped } = child;
|
|
2113
|
-
const key =
|
|
2175
|
+
const key = Utilities.hash(child);
|
|
2114
2176
|
if (isGrouped) {
|
|
2115
2177
|
hasGroup = true;
|
|
2116
2178
|
}
|
|
@@ -2132,15 +2194,15 @@ class SdSelectionVisiblePipe {
|
|
|
2132
2194
|
}
|
|
2133
2195
|
}
|
|
2134
2196
|
if (flag) {
|
|
2135
|
-
rowData.meta.selector.actions.push(
|
|
2197
|
+
rowData.meta.selector.actions.push(Utilities.hash(action));
|
|
2136
2198
|
if (hasGroup) {
|
|
2137
|
-
groupedActions.push(
|
|
2199
|
+
groupedActions.push(Utilities.hash(action));
|
|
2138
2200
|
}
|
|
2139
2201
|
}
|
|
2140
2202
|
}
|
|
2141
2203
|
else {
|
|
2142
2204
|
const { hidden, isGrouped } = action;
|
|
2143
|
-
const key =
|
|
2205
|
+
const key = Utilities.hash(action);
|
|
2144
2206
|
if (typeof hidden === 'function') {
|
|
2145
2207
|
if (!hidden(rowData.data)) {
|
|
2146
2208
|
rowData.meta.selector.actions.push(key);
|
|
@@ -2252,11 +2314,11 @@ class TableExportService {
|
|
|
2252
2314
|
for (const item of exportItems) {
|
|
2253
2315
|
const obj = {};
|
|
2254
2316
|
const handle = async (exportColumn) => {
|
|
2255
|
-
obj[exportColumn.field] =
|
|
2317
|
+
obj[exportColumn.field] = Utilities.getNestedValue(item, exportColumn.field);
|
|
2256
2318
|
const column = allColumns.find(e => e.field === exportColumn.field);
|
|
2257
2319
|
const exportedColumn = allExportedColumns.find(e => e.field === exportColumn.field);
|
|
2258
2320
|
if (exportedColumn?.transform) {
|
|
2259
|
-
obj[exportedColumn.field] = exportedColumn.transform(
|
|
2321
|
+
obj[exportedColumn.field] = exportedColumn.transform(Utilities.getNestedValue(item, exportedColumn.field), item);
|
|
2260
2322
|
return;
|
|
2261
2323
|
}
|
|
2262
2324
|
if (!column)
|
|
@@ -2271,7 +2333,7 @@ class TableExportService {
|
|
|
2271
2333
|
}
|
|
2272
2334
|
if (!columns.some(e => e.field === column.field))
|
|
2273
2335
|
return;
|
|
2274
|
-
const itemValue =
|
|
2336
|
+
const itemValue = Utilities.getNestedValue(item, column.field);
|
|
2275
2337
|
const fieldStr = column.field;
|
|
2276
2338
|
if (column.transform) {
|
|
2277
2339
|
const transform = column.transform(itemValue, item, { isExport: true });
|
|
@@ -2451,8 +2513,8 @@ class TableFormatService {
|
|
|
2451
2513
|
const data = column.option.items();
|
|
2452
2514
|
cacheValues[column.field] = (Array.isArray(data) ? data : []).map(e => ({
|
|
2453
2515
|
...e,
|
|
2454
|
-
[column.option.valueField]:
|
|
2455
|
-
[column.option.displayField]:
|
|
2516
|
+
[column.option.valueField]: Utilities.getNestedValue(e, column.option.valueField),
|
|
2517
|
+
[column.option.displayField]: Utilities.getNestedValue(e, column.option.displayField),
|
|
2456
2518
|
}));
|
|
2457
2519
|
cacheObjValues[column.field] = ArrayUtilities.toObject(column.option.valueField, cacheValues[column.field]);
|
|
2458
2520
|
}
|
|
@@ -2471,8 +2533,8 @@ class TableFormatService {
|
|
|
2471
2533
|
else {
|
|
2472
2534
|
cacheValues[column.field] = column.option.items.map(e => ({
|
|
2473
2535
|
...e,
|
|
2474
|
-
[column.option.valueField]:
|
|
2475
|
-
[column.option.displayField]:
|
|
2536
|
+
[column.option.valueField]: Utilities.getNestedValue(e, column.option.valueField),
|
|
2537
|
+
[column.option.displayField]: Utilities.getNestedValue(e, column.option.displayField),
|
|
2476
2538
|
}));
|
|
2477
2539
|
cacheObjValues[column.field] = ArrayUtilities.toObject(column.option.valueField, cacheValues[column.field]);
|
|
2478
2540
|
}
|
|
@@ -2483,8 +2545,8 @@ class TableFormatService {
|
|
|
2483
2545
|
for (const result of results) {
|
|
2484
2546
|
cacheValues[result.key] = result.data.map(e => ({
|
|
2485
2547
|
...e,
|
|
2486
|
-
[result.valueField]:
|
|
2487
|
-
[result.displayField]:
|
|
2548
|
+
[result.valueField]: Utilities.getNestedValue(e, result.valueField),
|
|
2549
|
+
[result.displayField]: Utilities.getNestedValue(e, result.displayField),
|
|
2488
2550
|
}));
|
|
2489
2551
|
cacheObjValues[result.key] = ArrayUtilities.toObject(result.valueField, cacheValues[result.key]);
|
|
2490
2552
|
}
|
|
@@ -2503,7 +2565,7 @@ class TableFormatService {
|
|
|
2503
2565
|
const { option: { views, valueField, displayField }, } = column;
|
|
2504
2566
|
cacheObjValues[fieldStr] = cacheObjValues[fieldStr] || {};
|
|
2505
2567
|
const values = ArrayUtilities.distinct(items
|
|
2506
|
-
.map(item =>
|
|
2568
|
+
.map(item => Utilities.getNestedValue(item.data, fieldStr))
|
|
2507
2569
|
.filter(val => val?.toString())
|
|
2508
2570
|
.reduce((current, next) => [...current, ...(Array.isArray(next) ? next : [next])], [])
|
|
2509
2571
|
.filter(val => !Object.keys(cacheObjValues[fieldStr]).includes(val)));
|
|
@@ -2512,10 +2574,10 @@ class TableFormatService {
|
|
|
2512
2574
|
console.error(err);
|
|
2513
2575
|
return [];
|
|
2514
2576
|
}))
|
|
2515
|
-
.filter((item) => values.includes(
|
|
2577
|
+
.filter((item) => values.includes(Utilities.getNestedValue(item, valueField)))
|
|
2516
2578
|
.map((e) => ({
|
|
2517
|
-
[valueField]:
|
|
2518
|
-
[displayField]:
|
|
2579
|
+
[valueField]: Utilities.getNestedValue(e, valueField),
|
|
2580
|
+
[displayField]: Utilities.getNestedValue(e, displayField),
|
|
2519
2581
|
}));
|
|
2520
2582
|
Object.assign(cacheObjValues[fieldStr], ArrayUtilities.toObject(valueField, lazyItems) || {});
|
|
2521
2583
|
}
|
|
@@ -2523,7 +2585,7 @@ class TableFormatService {
|
|
|
2523
2585
|
// Format dữ liệu cho từng hàng
|
|
2524
2586
|
for (const item of items) {
|
|
2525
2587
|
const rowData = item.data;
|
|
2526
|
-
const value =
|
|
2588
|
+
const value = Utilities.getNestedValue(rowData, fieldStr);
|
|
2527
2589
|
item.meta.display[fieldStr] = {
|
|
2528
2590
|
badge: undefined,
|
|
2529
2591
|
cellStyle: column.align === 'right' ? { 'text-align': 'right!important' } : undefined,
|
|
@@ -2571,7 +2633,7 @@ class TableFormatService {
|
|
|
2571
2633
|
}
|
|
2572
2634
|
}
|
|
2573
2635
|
if (display.data === null || display.data === undefined || display.data === '') {
|
|
2574
|
-
display.data =
|
|
2636
|
+
display.data = EMPTY_STR;
|
|
2575
2637
|
display.badge = undefined;
|
|
2576
2638
|
}
|
|
2577
2639
|
}
|
|
@@ -2667,7 +2729,7 @@ class SdTableFilterService {
|
|
|
2667
2729
|
register = (filter, args) => {
|
|
2668
2730
|
let cacheSession = false;
|
|
2669
2731
|
const { id, columns, externalFilters } = args;
|
|
2670
|
-
const tempKey =
|
|
2732
|
+
const tempKey = Utilities.hash({
|
|
2671
2733
|
id,
|
|
2672
2734
|
columns: columns?.map(e => e.field).filter(field => !!field) || [],
|
|
2673
2735
|
externalFilters: externalFilters?.map(e => e.field).filter(field => !!field) || [],
|
|
@@ -2917,6 +2979,7 @@ class SdTable extends SdBaseSecureComponent {
|
|
|
2917
2979
|
paginator = viewChild(MatPaginator);
|
|
2918
2980
|
sort = viewChild(MatSort);
|
|
2919
2981
|
sdSubInformation = contentChild(SdTableExpandDefDirective);
|
|
2982
|
+
sdGroupDef = contentChild(SdTableGroupDefDirective);
|
|
2920
2983
|
sdCellDefs = contentChildren(SdTableCellDefDirective);
|
|
2921
2984
|
sdFooterDefs = contentChildren(SdMaterialFooterDefDirective);
|
|
2922
2985
|
sdFilterDefs = contentChildren(SdTableFilterDefDirective);
|
|
@@ -3167,7 +3230,7 @@ class SdTable extends SdBaseSecureComponent {
|
|
|
3167
3230
|
const { field, type } = column;
|
|
3168
3231
|
const filterValue = (rawColumnFilter[field] || '').toString().trim().toLowerCase();
|
|
3169
3232
|
// SỬA: Dùng getNestedValue để hỗ trợ nested field trong filterLocal
|
|
3170
|
-
const rawColVal =
|
|
3233
|
+
const rawColVal = Utilities.getNestedValue(item, field);
|
|
3171
3234
|
const columnValue = (rawColVal || '').toString().trim().toLowerCase();
|
|
3172
3235
|
if (filterValue) {
|
|
3173
3236
|
if (!columnValue && type !== 'datetime' && type !== 'date' && type !== 'time') {
|
|
@@ -3182,7 +3245,7 @@ class SdTable extends SdBaseSecureComponent {
|
|
|
3182
3245
|
const columnType = column;
|
|
3183
3246
|
const isMultiple = columnType.option.selection === 'MULTIPLE';
|
|
3184
3247
|
if (isMultiple && Array.isArray(rawColVal)) {
|
|
3185
|
-
const columnValues = rawColVal.map((i) => (
|
|
3248
|
+
const columnValues = rawColVal.map((i) => (Utilities.getNestedValue(i, columnType.option.valueField) ?? '').toString().trim().toLowerCase()) ?? [];
|
|
3186
3249
|
const filterValues = rawColumnFilter[field]?.map((v) => (v ?? '').toString().trim().toLowerCase());
|
|
3187
3250
|
if (filterValues?.length && filterValues.every(fv => !columnValues.includes(fv))) {
|
|
3188
3251
|
return false;
|
|
@@ -3259,8 +3322,8 @@ class SdTable extends SdBaseSecureComponent {
|
|
|
3259
3322
|
const data = tableItemCurrent.data;
|
|
3260
3323
|
const next = tableItemNext.data;
|
|
3261
3324
|
// SỬA: Dùng getNestedValue cho sorting
|
|
3262
|
-
const dataVal =
|
|
3263
|
-
const nextVal =
|
|
3325
|
+
const dataVal = Utilities.getNestedValue(data, field);
|
|
3326
|
+
const nextVal = Utilities.getNestedValue(next, field);
|
|
3264
3327
|
if (type === 'number') {
|
|
3265
3328
|
return (dataVal || 0) - (nextVal || 0);
|
|
3266
3329
|
}
|
|
@@ -3427,6 +3490,9 @@ class SdTable extends SdBaseSecureComponent {
|
|
|
3427
3490
|
await this.#expandDefaultBranches(this.items(), treeOpt);
|
|
3428
3491
|
this.treeRevision.update(n => n + 1);
|
|
3429
3492
|
}
|
|
3493
|
+
// Restore selection từ preservedSelectedMap (chỉ khi preserveSelection bật).
|
|
3494
|
+
// Phải chạy TRƯỚC applyDefaultSelected để user-selection ưu tiên hơn default.
|
|
3495
|
+
this.#restorePreservedSelection();
|
|
3430
3496
|
// Áp dụng defaultSelected: pre-select các item thỏa predicate
|
|
3431
3497
|
this.#applyDefaultSelected();
|
|
3432
3498
|
await this.tableOption()?.reload?.onReload?.(this.items(), additionArgs);
|
|
@@ -3674,6 +3740,12 @@ class SdTable extends SdBaseSecureComponent {
|
|
|
3674
3740
|
this.#getSelectionRows()
|
|
3675
3741
|
.filter(e => e !== rowData)
|
|
3676
3742
|
.forEach(e => (e.meta.selector.isSelected = false));
|
|
3743
|
+
// single + preserve: chỉ giữ MỘT item trong map (item vừa chọn nếu isSelected,
|
|
3744
|
+
// hoặc empty nếu vừa bỏ chọn). Off-page items có thể đã ở trong map → xoá hết
|
|
3745
|
+
// trước khi #updateSelectedItems sync entry mới.
|
|
3746
|
+
if (this.#preserveEnabled()) {
|
|
3747
|
+
this.#preservedSelectedMap.clear();
|
|
3748
|
+
}
|
|
3677
3749
|
opt.selector?.onSelect?.(rowData.data, selectedData());
|
|
3678
3750
|
this.isSelectAll.set(false);
|
|
3679
3751
|
this.#updateSelectedItems();
|
|
@@ -3699,6 +3771,10 @@ class SdTable extends SdBaseSecureComponent {
|
|
|
3699
3771
|
items = items || this.items();
|
|
3700
3772
|
this.isSelectAll.set(false);
|
|
3701
3773
|
items?.forEach(e => (e.meta.selector.isSelected = false));
|
|
3774
|
+
// User explicit X — clear toàn bộ preserved map (bao gồm cả off-page items).
|
|
3775
|
+
if (this.#preserveEnabled()) {
|
|
3776
|
+
this.#preservedSelectedMap.clear();
|
|
3777
|
+
}
|
|
3702
3778
|
this.#updateSelectedItems();
|
|
3703
3779
|
};
|
|
3704
3780
|
#getSelectionRows = () => {
|
|
@@ -3725,6 +3801,83 @@ class SdTable extends SdBaseSecureComponent {
|
|
|
3725
3801
|
const visible = this.#getSelectionRows();
|
|
3726
3802
|
this.isSelectAll.set(visible.length > 0 && visible.every(e => e.meta.selector?.isSelected));
|
|
3727
3803
|
};
|
|
3804
|
+
// ==========================================
|
|
3805
|
+
// GROUP HELPERS — sync selection + expand state cho group header rows
|
|
3806
|
+
// ==========================================
|
|
3807
|
+
/** Children selectable của 1 group header (lọc bỏ children không selectable). */
|
|
3808
|
+
#groupSelectableChildren = (header) => {
|
|
3809
|
+
const children = header.meta.group?.items || [];
|
|
3810
|
+
return children.filter(c => c.meta.selector?.selectable !== false);
|
|
3811
|
+
};
|
|
3812
|
+
/** true nếu MỌI selectable child trong group đều selected. Group rỗng (không child) → false. */
|
|
3813
|
+
isGroupAllSelected = (header) => {
|
|
3814
|
+
const sel = this.#groupSelectableChildren(header);
|
|
3815
|
+
return sel.length > 0 && sel.every(c => c.meta.selector.isSelected);
|
|
3816
|
+
};
|
|
3817
|
+
/** true nếu CÓ MỘT VÀI selectable child selected nhưng KHÔNG phải tất cả. */
|
|
3818
|
+
isGroupIndeterminate = (header) => {
|
|
3819
|
+
const sel = this.#groupSelectableChildren(header);
|
|
3820
|
+
if (sel.length === 0)
|
|
3821
|
+
return false;
|
|
3822
|
+
const some = sel.some(c => c.meta.selector.isSelected);
|
|
3823
|
+
const all = sel.every(c => c.meta.selector.isSelected);
|
|
3824
|
+
return some && !all;
|
|
3825
|
+
};
|
|
3826
|
+
/** Toggle select-all cho 1 group: set isSelected cho mọi selectable child, sync state. */
|
|
3827
|
+
onSelectGroup = (header, checked) => {
|
|
3828
|
+
const sel = this.#groupSelectableChildren(header);
|
|
3829
|
+
sel.forEach(c => (c.meta.selector.isSelected = checked));
|
|
3830
|
+
const opt = this.tableOption();
|
|
3831
|
+
opt?.selector?.onSelectAll?.(this.#getSelectedRowData());
|
|
3832
|
+
this.#syncSelectAllState();
|
|
3833
|
+
this.#updateSelectedItems();
|
|
3834
|
+
};
|
|
3835
|
+
// Map<groupKey, isExpanded> — table own state, pass vào SdGroupPipe arg 3.
|
|
3836
|
+
// why: pipe stateless, persist toggle qua các lần re-eval bằng Map external. Mutate Map
|
|
3837
|
+
// KHÔNG tự re-trigger pipe (default pure: true) — gọi items.update để invalidate input.
|
|
3838
|
+
groupExpandState = new Map();
|
|
3839
|
+
/** Toggle expand/collapse cho 1 group (chỉ ý nghĩa khi option.group.collapsible). */
|
|
3840
|
+
toggleGroupExpand = (header) => {
|
|
3841
|
+
if (!header.meta.group?.key)
|
|
3842
|
+
return;
|
|
3843
|
+
const key = header.meta.group.key;
|
|
3844
|
+
const defaultExpanded = !this.tableOption()?.group?.defaultCollapsed;
|
|
3845
|
+
const current = this.groupExpandState.has(key)
|
|
3846
|
+
? !!this.groupExpandState.get(key)
|
|
3847
|
+
: defaultExpanded;
|
|
3848
|
+
this.groupExpandState.set(key, !current);
|
|
3849
|
+
header.meta.group.isExpanded = !current;
|
|
3850
|
+
// why: trigger pipe re-eval — Map mutation không thay đổi reference items() nên cần update.
|
|
3851
|
+
this.items.update(arr => [...arr]);
|
|
3852
|
+
};
|
|
3853
|
+
/**
|
|
3854
|
+
* Predicate cho matRowDef.when — phân biệt group header row vs data row.
|
|
3855
|
+
* Group header row dùng matRowDef riêng với column list ['sdGroupHeader'] (1 cell duy nhất).
|
|
3856
|
+
* Data row dùng displayedColumns nguyên vẹn.
|
|
3857
|
+
*/
|
|
3858
|
+
isGroupHeaderRow = (_idx, row) => row?.meta?.group?.isGroupHeader === true;
|
|
3859
|
+
isDataRow = (_idx, row) => row?.meta?.group?.isGroupHeader !== true;
|
|
3860
|
+
/**
|
|
3861
|
+
* Colspan cho cell sdGroupHeader trên group row = displayedColumns.length.
|
|
3862
|
+
* Span TOÀN BỘ width data row vì group row chỉ có 1 cell.
|
|
3863
|
+
*/
|
|
3864
|
+
sdGroupColspan = computed(() => (this.configuration()?.displayedColumns?.length || 1));
|
|
3865
|
+
/** Build context object truyền vào SdTableGroupDefDirective template. */
|
|
3866
|
+
groupContext = (header) => {
|
|
3867
|
+
const g = header.meta.group;
|
|
3868
|
+
const items = g?.items || [];
|
|
3869
|
+
return {
|
|
3870
|
+
items,
|
|
3871
|
+
data: items.map(i => i.data),
|
|
3872
|
+
key: g?.key || '',
|
|
3873
|
+
values: g?.values || {},
|
|
3874
|
+
isExpanded: g?.isExpanded ?? true,
|
|
3875
|
+
isSelected: this.isGroupAllSelected(header),
|
|
3876
|
+
indeterminate: this.isGroupIndeterminate(header),
|
|
3877
|
+
toggleExpand: () => this.toggleGroupExpand(header),
|
|
3878
|
+
toggleSelect: () => this.onSelectGroup(header, !this.isGroupAllSelected(header)),
|
|
3879
|
+
};
|
|
3880
|
+
};
|
|
3728
3881
|
rowStyle = (row, index) => {
|
|
3729
3882
|
const fn = this.tableOption()?.style?.rowCss;
|
|
3730
3883
|
if (!fn)
|
|
@@ -3735,8 +3888,44 @@ class SdTable extends SdBaseSecureComponent {
|
|
|
3735
3888
|
: undefined;
|
|
3736
3889
|
return fn(row.data, index, ctx);
|
|
3737
3890
|
};
|
|
3891
|
+
// why: khi preserveSelection bật, giữ map nội bộ id → SdTableItem để selection
|
|
3892
|
+
// không mất qua filter / paginate / sort / reload (kể cả server re-fetch tạo refs mới).
|
|
3893
|
+
// Map chỉ bị clear khi user gọi onClearSelection (nút X) hoặc bỏ chọn từng item.
|
|
3894
|
+
#preservedSelectedMap = new Map();
|
|
3895
|
+
#preserveEnabled = () => this.tableOption()?.selector?.preserveSelection === true;
|
|
3896
|
+
// Restore isSelected cho item visible nào id đã có trong preserved map.
|
|
3897
|
+
// Đồng thời update reference trong map sang SdTableItem mới (cần thiết khi server
|
|
3898
|
+
// re-fetch tạo refs mới, ta muốn map giữ ref hiện hành để các tham chiếu downstream OK).
|
|
3899
|
+
#restorePreservedSelection = () => {
|
|
3900
|
+
if (!this.#preserveEnabled())
|
|
3901
|
+
return;
|
|
3902
|
+
const rows = this.#getSelectionRows();
|
|
3903
|
+
rows.forEach(item => {
|
|
3904
|
+
if (this.#preservedSelectedMap.has(item.meta.id)) {
|
|
3905
|
+
item.meta.selector.isSelected = true;
|
|
3906
|
+
this.#preservedSelectedMap.set(item.meta.id, item);
|
|
3907
|
+
}
|
|
3908
|
+
});
|
|
3909
|
+
};
|
|
3738
3910
|
#updateSelectedItems = () => {
|
|
3739
|
-
this
|
|
3911
|
+
const rows = this.#getSelectionRows();
|
|
3912
|
+
if (this.#preserveEnabled()) {
|
|
3913
|
+
// Sync map theo state visible: add nếu selected, remove nếu deselected.
|
|
3914
|
+
// Off-page items giữ nguyên trong map (không bị visit ở đây).
|
|
3915
|
+
rows.forEach(item => {
|
|
3916
|
+
const id = item.meta.id;
|
|
3917
|
+
if (item.meta.selector.isSelected) {
|
|
3918
|
+
this.#preservedSelectedMap.set(id, item);
|
|
3919
|
+
}
|
|
3920
|
+
else {
|
|
3921
|
+
this.#preservedSelectedMap.delete(id);
|
|
3922
|
+
}
|
|
3923
|
+
});
|
|
3924
|
+
this.selectedTableItems.set(Array.from(this.#preservedSelectedMap.values()));
|
|
3925
|
+
}
|
|
3926
|
+
else {
|
|
3927
|
+
this.selectedTableItems.set(rows.filter(item => item.meta.selector.isSelected));
|
|
3928
|
+
}
|
|
3740
3929
|
this.#ref.detectChanges();
|
|
3741
3930
|
};
|
|
3742
3931
|
clearFilter = () => {
|
|
@@ -4082,7 +4271,7 @@ class SdTable extends SdBaseSecureComponent {
|
|
|
4082
4271
|
provide: MatPaginatorIntl,
|
|
4083
4272
|
useClass: MatPaginatorIntlCro,
|
|
4084
4273
|
},
|
|
4085
|
-
], queries: [{ propertyName: "sdSubInformation", first: true, predicate: SdTableExpandDefDirective, descendants: true, isSignal: true }, { propertyName: "sdCellDefs", predicate: SdTableCellDefDirective, isSignal: true }, { propertyName: "sdFooterDefs", predicate: SdMaterialFooterDefDirective, isSignal: true }, { propertyName: "sdFilterDefs", predicate: SdTableFilterDefDirective, isSignal: true }, { propertyName: "sdTitleDefs", predicate: SdTableTitleDefDirective, isSignal: true }], viewQueries: [{ propertyName: "table", first: true, predicate: MatTable, descendants: true, isSignal: true }, { propertyName: "configComponent", first: true, predicate: ConfigComponent, descendants: true, isSignal: true }, { propertyName: "sdPopupExport", first: true, predicate: SdPopupExport, descendants: true, isSignal: true }, { propertyName: "scroll", first: true, predicate: SdScrollDirective, descendants: true, isSignal: true }, { propertyName: "quickAction", first: true, predicate: SdQuickAction, descendants: true, isSignal: true }, { propertyName: "externalFilter", first: true, predicate: ExternalFilterComponent, descendants: true, isSignal: true }, { propertyName: "mobileFilter", first: true, predicate: MobileFilterComponent, descendants: true, isSignal: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true, isSignal: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@let _configuration = configuration();\r\n@let _tableOption = tableOption()!;\r\n@let _loading = loading();\r\n@let _items = items();\r\n@let _total = total();\r\n@let _isFiltered = isFiltered();\r\n@let _requireFiltered = requireFiltered();\r\n@let _export = _tableOption?.export;\r\n@let _exporting = exporting();\r\n@let _titleDef = titleDef();\r\n\r\n@if (_configuration) {\r\n @if (!_tableOption.filter?.disabled && !!_tableOption.filter?.externalFilters?.length && filterRegister) {\r\n <external-filter\r\n class=\"mb-16\"\r\n [autoId]=\"autoId()\"\r\n [filterRegister]=\"filterRegister\"\r\n [filter]=\"_tableOption.filter!\"\r\n [externalFilters]=\"_tableOption.filter?.externalFilters!\">\r\n </external-filter>\r\n }\r\n @let groupedItems = _items | sdTree: _tableOption.tree : treeRevision() | sdGroup: _tableOption;\r\n <ng-content select=\"[sdTableTop]\"></ng-content>\r\n <div class=\"c-container\">\r\n @if (_loading) {\r\n <div class=\"c-loading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n }\r\n <div\r\n class=\"c-table\"\r\n sdScroll\r\n stickyShadow\r\n [style.max-height]=\"_tableOption.style?.maxHeight\"\r\n [style.min-height]=\"_tableOption.style?.minHeight\">\r\n <table\r\n mat-table\r\n [dataSource]=\"groupedItems\"\r\n [trackBy]=\"trackBy\"\r\n matSort\r\n [matSortDisabled]=\"!_tableOption.sort?.enable\"\r\n multiTemplateDataRows\r\n cdkDropList\r\n [cdkDropListData]=\"groupedItems\"\r\n [cdkDropListDisabled]=\"!_tableOption.rowReorder?.enabled\"\r\n [cdkDropListSortPredicate]=\"reorderSortPredicate\"\r\n (cdkDropListDropped)=\"onReorderDrop($event)\">\r\n @if (_tableOption.rowReorder?.enabled) {\r\n <ng-container matColumnDef=\"sdReorder\">\r\n <th mat-header-cell *matHeaderCellDef class=\"sd-reorder-header\" [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td mat-cell *matCellDef=\"let row\" class=\"sd-reorder-cell\">\r\n @if (!row.meta?.group?.items?.length) {\r\n <mat-icon cdkDragHandle [class.sd-reorder-disabled]=\"isReorderDisabled(row)\">\r\n {{ _tableOption.rowReorder?.icon || 'drag_indicator' }}\r\n </mat-icon>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n\r\n @if (_tableOption.tree) {\r\n <ng-container matColumnDef=\"sdTreeToggle\">\r\n <th\r\n mat-header-cell\r\n *matHeaderCellDef\r\n class=\"sd-tree-toggle-cell p-0\"\r\n [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td mat-cell *matCellDef=\"let row\" class=\"sd-tree-toggle-cell p-0\">\r\n @if (row.meta?.tree) {\r\n <div\r\n class=\"sd-tree-toggle-inner\"\r\n [style.padding-left.px]=\"(row.meta.tree.level ?? 0) * (_tableOption.tree?.indentSize ?? 20)\">\r\n @if (row.meta.tree.hasChildren) {\r\n @if (row.meta.tree.isExpanding) {\r\n <div class=\"lds-ring sd-tree-spinner\">\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n </div>\r\n } @else {\r\n <sd-button\r\n type=\"link\"\r\n [prefixIcon]=\"row.meta.tree.isExpanded ? 'expand_less' : 'expand_more'\"\r\n (click)=\"onTreeToggle(row); $event.stopPropagation()\"\r\n width=\"35px\">\r\n </sd-button>\r\n }\r\n }\r\n </div>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n\r\n <ng-container matColumnDef=\"sdSubInformation\" sticky>\r\n <td class=\"p-0\" mat-cell *matCellDef=\"let item\" [attr.colspan]=\"_configuration.displayedColumns.length\">\r\n @if (sdSubInformation()?.templateRef) {\r\n @if (_tableOption.expand?.always) {\r\n <ng-container *ngTemplateOutlet=\"sdSubInformation()?.templateRef!; context: { item: item }\"> </ng-container>\r\n } @else {\r\n <div [@detailExpand]=\"item.isExpanded ? 'expanded' : 'collapsed'\">\r\n @if (item.isExpanded) {\r\n <ng-container *ngTemplateOutlet=\"sdSubInformation()?.templateRef!; context: { item: item }\"> </ng-container>\r\n }\r\n </div>\r\n }\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n\r\n <ng-container matColumnDef=\"sdSubInformationAction\" stickyEnd>\r\n <th class=\"p-0\" mat-header-cell *matHeaderCellDef style=\"width: 1px\" [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td mat-cell *matCellDef=\"let element\">\r\n @if (!element.isExpanding && !_tableOption.expand?.always) {\r\n <sd-button\r\n type=\"link\"\r\n [prefixIcon]=\"element.isExpanded ? 'expand_less' : 'expand_more'\"\r\n (click)=\"onExpand(element)\"\r\n width=\"35px\">\r\n </sd-button>\r\n }\r\n @if (element.isExpanding) {\r\n <div class=\"lds-ring\">\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n </div>\r\n }\r\n </td>\r\n </ng-container>\r\n\r\n <ng-container matColumnDef=\"sdSelection\" sticky>\r\n <th class=\"sd-selection-cell p-0\" mat-header-cell *matHeaderCellDef [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\">\r\n @let visibleSelectAll = _items | selectionVisibleSelectAll: _tableOption.selector | async;\r\n @if (visibleSelectAll) {\r\n <mat-checkbox\r\n class=\"c-selection px-8\"\r\n color=\"primary\"\r\n [ngModel]=\"isSelectAll()\"\r\n (ngModelChange)=\"isSelectAll.set($event)\"\r\n (change)=\"onSelectAll()\">\r\n </mat-checkbox>\r\n }\r\n </th>\r\n\r\n <td class=\"sd-selection-cell p-0\" mat-cell *matCellDef=\"let item\">\r\n @let visible = item | selectionVisible: _tableOption.selector;\r\n @if (visible) {\r\n @if (_tableOption.selector?.single) {\r\n <mat-radio-button\r\n class=\"c-selection px-8\"\r\n color=\"primary\"\r\n [checked]=\"item.meta.selector.isSelected\"\r\n (change)=\"item.meta.selector.isSelected = true; onSelect(item)\"\r\n [disabled]=\"selectedTableItems() | selectionDisabled: item : _tableOption.selector!\">\r\n </mat-radio-button>\r\n } @else {\r\n <mat-checkbox\r\n class=\"c-selection px-8\"\r\n color=\"primary\"\r\n [(ngModel)]=\"item.meta.selector.isSelected\"\r\n (change)=\"onSelect(item)\"\r\n [disabled]=\"selectedTableItems() | selectionDisabled: item : _tableOption.selector!\">\r\n </mat-checkbox>\r\n }\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n @if (_tableOption.index?.enabled) {\r\n @let _pageOffset = pageOffset();\r\n <ng-container matColumnDef=\"sdIndex\" sticky>\r\n <th\r\n class=\"text-center p-0\"\r\n mat-header-cell\r\n *matHeaderCellDef\r\n [style.width]=\"_tableOption.index?.width || '50px'\"\r\n [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\">\r\n {{ _tableOption.index?.title || '#' }}\r\n </th>\r\n <td class=\"text-center px-4\" mat-cell *matCellDef=\"let item; let i = index\">\r\n @if (!item?.sdGroup) {\r\n {{ _pageOffset + i + 1 }}\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n <ng-container\r\n matColumnDef=\"sdCommand\"\r\n [sticky]=\"_tableOption.command?.align !== 'right'\"\r\n [stickyEnd]=\"_tableOption.command?.align === 'right'\">\r\n <th class=\"p-0\" mat-header-cell *matHeaderCellDef style=\"width: 50px\" [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td class=\"px-8\" mat-cell *matCellDef=\"let item\">\r\n <desktop-command\r\n [autoId]=\"autoId()\"\r\n [commands]=\"_tableOption.command?.commands || _tableOption.commands || []\"\r\n [item]=\"item\"\r\n [itemIndex]=\"groupedItems.indexOf(item)\"></desktop-command>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n <ng-container matColumnDef=\"sdGroup\">\r\n <th mat-header-cell *matHeaderCellDef class=\"px-8 py-8\" [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td class=\"p-0\" mat-cell *matCellDef=\"let item\" [attr.colspan]=\"!item?.sdGroup ? 1 : _configuration.displayedColumns.length\">\r\n <div [innerHtml]=\"item?.sdGroup?.htmlTemplate | sdSafeHtml\"></div>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n @for (column of _configuration.firstColumns; track column.field) {\r\n <ng-container [matColumnDef]=\"column.field\" [sticky]=\"_configuration.fixedColumn[column.field]\">\r\n <th\r\n mat-header-cell\r\n *matHeaderCellDef\r\n class=\"px-8 py-8 c-th\"\r\n [sdColumnResize]=\"!!_tableOption.config?.resizable && column.type !== 'children'\"\r\n [minWidth]=\"column.minWidth\"\r\n [maxWidth]=\"column.maxWidth\"\r\n (resizeEnd)=\"onColumnResize(column.field, $event)\"\r\n [style.width]=\"column.width\"\r\n [style.min-width]=\"column.minWidth || column.width\"\r\n [style.max-width]=\"column.maxWidth\"\r\n [attr.rowspan]=\"_configuration.multipleHeader && column.type !== 'children' ? 2 : 1\"\r\n [attr.colspan]=\"column.type === 'children' ? column.children.length : 1\">\r\n <div>\r\n @if (column.type === 'children') {\r\n <div\r\n aria-hidden=\"true\"\r\n class=\"c-header-title\"\r\n [class.justify-content-end]=\"column.align === 'right'\"\r\n [class.text-right]=\"column.align === 'right'\">\r\n <column-title [column]=\"column\" [titleDef]=\"_titleDef[column.field]\"></column-title>\r\n </div>\r\n } @else {\r\n <div\r\n aria-hidden=\"true\"\r\n mat-sort-header\r\n class=\"c-header-title\"\r\n [class.justify-content-end]=\"column.align === 'right'\"\r\n [class.text-right]=\"column.align === 'right'\"\r\n [disabled]=\"!column.sortable\">\r\n <column-title [column]=\"column\" [titleDef]=\"_titleDef[column.field]\"></column-title>\r\n </div>\r\n @let hideInlineFilter =\r\n _tableOption.filter?.disabled ||\r\n _tableOption.filter?.hideInlineFilter === true ||\r\n (_tableOption.filter?.hideInlineFilter === 'auto' && !_isFiltered && _total! <= 10);\r\n @if (!hideInlineFilter) {\r\n <ng-container *sdDesktop>\r\n <column-filter\r\n [autoId]=\"autoId()\"\r\n [value]=\"columnFilter?.[column.field!]!\"\r\n [operator]=\"columnOperator[column.field]\"\r\n (operatorChange)=\"columnOperator[column.field] = $event!; onOperatorChange(column, $event)\"\r\n [columnFilter]=\"columnFilter!\"\r\n [cacheValues]=\"cacheValues\"\r\n [column]=\"column\"\r\n (filterChange)=\"onFilterChange()\"\r\n (filterCommit)=\"onFilterCommit()\">\r\n </column-filter>\r\n </ng-container>\r\n }\r\n }\r\n </div>\r\n </th>\r\n <td\r\n class=\"c-td px-0\"\r\n [class.d-none]=\"column.type === 'children'\"\r\n mat-cell\r\n *matCellDef=\"let item\"\r\n [sdHoverCopy]=\"(item.data && item.data[column.field]) || ''\"\r\n [sdHoverCopyDisabled]=\"!column.cell?.copiable\">\r\n @if (column.type !== 'children' && !item?.sdGroup) {\r\n <desktop-cell class=\"d-block px-8\" [column]=\"column\" [item]=\"item\" [cellDef]=\"cellDef()\"> </desktop-cell>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef>\r\n <ng-container *ngIf=\"footerDef()[column.field]\">\r\n <ng-container *ngTemplateOutlet=\"footerDef()[column.field].templateRef; context: { items: _items, column: column }\">\r\n </ng-container>\r\n </ng-container>\r\n </td>\r\n </ng-container>\r\n }\r\n @for (column of _configuration.secondColumns; track column.field) {\r\n <ng-container [matColumnDef]=\"column.field\">\r\n <th\r\n mat-header-cell\r\n *matHeaderCellDef\r\n class=\"c-th px-8\"\r\n [style.width]=\"column.width\"\r\n [style.min-width]=\"column.minWidth || column.width\"\r\n [style.max-width]=\"column.maxWidth\">\r\n <div>\r\n <div\r\n aria-hidden=\"true\"\r\n mat-sort-header\r\n class=\"c-header-title\"\r\n [class.justify-content-end]=\"column.align === 'right'\"\r\n [class.text-right]=\"column.align === 'right'\"\r\n [disabled]=\"!column.sortable\">\r\n <column-title [column]=\"column\" [titleDef]=\"_titleDef[column.field]\"></column-title>\r\n </div>\r\n @if (!_tableOption.filter?.disabled && !_tableOption.filter?.hideInlineFilter && columnOperator) {\r\n <ng-container *sdDesktop>\r\n <column-filter\r\n [autoId]=\"autoId()\"\r\n [value]=\"columnFilter?.[column.field!]!\"\r\n [operator]=\"columnOperator[column.field]\"\r\n [columnFilter]=\"columnFilter!\"\r\n [cacheValues]=\"cacheValues\"\r\n [column]=\"column\"\r\n (operatorChange)=\"columnOperator[column.field] = $event!; onOperatorChange(column, $event)\"\r\n (filterChange)=\"onFilterChange()\"\r\n (filterCommit)=\"onFilterCommit()\">\r\n </column-filter>\r\n </ng-container>\r\n }\r\n </div>\r\n </th>\r\n <td\r\n class=\"c-td px-0\"\r\n mat-cell\r\n *matCellDef=\"let item\"\r\n [sdHoverCopy]=\"item[column.field]\"\r\n [sdHoverCopyDisabled]=\"!column.cell?.copiable\">\r\n @if (column.type !== 'children') {\r\n <desktop-cell class=\"d-block px-8\" [column]=\"column\" [item]=\"item\" [cellDef]=\"cellDef()\"> </desktop-cell>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef>\r\n <ng-container *ngIf=\"footerDef()[column.field]\">\r\n <ng-container *ngTemplateOutlet=\"footerDef()[column.field].templateRef; context: { items: _items, column: column }\">\r\n </ng-container>\r\n </ng-container>\r\n </td>\r\n </ng-container>\r\n }\r\n <tr class=\"c-first-header\" mat-header-row *matHeaderRowDef=\"_configuration.firstHeaders; sticky: true\"></tr>\r\n @if (!!_configuration.secondHeaders.length) {\r\n <tr class=\"c-second-header\" mat-header-row *matHeaderRowDef=\"_configuration.secondHeaders; sticky: true\"></tr>\r\n }\r\n <tr\r\n mat-row\r\n cdkDrag\r\n [cdkDragData]=\"row\"\r\n [cdkDragDisabled]=\"\r\n !_tableOption.rowReorder?.enabled ||\r\n !!row.meta?.group?.items?.length ||\r\n (row.meta?.tree?.level ?? 0) > 0 ||\r\n isReorderDisabled(row)\r\n \"\r\n *matRowDef=\"let row; columns: _configuration.displayedColumns\"\r\n matRipple\r\n class=\"c-row\"\r\n [class.sd-tree-row]=\"!!_tableOption.tree\"\r\n [ngClass]=\"_tableOption.tree ? 'sd-tree-level-' + (row.meta?.tree?.level ?? 0) : null\"\r\n [ngStyle]=\"rowStyle(row)\"\r\n [class.selected]=\"row.meta.selector.isSelected\"></tr>\r\n\r\n <tr mat-row *matRowDef=\"let row; columns: ['sdSubInformation']\" class=\"c-detail-row\"></tr>\r\n @if (hasFooter() && !!_configuration.displayedFooters.length) {\r\n <tr mat-footer-row *matFooterRowDef=\"_configuration.displayedFooters; sticky: true\"></tr>\r\n }\r\n </table>\r\n @if (!_loading && !_total) {\r\n <div class=\"c-no-data-row\">\r\n @if (_isFiltered) {\r\n @if (tableConfiguration?.images?.filterEmpty) {\r\n <img class=\"c-image\" [src]=\"tableConfiguration!.images!.filterEmpty\" alt=\"filter-empty\" />\r\n } @else {\r\n <img class=\"c-image sd-image-filter-empty\" alt=\"filter-empty\" />\r\n }\r\n <div class=\"T16M\">{{ 'core.component.table.no-results' | translate }}</div>\r\n <div class=\"T16R text-secondary\">{{ 'core.component.table.no-results-hint' | translate }}</div>\r\n } @else {\r\n @if (_requireFiltered) {\r\n @if (tableConfiguration?.images?.filterRequired) {\r\n <img class=\"c-image\" [src]=\"tableConfiguration!.images!.filterRequired\" alt=\"filter-required\" />\r\n } @else {\r\n <img class=\"c-image sd-image-filter-required\" alt=\"filter-required\" />\r\n }\r\n <div class=\"T16R text-secondary\">{{ 'core.component.table.choose-filter-hint' | translate }}</div>\r\n } @else {\r\n @if (tableConfiguration?.images?.dataEmpty) {\r\n <img class=\"c-image\" [src]=\"tableConfiguration!.images!.dataEmpty\" alt=\"data-empty\" />\r\n } @else {\r\n <img class=\"c-image sd-image-data-empty\" alt=\"data-empty\" />\r\n }\r\n <div class=\"T16R text-secondary\">{{ 'core.component.table.no-data' | translate }}</div>\r\n }\r\n }\r\n </div>\r\n }\r\n </div>\r\n <div class=\"c-paginator\">\r\n <div class=\"c-action\">\r\n <ng-container *sdDesktop>\r\n @if (_tableOption.reload?.visible) {\r\n <sd-button\r\n class=\"mr-8\"\r\n [title]=\"'core.component.table.reload' | translate\"\r\n prefixIcon=\"refresh\"\r\n (click)=\"reload()\"\r\n [disabled]=\"!_items.length\"\r\n type=\"link\">\r\n </sd-button>\r\n }\r\n </ng-container>\r\n @if (_export && _items.length) {\r\n @if (_export.type === 'custom') {\r\n <sd-button class=\"mr-8\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" (click)=\"exportCustom()\" type=\"link\"> </sd-button>\r\n } @else {\r\n @if (_export.visible) {\r\n @if (_exporting) {\r\n <sd-button class=\"mr-8\" [loading]=\"_exporting\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" type=\"link\"> </sd-button>\r\n } @else {\r\n @if (_export.visible === 'ALL' || !_export.visible) {\r\n <sd-button class=\"mr-8\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" [matMenuTriggerFor]=\"menu\" type=\"link\"> </sd-button>\r\n <mat-menu #menu=\"matMenu\">\r\n <button mat-menu-item (click)=\"exportExcel()\" type=\"button\">\r\n <mat-icon fontSet=\"material-icons-outlined\">file_download</mat-icon>\r\n <span> {{ 'core.component.table.export-excel' | translate }}</span>\r\n </button>\r\n <button mat-menu-item (click)=\"exportCSV()\" type=\"button\">\r\n <mat-icon fontSet=\"material-icons-outlined\">file_download</mat-icon>\r\n <span> {{ 'core.component.table.export-csv' | translate }}</span>\r\n </button>\r\n </mat-menu>\r\n } @else if (_export.visible === 'EXCEL') {\r\n <sd-button class=\"mr-8\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" (click)=\"exportExcel()\" type=\"link\"> </sd-button>\r\n } @else if (_export.visible === 'CSV') {\r\n <sd-button class=\"mr-8\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" (click)=\"exportCSV()\" type=\"link\"> </sd-button>\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n <ng-container *sdDesktop>\r\n @if (configComponent()) {\r\n <sd-button\r\n class=\"mr-8\"\r\n [title]=\"'core.component.table.setup-short' | translate\"\r\n prefixIcon=\"settings\"\r\n (click)=\"configComponent()!.open()\"\r\n type=\"link\">\r\n </sd-button>\r\n }\r\n </ng-container>\r\n <!-- Mobile: n\u00FAt Filter m\u1EDF mobile-filter drawer (inline filter \u1EA9n tr\u00EAn mobile) -->\r\n <ng-container *sdMobile>\r\n @if (!_tableOption.filter?.disabled && mobileFilter()) {\r\n <sd-button\r\n [autoId]=\"autoId() + 'mobile-filter-open'\"\r\n class=\"mr-8\"\r\n prefixIcon=\"filter_alt\"\r\n (click)=\"mobileFilter()!.open()\"\r\n type=\"link\">\r\n </sd-button>\r\n }\r\n </ng-container>\r\n </div>\r\n @let hidePaginator = !_tableOption.paginate?.pageSize || _total === undefined || _total <= _tableOption.paginate?.pageSize!;\r\n <!-- Desktop paginator: full config (pageSize dropdown, first/last buttons) -->\r\n <ng-container *sdDesktop>\r\n <mat-paginator\r\n [class.d-none]=\"_tableOption.paginate?.hidden || hidePaginator\"\r\n [length]=\"_total\"\r\n [pageSize]=\"_tableOption.paginate?.pageSize\"\r\n [pageSizeOptions]=\"_tableOption.paginate?.pages!\"\r\n [showFirstLastButtons]=\"_tableOption.paginate?.showFirstLastButtons\"\r\n [hidePageSize]=\"_tableOption.paginate?.hidePageSize\"></mat-paginator>\r\n </ng-container>\r\n <!-- Mobile paginator: \u1EA9n pageSize dropdown + first/last buttons \u0111\u1EC3 ti\u1EBFt ki\u1EC7m kh\u00F4ng gian -->\r\n <ng-container *sdMobile>\r\n <mat-paginator\r\n [class.d-none]=\"_tableOption.paginate?.hidden || hidePaginator\"\r\n [length]=\"_total\"\r\n [pageSize]=\"_tableOption.paginate?.pageSize\"\r\n [showFirstLastButtons]=\"false\"\r\n hidePageSize></mat-paginator>\r\n </ng-container>\r\n <!-- \"\u0110ang hi\u1EC3n th\u1ECB...\" ch\u1EC9 desktop -->\r\n <ng-container *sdDesktop>\r\n @if (!_tableOption.paginate?.hidden && hidePaginator && _total !== undefined && _total > 0) {\r\n <div class=\"T14R pr-16\">\r\n {{ 'core.component.table.showing' | translate }} <span class=\"T14M ml-2\">1-{{ _total }}/{{ _total }}</span>\r\n </div>\r\n }\r\n </ng-container>\r\n </div>\r\n </div>\r\n <selector-action [tableOption]=\"_tableOption\" [selectedTableItems]=\"selectedTableItems()\" (clear)=\"onClearSelection(groupedItems)\" />\r\n @if (_tableOption.config?.visible) {\r\n <config [tableOption]=\"_tableOption\" />\r\n }\r\n <!-- Mobile filter drawer \u2014 ch\u1EC9 instantiate khi c\u1EA7n render tr\u00EAn mobile -->\r\n @if (!_tableOption.filter?.disabled && filterRegister) {\r\n <mobile-filter\r\n [autoId]=\"autoId()\"\r\n [filter]=\"_tableOption.filter!\"\r\n [externalFilters]=\"_tableOption.filter?.externalFilters!\"\r\n [columns]=\"_configuration.firstColumns\"\r\n [filterDefs]=\"sdFilterDefs()\"\r\n [filterRegister]=\"filterRegister\"\r\n [cacheValues]=\"cacheValues\">\r\n </mobile-filter>\r\n }\r\n}\r\n", styles: [":host{display:flex;flex-direction:column;overflow:auto;width:100%;height:100%}:host .c-header-title{height:40px;display:flex;align-items:center}:host .c-container{position:relative;min-height:50px;display:flex;flex-direction:column;flex:1}:host .c-container .c-table{position:relative;flex:1;display:flex;flex-direction:column}:host .c-container .c-table table{border-collapse:separate;width:100%}:host .c-container .c-table table tr.c-first-header.mat-mdc-header-row{height:40px}:host .c-container .c-table table tr.c-second-header.mat-mdc-header-row{height:40px}:host .c-container .c-table table tr.c-detail-row{height:0}:host .c-container .c-table table tr.c-row.activated{background-color:#e5ecff}:host .c-container .c-table table tr.c-row.selected{background-color:#eef2ff}:host .c-container .c-table table tr.c-row:not(.selected):not(.activated):hover{background-color:#f5f5f5}:host .c-container .c-table table tr.c-row td{border-bottom-width:0}:host .c-container .c-table table tr.c-row.c-expandable{cursor:pointer}:host .c-container .c-table table tr.c-row.c-expandable:hover{background:#f5f5f5}:host .c-container .c-table table th.mat-mdc-header-cell{background-color:#f2f3f4;border-bottom:0!important}:host .c-container .c-table table td.mat-mdc-cell,:host .c-container .c-table table td.mat-mdc-footer-cell,:host .c-container .c-table table th.mat-mdc-header-cell{border-bottom-color:#f2f2f2!important}:host .c-container .c-table .c-th{vertical-align:middle;font-weight:500;font-size:14px;line-height:20px;color:#212121}:host .c-container .c-table .c-th.sd-col-resize-host{position:relative}:host .c-container .c-table .c-th.sd-resizing{-webkit-user-select:none;user-select:none}:host .c-container .c-table .c-th .sd-col-resize-handle{position:absolute;top:0;right:0;width:6px;height:100%;cursor:col-resize;-webkit-user-select:none;user-select:none;z-index:2}:host .c-container .c-table .c-th .sd-col-resize-handle:hover{background:#00000014}:host .c-container .c-table .c-td:first{padding-left:10px}:host .c-container .c-table .c-no-data-row{flex:1;width:100%;position:sticky;left:0;display:flex;flex-direction:column;align-items:center;justify-content:center}:host .c-container .c-table .c-no-data-row .c-image{margin-bottom:16px;width:96px}:host .c-container .c-loading{position:absolute;inset:0 0 56px;background:#00000026;z-index:2;display:flex;align-items:center;justify-content:center}:host .c-container .c-paginator{display:flex;flex-direction:row;justify-content:space-between;align-items:center;background-color:#fff}:host .c-container .c-paginator .c-action{padding:5px}:host .c-container .c-empty{text-align:center;background-color:#fff;border:none!important}:host .c-container .c-empty mat-icon{font-size:150px;margin-top:30px;margin-bottom:30px;opacity:.2;width:auto;height:auto}:host button.c-btn-add{background-color:#fff;box-shadow:0 2px 4px #2f313629}:host .lds-ring{display:inline-block;position:relative;width:40px;height:40px}:host .lds-ring div{box-sizing:border-box;display:block;position:absolute;width:32px;height:32px;margin:4px;border:4px solid #cef;border-radius:50%;animation:lds-ring 1.2s cubic-bezier(.5,0,.5,1) infinite;border-color:#cef transparent transparent transparent}:host .lds-ring div:nth-child(1){animation-delay:-.45s}:host .lds-ring div:nth-child(2){animation-delay:-.3s}:host .lds-ring div:nth-child(3){animation-delay:-.15s}@keyframes lds-ring{0%{transform:rotate(0)}to{transform:rotate(360deg)}}:host .sd-reorder-header,:host .sd-reorder-cell{width:40px;min-width:40px;padding:0 4px;box-sizing:border-box}:host .sd-reorder-cell mat-icon{cursor:grab;color:#00000061;display:flex;align-items:center}:host .sd-reorder-cell mat-icon:active{cursor:grabbing}:host .sd-reorder-cell mat-icon.sd-reorder-disabled{opacity:.3;cursor:not-allowed;pointer-events:none}:host ::ng-deep .mat-sort-header-content{display:block;text-align:left;width:100%}:host ::ng-deep .mat-select-arrow{color:#a6a6a6}:host ::ng-deep .mat-sort-header-disabled{background-image:none!important;cursor:default!important;padding-right:0!important}:host ::ng-deep .mat-sort-header-container{align-items:start!important}:host ::ng-deep .mat-sort-header-arrow{margin-top:4px!important}:host ::ng-deep .mat-sort-header-arrow{display:none!important}:host ::ng-deep .mat-sort-header{cursor:pointer}:host ::ng-deep .mat-sort-header[aria-sort]{background-repeat:no-repeat;background-position:center right 0;background-size:16px 16px;cursor:pointer;padding-right:24px}:host ::ng-deep .mat-sort-header[aria-sort=none]{background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 0 24 24' width='24px' fill='%23000000'%3E%3Cpath d='M0 0h24v24H0V0z' fill='none'/%3E%3Cpath fill='%237A7A7A' d='M12 5.83L15.17 9l1.41-1.41L12 3 7.41 7.59 8.83 9 12 5.83zm0 12.34L8.83 15l-1.41 1.41L12 21l4.59-4.59L15.17 15 12 18.17z'/%3E%3C/svg%3E\")}:host ::ng-deep .mat-sort-header[aria-sort=ascending]{background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 0 24 24' width='24px' fill='%23000000'%3E%3Cpath d='M0 0h24v24H0V0z' fill='none'/%3E%3Cpath fill='%237A7A7A' d='M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z'/%3E%3C/svg%3E\")}:host ::ng-deep .mat-sort-header[aria-sort=descending]{background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 0 24 24' width='24px' fill='%23000000'%3E%3Cpath d='M0 0h24v24H0V0z' fill='none'/%3E%3Cpath fill='%237A7A7A' d='M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z'/%3E%3C/svg%3E\")}:host ::ng-deep .c-paginator .mat-mdc-paginator .mdc-text-field--outlined .mat-mdc-form-field-infix,:host ::ng-deep .c-paginator .mat-mdc-paginator .mdc-text-field--no-label .mat-mdc-form-field-infix{padding-top:2px;padding-bottom:2px;min-height:32px}:host ::ng-deep .c-paginator .mat-mdc-paginator-range-label{margin:0 4px}:host ::ng-deep .c-paginator .mat-mdc-paginator-page-size-select mat-select{margin-top:2px!important}:host ::ng-deep .cdk-drag-preview{box-shadow:0 4px 12px #00000026;background:#fff;display:table;width:100%}:host ::ng-deep .cdk-drag-preview td{padding:0 8px;border-bottom:1px solid rgba(0,0,0,.12)}:host ::ng-deep .cdk-drag-placeholder{opacity:0}:host ::ng-deep .cdk-drop-list-dragging tr.c-row:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}:host ::ng-deep .sd-selection-cell{width:42px;min-width:42px;max-width:42px}:host ::ng-deep .c-selection{transform:scale(.85);transform-origin:center}:host ::ng-deep .sd-tree-toggle-cell{width:40px;min-width:40px;max-width:100px}:host ::ng-deep .sd-tree-toggle-inner{display:flex;align-items:center;min-height:40px}:host ::ng-deep .sd-tree-spinner{transform:scale(.5);margin:0 auto}\n", ":host ::ng-deep .sticky-shadow-right{overflow:visible!important}:host ::ng-deep .sticky-shadow-right:after{content:\"\";position:absolute;top:0;right:0;bottom:0;width:8px;transform:translate(100%);background:linear-gradient(to right,rgba(0,0,0,.12),transparent);pointer-events:none}:host ::ng-deep .sticky-shadow-left{overflow:visible!important}:host ::ng-deep .sticky-shadow-left:after{content:\"\";position:absolute;top:0;left:0;bottom:0;width:8px;transform:translate(-100%);background:linear-gradient(to left,rgba(0,0,0,.12),transparent);pointer-events:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i2.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i4$1.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i6.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i6.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i6.MatFooterRowDef, selector: "[matFooterRowDef]", inputs: ["matFooterRowDef", "matFooterRowDefSticky"] }, { kind: "directive", type: i6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i6.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: i6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i6.MatFooterRow, selector: "mat-footer-row, tr[mat-footer-row]", exportAs: ["matFooterRow"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i7.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i7.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i8.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatRadioModule }, { kind: "component", type: i10.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i11.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i11.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i11.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: DesktopCommand, selector: "desktop-command", inputs: ["autoId", "item", "itemIndex", "commands"] }, { kind: "component", type: DesktopCellComponent, selector: "desktop-cell", inputs: ["column", "item", "cellDef"] }, { kind: "component", type: ColumnTitleComponent, selector: "column-title", inputs: ["column", "titleDef"] }, { kind: "component", type: ExternalFilterComponent, selector: "external-filter", inputs: ["autoId", "filter", "externalFilters", "filterRegister"] }, { kind: "component", type: ConfigComponent, selector: "config", inputs: ["tableOption"], outputs: ["changes"] }, { kind: "component", type: ColumnFilterComponent, selector: "column-filter", inputs: ["autoId", "column", "columnFilter", "cacheValues", "value", "operator", "isMobile"], outputs: ["operatorChange", "filterChange", "filterCommit"] }, { kind: "component", type: MobileFilterComponent, selector: "mobile-filter", inputs: ["autoId", "filter", "externalFilters", "columns", "filterDefs", "filterRegister", "cacheValues"] }, { kind: "pipe", type: SdGroupPipe, name: "sdGroup" }, { kind: "pipe", type: SdTreePipe, name: "sdTree" }, { kind: "pipe", type: SdSelectionVisiblePipe, name: "selectionVisible" }, { kind: "pipe", type: SdSelectionVisibleSelectAllPipe, name: "selectionVisibleSelectAll" }, { kind: "pipe", type: SdSafeHtmlPipe, name: "sdSafeHtml" }, { kind: "pipe", type: SdSelectionDisabledPipe, name: "selectionDisabled" }, { kind: "directive", type: SdScrollDirective, selector: "[sdScroll]" }, { kind: "directive", type: SdDesktopDirective, selector: "[sdDesktop]" }, { kind: "directive", type: SdMobileDirective, selector: "[sdMobile]" }, { kind: "directive", type: SdHoverCopyDirective, selector: "[sdHoverCopy]", inputs: ["sdHoverCopy", "sdHoverCopyDisabled"] }, { kind: "component", type: SelectorActionComponent, selector: "selector-action", inputs: ["tableOption", "selectedTableItems"], outputs: ["clear"] }, { kind: "directive", type: StickyShadowDirective, selector: "[stickyShadow]" }, { kind: "directive", type: SdColumnResizeDirective, selector: "[sdColumnResize]", inputs: ["sdColumnResize", "minWidth", "maxWidth"], outputs: ["resizeEnd"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], animations: [
|
|
4274
|
+
], queries: [{ propertyName: "sdSubInformation", first: true, predicate: SdTableExpandDefDirective, descendants: true, isSignal: true }, { propertyName: "sdGroupDef", first: true, predicate: SdTableGroupDefDirective, descendants: true, isSignal: true }, { propertyName: "sdCellDefs", predicate: SdTableCellDefDirective, isSignal: true }, { propertyName: "sdFooterDefs", predicate: SdMaterialFooterDefDirective, isSignal: true }, { propertyName: "sdFilterDefs", predicate: SdTableFilterDefDirective, isSignal: true }, { propertyName: "sdTitleDefs", predicate: SdTableTitleDefDirective, isSignal: true }], viewQueries: [{ propertyName: "table", first: true, predicate: MatTable, descendants: true, isSignal: true }, { propertyName: "configComponent", first: true, predicate: ConfigComponent, descendants: true, isSignal: true }, { propertyName: "sdPopupExport", first: true, predicate: SdPopupExport, descendants: true, isSignal: true }, { propertyName: "scroll", first: true, predicate: SdScrollDirective, descendants: true, isSignal: true }, { propertyName: "quickAction", first: true, predicate: SdQuickAction, descendants: true, isSignal: true }, { propertyName: "externalFilter", first: true, predicate: ExternalFilterComponent, descendants: true, isSignal: true }, { propertyName: "mobileFilter", first: true, predicate: MobileFilterComponent, descendants: true, isSignal: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true, isSignal: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@let _configuration = configuration();\r\n@let _tableOption = tableOption()!;\r\n@let _loading = loading();\r\n@let _items = items();\r\n@let _total = total();\r\n@let _isFiltered = isFiltered();\r\n@let _requireFiltered = requireFiltered();\r\n@let _export = _tableOption?.export;\r\n@let _exporting = exporting();\r\n@let _titleDef = titleDef();\r\n\r\n@if (_configuration) {\r\n @if (!_tableOption.filter?.disabled && !!_tableOption.filter?.externalFilters?.length && filterRegister) {\r\n <external-filter\r\n class=\"mb-16\"\r\n [autoId]=\"autoId()\"\r\n [filterRegister]=\"filterRegister\"\r\n [filter]=\"_tableOption.filter!\"\r\n [externalFilters]=\"_tableOption.filter?.externalFilters!\">\r\n </external-filter>\r\n }\r\n @let groupedItems = _items | sdTree: _tableOption.tree : treeRevision() | sdGroup: _tableOption : groupExpandState;\r\n <ng-content select=\"[sdTableTop]\"></ng-content>\r\n <div class=\"c-container\">\r\n @if (_loading) {\r\n <div class=\"c-loading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n }\r\n <div\r\n class=\"c-table\"\r\n sdScroll\r\n stickyShadow\r\n [style.max-height]=\"_tableOption.style?.maxHeight\"\r\n [style.min-height]=\"_tableOption.style?.minHeight\">\r\n <table\r\n mat-table\r\n [dataSource]=\"groupedItems\"\r\n [trackBy]=\"trackBy\"\r\n matSort\r\n [matSortDisabled]=\"!_tableOption.sort?.enable\"\r\n multiTemplateDataRows\r\n cdkDropList\r\n [cdkDropListData]=\"groupedItems\"\r\n [cdkDropListDisabled]=\"!_tableOption.rowReorder?.enabled\"\r\n [cdkDropListSortPredicate]=\"reorderSortPredicate\"\r\n (cdkDropListDropped)=\"onReorderDrop($event)\">\r\n @if (_tableOption.rowReorder?.enabled) {\r\n <ng-container matColumnDef=\"sdReorder\">\r\n <th mat-header-cell *matHeaderCellDef class=\"sd-reorder-header\" [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td mat-cell *matCellDef=\"let row\" class=\"sd-reorder-cell\">\r\n @if (!row.meta?.group?.items?.length) {\r\n <mat-icon cdkDragHandle [class.sd-reorder-disabled]=\"isReorderDisabled(row)\">\r\n {{ _tableOption.rowReorder?.icon || 'drag_indicator' }}\r\n </mat-icon>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n\r\n @if (_tableOption.tree) {\r\n <ng-container matColumnDef=\"sdTreeToggle\">\r\n <th\r\n mat-header-cell\r\n *matHeaderCellDef\r\n class=\"sd-tree-toggle-cell p-0\"\r\n [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td mat-cell *matCellDef=\"let row\" class=\"sd-tree-toggle-cell p-0\">\r\n @if (row.meta?.tree) {\r\n <div\r\n class=\"sd-tree-toggle-inner\"\r\n [style.padding-left.px]=\"(row.meta.tree.level ?? 0) * (_tableOption.tree?.indentSize ?? 20)\">\r\n @if (row.meta.tree.hasChildren) {\r\n @if (row.meta.tree.isExpanding) {\r\n <div class=\"lds-ring sd-tree-spinner\">\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n </div>\r\n } @else {\r\n <sd-button\r\n type=\"link\"\r\n [prefixIcon]=\"row.meta.tree.isExpanded ? 'expand_less' : 'expand_more'\"\r\n (click)=\"onTreeToggle(row); $event.stopPropagation()\"\r\n width=\"35px\">\r\n </sd-button>\r\n }\r\n }\r\n </div>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n\r\n <ng-container matColumnDef=\"sdSubInformation\" sticky>\r\n <td class=\"p-0\" mat-cell *matCellDef=\"let item\" [attr.colspan]=\"_configuration.displayedColumns.length\">\r\n @if (sdSubInformation()?.templateRef) {\r\n @if (_tableOption.expand?.always) {\r\n <ng-container *ngTemplateOutlet=\"sdSubInformation()?.templateRef!; context: { item: item }\"> </ng-container>\r\n } @else {\r\n <div [@detailExpand]=\"item.isExpanded ? 'expanded' : 'collapsed'\">\r\n @if (item.isExpanded) {\r\n <ng-container *ngTemplateOutlet=\"sdSubInformation()?.templateRef!; context: { item: item }\"> </ng-container>\r\n }\r\n </div>\r\n }\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n\r\n <ng-container matColumnDef=\"sdSubInformationAction\" stickyEnd>\r\n <th class=\"p-0\" mat-header-cell *matHeaderCellDef style=\"width: 1px\" [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td mat-cell *matCellDef=\"let element\">\r\n @if (!element.isExpanding && !_tableOption.expand?.always) {\r\n <sd-button\r\n type=\"link\"\r\n [prefixIcon]=\"element.isExpanded ? 'expand_less' : 'expand_more'\"\r\n (click)=\"onExpand(element)\"\r\n width=\"35px\">\r\n </sd-button>\r\n }\r\n @if (element.isExpanding) {\r\n <div class=\"lds-ring\">\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n </div>\r\n }\r\n </td>\r\n </ng-container>\r\n\r\n <ng-container matColumnDef=\"sdSelection\" sticky>\r\n <th class=\"sd-selection-cell p-0\" mat-header-cell *matHeaderCellDef [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\">\r\n @let visibleSelectAll = _items | selectionVisibleSelectAll: _tableOption.selector | async;\r\n @if (visibleSelectAll) {\r\n <mat-checkbox\r\n class=\"c-selection px-8\"\r\n color=\"primary\"\r\n [ngModel]=\"isSelectAll()\"\r\n (ngModelChange)=\"isSelectAll.set($event)\"\r\n (change)=\"onSelectAll()\">\r\n </mat-checkbox>\r\n }\r\n </th>\r\n\r\n <td class=\"sd-selection-cell p-0\" mat-cell *matCellDef=\"let item\">\r\n @let visible = item | selectionVisible: _tableOption.selector;\r\n @if (visible) {\r\n @if (_tableOption.selector?.single) {\r\n <mat-radio-button\r\n class=\"c-selection px-8\"\r\n color=\"primary\"\r\n [checked]=\"item.meta.selector.isSelected\"\r\n (change)=\"item.meta.selector.isSelected = true; onSelect(item)\"\r\n [disabled]=\"selectedTableItems() | selectionDisabled: item : _tableOption.selector!\">\r\n </mat-radio-button>\r\n } @else {\r\n <mat-checkbox\r\n class=\"c-selection px-8\"\r\n color=\"primary\"\r\n [(ngModel)]=\"item.meta.selector.isSelected\"\r\n (change)=\"onSelect(item)\"\r\n [disabled]=\"selectedTableItems() | selectionDisabled: item : _tableOption.selector!\">\r\n </mat-checkbox>\r\n }\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n @if (_tableOption.index?.enabled) {\r\n @let _pageOffset = pageOffset();\r\n @let _indexWidth = _tableOption.index?.width || '50px';\r\n <ng-container matColumnDef=\"sdIndex\" sticky>\r\n <th\r\n class=\"text-center p-0\"\r\n mat-header-cell\r\n *matHeaderCellDef\r\n [style.width]=\"_indexWidth\"\r\n [style.min-width]=\"_indexWidth\"\r\n [style.max-width]=\"_indexWidth\"\r\n [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\">\r\n {{ _tableOption.index?.title || '#' }}\r\n </th>\r\n <td class=\"text-center px-4\" mat-cell *matCellDef=\"let item; let i = dataIndex\" [style.min-width]=\"_indexWidth\" [style.max-width]=\"_indexWidth\">\r\n @if (!item?.meta?.group?.isGroupHeader) {\r\n @if (_tableOption.tree && item?.meta?.tree?.indexPath?.length) {\r\n <!-- why: tree \u2192 STT ph\u00E2n c\u1EA5p 1, 1.2, 1.2.1 (indexPath join '.'). T\u00F4 \u0111\u1EADm root (level 0). -->\r\n <span [class.sd-stt-root]=\"(item.meta.tree.level ?? 0) === 0\">\r\n {{ item.meta.tree.indexPath.join('.') }}\r\n </span>\r\n } @else {\r\n {{ _pageOffset + i + 1 }}\r\n }\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef [style.min-width]=\"_indexWidth\" [style.max-width]=\"_indexWidth\"></td>\r\n </ng-container>\r\n }\r\n <ng-container\r\n matColumnDef=\"sdCommand\"\r\n [sticky]=\"_tableOption.command?.align !== 'right'\"\r\n [stickyEnd]=\"_tableOption.command?.align === 'right'\">\r\n <th class=\"p-0\" mat-header-cell *matHeaderCellDef style=\"width: 50px\" [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td class=\"px-8\" mat-cell *matCellDef=\"let item\">\r\n <desktop-command\r\n [autoId]=\"autoId()\"\r\n [commands]=\"_tableOption.command?.commands || _tableOption.commands || []\"\r\n [item]=\"item\"\r\n [itemIndex]=\"groupedItems.indexOf(item)\"></desktop-command>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n <!-- why: group header row d\u00F9ng matRowDef RI\u00CANG v\u1EDBi column list ['sdGroupHeader']\r\n qua predicate when:isGroupHeaderRow. Cell colspan = displayedColumns.length \u0111\u1EC3\r\n span TO\u00C0N B\u1ED8 width data row. Tr\u00E1nh colspan trick overflow row khi c\u00E1c TD kh\u00E1c render. -->\r\n <ng-container matColumnDef=\"sdGroupHeader\">\r\n <td\r\n class=\"p-0 sd-group-header-cell\"\r\n mat-cell\r\n *matCellDef=\"let item\"\r\n [attr.colspan]=\"sdGroupColspan()\">\r\n <div class=\"sd-group-row d-flex align-items-center py-8\">\r\n <!-- why: slot 42px kh\u1EDBp width v\u1EDBi sd-selection-cell data row \u2192 checkbox group c\u0103n TR\u1EE4C d\u1ECDc \u0111\u00FAng v\u1EDBi checkbox data. -->\r\n @if (_tableOption.selector?.visible && !_tableOption.selector?.single) {\r\n <div class=\"sd-group-selection-slot d-flex align-items-center justify-content-center\">\r\n <mat-checkbox\r\n class=\"c-selection\"\r\n color=\"primary\"\r\n [checked]=\"isGroupAllSelected(item)\"\r\n [indeterminate]=\"isGroupIndeterminate(item)\"\r\n (change)=\"onSelectGroup(item, $event.checked)\">\r\n </mat-checkbox>\r\n </div>\r\n } @else {\r\n <div class=\"sd-group-selection-slot\"></div>\r\n }\r\n @if (_tableOption.group?.collapsible) {\r\n <sd-button\r\n type=\"link\"\r\n [prefixIcon]=\"item.meta.group.isExpanded ? 'expand_more' : 'chevron_right'\"\r\n width=\"32px\"\r\n (click)=\"toggleGroupExpand(item)\">\r\n </sd-button>\r\n }\r\n @if (sdGroupDef()?.templateRef; as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl; context: groupContext(item)\"></ng-container>\r\n } @else {\r\n <span class=\"T14R\">{{ item.meta.group.values | json }}</span>\r\n }\r\n </div>\r\n </td>\r\n </ng-container>\r\n <!-- why: filler column \u1EDF cu\u1ED1i h\u1EA5p th\u1EE5 leftover space khi t\u1ED5ng width c\u00E1c c\u1ED9t data < container \u2014 gi\u1EEF cho selection/STT/command kh\u00F4ng b\u1ECB d\u00E3n. -->\r\n <ng-container matColumnDef=\"sdFiller\">\r\n <th class=\"sd-filler-cell p-0\" mat-header-cell *matHeaderCellDef [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td class=\"sd-filler-cell p-0\" mat-cell *matCellDef=\"let item\"></td>\r\n <td class=\"sd-filler-cell p-0\" mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n @for (column of _configuration.firstColumns; track column.field) {\r\n <ng-container [matColumnDef]=\"column.field\" [sticky]=\"_configuration.fixedColumn[column.field]\">\r\n <th\r\n mat-header-cell\r\n *matHeaderCellDef\r\n class=\"px-8 py-8 c-th\"\r\n [sdColumnResize]=\"!!_tableOption.config?.resizable && column.type !== 'children'\"\r\n [minWidth]=\"column.minWidth\"\r\n [maxWidth]=\"column.maxWidth\"\r\n (resizeEnd)=\"onColumnResize(column.field, $event)\"\r\n [style.width]=\"column.width\"\r\n [style.min-width]=\"column.minWidth || column.width\"\r\n [style.max-width]=\"column.maxWidth\"\r\n [attr.rowspan]=\"_configuration.multipleHeader && column.type !== 'children' ? 2 : 1\"\r\n [attr.colspan]=\"column.type === 'children' ? column.children.length : 1\">\r\n <div>\r\n @if (column.type === 'children') {\r\n <div\r\n aria-hidden=\"true\"\r\n class=\"c-header-title\"\r\n [class.justify-content-end]=\"column.align === 'right'\"\r\n [class.text-right]=\"column.align === 'right'\">\r\n <column-title [column]=\"column\" [titleDef]=\"_titleDef[column.field]\"></column-title>\r\n </div>\r\n } @else {\r\n <div\r\n aria-hidden=\"true\"\r\n mat-sort-header\r\n class=\"c-header-title\"\r\n [class.justify-content-end]=\"column.align === 'right'\"\r\n [class.text-right]=\"column.align === 'right'\"\r\n [disabled]=\"!column.sortable\">\r\n <column-title [column]=\"column\" [titleDef]=\"_titleDef[column.field]\"></column-title>\r\n </div>\r\n @let hideInlineFilter =\r\n _tableOption.filter?.disabled ||\r\n _tableOption.filter?.hideInlineFilter === true ||\r\n (_tableOption.filter?.hideInlineFilter === 'auto' && !_isFiltered && _total! <= 10);\r\n @if (!hideInlineFilter) {\r\n <ng-container *sdDesktop>\r\n <column-filter\r\n [autoId]=\"autoId()\"\r\n [value]=\"columnFilter?.[column.field!]!\"\r\n [operator]=\"columnOperator[column.field]\"\r\n (operatorChange)=\"columnOperator[column.field] = $event!; onOperatorChange(column, $event)\"\r\n [columnFilter]=\"columnFilter!\"\r\n [cacheValues]=\"cacheValues\"\r\n [column]=\"column\"\r\n (filterChange)=\"onFilterChange()\"\r\n (filterCommit)=\"onFilterCommit()\">\r\n </column-filter>\r\n </ng-container>\r\n }\r\n }\r\n </div>\r\n </th>\r\n <td\r\n class=\"c-td px-0\"\r\n [class.d-none]=\"column.type === 'children'\"\r\n mat-cell\r\n *matCellDef=\"let item\"\r\n [sdHoverCopy]=\"(item.data && item.data[column.field]) || ''\"\r\n [sdHoverCopyDisabled]=\"!column.cell?.copiable\">\r\n @if (column.type !== 'children' && !item?.meta?.group?.isGroupHeader) {\r\n <desktop-cell class=\"d-block px-8\" [column]=\"column\" [item]=\"item\" [cellDef]=\"cellDef()\"> </desktop-cell>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef>\r\n <ng-container *ngIf=\"footerDef()[column.field]\">\r\n <ng-container *ngTemplateOutlet=\"footerDef()[column.field].templateRef; context: { items: _items, column: column }\">\r\n </ng-container>\r\n </ng-container>\r\n </td>\r\n </ng-container>\r\n }\r\n @for (column of _configuration.secondColumns; track column.field) {\r\n <ng-container [matColumnDef]=\"column.field\">\r\n <th\r\n mat-header-cell\r\n *matHeaderCellDef\r\n class=\"c-th px-8\"\r\n [style.width]=\"column.width\"\r\n [style.min-width]=\"column.minWidth || column.width\"\r\n [style.max-width]=\"column.maxWidth\">\r\n <div>\r\n <div\r\n aria-hidden=\"true\"\r\n mat-sort-header\r\n class=\"c-header-title\"\r\n [class.justify-content-end]=\"column.align === 'right'\"\r\n [class.text-right]=\"column.align === 'right'\"\r\n [disabled]=\"!column.sortable\">\r\n <column-title [column]=\"column\" [titleDef]=\"_titleDef[column.field]\"></column-title>\r\n </div>\r\n @if (!_tableOption.filter?.disabled && !_tableOption.filter?.hideInlineFilter && columnOperator) {\r\n <ng-container *sdDesktop>\r\n <column-filter\r\n [autoId]=\"autoId()\"\r\n [value]=\"columnFilter?.[column.field!]!\"\r\n [operator]=\"columnOperator[column.field]\"\r\n [columnFilter]=\"columnFilter!\"\r\n [cacheValues]=\"cacheValues\"\r\n [column]=\"column\"\r\n (operatorChange)=\"columnOperator[column.field] = $event!; onOperatorChange(column, $event)\"\r\n (filterChange)=\"onFilterChange()\"\r\n (filterCommit)=\"onFilterCommit()\">\r\n </column-filter>\r\n </ng-container>\r\n }\r\n </div>\r\n </th>\r\n <td\r\n class=\"c-td px-0\"\r\n mat-cell\r\n *matCellDef=\"let item\"\r\n [sdHoverCopy]=\"item[column.field]\"\r\n [sdHoverCopyDisabled]=\"!column.cell?.copiable\">\r\n @if (column.type !== 'children') {\r\n <desktop-cell class=\"d-block px-8\" [column]=\"column\" [item]=\"item\" [cellDef]=\"cellDef()\"> </desktop-cell>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef>\r\n <ng-container *ngIf=\"footerDef()[column.field]\">\r\n <ng-container *ngTemplateOutlet=\"footerDef()[column.field].templateRef; context: { items: _items, column: column }\">\r\n </ng-container>\r\n </ng-container>\r\n </td>\r\n </ng-container>\r\n }\r\n <tr class=\"c-first-header\" mat-header-row *matHeaderRowDef=\"_configuration.firstHeaders; sticky: true\"></tr>\r\n @if (!!_configuration.secondHeaders.length) {\r\n <tr class=\"c-second-header\" mat-header-row *matHeaderRowDef=\"_configuration.secondHeaders; sticky: true\"></tr>\r\n }\r\n <!-- Group header row \u2014 ch\u1EC9 1 cell sdGroupHeader colspan to\u00E0n width. -->\r\n <tr\r\n mat-row\r\n *matRowDef=\"let row; columns: ['sdGroupHeader']; when: isGroupHeaderRow\"\r\n class=\"c-group-row-tr\"></tr>\r\n\r\n <!-- Data row \u2014 d\u00F9ng displayedColumns \u0111\u1EA7y \u0111\u1EE7; when isDataRow \u0111\u1EC3 lo\u1EA1i tr\u1EEB group header. -->\r\n <tr\r\n mat-row\r\n cdkDrag\r\n [cdkDragData]=\"row\"\r\n [cdkDragDisabled]=\"\r\n !_tableOption.rowReorder?.enabled ||\r\n !!row.meta?.group?.items?.length ||\r\n (row.meta?.tree?.level ?? 0) > 0 ||\r\n isReorderDisabled(row)\r\n \"\r\n *matRowDef=\"let row; columns: _configuration.displayedColumns; when: isDataRow\"\r\n matRipple\r\n class=\"c-row\"\r\n [class.sd-tree-row]=\"!!_tableOption.tree\"\r\n [ngClass]=\"_tableOption.tree ? 'sd-tree-level-' + (row.meta?.tree?.level ?? 0) : null\"\r\n [ngStyle]=\"rowStyle(row)\"\r\n [class.selected]=\"row.meta.selector.isSelected\"></tr>\r\n\r\n <!-- Sub-information row \u2014 also gated b\u1EDFi isDataRow \u0111\u1EC3 KH\u00D4NG render empty expand row d\u01B0\u1EDBi group header. -->\r\n <tr mat-row *matRowDef=\"let row; columns: ['sdSubInformation']; when: isDataRow\" class=\"c-detail-row\"></tr>\r\n @if (hasFooter() && !!_configuration.displayedFooters.length) {\r\n <tr mat-footer-row *matFooterRowDef=\"_configuration.displayedFooters; sticky: true\"></tr>\r\n }\r\n </table>\r\n @if (!_loading && !_total) {\r\n <div class=\"c-no-data-row\">\r\n @if (_isFiltered) {\r\n @if (tableConfiguration?.images?.filterEmpty) {\r\n <img class=\"c-image\" [src]=\"tableConfiguration!.images!.filterEmpty\" alt=\"filter-empty\" />\r\n } @else {\r\n <img class=\"c-image sd-image-filter-empty\" alt=\"filter-empty\" />\r\n }\r\n <div class=\"T16M\">{{ 'core.component.table.no-results' | translate }}</div>\r\n <div class=\"T16R text-secondary\">{{ 'core.component.table.no-results-hint' | translate }}</div>\r\n } @else {\r\n @if (_requireFiltered) {\r\n @if (tableConfiguration?.images?.filterRequired) {\r\n <img class=\"c-image\" [src]=\"tableConfiguration!.images!.filterRequired\" alt=\"filter-required\" />\r\n } @else {\r\n <img class=\"c-image sd-image-filter-required\" alt=\"filter-required\" />\r\n }\r\n <div class=\"T16R text-secondary\">{{ 'core.component.table.choose-filter-hint' | translate }}</div>\r\n } @else {\r\n @if (tableConfiguration?.images?.dataEmpty) {\r\n <img class=\"c-image\" [src]=\"tableConfiguration!.images!.dataEmpty\" alt=\"data-empty\" />\r\n } @else {\r\n <img class=\"c-image sd-image-data-empty\" alt=\"data-empty\" />\r\n }\r\n <div class=\"T16R text-secondary\">{{ 'core.component.table.no-data' | translate }}</div>\r\n }\r\n }\r\n </div>\r\n }\r\n </div>\r\n <div class=\"c-paginator\">\r\n <div class=\"c-action\">\r\n <ng-container *sdDesktop>\r\n @if (_tableOption.reload?.visible) {\r\n <sd-button\r\n class=\"mr-8\"\r\n [title]=\"'core.component.table.reload' | translate\"\r\n prefixIcon=\"refresh\"\r\n (click)=\"reload()\"\r\n [disabled]=\"!_items.length\"\r\n type=\"link\">\r\n </sd-button>\r\n }\r\n </ng-container>\r\n @if (_export && _items.length) {\r\n @if (_export.type === 'custom') {\r\n <sd-button class=\"mr-8\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" (click)=\"exportCustom()\" type=\"link\"> </sd-button>\r\n } @else {\r\n @if (_export.visible) {\r\n @if (_exporting) {\r\n <sd-button class=\"mr-8\" [loading]=\"_exporting\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" type=\"link\"> </sd-button>\r\n } @else {\r\n @if (_export.visible === 'ALL' || !_export.visible) {\r\n <sd-button class=\"mr-8\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" [matMenuTriggerFor]=\"menu\" type=\"link\"> </sd-button>\r\n <mat-menu #menu=\"matMenu\">\r\n <button mat-menu-item (click)=\"exportExcel()\" type=\"button\">\r\n <mat-icon fontSet=\"material-icons-outlined\">file_download</mat-icon>\r\n <span> {{ 'core.component.table.export-excel' | translate }}</span>\r\n </button>\r\n <button mat-menu-item (click)=\"exportCSV()\" type=\"button\">\r\n <mat-icon fontSet=\"material-icons-outlined\">file_download</mat-icon>\r\n <span> {{ 'core.component.table.export-csv' | translate }}</span>\r\n </button>\r\n </mat-menu>\r\n } @else if (_export.visible === 'EXCEL') {\r\n <sd-button class=\"mr-8\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" (click)=\"exportExcel()\" type=\"link\"> </sd-button>\r\n } @else if (_export.visible === 'CSV') {\r\n <sd-button class=\"mr-8\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" (click)=\"exportCSV()\" type=\"link\"> </sd-button>\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n <ng-container *sdDesktop>\r\n @if (configComponent()) {\r\n <sd-button\r\n class=\"mr-8\"\r\n [title]=\"'core.component.table.setup-short' | translate\"\r\n prefixIcon=\"settings\"\r\n (click)=\"configComponent()!.open()\"\r\n type=\"link\">\r\n </sd-button>\r\n }\r\n </ng-container>\r\n <!-- Mobile: n\u00FAt Filter m\u1EDF mobile-filter drawer (inline filter \u1EA9n tr\u00EAn mobile) -->\r\n <ng-container *sdMobile>\r\n @if (!_tableOption.filter?.disabled && mobileFilter()) {\r\n <sd-button\r\n [autoId]=\"autoId() + 'mobile-filter-open'\"\r\n class=\"mr-8\"\r\n prefixIcon=\"filter_alt\"\r\n (click)=\"mobileFilter()!.open()\"\r\n type=\"link\">\r\n </sd-button>\r\n }\r\n </ng-container>\r\n </div>\r\n @let hidePaginator = !_tableOption.paginate?.pageSize || _total === undefined || _total <= _tableOption.paginate?.pageSize!;\r\n <!-- Desktop paginator: full config (pageSize dropdown, first/last buttons) -->\r\n <ng-container *sdDesktop>\r\n <mat-paginator\r\n [class.d-none]=\"_tableOption.paginate?.hidden || hidePaginator\"\r\n [length]=\"_total\"\r\n [pageSize]=\"_tableOption.paginate?.pageSize\"\r\n [pageSizeOptions]=\"_tableOption.paginate?.pages!\"\r\n [showFirstLastButtons]=\"_tableOption.paginate?.showFirstLastButtons\"\r\n [hidePageSize]=\"_tableOption.paginate?.hidePageSize\"></mat-paginator>\r\n </ng-container>\r\n <!-- Mobile paginator: \u1EA9n pageSize dropdown + first/last buttons \u0111\u1EC3 ti\u1EBFt ki\u1EC7m kh\u00F4ng gian -->\r\n <ng-container *sdMobile>\r\n <mat-paginator\r\n [class.d-none]=\"_tableOption.paginate?.hidden || hidePaginator\"\r\n [length]=\"_total\"\r\n [pageSize]=\"_tableOption.paginate?.pageSize\"\r\n [showFirstLastButtons]=\"false\"\r\n hidePageSize></mat-paginator>\r\n </ng-container>\r\n <!-- \"\u0110ang hi\u1EC3n th\u1ECB...\" ch\u1EC9 desktop -->\r\n <ng-container *sdDesktop>\r\n @if (!_tableOption.paginate?.hidden && hidePaginator && _total !== undefined && _total > 0) {\r\n <div class=\"T14R pr-16\">\r\n {{ 'core.component.table.showing' | translate }} <span class=\"T14M ml-2\">1-{{ _total }}/{{ _total }}</span>\r\n </div>\r\n }\r\n </ng-container>\r\n </div>\r\n </div>\r\n <selector-action [tableOption]=\"_tableOption\" [selectedTableItems]=\"selectedTableItems()\" (clear)=\"onClearSelection(groupedItems)\" />\r\n @if (_tableOption.config?.visible) {\r\n <config [tableOption]=\"_tableOption\" />\r\n }\r\n <!-- Mobile filter drawer \u2014 ch\u1EC9 instantiate khi c\u1EA7n render tr\u00EAn mobile -->\r\n @if (!_tableOption.filter?.disabled && filterRegister) {\r\n <mobile-filter\r\n [autoId]=\"autoId()\"\r\n [filter]=\"_tableOption.filter!\"\r\n [externalFilters]=\"_tableOption.filter?.externalFilters!\"\r\n [columns]=\"_configuration.firstColumns\"\r\n [filterDefs]=\"sdFilterDefs()\"\r\n [filterRegister]=\"filterRegister\"\r\n [cacheValues]=\"cacheValues\">\r\n </mobile-filter>\r\n }\r\n}\r\n", styles: [":host{display:flex;flex-direction:column;overflow:auto;width:100%;height:100%}:host .c-header-title{height:40px;display:flex;align-items:center}:host .c-container{position:relative;min-height:50px;display:flex;flex-direction:column;flex:1}:host .c-container .c-table{position:relative;flex:1;display:flex;flex-direction:column}:host .c-container .c-table table{border-collapse:separate;width:100%}:host .c-container .c-table table tr.c-first-header.mat-mdc-header-row{height:40px}:host .c-container .c-table table tr.c-second-header.mat-mdc-header-row{height:40px}:host .c-container .c-table table tr.c-detail-row{height:0}:host .c-container .c-table table tr.c-row.activated{background-color:#e5ecff}:host .c-container .c-table table tr.c-row.selected{background-color:#eef2ff}:host .c-container .c-table table tr.c-row:not(.selected):not(.activated):hover{background-color:#f5f5f5}:host .c-container .c-table table tr.c-row td{border-bottom-width:0}:host .c-container .c-table table tr.c-row.c-expandable{cursor:pointer}:host .c-container .c-table table tr.c-row.c-expandable:hover{background:#f5f5f5}:host .c-container .c-table table th.mat-mdc-header-cell{background-color:#f2f3f4;border-bottom:0!important}:host .c-container .c-table table td.mat-mdc-cell,:host .c-container .c-table table td.mat-mdc-footer-cell,:host .c-container .c-table table th.mat-mdc-header-cell{border-bottom-color:#f2f2f2!important}:host .c-container .c-table .c-th{vertical-align:middle;font-weight:500;font-size:14px;line-height:20px;color:#212121}:host .c-container .c-table .c-th.sd-col-resize-host{position:relative}:host .c-container .c-table .c-th.sd-resizing{-webkit-user-select:none;user-select:none}:host .c-container .c-table .c-th .sd-col-resize-handle{position:absolute;top:0;right:0;width:6px;height:100%;cursor:col-resize;-webkit-user-select:none;user-select:none;z-index:2}:host .c-container .c-table .c-th .sd-col-resize-handle:hover{background:#00000014}:host .c-container .c-table .c-td:first{padding-left:10px}:host .c-container .c-table .c-no-data-row{flex:1;width:100%;position:sticky;left:0;display:flex;flex-direction:column;align-items:center;justify-content:center}:host .c-container .c-table .c-no-data-row .c-image{margin-bottom:16px;width:96px}:host .c-container .c-loading{position:absolute;inset:0 0 56px;background:#00000026;z-index:2;display:flex;align-items:center;justify-content:center}:host .c-container .c-paginator{display:flex;flex-direction:row;justify-content:space-between;align-items:center;background-color:#fff}:host .c-container .c-paginator .c-action{padding:5px}:host .c-container .c-empty{text-align:center;background-color:#fff;border:none!important}:host .c-container .c-empty mat-icon{font-size:150px;margin-top:30px;margin-bottom:30px;opacity:.2;width:auto;height:auto}:host button.c-btn-add{background-color:#fff;box-shadow:0 2px 4px #2f313629}:host .lds-ring{display:inline-block;position:relative;width:40px;height:40px}:host .lds-ring div{box-sizing:border-box;display:block;position:absolute;width:32px;height:32px;margin:4px;border:4px solid #cef;border-radius:50%;animation:lds-ring 1.2s cubic-bezier(.5,0,.5,1) infinite;border-color:#cef transparent transparent transparent}:host .lds-ring div:nth-child(1){animation-delay:-.45s}:host .lds-ring div:nth-child(2){animation-delay:-.3s}:host .lds-ring div:nth-child(3){animation-delay:-.15s}@keyframes lds-ring{0%{transform:rotate(0)}to{transform:rotate(360deg)}}:host .sd-reorder-header,:host .sd-reorder-cell{width:40px;min-width:40px;padding:0 4px;box-sizing:border-box}:host .sd-reorder-cell mat-icon{cursor:grab;color:#00000061;display:flex;align-items:center}:host .sd-reorder-cell mat-icon:active{cursor:grabbing}:host .sd-reorder-cell mat-icon.sd-reorder-disabled{opacity:.3;cursor:not-allowed;pointer-events:none}:host ::ng-deep .mat-sort-header-content{display:block;text-align:left;width:100%}:host ::ng-deep .mat-select-arrow{color:#a6a6a6}:host ::ng-deep .mat-sort-header-disabled{background-image:none!important;cursor:default!important;padding-right:0!important}:host ::ng-deep .mat-sort-header-container{align-items:start!important}:host ::ng-deep .mat-sort-header-arrow{margin-top:4px!important}:host ::ng-deep .mat-sort-header-arrow{display:none!important}:host ::ng-deep .mat-sort-header{cursor:pointer}:host ::ng-deep .mat-sort-header[aria-sort]{background-repeat:no-repeat;background-position:center right 0;background-size:16px 16px;cursor:pointer;padding-right:24px}:host ::ng-deep .mat-sort-header[aria-sort=none]{background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 0 24 24' width='24px' fill='%23000000'%3E%3Cpath d='M0 0h24v24H0V0z' fill='none'/%3E%3Cpath fill='%237A7A7A' d='M12 5.83L15.17 9l1.41-1.41L12 3 7.41 7.59 8.83 9 12 5.83zm0 12.34L8.83 15l-1.41 1.41L12 21l4.59-4.59L15.17 15 12 18.17z'/%3E%3C/svg%3E\")}:host ::ng-deep .mat-sort-header[aria-sort=ascending]{background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 0 24 24' width='24px' fill='%23000000'%3E%3Cpath d='M0 0h24v24H0V0z' fill='none'/%3E%3Cpath fill='%237A7A7A' d='M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z'/%3E%3C/svg%3E\")}:host ::ng-deep .mat-sort-header[aria-sort=descending]{background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 0 24 24' width='24px' fill='%23000000'%3E%3Cpath d='M0 0h24v24H0V0z' fill='none'/%3E%3Cpath fill='%237A7A7A' d='M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z'/%3E%3C/svg%3E\")}:host ::ng-deep .c-paginator .mat-mdc-paginator .mdc-text-field--outlined .mat-mdc-form-field-infix,:host ::ng-deep .c-paginator .mat-mdc-paginator .mdc-text-field--no-label .mat-mdc-form-field-infix{padding-top:2px;padding-bottom:2px;min-height:32px}:host ::ng-deep .c-paginator .mat-mdc-paginator-range-label{margin:0 4px}:host ::ng-deep .c-paginator .mat-mdc-paginator-page-size-select mat-select{margin-top:2px!important}:host ::ng-deep .cdk-drag-preview{box-shadow:0 4px 12px #00000026;background:#fff;display:table;width:100%}:host ::ng-deep .cdk-drag-preview td{padding:0 8px;border-bottom:1px solid rgba(0,0,0,.12)}:host ::ng-deep .cdk-drag-placeholder{opacity:0}:host ::ng-deep .cdk-drop-list-dragging tr.c-row:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}:host ::ng-deep .sd-selection-cell{width:42px;min-width:42px;max-width:42px}:host ::ng-deep .sd-filler-cell{width:auto;min-width:0;padding:0!important;border:0}:host ::ng-deep .sd-group-header-cell{background:#f5f7fc;border-top:1px solid #e6e9f2;border-bottom:1px solid #e6e9f2}:host ::ng-deep .sd-group-row{min-height:36px}:host ::ng-deep .sd-group-selection-slot{width:42px;min-width:42px;max-width:42px}:host ::ng-deep .c-selection{transform:scale(.85);transform-origin:center}:host ::ng-deep .sd-tree-toggle-cell{width:40px;min-width:40px;max-width:100px}:host ::ng-deep .sd-tree-toggle-inner{display:flex;align-items:center;min-height:40px}:host ::ng-deep .sd-tree-spinner{transform:scale(.5);margin:0 auto}:host ::ng-deep tr.c-row.sd-tree-row.sd-tree-level-0{background:#fbfcfe}:host ::ng-deep tr.c-row.sd-tree-row.sd-tree-level-0>td{font-weight:500}:host ::ng-deep tr.c-row.sd-tree-row.sd-tree-level-1{background:#fff}:host ::ng-deep tr.c-row.sd-tree-row.sd-tree-level-2{background:#fafbfd}:host ::ng-deep tr.c-row.sd-tree-row.sd-tree-level-3{background:#f6f8fb}:host ::ng-deep tr.c-row.sd-tree-row:not(.sd-tree-level-0)>td.sd-tree-toggle-cell .sd-tree-toggle-inner{border-left:1px dashed #d8dde6}:host ::ng-deep .sd-stt-root{font-weight:700;color:#1f2330}\n", ":host ::ng-deep .sticky-shadow-right{overflow:visible!important}:host ::ng-deep .sticky-shadow-right:after{content:\"\";position:absolute;top:0;right:0;bottom:0;width:8px;transform:translate(100%);background:linear-gradient(to right,rgba(0,0,0,.12),transparent);pointer-events:none}:host ::ng-deep .sticky-shadow-left{overflow:visible!important}:host ::ng-deep .sticky-shadow-left:after{content:\"\";position:absolute;top:0;left:0;bottom:0;width:8px;transform:translate(-100%);background:linear-gradient(to left,rgba(0,0,0,.12),transparent);pointer-events:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.JsonPipe, name: "json" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i2.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i4$1.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i6.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i6.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i6.MatFooterRowDef, selector: "[matFooterRowDef]", inputs: ["matFooterRowDef", "matFooterRowDefSticky"] }, { kind: "directive", type: i6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i6.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: i6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i6.MatFooterRow, selector: "mat-footer-row, tr[mat-footer-row]", exportAs: ["matFooterRow"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i7.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i7.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i8.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatRadioModule }, { kind: "component", type: i10.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i11.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i11.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i11.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: DesktopCommand, selector: "desktop-command", inputs: ["autoId", "item", "itemIndex", "commands"] }, { kind: "component", type: DesktopCellComponent, selector: "desktop-cell", inputs: ["column", "item", "cellDef"] }, { kind: "component", type: ColumnTitleComponent, selector: "column-title", inputs: ["column", "titleDef"] }, { kind: "component", type: ExternalFilterComponent, selector: "external-filter", inputs: ["autoId", "filter", "externalFilters", "filterRegister"] }, { kind: "component", type: ConfigComponent, selector: "config", inputs: ["tableOption"], outputs: ["changes"] }, { kind: "component", type: ColumnFilterComponent, selector: "column-filter", inputs: ["autoId", "column", "columnFilter", "cacheValues", "value", "operator", "isMobile"], outputs: ["operatorChange", "filterChange", "filterCommit"] }, { kind: "component", type: MobileFilterComponent, selector: "mobile-filter", inputs: ["autoId", "filter", "externalFilters", "columns", "filterDefs", "filterRegister", "cacheValues"] }, { kind: "pipe", type: SdGroupPipe, name: "sdGroup" }, { kind: "pipe", type: SdTreePipe, name: "sdTree" }, { kind: "pipe", type: SdSelectionVisiblePipe, name: "selectionVisible" }, { kind: "pipe", type: SdSelectionVisibleSelectAllPipe, name: "selectionVisibleSelectAll" }, { kind: "pipe", type: SdSelectionDisabledPipe, name: "selectionDisabled" }, { kind: "directive", type: SdScrollDirective, selector: "[sdScroll]" }, { kind: "directive", type: SdDesktopDirective, selector: "[sdDesktop]" }, { kind: "directive", type: SdMobileDirective, selector: "[sdMobile]" }, { kind: "directive", type: SdHoverCopyDirective, selector: "[sdHoverCopy]", inputs: ["sdHoverCopy", "sdHoverCopyDisabled"] }, { kind: "component", type: SelectorActionComponent, selector: "selector-action", inputs: ["tableOption", "selectedTableItems"], outputs: ["clear"] }, { kind: "directive", type: StickyShadowDirective, selector: "[stickyShadow]" }, { kind: "directive", type: SdColumnResizeDirective, selector: "[sdColumnResize]", inputs: ["sdColumnResize", "minWidth", "maxWidth"], outputs: ["resizeEnd"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], animations: [
|
|
4086
4275
|
trigger('detailExpand', [
|
|
4087
4276
|
state('collapsed', style({ height: '0', minHeight: '0', visibility: 'hidden' })),
|
|
4088
4277
|
state('expanded', style({ height: '*', visibility: 'visible' })),
|
|
@@ -4147,7 +4336,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
|
|
|
4147
4336
|
StickyShadowDirective,
|
|
4148
4337
|
SdColumnResizeDirective,
|
|
4149
4338
|
TranslatePipe,
|
|
4150
|
-
], template: "@let _configuration = configuration();\r\n@let _tableOption = tableOption()!;\r\n@let _loading = loading();\r\n@let _items = items();\r\n@let _total = total();\r\n@let _isFiltered = isFiltered();\r\n@let _requireFiltered = requireFiltered();\r\n@let _export = _tableOption?.export;\r\n@let _exporting = exporting();\r\n@let _titleDef = titleDef();\r\n\r\n@if (_configuration) {\r\n @if (!_tableOption.filter?.disabled && !!_tableOption.filter?.externalFilters?.length && filterRegister) {\r\n <external-filter\r\n class=\"mb-16\"\r\n [autoId]=\"autoId()\"\r\n [filterRegister]=\"filterRegister\"\r\n [filter]=\"_tableOption.filter!\"\r\n [externalFilters]=\"_tableOption.filter?.externalFilters!\">\r\n </external-filter>\r\n }\r\n @let groupedItems = _items | sdTree: _tableOption.tree : treeRevision() | sdGroup: _tableOption;\r\n <ng-content select=\"[sdTableTop]\"></ng-content>\r\n <div class=\"c-container\">\r\n @if (_loading) {\r\n <div class=\"c-loading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n }\r\n <div\r\n class=\"c-table\"\r\n sdScroll\r\n stickyShadow\r\n [style.max-height]=\"_tableOption.style?.maxHeight\"\r\n [style.min-height]=\"_tableOption.style?.minHeight\">\r\n <table\r\n mat-table\r\n [dataSource]=\"groupedItems\"\r\n [trackBy]=\"trackBy\"\r\n matSort\r\n [matSortDisabled]=\"!_tableOption.sort?.enable\"\r\n multiTemplateDataRows\r\n cdkDropList\r\n [cdkDropListData]=\"groupedItems\"\r\n [cdkDropListDisabled]=\"!_tableOption.rowReorder?.enabled\"\r\n [cdkDropListSortPredicate]=\"reorderSortPredicate\"\r\n (cdkDropListDropped)=\"onReorderDrop($event)\">\r\n @if (_tableOption.rowReorder?.enabled) {\r\n <ng-container matColumnDef=\"sdReorder\">\r\n <th mat-header-cell *matHeaderCellDef class=\"sd-reorder-header\" [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td mat-cell *matCellDef=\"let row\" class=\"sd-reorder-cell\">\r\n @if (!row.meta?.group?.items?.length) {\r\n <mat-icon cdkDragHandle [class.sd-reorder-disabled]=\"isReorderDisabled(row)\">\r\n {{ _tableOption.rowReorder?.icon || 'drag_indicator' }}\r\n </mat-icon>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n\r\n @if (_tableOption.tree) {\r\n <ng-container matColumnDef=\"sdTreeToggle\">\r\n <th\r\n mat-header-cell\r\n *matHeaderCellDef\r\n class=\"sd-tree-toggle-cell p-0\"\r\n [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td mat-cell *matCellDef=\"let row\" class=\"sd-tree-toggle-cell p-0\">\r\n @if (row.meta?.tree) {\r\n <div\r\n class=\"sd-tree-toggle-inner\"\r\n [style.padding-left.px]=\"(row.meta.tree.level ?? 0) * (_tableOption.tree?.indentSize ?? 20)\">\r\n @if (row.meta.tree.hasChildren) {\r\n @if (row.meta.tree.isExpanding) {\r\n <div class=\"lds-ring sd-tree-spinner\">\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n </div>\r\n } @else {\r\n <sd-button\r\n type=\"link\"\r\n [prefixIcon]=\"row.meta.tree.isExpanded ? 'expand_less' : 'expand_more'\"\r\n (click)=\"onTreeToggle(row); $event.stopPropagation()\"\r\n width=\"35px\">\r\n </sd-button>\r\n }\r\n }\r\n </div>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n\r\n <ng-container matColumnDef=\"sdSubInformation\" sticky>\r\n <td class=\"p-0\" mat-cell *matCellDef=\"let item\" [attr.colspan]=\"_configuration.displayedColumns.length\">\r\n @if (sdSubInformation()?.templateRef) {\r\n @if (_tableOption.expand?.always) {\r\n <ng-container *ngTemplateOutlet=\"sdSubInformation()?.templateRef!; context: { item: item }\"> </ng-container>\r\n } @else {\r\n <div [@detailExpand]=\"item.isExpanded ? 'expanded' : 'collapsed'\">\r\n @if (item.isExpanded) {\r\n <ng-container *ngTemplateOutlet=\"sdSubInformation()?.templateRef!; context: { item: item }\"> </ng-container>\r\n }\r\n </div>\r\n }\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n\r\n <ng-container matColumnDef=\"sdSubInformationAction\" stickyEnd>\r\n <th class=\"p-0\" mat-header-cell *matHeaderCellDef style=\"width: 1px\" [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td mat-cell *matCellDef=\"let element\">\r\n @if (!element.isExpanding && !_tableOption.expand?.always) {\r\n <sd-button\r\n type=\"link\"\r\n [prefixIcon]=\"element.isExpanded ? 'expand_less' : 'expand_more'\"\r\n (click)=\"onExpand(element)\"\r\n width=\"35px\">\r\n </sd-button>\r\n }\r\n @if (element.isExpanding) {\r\n <div class=\"lds-ring\">\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n </div>\r\n }\r\n </td>\r\n </ng-container>\r\n\r\n <ng-container matColumnDef=\"sdSelection\" sticky>\r\n <th class=\"sd-selection-cell p-0\" mat-header-cell *matHeaderCellDef [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\">\r\n @let visibleSelectAll = _items | selectionVisibleSelectAll: _tableOption.selector | async;\r\n @if (visibleSelectAll) {\r\n <mat-checkbox\r\n class=\"c-selection px-8\"\r\n color=\"primary\"\r\n [ngModel]=\"isSelectAll()\"\r\n (ngModelChange)=\"isSelectAll.set($event)\"\r\n (change)=\"onSelectAll()\">\r\n </mat-checkbox>\r\n }\r\n </th>\r\n\r\n <td class=\"sd-selection-cell p-0\" mat-cell *matCellDef=\"let item\">\r\n @let visible = item | selectionVisible: _tableOption.selector;\r\n @if (visible) {\r\n @if (_tableOption.selector?.single) {\r\n <mat-radio-button\r\n class=\"c-selection px-8\"\r\n color=\"primary\"\r\n [checked]=\"item.meta.selector.isSelected\"\r\n (change)=\"item.meta.selector.isSelected = true; onSelect(item)\"\r\n [disabled]=\"selectedTableItems() | selectionDisabled: item : _tableOption.selector!\">\r\n </mat-radio-button>\r\n } @else {\r\n <mat-checkbox\r\n class=\"c-selection px-8\"\r\n color=\"primary\"\r\n [(ngModel)]=\"item.meta.selector.isSelected\"\r\n (change)=\"onSelect(item)\"\r\n [disabled]=\"selectedTableItems() | selectionDisabled: item : _tableOption.selector!\">\r\n </mat-checkbox>\r\n }\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n @if (_tableOption.index?.enabled) {\r\n @let _pageOffset = pageOffset();\r\n <ng-container matColumnDef=\"sdIndex\" sticky>\r\n <th\r\n class=\"text-center p-0\"\r\n mat-header-cell\r\n *matHeaderCellDef\r\n [style.width]=\"_tableOption.index?.width || '50px'\"\r\n [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\">\r\n {{ _tableOption.index?.title || '#' }}\r\n </th>\r\n <td class=\"text-center px-4\" mat-cell *matCellDef=\"let item; let i = index\">\r\n @if (!item?.sdGroup) {\r\n {{ _pageOffset + i + 1 }}\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n <ng-container\r\n matColumnDef=\"sdCommand\"\r\n [sticky]=\"_tableOption.command?.align !== 'right'\"\r\n [stickyEnd]=\"_tableOption.command?.align === 'right'\">\r\n <th class=\"p-0\" mat-header-cell *matHeaderCellDef style=\"width: 50px\" [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td class=\"px-8\" mat-cell *matCellDef=\"let item\">\r\n <desktop-command\r\n [autoId]=\"autoId()\"\r\n [commands]=\"_tableOption.command?.commands || _tableOption.commands || []\"\r\n [item]=\"item\"\r\n [itemIndex]=\"groupedItems.indexOf(item)\"></desktop-command>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n <ng-container matColumnDef=\"sdGroup\">\r\n <th mat-header-cell *matHeaderCellDef class=\"px-8 py-8\" [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td class=\"p-0\" mat-cell *matCellDef=\"let item\" [attr.colspan]=\"!item?.sdGroup ? 1 : _configuration.displayedColumns.length\">\r\n <div [innerHtml]=\"item?.sdGroup?.htmlTemplate | sdSafeHtml\"></div>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n @for (column of _configuration.firstColumns; track column.field) {\r\n <ng-container [matColumnDef]=\"column.field\" [sticky]=\"_configuration.fixedColumn[column.field]\">\r\n <th\r\n mat-header-cell\r\n *matHeaderCellDef\r\n class=\"px-8 py-8 c-th\"\r\n [sdColumnResize]=\"!!_tableOption.config?.resizable && column.type !== 'children'\"\r\n [minWidth]=\"column.minWidth\"\r\n [maxWidth]=\"column.maxWidth\"\r\n (resizeEnd)=\"onColumnResize(column.field, $event)\"\r\n [style.width]=\"column.width\"\r\n [style.min-width]=\"column.minWidth || column.width\"\r\n [style.max-width]=\"column.maxWidth\"\r\n [attr.rowspan]=\"_configuration.multipleHeader && column.type !== 'children' ? 2 : 1\"\r\n [attr.colspan]=\"column.type === 'children' ? column.children.length : 1\">\r\n <div>\r\n @if (column.type === 'children') {\r\n <div\r\n aria-hidden=\"true\"\r\n class=\"c-header-title\"\r\n [class.justify-content-end]=\"column.align === 'right'\"\r\n [class.text-right]=\"column.align === 'right'\">\r\n <column-title [column]=\"column\" [titleDef]=\"_titleDef[column.field]\"></column-title>\r\n </div>\r\n } @else {\r\n <div\r\n aria-hidden=\"true\"\r\n mat-sort-header\r\n class=\"c-header-title\"\r\n [class.justify-content-end]=\"column.align === 'right'\"\r\n [class.text-right]=\"column.align === 'right'\"\r\n [disabled]=\"!column.sortable\">\r\n <column-title [column]=\"column\" [titleDef]=\"_titleDef[column.field]\"></column-title>\r\n </div>\r\n @let hideInlineFilter =\r\n _tableOption.filter?.disabled ||\r\n _tableOption.filter?.hideInlineFilter === true ||\r\n (_tableOption.filter?.hideInlineFilter === 'auto' && !_isFiltered && _total! <= 10);\r\n @if (!hideInlineFilter) {\r\n <ng-container *sdDesktop>\r\n <column-filter\r\n [autoId]=\"autoId()\"\r\n [value]=\"columnFilter?.[column.field!]!\"\r\n [operator]=\"columnOperator[column.field]\"\r\n (operatorChange)=\"columnOperator[column.field] = $event!; onOperatorChange(column, $event)\"\r\n [columnFilter]=\"columnFilter!\"\r\n [cacheValues]=\"cacheValues\"\r\n [column]=\"column\"\r\n (filterChange)=\"onFilterChange()\"\r\n (filterCommit)=\"onFilterCommit()\">\r\n </column-filter>\r\n </ng-container>\r\n }\r\n }\r\n </div>\r\n </th>\r\n <td\r\n class=\"c-td px-0\"\r\n [class.d-none]=\"column.type === 'children'\"\r\n mat-cell\r\n *matCellDef=\"let item\"\r\n [sdHoverCopy]=\"(item.data && item.data[column.field]) || ''\"\r\n [sdHoverCopyDisabled]=\"!column.cell?.copiable\">\r\n @if (column.type !== 'children' && !item?.sdGroup) {\r\n <desktop-cell class=\"d-block px-8\" [column]=\"column\" [item]=\"item\" [cellDef]=\"cellDef()\"> </desktop-cell>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef>\r\n <ng-container *ngIf=\"footerDef()[column.field]\">\r\n <ng-container *ngTemplateOutlet=\"footerDef()[column.field].templateRef; context: { items: _items, column: column }\">\r\n </ng-container>\r\n </ng-container>\r\n </td>\r\n </ng-container>\r\n }\r\n @for (column of _configuration.secondColumns; track column.field) {\r\n <ng-container [matColumnDef]=\"column.field\">\r\n <th\r\n mat-header-cell\r\n *matHeaderCellDef\r\n class=\"c-th px-8\"\r\n [style.width]=\"column.width\"\r\n [style.min-width]=\"column.minWidth || column.width\"\r\n [style.max-width]=\"column.maxWidth\">\r\n <div>\r\n <div\r\n aria-hidden=\"true\"\r\n mat-sort-header\r\n class=\"c-header-title\"\r\n [class.justify-content-end]=\"column.align === 'right'\"\r\n [class.text-right]=\"column.align === 'right'\"\r\n [disabled]=\"!column.sortable\">\r\n <column-title [column]=\"column\" [titleDef]=\"_titleDef[column.field]\"></column-title>\r\n </div>\r\n @if (!_tableOption.filter?.disabled && !_tableOption.filter?.hideInlineFilter && columnOperator) {\r\n <ng-container *sdDesktop>\r\n <column-filter\r\n [autoId]=\"autoId()\"\r\n [value]=\"columnFilter?.[column.field!]!\"\r\n [operator]=\"columnOperator[column.field]\"\r\n [columnFilter]=\"columnFilter!\"\r\n [cacheValues]=\"cacheValues\"\r\n [column]=\"column\"\r\n (operatorChange)=\"columnOperator[column.field] = $event!; onOperatorChange(column, $event)\"\r\n (filterChange)=\"onFilterChange()\"\r\n (filterCommit)=\"onFilterCommit()\">\r\n </column-filter>\r\n </ng-container>\r\n }\r\n </div>\r\n </th>\r\n <td\r\n class=\"c-td px-0\"\r\n mat-cell\r\n *matCellDef=\"let item\"\r\n [sdHoverCopy]=\"item[column.field]\"\r\n [sdHoverCopyDisabled]=\"!column.cell?.copiable\">\r\n @if (column.type !== 'children') {\r\n <desktop-cell class=\"d-block px-8\" [column]=\"column\" [item]=\"item\" [cellDef]=\"cellDef()\"> </desktop-cell>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef>\r\n <ng-container *ngIf=\"footerDef()[column.field]\">\r\n <ng-container *ngTemplateOutlet=\"footerDef()[column.field].templateRef; context: { items: _items, column: column }\">\r\n </ng-container>\r\n </ng-container>\r\n </td>\r\n </ng-container>\r\n }\r\n <tr class=\"c-first-header\" mat-header-row *matHeaderRowDef=\"_configuration.firstHeaders; sticky: true\"></tr>\r\n @if (!!_configuration.secondHeaders.length) {\r\n <tr class=\"c-second-header\" mat-header-row *matHeaderRowDef=\"_configuration.secondHeaders; sticky: true\"></tr>\r\n }\r\n <tr\r\n mat-row\r\n cdkDrag\r\n [cdkDragData]=\"row\"\r\n [cdkDragDisabled]=\"\r\n !_tableOption.rowReorder?.enabled ||\r\n !!row.meta?.group?.items?.length ||\r\n (row.meta?.tree?.level ?? 0) > 0 ||\r\n isReorderDisabled(row)\r\n \"\r\n *matRowDef=\"let row; columns: _configuration.displayedColumns\"\r\n matRipple\r\n class=\"c-row\"\r\n [class.sd-tree-row]=\"!!_tableOption.tree\"\r\n [ngClass]=\"_tableOption.tree ? 'sd-tree-level-' + (row.meta?.tree?.level ?? 0) : null\"\r\n [ngStyle]=\"rowStyle(row)\"\r\n [class.selected]=\"row.meta.selector.isSelected\"></tr>\r\n\r\n <tr mat-row *matRowDef=\"let row; columns: ['sdSubInformation']\" class=\"c-detail-row\"></tr>\r\n @if (hasFooter() && !!_configuration.displayedFooters.length) {\r\n <tr mat-footer-row *matFooterRowDef=\"_configuration.displayedFooters; sticky: true\"></tr>\r\n }\r\n </table>\r\n @if (!_loading && !_total) {\r\n <div class=\"c-no-data-row\">\r\n @if (_isFiltered) {\r\n @if (tableConfiguration?.images?.filterEmpty) {\r\n <img class=\"c-image\" [src]=\"tableConfiguration!.images!.filterEmpty\" alt=\"filter-empty\" />\r\n } @else {\r\n <img class=\"c-image sd-image-filter-empty\" alt=\"filter-empty\" />\r\n }\r\n <div class=\"T16M\">{{ 'core.component.table.no-results' | translate }}</div>\r\n <div class=\"T16R text-secondary\">{{ 'core.component.table.no-results-hint' | translate }}</div>\r\n } @else {\r\n @if (_requireFiltered) {\r\n @if (tableConfiguration?.images?.filterRequired) {\r\n <img class=\"c-image\" [src]=\"tableConfiguration!.images!.filterRequired\" alt=\"filter-required\" />\r\n } @else {\r\n <img class=\"c-image sd-image-filter-required\" alt=\"filter-required\" />\r\n }\r\n <div class=\"T16R text-secondary\">{{ 'core.component.table.choose-filter-hint' | translate }}</div>\r\n } @else {\r\n @if (tableConfiguration?.images?.dataEmpty) {\r\n <img class=\"c-image\" [src]=\"tableConfiguration!.images!.dataEmpty\" alt=\"data-empty\" />\r\n } @else {\r\n <img class=\"c-image sd-image-data-empty\" alt=\"data-empty\" />\r\n }\r\n <div class=\"T16R text-secondary\">{{ 'core.component.table.no-data' | translate }}</div>\r\n }\r\n }\r\n </div>\r\n }\r\n </div>\r\n <div class=\"c-paginator\">\r\n <div class=\"c-action\">\r\n <ng-container *sdDesktop>\r\n @if (_tableOption.reload?.visible) {\r\n <sd-button\r\n class=\"mr-8\"\r\n [title]=\"'core.component.table.reload' | translate\"\r\n prefixIcon=\"refresh\"\r\n (click)=\"reload()\"\r\n [disabled]=\"!_items.length\"\r\n type=\"link\">\r\n </sd-button>\r\n }\r\n </ng-container>\r\n @if (_export && _items.length) {\r\n @if (_export.type === 'custom') {\r\n <sd-button class=\"mr-8\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" (click)=\"exportCustom()\" type=\"link\"> </sd-button>\r\n } @else {\r\n @if (_export.visible) {\r\n @if (_exporting) {\r\n <sd-button class=\"mr-8\" [loading]=\"_exporting\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" type=\"link\"> </sd-button>\r\n } @else {\r\n @if (_export.visible === 'ALL' || !_export.visible) {\r\n <sd-button class=\"mr-8\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" [matMenuTriggerFor]=\"menu\" type=\"link\"> </sd-button>\r\n <mat-menu #menu=\"matMenu\">\r\n <button mat-menu-item (click)=\"exportExcel()\" type=\"button\">\r\n <mat-icon fontSet=\"material-icons-outlined\">file_download</mat-icon>\r\n <span> {{ 'core.component.table.export-excel' | translate }}</span>\r\n </button>\r\n <button mat-menu-item (click)=\"exportCSV()\" type=\"button\">\r\n <mat-icon fontSet=\"material-icons-outlined\">file_download</mat-icon>\r\n <span> {{ 'core.component.table.export-csv' | translate }}</span>\r\n </button>\r\n </mat-menu>\r\n } @else if (_export.visible === 'EXCEL') {\r\n <sd-button class=\"mr-8\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" (click)=\"exportExcel()\" type=\"link\"> </sd-button>\r\n } @else if (_export.visible === 'CSV') {\r\n <sd-button class=\"mr-8\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" (click)=\"exportCSV()\" type=\"link\"> </sd-button>\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n <ng-container *sdDesktop>\r\n @if (configComponent()) {\r\n <sd-button\r\n class=\"mr-8\"\r\n [title]=\"'core.component.table.setup-short' | translate\"\r\n prefixIcon=\"settings\"\r\n (click)=\"configComponent()!.open()\"\r\n type=\"link\">\r\n </sd-button>\r\n }\r\n </ng-container>\r\n <!-- Mobile: n\u00FAt Filter m\u1EDF mobile-filter drawer (inline filter \u1EA9n tr\u00EAn mobile) -->\r\n <ng-container *sdMobile>\r\n @if (!_tableOption.filter?.disabled && mobileFilter()) {\r\n <sd-button\r\n [autoId]=\"autoId() + 'mobile-filter-open'\"\r\n class=\"mr-8\"\r\n prefixIcon=\"filter_alt\"\r\n (click)=\"mobileFilter()!.open()\"\r\n type=\"link\">\r\n </sd-button>\r\n }\r\n </ng-container>\r\n </div>\r\n @let hidePaginator = !_tableOption.paginate?.pageSize || _total === undefined || _total <= _tableOption.paginate?.pageSize!;\r\n <!-- Desktop paginator: full config (pageSize dropdown, first/last buttons) -->\r\n <ng-container *sdDesktop>\r\n <mat-paginator\r\n [class.d-none]=\"_tableOption.paginate?.hidden || hidePaginator\"\r\n [length]=\"_total\"\r\n [pageSize]=\"_tableOption.paginate?.pageSize\"\r\n [pageSizeOptions]=\"_tableOption.paginate?.pages!\"\r\n [showFirstLastButtons]=\"_tableOption.paginate?.showFirstLastButtons\"\r\n [hidePageSize]=\"_tableOption.paginate?.hidePageSize\"></mat-paginator>\r\n </ng-container>\r\n <!-- Mobile paginator: \u1EA9n pageSize dropdown + first/last buttons \u0111\u1EC3 ti\u1EBFt ki\u1EC7m kh\u00F4ng gian -->\r\n <ng-container *sdMobile>\r\n <mat-paginator\r\n [class.d-none]=\"_tableOption.paginate?.hidden || hidePaginator\"\r\n [length]=\"_total\"\r\n [pageSize]=\"_tableOption.paginate?.pageSize\"\r\n [showFirstLastButtons]=\"false\"\r\n hidePageSize></mat-paginator>\r\n </ng-container>\r\n <!-- \"\u0110ang hi\u1EC3n th\u1ECB...\" ch\u1EC9 desktop -->\r\n <ng-container *sdDesktop>\r\n @if (!_tableOption.paginate?.hidden && hidePaginator && _total !== undefined && _total > 0) {\r\n <div class=\"T14R pr-16\">\r\n {{ 'core.component.table.showing' | translate }} <span class=\"T14M ml-2\">1-{{ _total }}/{{ _total }}</span>\r\n </div>\r\n }\r\n </ng-container>\r\n </div>\r\n </div>\r\n <selector-action [tableOption]=\"_tableOption\" [selectedTableItems]=\"selectedTableItems()\" (clear)=\"onClearSelection(groupedItems)\" />\r\n @if (_tableOption.config?.visible) {\r\n <config [tableOption]=\"_tableOption\" />\r\n }\r\n <!-- Mobile filter drawer \u2014 ch\u1EC9 instantiate khi c\u1EA7n render tr\u00EAn mobile -->\r\n @if (!_tableOption.filter?.disabled && filterRegister) {\r\n <mobile-filter\r\n [autoId]=\"autoId()\"\r\n [filter]=\"_tableOption.filter!\"\r\n [externalFilters]=\"_tableOption.filter?.externalFilters!\"\r\n [columns]=\"_configuration.firstColumns\"\r\n [filterDefs]=\"sdFilterDefs()\"\r\n [filterRegister]=\"filterRegister\"\r\n [cacheValues]=\"cacheValues\">\r\n </mobile-filter>\r\n }\r\n}\r\n", styles: [":host{display:flex;flex-direction:column;overflow:auto;width:100%;height:100%}:host .c-header-title{height:40px;display:flex;align-items:center}:host .c-container{position:relative;min-height:50px;display:flex;flex-direction:column;flex:1}:host .c-container .c-table{position:relative;flex:1;display:flex;flex-direction:column}:host .c-container .c-table table{border-collapse:separate;width:100%}:host .c-container .c-table table tr.c-first-header.mat-mdc-header-row{height:40px}:host .c-container .c-table table tr.c-second-header.mat-mdc-header-row{height:40px}:host .c-container .c-table table tr.c-detail-row{height:0}:host .c-container .c-table table tr.c-row.activated{background-color:#e5ecff}:host .c-container .c-table table tr.c-row.selected{background-color:#eef2ff}:host .c-container .c-table table tr.c-row:not(.selected):not(.activated):hover{background-color:#f5f5f5}:host .c-container .c-table table tr.c-row td{border-bottom-width:0}:host .c-container .c-table table tr.c-row.c-expandable{cursor:pointer}:host .c-container .c-table table tr.c-row.c-expandable:hover{background:#f5f5f5}:host .c-container .c-table table th.mat-mdc-header-cell{background-color:#f2f3f4;border-bottom:0!important}:host .c-container .c-table table td.mat-mdc-cell,:host .c-container .c-table table td.mat-mdc-footer-cell,:host .c-container .c-table table th.mat-mdc-header-cell{border-bottom-color:#f2f2f2!important}:host .c-container .c-table .c-th{vertical-align:middle;font-weight:500;font-size:14px;line-height:20px;color:#212121}:host .c-container .c-table .c-th.sd-col-resize-host{position:relative}:host .c-container .c-table .c-th.sd-resizing{-webkit-user-select:none;user-select:none}:host .c-container .c-table .c-th .sd-col-resize-handle{position:absolute;top:0;right:0;width:6px;height:100%;cursor:col-resize;-webkit-user-select:none;user-select:none;z-index:2}:host .c-container .c-table .c-th .sd-col-resize-handle:hover{background:#00000014}:host .c-container .c-table .c-td:first{padding-left:10px}:host .c-container .c-table .c-no-data-row{flex:1;width:100%;position:sticky;left:0;display:flex;flex-direction:column;align-items:center;justify-content:center}:host .c-container .c-table .c-no-data-row .c-image{margin-bottom:16px;width:96px}:host .c-container .c-loading{position:absolute;inset:0 0 56px;background:#00000026;z-index:2;display:flex;align-items:center;justify-content:center}:host .c-container .c-paginator{display:flex;flex-direction:row;justify-content:space-between;align-items:center;background-color:#fff}:host .c-container .c-paginator .c-action{padding:5px}:host .c-container .c-empty{text-align:center;background-color:#fff;border:none!important}:host .c-container .c-empty mat-icon{font-size:150px;margin-top:30px;margin-bottom:30px;opacity:.2;width:auto;height:auto}:host button.c-btn-add{background-color:#fff;box-shadow:0 2px 4px #2f313629}:host .lds-ring{display:inline-block;position:relative;width:40px;height:40px}:host .lds-ring div{box-sizing:border-box;display:block;position:absolute;width:32px;height:32px;margin:4px;border:4px solid #cef;border-radius:50%;animation:lds-ring 1.2s cubic-bezier(.5,0,.5,1) infinite;border-color:#cef transparent transparent transparent}:host .lds-ring div:nth-child(1){animation-delay:-.45s}:host .lds-ring div:nth-child(2){animation-delay:-.3s}:host .lds-ring div:nth-child(3){animation-delay:-.15s}@keyframes lds-ring{0%{transform:rotate(0)}to{transform:rotate(360deg)}}:host .sd-reorder-header,:host .sd-reorder-cell{width:40px;min-width:40px;padding:0 4px;box-sizing:border-box}:host .sd-reorder-cell mat-icon{cursor:grab;color:#00000061;display:flex;align-items:center}:host .sd-reorder-cell mat-icon:active{cursor:grabbing}:host .sd-reorder-cell mat-icon.sd-reorder-disabled{opacity:.3;cursor:not-allowed;pointer-events:none}:host ::ng-deep .mat-sort-header-content{display:block;text-align:left;width:100%}:host ::ng-deep .mat-select-arrow{color:#a6a6a6}:host ::ng-deep .mat-sort-header-disabled{background-image:none!important;cursor:default!important;padding-right:0!important}:host ::ng-deep .mat-sort-header-container{align-items:start!important}:host ::ng-deep .mat-sort-header-arrow{margin-top:4px!important}:host ::ng-deep .mat-sort-header-arrow{display:none!important}:host ::ng-deep .mat-sort-header{cursor:pointer}:host ::ng-deep .mat-sort-header[aria-sort]{background-repeat:no-repeat;background-position:center right 0;background-size:16px 16px;cursor:pointer;padding-right:24px}:host ::ng-deep .mat-sort-header[aria-sort=none]{background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 0 24 24' width='24px' fill='%23000000'%3E%3Cpath d='M0 0h24v24H0V0z' fill='none'/%3E%3Cpath fill='%237A7A7A' d='M12 5.83L15.17 9l1.41-1.41L12 3 7.41 7.59 8.83 9 12 5.83zm0 12.34L8.83 15l-1.41 1.41L12 21l4.59-4.59L15.17 15 12 18.17z'/%3E%3C/svg%3E\")}:host ::ng-deep .mat-sort-header[aria-sort=ascending]{background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 0 24 24' width='24px' fill='%23000000'%3E%3Cpath d='M0 0h24v24H0V0z' fill='none'/%3E%3Cpath fill='%237A7A7A' d='M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z'/%3E%3C/svg%3E\")}:host ::ng-deep .mat-sort-header[aria-sort=descending]{background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 0 24 24' width='24px' fill='%23000000'%3E%3Cpath d='M0 0h24v24H0V0z' fill='none'/%3E%3Cpath fill='%237A7A7A' d='M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z'/%3E%3C/svg%3E\")}:host ::ng-deep .c-paginator .mat-mdc-paginator .mdc-text-field--outlined .mat-mdc-form-field-infix,:host ::ng-deep .c-paginator .mat-mdc-paginator .mdc-text-field--no-label .mat-mdc-form-field-infix{padding-top:2px;padding-bottom:2px;min-height:32px}:host ::ng-deep .c-paginator .mat-mdc-paginator-range-label{margin:0 4px}:host ::ng-deep .c-paginator .mat-mdc-paginator-page-size-select mat-select{margin-top:2px!important}:host ::ng-deep .cdk-drag-preview{box-shadow:0 4px 12px #00000026;background:#fff;display:table;width:100%}:host ::ng-deep .cdk-drag-preview td{padding:0 8px;border-bottom:1px solid rgba(0,0,0,.12)}:host ::ng-deep .cdk-drag-placeholder{opacity:0}:host ::ng-deep .cdk-drop-list-dragging tr.c-row:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}:host ::ng-deep .sd-selection-cell{width:42px;min-width:42px;max-width:42px}:host ::ng-deep .c-selection{transform:scale(.85);transform-origin:center}:host ::ng-deep .sd-tree-toggle-cell{width:40px;min-width:40px;max-width:100px}:host ::ng-deep .sd-tree-toggle-inner{display:flex;align-items:center;min-height:40px}:host ::ng-deep .sd-tree-spinner{transform:scale(.5);margin:0 auto}\n", ":host ::ng-deep .sticky-shadow-right{overflow:visible!important}:host ::ng-deep .sticky-shadow-right:after{content:\"\";position:absolute;top:0;right:0;bottom:0;width:8px;transform:translate(100%);background:linear-gradient(to right,rgba(0,0,0,.12),transparent);pointer-events:none}:host ::ng-deep .sticky-shadow-left{overflow:visible!important}:host ::ng-deep .sticky-shadow-left:after{content:\"\";position:absolute;top:0;left:0;bottom:0;width:8px;transform:translate(-100%);background:linear-gradient(to left,rgba(0,0,0,.12),transparent);pointer-events:none}\n"] }]
|
|
4339
|
+
], template: "@let _configuration = configuration();\r\n@let _tableOption = tableOption()!;\r\n@let _loading = loading();\r\n@let _items = items();\r\n@let _total = total();\r\n@let _isFiltered = isFiltered();\r\n@let _requireFiltered = requireFiltered();\r\n@let _export = _tableOption?.export;\r\n@let _exporting = exporting();\r\n@let _titleDef = titleDef();\r\n\r\n@if (_configuration) {\r\n @if (!_tableOption.filter?.disabled && !!_tableOption.filter?.externalFilters?.length && filterRegister) {\r\n <external-filter\r\n class=\"mb-16\"\r\n [autoId]=\"autoId()\"\r\n [filterRegister]=\"filterRegister\"\r\n [filter]=\"_tableOption.filter!\"\r\n [externalFilters]=\"_tableOption.filter?.externalFilters!\">\r\n </external-filter>\r\n }\r\n @let groupedItems = _items | sdTree: _tableOption.tree : treeRevision() | sdGroup: _tableOption : groupExpandState;\r\n <ng-content select=\"[sdTableTop]\"></ng-content>\r\n <div class=\"c-container\">\r\n @if (_loading) {\r\n <div class=\"c-loading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n }\r\n <div\r\n class=\"c-table\"\r\n sdScroll\r\n stickyShadow\r\n [style.max-height]=\"_tableOption.style?.maxHeight\"\r\n [style.min-height]=\"_tableOption.style?.minHeight\">\r\n <table\r\n mat-table\r\n [dataSource]=\"groupedItems\"\r\n [trackBy]=\"trackBy\"\r\n matSort\r\n [matSortDisabled]=\"!_tableOption.sort?.enable\"\r\n multiTemplateDataRows\r\n cdkDropList\r\n [cdkDropListData]=\"groupedItems\"\r\n [cdkDropListDisabled]=\"!_tableOption.rowReorder?.enabled\"\r\n [cdkDropListSortPredicate]=\"reorderSortPredicate\"\r\n (cdkDropListDropped)=\"onReorderDrop($event)\">\r\n @if (_tableOption.rowReorder?.enabled) {\r\n <ng-container matColumnDef=\"sdReorder\">\r\n <th mat-header-cell *matHeaderCellDef class=\"sd-reorder-header\" [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td mat-cell *matCellDef=\"let row\" class=\"sd-reorder-cell\">\r\n @if (!row.meta?.group?.items?.length) {\r\n <mat-icon cdkDragHandle [class.sd-reorder-disabled]=\"isReorderDisabled(row)\">\r\n {{ _tableOption.rowReorder?.icon || 'drag_indicator' }}\r\n </mat-icon>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n\r\n @if (_tableOption.tree) {\r\n <ng-container matColumnDef=\"sdTreeToggle\">\r\n <th\r\n mat-header-cell\r\n *matHeaderCellDef\r\n class=\"sd-tree-toggle-cell p-0\"\r\n [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td mat-cell *matCellDef=\"let row\" class=\"sd-tree-toggle-cell p-0\">\r\n @if (row.meta?.tree) {\r\n <div\r\n class=\"sd-tree-toggle-inner\"\r\n [style.padding-left.px]=\"(row.meta.tree.level ?? 0) * (_tableOption.tree?.indentSize ?? 20)\">\r\n @if (row.meta.tree.hasChildren) {\r\n @if (row.meta.tree.isExpanding) {\r\n <div class=\"lds-ring sd-tree-spinner\">\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n </div>\r\n } @else {\r\n <sd-button\r\n type=\"link\"\r\n [prefixIcon]=\"row.meta.tree.isExpanded ? 'expand_less' : 'expand_more'\"\r\n (click)=\"onTreeToggle(row); $event.stopPropagation()\"\r\n width=\"35px\">\r\n </sd-button>\r\n }\r\n }\r\n </div>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n }\r\n\r\n <ng-container matColumnDef=\"sdSubInformation\" sticky>\r\n <td class=\"p-0\" mat-cell *matCellDef=\"let item\" [attr.colspan]=\"_configuration.displayedColumns.length\">\r\n @if (sdSubInformation()?.templateRef) {\r\n @if (_tableOption.expand?.always) {\r\n <ng-container *ngTemplateOutlet=\"sdSubInformation()?.templateRef!; context: { item: item }\"> </ng-container>\r\n } @else {\r\n <div [@detailExpand]=\"item.isExpanded ? 'expanded' : 'collapsed'\">\r\n @if (item.isExpanded) {\r\n <ng-container *ngTemplateOutlet=\"sdSubInformation()?.templateRef!; context: { item: item }\"> </ng-container>\r\n }\r\n </div>\r\n }\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n\r\n <ng-container matColumnDef=\"sdSubInformationAction\" stickyEnd>\r\n <th class=\"p-0\" mat-header-cell *matHeaderCellDef style=\"width: 1px\" [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td mat-cell *matCellDef=\"let element\">\r\n @if (!element.isExpanding && !_tableOption.expand?.always) {\r\n <sd-button\r\n type=\"link\"\r\n [prefixIcon]=\"element.isExpanded ? 'expand_less' : 'expand_more'\"\r\n (click)=\"onExpand(element)\"\r\n width=\"35px\">\r\n </sd-button>\r\n }\r\n @if (element.isExpanding) {\r\n <div class=\"lds-ring\">\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n </div>\r\n }\r\n </td>\r\n </ng-container>\r\n\r\n <ng-container matColumnDef=\"sdSelection\" sticky>\r\n <th class=\"sd-selection-cell p-0\" mat-header-cell *matHeaderCellDef [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\">\r\n @let visibleSelectAll = _items | selectionVisibleSelectAll: _tableOption.selector | async;\r\n @if (visibleSelectAll) {\r\n <mat-checkbox\r\n class=\"c-selection px-8\"\r\n color=\"primary\"\r\n [ngModel]=\"isSelectAll()\"\r\n (ngModelChange)=\"isSelectAll.set($event)\"\r\n (change)=\"onSelectAll()\">\r\n </mat-checkbox>\r\n }\r\n </th>\r\n\r\n <td class=\"sd-selection-cell p-0\" mat-cell *matCellDef=\"let item\">\r\n @let visible = item | selectionVisible: _tableOption.selector;\r\n @if (visible) {\r\n @if (_tableOption.selector?.single) {\r\n <mat-radio-button\r\n class=\"c-selection px-8\"\r\n color=\"primary\"\r\n [checked]=\"item.meta.selector.isSelected\"\r\n (change)=\"item.meta.selector.isSelected = true; onSelect(item)\"\r\n [disabled]=\"selectedTableItems() | selectionDisabled: item : _tableOption.selector!\">\r\n </mat-radio-button>\r\n } @else {\r\n <mat-checkbox\r\n class=\"c-selection px-8\"\r\n color=\"primary\"\r\n [(ngModel)]=\"item.meta.selector.isSelected\"\r\n (change)=\"onSelect(item)\"\r\n [disabled]=\"selectedTableItems() | selectionDisabled: item : _tableOption.selector!\">\r\n </mat-checkbox>\r\n }\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n @if (_tableOption.index?.enabled) {\r\n @let _pageOffset = pageOffset();\r\n @let _indexWidth = _tableOption.index?.width || '50px';\r\n <ng-container matColumnDef=\"sdIndex\" sticky>\r\n <th\r\n class=\"text-center p-0\"\r\n mat-header-cell\r\n *matHeaderCellDef\r\n [style.width]=\"_indexWidth\"\r\n [style.min-width]=\"_indexWidth\"\r\n [style.max-width]=\"_indexWidth\"\r\n [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\">\r\n {{ _tableOption.index?.title || '#' }}\r\n </th>\r\n <td class=\"text-center px-4\" mat-cell *matCellDef=\"let item; let i = dataIndex\" [style.min-width]=\"_indexWidth\" [style.max-width]=\"_indexWidth\">\r\n @if (!item?.meta?.group?.isGroupHeader) {\r\n @if (_tableOption.tree && item?.meta?.tree?.indexPath?.length) {\r\n <!-- why: tree \u2192 STT ph\u00E2n c\u1EA5p 1, 1.2, 1.2.1 (indexPath join '.'). T\u00F4 \u0111\u1EADm root (level 0). -->\r\n <span [class.sd-stt-root]=\"(item.meta.tree.level ?? 0) === 0\">\r\n {{ item.meta.tree.indexPath.join('.') }}\r\n </span>\r\n } @else {\r\n {{ _pageOffset + i + 1 }}\r\n }\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef [style.min-width]=\"_indexWidth\" [style.max-width]=\"_indexWidth\"></td>\r\n </ng-container>\r\n }\r\n <ng-container\r\n matColumnDef=\"sdCommand\"\r\n [sticky]=\"_tableOption.command?.align !== 'right'\"\r\n [stickyEnd]=\"_tableOption.command?.align === 'right'\">\r\n <th class=\"p-0\" mat-header-cell *matHeaderCellDef style=\"width: 50px\" [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td class=\"px-8\" mat-cell *matCellDef=\"let item\">\r\n <desktop-command\r\n [autoId]=\"autoId()\"\r\n [commands]=\"_tableOption.command?.commands || _tableOption.commands || []\"\r\n [item]=\"item\"\r\n [itemIndex]=\"groupedItems.indexOf(item)\"></desktop-command>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n <!-- why: group header row d\u00F9ng matRowDef RI\u00CANG v\u1EDBi column list ['sdGroupHeader']\r\n qua predicate when:isGroupHeaderRow. Cell colspan = displayedColumns.length \u0111\u1EC3\r\n span TO\u00C0N B\u1ED8 width data row. Tr\u00E1nh colspan trick overflow row khi c\u00E1c TD kh\u00E1c render. -->\r\n <ng-container matColumnDef=\"sdGroupHeader\">\r\n <td\r\n class=\"p-0 sd-group-header-cell\"\r\n mat-cell\r\n *matCellDef=\"let item\"\r\n [attr.colspan]=\"sdGroupColspan()\">\r\n <div class=\"sd-group-row d-flex align-items-center py-8\">\r\n <!-- why: slot 42px kh\u1EDBp width v\u1EDBi sd-selection-cell data row \u2192 checkbox group c\u0103n TR\u1EE4C d\u1ECDc \u0111\u00FAng v\u1EDBi checkbox data. -->\r\n @if (_tableOption.selector?.visible && !_tableOption.selector?.single) {\r\n <div class=\"sd-group-selection-slot d-flex align-items-center justify-content-center\">\r\n <mat-checkbox\r\n class=\"c-selection\"\r\n color=\"primary\"\r\n [checked]=\"isGroupAllSelected(item)\"\r\n [indeterminate]=\"isGroupIndeterminate(item)\"\r\n (change)=\"onSelectGroup(item, $event.checked)\">\r\n </mat-checkbox>\r\n </div>\r\n } @else {\r\n <div class=\"sd-group-selection-slot\"></div>\r\n }\r\n @if (_tableOption.group?.collapsible) {\r\n <sd-button\r\n type=\"link\"\r\n [prefixIcon]=\"item.meta.group.isExpanded ? 'expand_more' : 'chevron_right'\"\r\n width=\"32px\"\r\n (click)=\"toggleGroupExpand(item)\">\r\n </sd-button>\r\n }\r\n @if (sdGroupDef()?.templateRef; as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl; context: groupContext(item)\"></ng-container>\r\n } @else {\r\n <span class=\"T14R\">{{ item.meta.group.values | json }}</span>\r\n }\r\n </div>\r\n </td>\r\n </ng-container>\r\n <!-- why: filler column \u1EDF cu\u1ED1i h\u1EA5p th\u1EE5 leftover space khi t\u1ED5ng width c\u00E1c c\u1ED9t data < container \u2014 gi\u1EEF cho selection/STT/command kh\u00F4ng b\u1ECB d\u00E3n. -->\r\n <ng-container matColumnDef=\"sdFiller\">\r\n <th class=\"sd-filler-cell p-0\" mat-header-cell *matHeaderCellDef [attr.rowspan]=\"_configuration.multipleHeader ? 2 : 1\"></th>\r\n <td class=\"sd-filler-cell p-0\" mat-cell *matCellDef=\"let item\"></td>\r\n <td class=\"sd-filler-cell p-0\" mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n @for (column of _configuration.firstColumns; track column.field) {\r\n <ng-container [matColumnDef]=\"column.field\" [sticky]=\"_configuration.fixedColumn[column.field]\">\r\n <th\r\n mat-header-cell\r\n *matHeaderCellDef\r\n class=\"px-8 py-8 c-th\"\r\n [sdColumnResize]=\"!!_tableOption.config?.resizable && column.type !== 'children'\"\r\n [minWidth]=\"column.minWidth\"\r\n [maxWidth]=\"column.maxWidth\"\r\n (resizeEnd)=\"onColumnResize(column.field, $event)\"\r\n [style.width]=\"column.width\"\r\n [style.min-width]=\"column.minWidth || column.width\"\r\n [style.max-width]=\"column.maxWidth\"\r\n [attr.rowspan]=\"_configuration.multipleHeader && column.type !== 'children' ? 2 : 1\"\r\n [attr.colspan]=\"column.type === 'children' ? column.children.length : 1\">\r\n <div>\r\n @if (column.type === 'children') {\r\n <div\r\n aria-hidden=\"true\"\r\n class=\"c-header-title\"\r\n [class.justify-content-end]=\"column.align === 'right'\"\r\n [class.text-right]=\"column.align === 'right'\">\r\n <column-title [column]=\"column\" [titleDef]=\"_titleDef[column.field]\"></column-title>\r\n </div>\r\n } @else {\r\n <div\r\n aria-hidden=\"true\"\r\n mat-sort-header\r\n class=\"c-header-title\"\r\n [class.justify-content-end]=\"column.align === 'right'\"\r\n [class.text-right]=\"column.align === 'right'\"\r\n [disabled]=\"!column.sortable\">\r\n <column-title [column]=\"column\" [titleDef]=\"_titleDef[column.field]\"></column-title>\r\n </div>\r\n @let hideInlineFilter =\r\n _tableOption.filter?.disabled ||\r\n _tableOption.filter?.hideInlineFilter === true ||\r\n (_tableOption.filter?.hideInlineFilter === 'auto' && !_isFiltered && _total! <= 10);\r\n @if (!hideInlineFilter) {\r\n <ng-container *sdDesktop>\r\n <column-filter\r\n [autoId]=\"autoId()\"\r\n [value]=\"columnFilter?.[column.field!]!\"\r\n [operator]=\"columnOperator[column.field]\"\r\n (operatorChange)=\"columnOperator[column.field] = $event!; onOperatorChange(column, $event)\"\r\n [columnFilter]=\"columnFilter!\"\r\n [cacheValues]=\"cacheValues\"\r\n [column]=\"column\"\r\n (filterChange)=\"onFilterChange()\"\r\n (filterCommit)=\"onFilterCommit()\">\r\n </column-filter>\r\n </ng-container>\r\n }\r\n }\r\n </div>\r\n </th>\r\n <td\r\n class=\"c-td px-0\"\r\n [class.d-none]=\"column.type === 'children'\"\r\n mat-cell\r\n *matCellDef=\"let item\"\r\n [sdHoverCopy]=\"(item.data && item.data[column.field]) || ''\"\r\n [sdHoverCopyDisabled]=\"!column.cell?.copiable\">\r\n @if (column.type !== 'children' && !item?.meta?.group?.isGroupHeader) {\r\n <desktop-cell class=\"d-block px-8\" [column]=\"column\" [item]=\"item\" [cellDef]=\"cellDef()\"> </desktop-cell>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef>\r\n <ng-container *ngIf=\"footerDef()[column.field]\">\r\n <ng-container *ngTemplateOutlet=\"footerDef()[column.field].templateRef; context: { items: _items, column: column }\">\r\n </ng-container>\r\n </ng-container>\r\n </td>\r\n </ng-container>\r\n }\r\n @for (column of _configuration.secondColumns; track column.field) {\r\n <ng-container [matColumnDef]=\"column.field\">\r\n <th\r\n mat-header-cell\r\n *matHeaderCellDef\r\n class=\"c-th px-8\"\r\n [style.width]=\"column.width\"\r\n [style.min-width]=\"column.minWidth || column.width\"\r\n [style.max-width]=\"column.maxWidth\">\r\n <div>\r\n <div\r\n aria-hidden=\"true\"\r\n mat-sort-header\r\n class=\"c-header-title\"\r\n [class.justify-content-end]=\"column.align === 'right'\"\r\n [class.text-right]=\"column.align === 'right'\"\r\n [disabled]=\"!column.sortable\">\r\n <column-title [column]=\"column\" [titleDef]=\"_titleDef[column.field]\"></column-title>\r\n </div>\r\n @if (!_tableOption.filter?.disabled && !_tableOption.filter?.hideInlineFilter && columnOperator) {\r\n <ng-container *sdDesktop>\r\n <column-filter\r\n [autoId]=\"autoId()\"\r\n [value]=\"columnFilter?.[column.field!]!\"\r\n [operator]=\"columnOperator[column.field]\"\r\n [columnFilter]=\"columnFilter!\"\r\n [cacheValues]=\"cacheValues\"\r\n [column]=\"column\"\r\n (operatorChange)=\"columnOperator[column.field] = $event!; onOperatorChange(column, $event)\"\r\n (filterChange)=\"onFilterChange()\"\r\n (filterCommit)=\"onFilterCommit()\">\r\n </column-filter>\r\n </ng-container>\r\n }\r\n </div>\r\n </th>\r\n <td\r\n class=\"c-td px-0\"\r\n mat-cell\r\n *matCellDef=\"let item\"\r\n [sdHoverCopy]=\"item[column.field]\"\r\n [sdHoverCopyDisabled]=\"!column.cell?.copiable\">\r\n @if (column.type !== 'children') {\r\n <desktop-cell class=\"d-block px-8\" [column]=\"column\" [item]=\"item\" [cellDef]=\"cellDef()\"> </desktop-cell>\r\n }\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef>\r\n <ng-container *ngIf=\"footerDef()[column.field]\">\r\n <ng-container *ngTemplateOutlet=\"footerDef()[column.field].templateRef; context: { items: _items, column: column }\">\r\n </ng-container>\r\n </ng-container>\r\n </td>\r\n </ng-container>\r\n }\r\n <tr class=\"c-first-header\" mat-header-row *matHeaderRowDef=\"_configuration.firstHeaders; sticky: true\"></tr>\r\n @if (!!_configuration.secondHeaders.length) {\r\n <tr class=\"c-second-header\" mat-header-row *matHeaderRowDef=\"_configuration.secondHeaders; sticky: true\"></tr>\r\n }\r\n <!-- Group header row \u2014 ch\u1EC9 1 cell sdGroupHeader colspan to\u00E0n width. -->\r\n <tr\r\n mat-row\r\n *matRowDef=\"let row; columns: ['sdGroupHeader']; when: isGroupHeaderRow\"\r\n class=\"c-group-row-tr\"></tr>\r\n\r\n <!-- Data row \u2014 d\u00F9ng displayedColumns \u0111\u1EA7y \u0111\u1EE7; when isDataRow \u0111\u1EC3 lo\u1EA1i tr\u1EEB group header. -->\r\n <tr\r\n mat-row\r\n cdkDrag\r\n [cdkDragData]=\"row\"\r\n [cdkDragDisabled]=\"\r\n !_tableOption.rowReorder?.enabled ||\r\n !!row.meta?.group?.items?.length ||\r\n (row.meta?.tree?.level ?? 0) > 0 ||\r\n isReorderDisabled(row)\r\n \"\r\n *matRowDef=\"let row; columns: _configuration.displayedColumns; when: isDataRow\"\r\n matRipple\r\n class=\"c-row\"\r\n [class.sd-tree-row]=\"!!_tableOption.tree\"\r\n [ngClass]=\"_tableOption.tree ? 'sd-tree-level-' + (row.meta?.tree?.level ?? 0) : null\"\r\n [ngStyle]=\"rowStyle(row)\"\r\n [class.selected]=\"row.meta.selector.isSelected\"></tr>\r\n\r\n <!-- Sub-information row \u2014 also gated b\u1EDFi isDataRow \u0111\u1EC3 KH\u00D4NG render empty expand row d\u01B0\u1EDBi group header. -->\r\n <tr mat-row *matRowDef=\"let row; columns: ['sdSubInformation']; when: isDataRow\" class=\"c-detail-row\"></tr>\r\n @if (hasFooter() && !!_configuration.displayedFooters.length) {\r\n <tr mat-footer-row *matFooterRowDef=\"_configuration.displayedFooters; sticky: true\"></tr>\r\n }\r\n </table>\r\n @if (!_loading && !_total) {\r\n <div class=\"c-no-data-row\">\r\n @if (_isFiltered) {\r\n @if (tableConfiguration?.images?.filterEmpty) {\r\n <img class=\"c-image\" [src]=\"tableConfiguration!.images!.filterEmpty\" alt=\"filter-empty\" />\r\n } @else {\r\n <img class=\"c-image sd-image-filter-empty\" alt=\"filter-empty\" />\r\n }\r\n <div class=\"T16M\">{{ 'core.component.table.no-results' | translate }}</div>\r\n <div class=\"T16R text-secondary\">{{ 'core.component.table.no-results-hint' | translate }}</div>\r\n } @else {\r\n @if (_requireFiltered) {\r\n @if (tableConfiguration?.images?.filterRequired) {\r\n <img class=\"c-image\" [src]=\"tableConfiguration!.images!.filterRequired\" alt=\"filter-required\" />\r\n } @else {\r\n <img class=\"c-image sd-image-filter-required\" alt=\"filter-required\" />\r\n }\r\n <div class=\"T16R text-secondary\">{{ 'core.component.table.choose-filter-hint' | translate }}</div>\r\n } @else {\r\n @if (tableConfiguration?.images?.dataEmpty) {\r\n <img class=\"c-image\" [src]=\"tableConfiguration!.images!.dataEmpty\" alt=\"data-empty\" />\r\n } @else {\r\n <img class=\"c-image sd-image-data-empty\" alt=\"data-empty\" />\r\n }\r\n <div class=\"T16R text-secondary\">{{ 'core.component.table.no-data' | translate }}</div>\r\n }\r\n }\r\n </div>\r\n }\r\n </div>\r\n <div class=\"c-paginator\">\r\n <div class=\"c-action\">\r\n <ng-container *sdDesktop>\r\n @if (_tableOption.reload?.visible) {\r\n <sd-button\r\n class=\"mr-8\"\r\n [title]=\"'core.component.table.reload' | translate\"\r\n prefixIcon=\"refresh\"\r\n (click)=\"reload()\"\r\n [disabled]=\"!_items.length\"\r\n type=\"link\">\r\n </sd-button>\r\n }\r\n </ng-container>\r\n @if (_export && _items.length) {\r\n @if (_export.type === 'custom') {\r\n <sd-button class=\"mr-8\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" (click)=\"exportCustom()\" type=\"link\"> </sd-button>\r\n } @else {\r\n @if (_export.visible) {\r\n @if (_exporting) {\r\n <sd-button class=\"mr-8\" [loading]=\"_exporting\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" type=\"link\"> </sd-button>\r\n } @else {\r\n @if (_export.visible === 'ALL' || !_export.visible) {\r\n <sd-button class=\"mr-8\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" [matMenuTriggerFor]=\"menu\" type=\"link\"> </sd-button>\r\n <mat-menu #menu=\"matMenu\">\r\n <button mat-menu-item (click)=\"exportExcel()\" type=\"button\">\r\n <mat-icon fontSet=\"material-icons-outlined\">file_download</mat-icon>\r\n <span> {{ 'core.component.table.export-excel' | translate }}</span>\r\n </button>\r\n <button mat-menu-item (click)=\"exportCSV()\" type=\"button\">\r\n <mat-icon fontSet=\"material-icons-outlined\">file_download</mat-icon>\r\n <span> {{ 'core.component.table.export-csv' | translate }}</span>\r\n </button>\r\n </mat-menu>\r\n } @else if (_export.visible === 'EXCEL') {\r\n <sd-button class=\"mr-8\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" (click)=\"exportExcel()\" type=\"link\"> </sd-button>\r\n } @else if (_export.visible === 'CSV') {\r\n <sd-button class=\"mr-8\" [title]=\"exportTitle()\" prefixIcon=\"get_app\" (click)=\"exportCSV()\" type=\"link\"> </sd-button>\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n <ng-container *sdDesktop>\r\n @if (configComponent()) {\r\n <sd-button\r\n class=\"mr-8\"\r\n [title]=\"'core.component.table.setup-short' | translate\"\r\n prefixIcon=\"settings\"\r\n (click)=\"configComponent()!.open()\"\r\n type=\"link\">\r\n </sd-button>\r\n }\r\n </ng-container>\r\n <!-- Mobile: n\u00FAt Filter m\u1EDF mobile-filter drawer (inline filter \u1EA9n tr\u00EAn mobile) -->\r\n <ng-container *sdMobile>\r\n @if (!_tableOption.filter?.disabled && mobileFilter()) {\r\n <sd-button\r\n [autoId]=\"autoId() + 'mobile-filter-open'\"\r\n class=\"mr-8\"\r\n prefixIcon=\"filter_alt\"\r\n (click)=\"mobileFilter()!.open()\"\r\n type=\"link\">\r\n </sd-button>\r\n }\r\n </ng-container>\r\n </div>\r\n @let hidePaginator = !_tableOption.paginate?.pageSize || _total === undefined || _total <= _tableOption.paginate?.pageSize!;\r\n <!-- Desktop paginator: full config (pageSize dropdown, first/last buttons) -->\r\n <ng-container *sdDesktop>\r\n <mat-paginator\r\n [class.d-none]=\"_tableOption.paginate?.hidden || hidePaginator\"\r\n [length]=\"_total\"\r\n [pageSize]=\"_tableOption.paginate?.pageSize\"\r\n [pageSizeOptions]=\"_tableOption.paginate?.pages!\"\r\n [showFirstLastButtons]=\"_tableOption.paginate?.showFirstLastButtons\"\r\n [hidePageSize]=\"_tableOption.paginate?.hidePageSize\"></mat-paginator>\r\n </ng-container>\r\n <!-- Mobile paginator: \u1EA9n pageSize dropdown + first/last buttons \u0111\u1EC3 ti\u1EBFt ki\u1EC7m kh\u00F4ng gian -->\r\n <ng-container *sdMobile>\r\n <mat-paginator\r\n [class.d-none]=\"_tableOption.paginate?.hidden || hidePaginator\"\r\n [length]=\"_total\"\r\n [pageSize]=\"_tableOption.paginate?.pageSize\"\r\n [showFirstLastButtons]=\"false\"\r\n hidePageSize></mat-paginator>\r\n </ng-container>\r\n <!-- \"\u0110ang hi\u1EC3n th\u1ECB...\" ch\u1EC9 desktop -->\r\n <ng-container *sdDesktop>\r\n @if (!_tableOption.paginate?.hidden && hidePaginator && _total !== undefined && _total > 0) {\r\n <div class=\"T14R pr-16\">\r\n {{ 'core.component.table.showing' | translate }} <span class=\"T14M ml-2\">1-{{ _total }}/{{ _total }}</span>\r\n </div>\r\n }\r\n </ng-container>\r\n </div>\r\n </div>\r\n <selector-action [tableOption]=\"_tableOption\" [selectedTableItems]=\"selectedTableItems()\" (clear)=\"onClearSelection(groupedItems)\" />\r\n @if (_tableOption.config?.visible) {\r\n <config [tableOption]=\"_tableOption\" />\r\n }\r\n <!-- Mobile filter drawer \u2014 ch\u1EC9 instantiate khi c\u1EA7n render tr\u00EAn mobile -->\r\n @if (!_tableOption.filter?.disabled && filterRegister) {\r\n <mobile-filter\r\n [autoId]=\"autoId()\"\r\n [filter]=\"_tableOption.filter!\"\r\n [externalFilters]=\"_tableOption.filter?.externalFilters!\"\r\n [columns]=\"_configuration.firstColumns\"\r\n [filterDefs]=\"sdFilterDefs()\"\r\n [filterRegister]=\"filterRegister\"\r\n [cacheValues]=\"cacheValues\">\r\n </mobile-filter>\r\n }\r\n}\r\n", styles: [":host{display:flex;flex-direction:column;overflow:auto;width:100%;height:100%}:host .c-header-title{height:40px;display:flex;align-items:center}:host .c-container{position:relative;min-height:50px;display:flex;flex-direction:column;flex:1}:host .c-container .c-table{position:relative;flex:1;display:flex;flex-direction:column}:host .c-container .c-table table{border-collapse:separate;width:100%}:host .c-container .c-table table tr.c-first-header.mat-mdc-header-row{height:40px}:host .c-container .c-table table tr.c-second-header.mat-mdc-header-row{height:40px}:host .c-container .c-table table tr.c-detail-row{height:0}:host .c-container .c-table table tr.c-row.activated{background-color:#e5ecff}:host .c-container .c-table table tr.c-row.selected{background-color:#eef2ff}:host .c-container .c-table table tr.c-row:not(.selected):not(.activated):hover{background-color:#f5f5f5}:host .c-container .c-table table tr.c-row td{border-bottom-width:0}:host .c-container .c-table table tr.c-row.c-expandable{cursor:pointer}:host .c-container .c-table table tr.c-row.c-expandable:hover{background:#f5f5f5}:host .c-container .c-table table th.mat-mdc-header-cell{background-color:#f2f3f4;border-bottom:0!important}:host .c-container .c-table table td.mat-mdc-cell,:host .c-container .c-table table td.mat-mdc-footer-cell,:host .c-container .c-table table th.mat-mdc-header-cell{border-bottom-color:#f2f2f2!important}:host .c-container .c-table .c-th{vertical-align:middle;font-weight:500;font-size:14px;line-height:20px;color:#212121}:host .c-container .c-table .c-th.sd-col-resize-host{position:relative}:host .c-container .c-table .c-th.sd-resizing{-webkit-user-select:none;user-select:none}:host .c-container .c-table .c-th .sd-col-resize-handle{position:absolute;top:0;right:0;width:6px;height:100%;cursor:col-resize;-webkit-user-select:none;user-select:none;z-index:2}:host .c-container .c-table .c-th .sd-col-resize-handle:hover{background:#00000014}:host .c-container .c-table .c-td:first{padding-left:10px}:host .c-container .c-table .c-no-data-row{flex:1;width:100%;position:sticky;left:0;display:flex;flex-direction:column;align-items:center;justify-content:center}:host .c-container .c-table .c-no-data-row .c-image{margin-bottom:16px;width:96px}:host .c-container .c-loading{position:absolute;inset:0 0 56px;background:#00000026;z-index:2;display:flex;align-items:center;justify-content:center}:host .c-container .c-paginator{display:flex;flex-direction:row;justify-content:space-between;align-items:center;background-color:#fff}:host .c-container .c-paginator .c-action{padding:5px}:host .c-container .c-empty{text-align:center;background-color:#fff;border:none!important}:host .c-container .c-empty mat-icon{font-size:150px;margin-top:30px;margin-bottom:30px;opacity:.2;width:auto;height:auto}:host button.c-btn-add{background-color:#fff;box-shadow:0 2px 4px #2f313629}:host .lds-ring{display:inline-block;position:relative;width:40px;height:40px}:host .lds-ring div{box-sizing:border-box;display:block;position:absolute;width:32px;height:32px;margin:4px;border:4px solid #cef;border-radius:50%;animation:lds-ring 1.2s cubic-bezier(.5,0,.5,1) infinite;border-color:#cef transparent transparent transparent}:host .lds-ring div:nth-child(1){animation-delay:-.45s}:host .lds-ring div:nth-child(2){animation-delay:-.3s}:host .lds-ring div:nth-child(3){animation-delay:-.15s}@keyframes lds-ring{0%{transform:rotate(0)}to{transform:rotate(360deg)}}:host .sd-reorder-header,:host .sd-reorder-cell{width:40px;min-width:40px;padding:0 4px;box-sizing:border-box}:host .sd-reorder-cell mat-icon{cursor:grab;color:#00000061;display:flex;align-items:center}:host .sd-reorder-cell mat-icon:active{cursor:grabbing}:host .sd-reorder-cell mat-icon.sd-reorder-disabled{opacity:.3;cursor:not-allowed;pointer-events:none}:host ::ng-deep .mat-sort-header-content{display:block;text-align:left;width:100%}:host ::ng-deep .mat-select-arrow{color:#a6a6a6}:host ::ng-deep .mat-sort-header-disabled{background-image:none!important;cursor:default!important;padding-right:0!important}:host ::ng-deep .mat-sort-header-container{align-items:start!important}:host ::ng-deep .mat-sort-header-arrow{margin-top:4px!important}:host ::ng-deep .mat-sort-header-arrow{display:none!important}:host ::ng-deep .mat-sort-header{cursor:pointer}:host ::ng-deep .mat-sort-header[aria-sort]{background-repeat:no-repeat;background-position:center right 0;background-size:16px 16px;cursor:pointer;padding-right:24px}:host ::ng-deep .mat-sort-header[aria-sort=none]{background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 0 24 24' width='24px' fill='%23000000'%3E%3Cpath d='M0 0h24v24H0V0z' fill='none'/%3E%3Cpath fill='%237A7A7A' d='M12 5.83L15.17 9l1.41-1.41L12 3 7.41 7.59 8.83 9 12 5.83zm0 12.34L8.83 15l-1.41 1.41L12 21l4.59-4.59L15.17 15 12 18.17z'/%3E%3C/svg%3E\")}:host ::ng-deep .mat-sort-header[aria-sort=ascending]{background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 0 24 24' width='24px' fill='%23000000'%3E%3Cpath d='M0 0h24v24H0V0z' fill='none'/%3E%3Cpath fill='%237A7A7A' d='M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z'/%3E%3C/svg%3E\")}:host ::ng-deep .mat-sort-header[aria-sort=descending]{background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 0 24 24' width='24px' fill='%23000000'%3E%3Cpath d='M0 0h24v24H0V0z' fill='none'/%3E%3Cpath fill='%237A7A7A' d='M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z'/%3E%3C/svg%3E\")}:host ::ng-deep .c-paginator .mat-mdc-paginator .mdc-text-field--outlined .mat-mdc-form-field-infix,:host ::ng-deep .c-paginator .mat-mdc-paginator .mdc-text-field--no-label .mat-mdc-form-field-infix{padding-top:2px;padding-bottom:2px;min-height:32px}:host ::ng-deep .c-paginator .mat-mdc-paginator-range-label{margin:0 4px}:host ::ng-deep .c-paginator .mat-mdc-paginator-page-size-select mat-select{margin-top:2px!important}:host ::ng-deep .cdk-drag-preview{box-shadow:0 4px 12px #00000026;background:#fff;display:table;width:100%}:host ::ng-deep .cdk-drag-preview td{padding:0 8px;border-bottom:1px solid rgba(0,0,0,.12)}:host ::ng-deep .cdk-drag-placeholder{opacity:0}:host ::ng-deep .cdk-drop-list-dragging tr.c-row:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}:host ::ng-deep .sd-selection-cell{width:42px;min-width:42px;max-width:42px}:host ::ng-deep .sd-filler-cell{width:auto;min-width:0;padding:0!important;border:0}:host ::ng-deep .sd-group-header-cell{background:#f5f7fc;border-top:1px solid #e6e9f2;border-bottom:1px solid #e6e9f2}:host ::ng-deep .sd-group-row{min-height:36px}:host ::ng-deep .sd-group-selection-slot{width:42px;min-width:42px;max-width:42px}:host ::ng-deep .c-selection{transform:scale(.85);transform-origin:center}:host ::ng-deep .sd-tree-toggle-cell{width:40px;min-width:40px;max-width:100px}:host ::ng-deep .sd-tree-toggle-inner{display:flex;align-items:center;min-height:40px}:host ::ng-deep .sd-tree-spinner{transform:scale(.5);margin:0 auto}:host ::ng-deep tr.c-row.sd-tree-row.sd-tree-level-0{background:#fbfcfe}:host ::ng-deep tr.c-row.sd-tree-row.sd-tree-level-0>td{font-weight:500}:host ::ng-deep tr.c-row.sd-tree-row.sd-tree-level-1{background:#fff}:host ::ng-deep tr.c-row.sd-tree-row.sd-tree-level-2{background:#fafbfd}:host ::ng-deep tr.c-row.sd-tree-row.sd-tree-level-3{background:#f6f8fb}:host ::ng-deep tr.c-row.sd-tree-row:not(.sd-tree-level-0)>td.sd-tree-toggle-cell .sd-tree-toggle-inner{border-left:1px dashed #d8dde6}:host ::ng-deep .sd-stt-root{font-weight:700;color:#1f2330}\n", ":host ::ng-deep .sticky-shadow-right{overflow:visible!important}:host ::ng-deep .sticky-shadow-right:after{content:\"\";position:absolute;top:0;right:0;bottom:0;width:8px;transform:translate(100%);background:linear-gradient(to right,rgba(0,0,0,.12),transparent);pointer-events:none}:host ::ng-deep .sticky-shadow-left{overflow:visible!important}:host ::ng-deep .sticky-shadow-left:after{content:\"\";position:absolute;top:0;left:0;bottom:0;width:8px;transform:translate(-100%);background:linear-gradient(to left,rgba(0,0,0,.12),transparent);pointer-events:none}\n"] }]
|
|
4151
4340
|
}], ctorParameters: () => [] });
|
|
4152
4341
|
|
|
4153
4342
|
const SdConvertToPagingReq = (filterRequest, args) => {
|
|
@@ -4331,5 +4520,5 @@ const SdConvertToPagingReq = (filterRequest, args) => {
|
|
|
4331
4520
|
* Generated bundle index. Do not edit.
|
|
4332
4521
|
*/
|
|
4333
4522
|
|
|
4334
|
-
export { MatPaginatorIntlCro, SD_TABLE_CONFIGURATION, SdConvertToPagingReq, SdMaterialFooterDefDirective, SdTable, SdTableCellDefDirective, SdTableExpandDefDirective, SdTableFilterDefDirective, SdTableTitleDefDirective };
|
|
4523
|
+
export { MatPaginatorIntlCro, SD_TABLE_CONFIGURATION, SdConvertToPagingReq, SdMaterialFooterDefDirective, SdTable, SdTableCellDefDirective, SdTableExpandDefDirective, SdTableFilterDefDirective, SdTableGroupDefDirective, SdTableTitleDefDirective };
|
|
4335
4524
|
//# sourceMappingURL=sd-angular-core-components-table.mjs.map
|