commons-shared-web-ui 0.0.60 → 0.0.62
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/.claude/settings.local.json +10 -0
- package/documentation/alert.md +123 -0
- package/documentation/button-dropdown.md +126 -0
- package/documentation/button.md +184 -0
- package/documentation/cards-usage-guidelines.md +131 -0
- package/documentation/configurable-form.md +605 -0
- package/documentation/confirmation-modal.md +250 -0
- package/documentation/filter-sidebar.md +178 -0
- package/documentation/filter-table-selector.md +228 -0
- package/documentation/form-builder.md +599 -0
- package/documentation/form-components.md +384 -0
- package/documentation/form-field-configuration.md +250 -0
- package/documentation/nav.md +427 -0
- package/documentation/pagination.md +181 -0
- package/documentation/side-nav-documentation.md +169 -0
- package/documentation/smart-form.md +2819 -0
- package/documentation/smart-table.md +1297 -0
- package/documentation/snackbar.md +118 -0
- package/documentation/style-externalization.md +88 -0
- package/documentation/summary-card.md +279 -0
- package/documentation/table-column-configuration.md +221 -0
- package/documentation/time-picker.md +274 -0
- package/ng-package.json +30 -0
- package/package.json +53 -34
- package/src/lib/modules/alert/alert.models.ts +6 -0
- package/src/lib/modules/alert/alert.module.ts +16 -0
- package/src/lib/modules/alert/components/alert/alert.component.html +27 -0
- package/src/lib/modules/alert/components/alert/alert.component.scss +92 -0
- package/src/lib/modules/alert/components/alert/alert.component.ts +81 -0
- package/src/lib/modules/button/button.models.ts +13 -0
- package/src/lib/modules/button/button.module.ts +16 -0
- package/src/lib/modules/button/components/button/button.component.html +22 -0
- package/src/lib/modules/button/components/button/button.component.scss +92 -0
- package/src/lib/modules/button/components/button/button.component.ts +67 -0
- package/src/lib/modules/button-dropdown/button-dropdown.models.ts +26 -0
- package/src/lib/modules/button-dropdown/button-dropdown.module.ts +22 -0
- package/src/lib/modules/button-dropdown/components/button-dropdown/button-dropdown.component.html +41 -0
- package/src/lib/modules/button-dropdown/components/button-dropdown/button-dropdown.component.scss +135 -0
- package/src/lib/modules/button-dropdown/components/button-dropdown/button-dropdown.component.ts +160 -0
- package/src/lib/modules/configurable-form/component/configurable-form.component.html +294 -0
- package/src/lib/modules/configurable-form/component/configurable-form.component.scss +503 -0
- package/src/lib/modules/configurable-form/component/configurable-form.component.ts +628 -0
- package/src/lib/modules/configurable-form/configurable-form.examples.ts +154 -0
- package/src/lib/modules/configurable-form/configurable-form.model.ts +131 -0
- package/src/lib/modules/configurable-form/configurable-form.module.ts +19 -0
- package/src/lib/modules/confirmation-modal/components/confirmation-modal/confirmation-modal.component.html +77 -0
- package/src/lib/modules/confirmation-modal/components/confirmation-modal/confirmation-modal.component.scss +395 -0
- package/src/lib/modules/confirmation-modal/components/confirmation-modal/confirmation-modal.component.ts +266 -0
- package/src/lib/modules/confirmation-modal/confirmation-modal.models.ts +71 -0
- package/src/lib/modules/confirmation-modal/confirmation-modal.module.ts +20 -0
- package/src/lib/modules/filter/components/filter/filter.component.html +131 -0
- package/src/lib/modules/filter/components/filter/filter.component.scss +245 -0
- package/src/lib/modules/filter/components/filter/filter.component.ts +216 -0
- package/src/lib/modules/filter/filter.models.ts +88 -0
- package/src/lib/modules/filter/filter.module.ts +24 -0
- package/src/lib/modules/filter-sidebar/components/filter-sidebar/filter-sidebar.component.html +112 -0
- package/src/lib/modules/filter-sidebar/components/filter-sidebar/filter-sidebar.component.scss +186 -0
- package/src/lib/modules/filter-sidebar/components/filter-sidebar/filter-sidebar.component.ts +163 -0
- package/src/lib/modules/filter-sidebar/filter-sidebar.models.ts +95 -0
- package/src/lib/modules/filter-sidebar/filter-sidebar.module.ts +24 -0
- package/src/lib/modules/filter-table-selector/components/filter-table-selector/filter-table-selector.component.html +73 -0
- package/src/lib/modules/filter-table-selector/components/filter-table-selector/filter-table-selector.component.scss +321 -0
- package/src/lib/modules/filter-table-selector/components/filter-table-selector/filter-table-selector.component.ts +361 -0
- package/src/lib/modules/filter-table-selector/filter-table-selector.models.ts +91 -0
- package/src/lib/modules/filter-table-selector/filter-table-selector.module.ts +22 -0
- package/src/lib/modules/form-builder/components/field-configurator/configurator-config-panel/configurator-config-panel.component.html +63 -0
- package/src/lib/modules/form-builder/components/field-configurator/configurator-config-panel/configurator-config-panel.component.scss +496 -0
- package/src/lib/modules/form-builder/components/field-configurator/configurator-config-panel/configurator-config-panel.component.ts +445 -0
- package/src/lib/modules/form-builder/components/field-configurator/configurator-tree/configurator-tree.component.html +75 -0
- package/src/lib/modules/form-builder/components/field-configurator/configurator-tree/configurator-tree.component.scss +210 -0
- package/src/lib/modules/form-builder/components/field-configurator/configurator-tree/configurator-tree.component.ts +55 -0
- package/src/lib/modules/form-builder/components/field-configurator/field-configurator.component.html +25 -0
- package/src/lib/modules/form-builder/components/field-configurator/field-configurator.component.scss +82 -0
- package/src/lib/modules/form-builder/components/field-configurator/field-configurator.component.ts +95 -0
- package/src/lib/modules/form-builder/components/field-selection/field-selection.component.html +20 -0
- package/src/lib/modules/form-builder/components/field-selection/field-selection.component.scss +37 -0
- package/src/lib/modules/form-builder/components/field-selection/field-selection.component.ts +94 -0
- package/src/lib/modules/form-builder/components/field-selection/group-node/group-node.component.html +46 -0
- package/src/lib/modules/form-builder/components/field-selection/group-node/group-node.component.scss +102 -0
- package/src/lib/modules/form-builder/components/field-selection/group-node/group-node.component.ts +50 -0
- package/src/lib/modules/form-builder/components/field-selection/selection-field-node/selection-field-node.component.html +35 -0
- package/src/lib/modules/form-builder/components/field-selection/selection-field-node/selection-field-node.component.scss +67 -0
- package/src/lib/modules/form-builder/components/field-selection/selection-field-node/selection-field-node.component.ts +34 -0
- package/src/lib/modules/form-builder/components/field-selection/selection-section-node/selection-section-node.component.html +68 -0
- package/src/lib/modules/form-builder/components/field-selection/selection-section-node/selection-section-node.component.scss +113 -0
- package/src/lib/modules/form-builder/components/field-selection/selection-section-node/selection-section-node.component.ts +74 -0
- package/src/lib/modules/form-builder/configs/field-type-schema.map.ts +533 -0
- package/src/lib/modules/form-builder/form-builder.module.ts +36 -0
- package/src/lib/modules/form-builder/index.ts +9 -0
- package/src/lib/modules/form-builder/models/builder.models.ts +7 -0
- package/src/lib/modules/form-builder/models/field-configurator.models.ts +38 -0
- package/src/lib/modules/form-builder/models/field-selection.models.ts +51 -0
- package/src/lib/modules/form-builder/services/field-configurator.service.ts +258 -0
- package/src/lib/modules/form-builder/services/field-selection.service.ts +299 -0
- package/src/lib/modules/form-builder/services/form-schema-tree.service.ts +670 -0
- package/src/lib/modules/form-builder/tokens/builder.tokens.ts +10 -0
- package/src/lib/modules/form-builder/utils/constants.ts +43 -0
- package/src/lib/modules/form-components/components/checkbox/checkbox.component.html +29 -0
- package/src/lib/modules/form-components/components/checkbox/checkbox.component.scss +111 -0
- package/src/lib/modules/form-components/components/checkbox/checkbox.component.ts +207 -0
- package/src/lib/modules/form-components/components/checkbox/checkbox.models.ts +35 -0
- package/src/lib/modules/form-components/components/datepicker/datepicker.component.html +42 -0
- package/src/lib/modules/form-components/components/datepicker/datepicker.component.scss +115 -0
- package/src/lib/modules/form-components/components/datepicker/datepicker.component.ts +267 -0
- package/src/lib/modules/form-components/components/datepicker/datepicker.models.ts +45 -0
- package/src/lib/modules/form-components/components/dropdown/dropdown.component.html +74 -0
- package/src/lib/modules/form-components/components/dropdown/dropdown.component.scss +252 -0
- package/src/lib/modules/form-components/components/dropdown/dropdown.component.ts +377 -0
- package/src/lib/modules/form-components/components/dropdown/dropdown.models.ts +53 -0
- package/src/lib/modules/form-components/components/input/input.component.html +51 -0
- package/src/lib/modules/form-components/components/input/input.component.scss +128 -0
- package/src/lib/modules/form-components/components/input/input.component.ts +250 -0
- package/src/lib/modules/form-components/components/input/input.models.ts +55 -0
- package/src/lib/modules/form-components/components/radio/radio.component.html +22 -0
- package/src/lib/modules/form-components/components/radio/radio.component.scss +107 -0
- package/src/lib/modules/form-components/components/radio/radio.component.ts +181 -0
- package/src/lib/modules/form-components/components/radio/radio.models.ts +39 -0
- package/src/lib/modules/form-components/components/search/search.component.html +15 -0
- package/src/lib/modules/form-components/components/search/search.component.scss +87 -0
- package/src/lib/modules/form-components/components/search/search.component.ts +213 -0
- package/src/lib/modules/form-components/components/search/search.models.ts +40 -0
- package/src/lib/modules/form-components/components/toggle/toggle.component.html +15 -0
- package/src/lib/modules/form-components/components/toggle/toggle.component.scss +81 -0
- package/src/lib/modules/form-components/components/toggle/toggle.component.ts +166 -0
- package/src/lib/modules/form-components/components/toggle/toggle.models.ts +27 -0
- package/src/lib/modules/form-components/directives/click-outside.directive.ts +22 -0
- package/src/lib/modules/form-components/form-components.module.ts +42 -0
- package/src/lib/modules/form-field-configuration/components/_ffc-controls.scss +89 -0
- package/src/lib/modules/form-field-configuration/components/config-field-node/config-field-node.component.html +68 -0
- package/src/lib/modules/form-field-configuration/components/config-field-node/config-field-node.component.scss +73 -0
- package/src/lib/modules/form-field-configuration/components/config-field-node/config-field-node.component.ts +34 -0
- package/src/lib/modules/form-field-configuration/components/config-section-node/config-section-node.component.html +78 -0
- package/src/lib/modules/form-field-configuration/components/config-section-node/config-section-node.component.scss +83 -0
- package/src/lib/modules/form-field-configuration/components/config-section-node/config-section-node.component.ts +94 -0
- package/src/lib/modules/form-field-configuration/components/form-field-configuration/form-field-configuration.component.html +38 -0
- package/src/lib/modules/form-field-configuration/components/form-field-configuration/form-field-configuration.component.scss +42 -0
- package/src/lib/modules/form-field-configuration/components/form-field-configuration/form-field-configuration.component.ts +92 -0
- package/src/lib/modules/form-field-configuration/form-field-configuration.module.ts +23 -0
- package/src/lib/modules/form-field-configuration/index.ts +7 -0
- package/src/lib/modules/form-field-configuration/models/field-configuration.models.ts +62 -0
- package/src/lib/modules/form-field-configuration/services/config-schema-tree.service.ts +159 -0
- package/src/lib/modules/form-field-configuration/services/field-configuration.service.ts +228 -0
- package/src/lib/modules/material/material.module.ts +94 -0
- package/src/lib/modules/nav/components/nav/nav.component.html +34 -0
- package/src/lib/modules/nav/components/nav/nav.component.scss +171 -0
- package/src/lib/modules/nav/components/nav/nav.component.ts +82 -0
- package/src/lib/modules/nav/nav.models.ts +31 -0
- package/src/lib/modules/nav/nav.module.ts +17 -0
- package/src/lib/modules/pagination/components/pagination/pagination.component.html +52 -0
- package/src/lib/modules/pagination/components/pagination/pagination.component.scss +155 -0
- package/src/lib/modules/pagination/components/pagination/pagination.component.ts +109 -0
- package/src/lib/modules/pagination/pagination.module.ts +17 -0
- package/src/lib/modules/side-nav/components/side-nav/side-nav.component.html +56 -0
- package/src/lib/modules/side-nav/components/side-nav/side-nav.component.scss +342 -0
- package/src/lib/modules/side-nav/components/side-nav/side-nav.component.ts +135 -0
- package/src/lib/modules/side-nav/side-nav.models.ts +38 -0
- package/src/lib/modules/side-nav/side-nav.module.ts +16 -0
- package/src/lib/modules/smart-form/components/form-field/form-field.component.html +1379 -0
- package/src/lib/modules/smart-form/components/form-field/form-field.component.scss +2255 -0
- package/src/lib/modules/smart-form/components/form-field/form-field.component.ts +3174 -0
- package/src/lib/modules/smart-form/components/form-section/form-section.component.html +67 -0
- package/src/lib/modules/smart-form/components/form-section/form-section.component.scss +209 -0
- package/src/lib/modules/smart-form/components/form-section/form-section.component.ts +142 -0
- package/src/lib/modules/smart-form/components/smart-form/smart-form.component.html +253 -0
- package/src/lib/modules/smart-form/components/smart-form/smart-form.component.scss +689 -0
- package/src/lib/modules/smart-form/components/smart-form/smart-form.component.ts +1134 -0
- package/src/lib/modules/smart-form/index.ts +10 -0
- package/src/lib/modules/smart-form/models/form-schema.model.ts +803 -0
- package/src/lib/modules/smart-form/models/hierarchy-config.model.ts +22 -0
- package/src/lib/modules/smart-form/services/expression.service.ts +75 -0
- package/src/lib/modules/smart-form/services/smart-form-controller.service.ts +67 -0
- package/src/lib/modules/smart-form/smart-form.examples.ts +1324 -0
- package/src/lib/modules/smart-form/smart-form.module.ts +40 -0
- package/src/lib/modules/smart-form/smart-form.theme.scss +1 -0
- package/src/lib/modules/smart-form/utils/translation.utils.ts +82 -0
- package/src/lib/modules/smart-form/utils/trusted-url.pipe.ts +25 -0
- package/src/lib/modules/smart-form/utils/validation.utils.ts +98 -0
- package/src/lib/modules/smart-table/components/smart-table/smart-table.component.html +283 -0
- package/src/lib/modules/smart-table/components/smart-table/smart-table.component.scss +685 -0
- package/src/lib/modules/smart-table/components/smart-table/smart-table.component.ts +1219 -0
- package/src/lib/modules/smart-table/models/table-config.model.ts +247 -0
- package/src/lib/modules/smart-table/smart-table.module.ts +30 -0
- package/src/lib/modules/smart-table/utils/safe-html.pipe.ts +28 -0
- package/src/lib/modules/smart-table/utils/smart-table.utils.ts +18 -0
- package/src/lib/modules/snackbar/components/snackbar.component.html +41 -0
- package/src/lib/modules/snackbar/components/snackbar.component.scss +99 -0
- package/src/lib/modules/snackbar/components/snackbar.component.ts +18 -0
- package/src/lib/modules/snackbar/models/snackbar.models.ts +10 -0
- package/src/lib/modules/snackbar/services/snackbar.service.ts +40 -0
- package/src/lib/modules/snackbar/snackbar.module.ts +11 -0
- package/src/lib/modules/summary-card/components/summary-card/summary-card.component.html +47 -0
- package/src/lib/modules/summary-card/components/summary-card/summary-card.component.scss +199 -0
- package/src/lib/modules/summary-card/components/summary-card/summary-card.component.ts +126 -0
- package/src/lib/modules/summary-card/summary-card.module.ts +18 -0
- package/src/lib/modules/table-column-configuration/components/_tcc-controls.scss +53 -0
- package/src/lib/modules/table-column-configuration/components/config-column-node/config-column-node.component.html +47 -0
- package/src/lib/modules/table-column-configuration/components/config-column-node/config-column-node.component.scss +50 -0
- package/src/lib/modules/table-column-configuration/components/config-column-node/config-column-node.component.ts +33 -0
- package/src/lib/modules/table-column-configuration/components/table-column-configuration/table-column-configuration.component.html +30 -0
- package/src/lib/modules/table-column-configuration/components/table-column-configuration/table-column-configuration.component.scss +36 -0
- package/src/lib/modules/table-column-configuration/components/table-column-configuration/table-column-configuration.component.ts +78 -0
- package/src/lib/modules/table-column-configuration/index.ts +5 -0
- package/src/lib/modules/table-column-configuration/models/table-column-configuration.models.ts +20 -0
- package/src/lib/modules/table-column-configuration/services/table-column-configuration.service.ts +77 -0
- package/src/lib/modules/table-column-configuration/table-column-configuration.module.ts +21 -0
- package/src/lib/modules/time-picker/components/time-picker/time-picker.component.html +37 -0
- package/src/lib/modules/time-picker/components/time-picker/time-picker.component.scss +102 -0
- package/src/lib/modules/time-picker/components/time-picker/time-picker.component.ts +178 -0
- package/src/lib/modules/time-picker/components/time-wheel-panel/time-wheel-panel.component.html +78 -0
- package/src/lib/modules/time-picker/components/time-wheel-panel/time-wheel-panel.component.scss +226 -0
- package/src/lib/modules/time-picker/components/time-wheel-panel/time-wheel-panel.component.ts +595 -0
- package/src/lib/modules/time-picker/models/time-picker.models.ts +49 -0
- package/src/lib/modules/time-picker/time-picker.module.ts +23 -0
- package/src/lib/shared-ui.module.ts +55 -0
- package/src/lib/utils/constants.ts +11 -0
- package/src/lib/utils/storage.utils.ts +37 -0
- package/src/lib/utils/string.utils.ts +23 -0
- package/src/lib/utils/translation.utils.ts +87 -0
- package/src/public-api.ts +127 -0
- package/tsconfig.lib.json +15 -0
- package/fesm2022/commons-shared-web-ui.mjs +0 -16097
- package/fesm2022/commons-shared-web-ui.mjs.map +0 -1
- package/index.d.ts +0 -5022
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
export interface TableOption {
|
|
2
|
+
label: string;
|
|
3
|
+
value: any;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface TableColumnSubField {
|
|
7
|
+
key: string;
|
|
8
|
+
label?: string;
|
|
9
|
+
dataType: 'text' | 'number' | 'email' | 'select' | 'date';
|
|
10
|
+
placeholder?: string;
|
|
11
|
+
editable?: boolean;
|
|
12
|
+
options?: TableOption[];
|
|
13
|
+
editConfig?: {
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
defaultValue?: any;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface TableColumn {
|
|
20
|
+
key: string;
|
|
21
|
+
label: string;
|
|
22
|
+
type: 'text' | 'number' | 'date' | 'custom' | 'html' | 'badge';
|
|
23
|
+
sortable?: boolean;
|
|
24
|
+
editable?: boolean;
|
|
25
|
+
dataType?: 'text' | 'number' | 'date' | 'email' | 'select';
|
|
26
|
+
options?: TableOption[]; // For select dataType
|
|
27
|
+
badgeConfig?: { [key: string]: 'success' | 'warning' | 'danger' | 'info' | 'neutral' }; // Map values to badge variants
|
|
28
|
+
width?: string;
|
|
29
|
+
cellClass?: string;
|
|
30
|
+
headerClass?: string;
|
|
31
|
+
sticky?: boolean;
|
|
32
|
+
labelPath?: string; // Path to fetch nested value (e.g. 'user.address.city')
|
|
33
|
+
emptyValue?: string; // Shown when the cell value is null, undefined, or empty string
|
|
34
|
+
dateFormat?: string; // Date format (e.g. 'short', 'medium', 'dd/MM/yyyy')
|
|
35
|
+
clickAction?: 'route' | 'callback';
|
|
36
|
+
clickRoute?: string; // Route pattern for redirection (e.g. '/users/:id')
|
|
37
|
+
subFields?: TableColumnSubField[]; // For columns displaying/editing multiple fields
|
|
38
|
+
editConfig?: {
|
|
39
|
+
disabled?: boolean;
|
|
40
|
+
defaultValue?: any;
|
|
41
|
+
};
|
|
42
|
+
/** Set to false to hide this column. Default: true. Driven by the column configurator. */
|
|
43
|
+
isEnabled?: boolean;
|
|
44
|
+
/** Backward-compatible visibility alias, kept in sync with isEnabled by the column configurator. */
|
|
45
|
+
visible?: boolean;
|
|
46
|
+
/** Configurator-only flag: when true the column can never be hidden (toggle is replaced by a lock). */
|
|
47
|
+
lockVisibility?: boolean;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface TableFilter {
|
|
51
|
+
key: string;
|
|
52
|
+
label: string;
|
|
53
|
+
type: 'select' | 'text' | 'date'; // Added type for future extension
|
|
54
|
+
options?: TableOption[];
|
|
55
|
+
apiUrl?: string;
|
|
56
|
+
apiMethod?: 'GET' | 'POST';
|
|
57
|
+
apiPayload?: any;
|
|
58
|
+
labelKey?: string;
|
|
59
|
+
valueKey?: string;
|
|
60
|
+
labelPath?: string;
|
|
61
|
+
valuePath?: string;
|
|
62
|
+
requestKey?: string;
|
|
63
|
+
dataPath?: string;
|
|
64
|
+
handling?: 'standard' | 'nested_string';
|
|
65
|
+
nestedStringConfig?: NestedStringConfig;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* A single condition evaluated against a row to decide action visibility.
|
|
70
|
+
*
|
|
71
|
+
* `field` is a path into the row (supports nesting + array index, e.g.
|
|
72
|
+
* 'status.code', 'subStatus.code', 'name[0].text'). When the resolved value is
|
|
73
|
+
* an object (e.g. `{ code, name, value }`), it is normalized to its `code`
|
|
74
|
+
* (then `name`, then `value`) so the SAME rule works whether the API returns
|
|
75
|
+
* `status: { code: 'ACTIVE' }` or `status: 'ACTIVE'`.
|
|
76
|
+
*
|
|
77
|
+
* String comparisons are case-insensitive.
|
|
78
|
+
*/
|
|
79
|
+
export interface VisibilityRule {
|
|
80
|
+
/** Path into the row, e.g. 'status.code' or just 'status'. */
|
|
81
|
+
field: string;
|
|
82
|
+
/** Comparison operator. Default: 'eq'. */
|
|
83
|
+
operator?: 'eq' | 'neq' | 'in' | 'nin' | 'truthy' | 'falsy';
|
|
84
|
+
/** Comparison value for 'eq' / 'neq'. */
|
|
85
|
+
value?: any;
|
|
86
|
+
/** Comparison list for 'in' / 'nin'. */
|
|
87
|
+
values?: any[];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Row-aware visibility config shared by actions and action items.
|
|
92
|
+
* - `visibleWhen`: ALL rules must pass (AND) for the action to show.
|
|
93
|
+
* - `hiddenWhen`: if ANY rule passes (OR), the action is hidden.
|
|
94
|
+
* `hiddenWhen` takes precedence over `visibleWhen`. Either may be a single
|
|
95
|
+
* rule or an array of rules.
|
|
96
|
+
*/
|
|
97
|
+
export interface ActionVisibility {
|
|
98
|
+
visibleWhen?: VisibilityRule | VisibilityRule[];
|
|
99
|
+
hiddenWhen?: VisibilityRule | VisibilityRule[];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface TableActionItem extends ActionVisibility {
|
|
103
|
+
label: string;
|
|
104
|
+
type: 'api' | 'callback' | 'route' | 'delete';
|
|
105
|
+
icon?: string;
|
|
106
|
+
apiUrl?: string;
|
|
107
|
+
apiMethod?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
108
|
+
route?: string;
|
|
109
|
+
confirmationNeeded?: boolean;
|
|
110
|
+
confirmationMessage?: string;
|
|
111
|
+
callback?: (row: any) => void;
|
|
112
|
+
/** Set to false to hide this action item. Default: true */
|
|
113
|
+
isEnabled?: boolean;
|
|
114
|
+
/** Config for native 'delete' action type — drives the built-in confirmation modal */
|
|
115
|
+
deleteConfig?: {
|
|
116
|
+
apiUrl: string; // URL with :id placeholder e.g. 'gateway/service/api/v1/items/:id'
|
|
117
|
+
idField?: string; // Row field used as id (default: 'id')
|
|
118
|
+
modalTitle?: string;
|
|
119
|
+
modalMessage?: string;
|
|
120
|
+
confirmLabel?: string;
|
|
121
|
+
cancelLabel?: string;
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface TableAction extends ActionVisibility {
|
|
126
|
+
label: string;
|
|
127
|
+
type: 'api' | 'callback' | 'route' | 'edit' | 'dropdown';
|
|
128
|
+
icon?: string; // FontAwesome class or similar
|
|
129
|
+
btnVariant?: 'primary' | 'secondary' | 'outline' | 'danger' | 'warning' | 'success' | 'danger-outline'; // utilizing button variants
|
|
130
|
+
apiUrl?: string;
|
|
131
|
+
apiMethod?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
132
|
+
route?: string;
|
|
133
|
+
confirmationNeeded?: boolean;
|
|
134
|
+
confirmationMessage?: string;
|
|
135
|
+
callback?: (row: any) => void;
|
|
136
|
+
items?: TableActionItem[]; // For dropdown type
|
|
137
|
+
/** Set to false to hide this action. Default: true */
|
|
138
|
+
isEnabled?: boolean;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface PaginationConfig {
|
|
142
|
+
enabled: boolean;
|
|
143
|
+
pageSize: number;
|
|
144
|
+
pageSizeOptions: number[];
|
|
145
|
+
totalCountConfig?: {
|
|
146
|
+
source: 'same' | 'separate';
|
|
147
|
+
apiUrl?: string;
|
|
148
|
+
responsePath?: string;
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export interface TableTheme {
|
|
153
|
+
primaryColor?: string;
|
|
154
|
+
headerBg?: string;
|
|
155
|
+
headerColor?: string;
|
|
156
|
+
rowHoverBg?: string;
|
|
157
|
+
borderColor?: string;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export interface NestedStringConfig {
|
|
161
|
+
paramName: string;
|
|
162
|
+
baseValue?: string;
|
|
163
|
+
separator: string;
|
|
164
|
+
assignment: string;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export interface QueryParamsConfig {
|
|
168
|
+
pageKey?: string;
|
|
169
|
+
sizeKey?: string;
|
|
170
|
+
pageIndexOffset?: number; // e.g. -1 for 0-based index from 1-based UI
|
|
171
|
+
filterHandling?: 'standard' | 'nested_string';
|
|
172
|
+
nestedStringConfig?: NestedStringConfig;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export interface TableConfig {
|
|
176
|
+
columns: TableColumn[];
|
|
177
|
+
apiUrl?: string; // Optional when tableData is provided externally
|
|
178
|
+
apiMethod?: 'GET' | 'POST';
|
|
179
|
+
apiPayload?: any;
|
|
180
|
+
dataResponsePath?: string;
|
|
181
|
+
filters?: TableFilter[];
|
|
182
|
+
filterData?: { [key: string]: any[] };
|
|
183
|
+
pagination?: PaginationConfig;
|
|
184
|
+
actions?: TableAction[]; // Row level actions
|
|
185
|
+
topBarButtons?: TableAction[]; // Buttons above the table
|
|
186
|
+
sortBy?: string;
|
|
187
|
+
orderBy?: 'ASC' | 'DESC';
|
|
188
|
+
theme?: TableTheme;
|
|
189
|
+
requestParams?: Function;
|
|
190
|
+
selectable?: boolean; // Checkbox selection
|
|
191
|
+
queryParamsConfig?: QueryParamsConfig;
|
|
192
|
+
labels?: TableLabels;
|
|
193
|
+
searchConfig?: SearchConfig;
|
|
194
|
+
maxHeight?: string;
|
|
195
|
+
stickyHeader?: boolean;
|
|
196
|
+
|
|
197
|
+
stickyColumnCount?: number;
|
|
198
|
+
token?: string; // Full token string (e.g. "Bearer ...")
|
|
199
|
+
tokenHeader?: string; // Header key (default: "Authorization")
|
|
200
|
+
editingRowClass?: string; // Optional CSS class to apply to rows being edited
|
|
201
|
+
/** Fallback text for any cell whose value is null, undefined, or empty string.
|
|
202
|
+
* Overridden per-column via TableColumn.emptyValue. Library default: '-' */
|
|
203
|
+
emptyValue?: string;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export interface SearchConfig {
|
|
207
|
+
enabled: boolean;
|
|
208
|
+
searchKey?: string; // Query param key (default: 'search')
|
|
209
|
+
debounceTime?: number; // ms (default: 300)
|
|
210
|
+
handling?: 'standard' | 'nested_string'; // standard: ?search=term, nested_string: ?params=SEARCH_TERM=term
|
|
211
|
+
minimumCharacter?: number; // Min chars before the API is called (default: 3). Clearing the input always re-triggers.
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export interface TableLabels {
|
|
215
|
+
searchPlaceholder?: string;
|
|
216
|
+
actionColumnHeader?: string;
|
|
217
|
+
noDataMessage?: string;
|
|
218
|
+
itemsPerPageLabel?: string;
|
|
219
|
+
defaultConfirmationMessage?: string;
|
|
220
|
+
saveLabel?: string;
|
|
221
|
+
cancelLabel?: string;
|
|
222
|
+
addLabel?: string;
|
|
223
|
+
/** Variant for the Add button (new row). Defaults to 'danger'. */
|
|
224
|
+
addButtonVariant?: 'primary' | 'secondary' | 'outline' | 'danger' | 'warning' | 'success' | 'danger-outline';
|
|
225
|
+
/** Variant for the Save button (edit row). Defaults to 'primary'. */
|
|
226
|
+
saveButtonVariant?: 'primary' | 'secondary' | 'outline' | 'danger' | 'warning' | 'success' | 'danger-outline';
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Emitted by the SmartTableComponent when operating in external-data mode
|
|
231
|
+
* (i.e. when [tableData] input is provided by the parent).
|
|
232
|
+
* The parent is responsible for fetching updated data based on this event
|
|
233
|
+
* and providing it back via [tableData] and [totalItemsCount].
|
|
234
|
+
*/
|
|
235
|
+
export interface TableDataChangeEvent {
|
|
236
|
+
page: number;
|
|
237
|
+
pageSize: number;
|
|
238
|
+
sortBy?: string;
|
|
239
|
+
orderBy?: 'ASC' | 'DESC';
|
|
240
|
+
searchTerm?: string;
|
|
241
|
+
filters?: { [key: string]: any };
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export interface TableRowSaveEvent {
|
|
245
|
+
row: any;
|
|
246
|
+
isNew: boolean;
|
|
247
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { NgModule } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { FormsModule } from '@angular/forms';
|
|
4
|
+
import { SmartTableComponent } from './components/smart-table/smart-table.component';
|
|
5
|
+
import { PaginationModule } from '../pagination/pagination.module';
|
|
6
|
+
import { ButtonModule } from '../button/button.module';
|
|
7
|
+
import { MaterialModule } from '../material/material.module';
|
|
8
|
+
import { ConfirmationModalModule } from '../confirmation-modal/confirmation-modal.module';
|
|
9
|
+
import { SafeHtmlPipe } from './utils/safe-html.pipe';
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@NgModule({
|
|
13
|
+
declarations: [
|
|
14
|
+
SmartTableComponent,
|
|
15
|
+
SafeHtmlPipe
|
|
16
|
+
],
|
|
17
|
+
imports: [
|
|
18
|
+
CommonModule,
|
|
19
|
+
FormsModule,
|
|
20
|
+
PaginationModule,
|
|
21
|
+
ButtonModule,
|
|
22
|
+
MaterialModule,
|
|
23
|
+
ConfirmationModalModule
|
|
24
|
+
],
|
|
25
|
+
exports: [
|
|
26
|
+
SmartTableComponent
|
|
27
|
+
]
|
|
28
|
+
})
|
|
29
|
+
export class SmartTableModule { }
|
|
30
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Pipe, PipeTransform, SecurityContext } from '@angular/core';
|
|
2
|
+
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Marks rich-text HTML (e.g. from a smart-table "html" column, always sourced from this
|
|
6
|
+
* app's own rich-text editor output, never arbitrary external/user-supplied markup) as
|
|
7
|
+
* trusted so [innerHTML] renders it without Angular's default HTML sanitizer stripping it.
|
|
8
|
+
*
|
|
9
|
+
* Deliberately does NOT run the value through DomSanitizer.sanitize(SecurityContext.HTML, ...)
|
|
10
|
+
* first — that sanitizer strips `style` attributes entirely (they're not in its allowlist),
|
|
11
|
+
* which silently destroyed rich-text formatting like text color and highlight color while
|
|
12
|
+
* leaving semantic-tag formatting (bold/italic/underline) untouched, since only tags — not
|
|
13
|
+
* inline styles — survive that pass.
|
|
14
|
+
*/
|
|
15
|
+
@Pipe({
|
|
16
|
+
name: 'safeHtml',
|
|
17
|
+
standalone: false
|
|
18
|
+
})
|
|
19
|
+
export class SafeHtmlPipe implements PipeTransform {
|
|
20
|
+
constructor(private sanitizer: DomSanitizer) { }
|
|
21
|
+
|
|
22
|
+
transform(value: string): SafeHtml | null {
|
|
23
|
+
if (!value) {
|
|
24
|
+
return '';
|
|
25
|
+
}
|
|
26
|
+
return this.sanitizer.bypassSecurityTrustHtml(value);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function appendBaseUrlRecursively(obj: any, baseURL: string): void {
|
|
2
|
+
if (obj && typeof obj === 'object') {
|
|
3
|
+
if (obj.apiUrl && typeof obj.apiUrl === 'string' && !obj.apiUrl.startsWith('http://') && !obj.apiUrl.startsWith('https://')) {
|
|
4
|
+
let finalApiUrl = obj.apiUrl;
|
|
5
|
+
if (baseURL.endsWith('/') && finalApiUrl.startsWith('/')) {
|
|
6
|
+
finalApiUrl = finalApiUrl.substring(1);
|
|
7
|
+
} else if (!baseURL.endsWith('/') && !finalApiUrl.startsWith('/')) {
|
|
8
|
+
finalApiUrl = '/' + finalApiUrl;
|
|
9
|
+
}
|
|
10
|
+
obj.apiUrl = baseURL + finalApiUrl;
|
|
11
|
+
}
|
|
12
|
+
for (const key in obj) {
|
|
13
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
14
|
+
appendBaseUrlRecursively(obj[key], baseURL);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<div class="cc-snackbar-container" [ngClass]="variantClass">
|
|
2
|
+
<div class="cc-snackbar-icon">
|
|
3
|
+
<!-- Success Icon -->
|
|
4
|
+
<svg *ngIf="data.variant === 'success'" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
5
|
+
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
|
|
6
|
+
<polyline points="22 4 12 14.01 9 11.01"></polyline>
|
|
7
|
+
</svg>
|
|
8
|
+
|
|
9
|
+
<!-- Error Icon -->
|
|
10
|
+
<svg *ngIf="data.variant === 'error'" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
11
|
+
<circle cx="12" cy="12" r="10"></circle>
|
|
12
|
+
<line x1="15" y1="9" x2="9" y2="15"></line>
|
|
13
|
+
<line x1="9" y1="9" x2="15" y2="15"></line>
|
|
14
|
+
</svg>
|
|
15
|
+
|
|
16
|
+
<!-- Warning Icon -->
|
|
17
|
+
<svg *ngIf="data.variant === 'warning'" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
18
|
+
<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path>
|
|
19
|
+
<line x1="12" y1="9" x2="12" y2="13"></line>
|
|
20
|
+
<line x1="12" y1="17" x2="12.01" y2="17"></line>
|
|
21
|
+
</svg>
|
|
22
|
+
|
|
23
|
+
<!-- Info Icon -->
|
|
24
|
+
<svg *ngIf="data.variant === 'info' || !data.variant" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
25
|
+
<circle cx="12" cy="12" r="10"></circle>
|
|
26
|
+
<line x1="12" y1="16" x2="12" y2="12"></line>
|
|
27
|
+
<line x1="12" y1="8" x2="12.01" y2="8"></line>
|
|
28
|
+
</svg>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<div class="cc-snackbar-message">
|
|
32
|
+
{{ data.message }}
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<button *ngIf="data.showCloseButton" class="cc-snackbar-close" (click)="snackBarRef.dismiss()">
|
|
36
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
37
|
+
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
38
|
+
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
39
|
+
</svg>
|
|
40
|
+
</button>
|
|
41
|
+
</div>
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
.cc-snackbar-container {
|
|
2
|
+
display: flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
gap: var(--cc-sb-gap, 12px);
|
|
5
|
+
padding: var(--cc-sb-padding, 12px 16px);
|
|
6
|
+
border-radius: var(--cc-sb-radius, 8px);
|
|
7
|
+
box-shadow: var(--cc-sb-shadow, 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06));
|
|
8
|
+
font-family: var(--cc-sb-font-family, 'Inter', sans-serif);
|
|
9
|
+
font-size: var(--cc-sb-font-size, 14px);
|
|
10
|
+
font-weight: var(--cc-sb-font-weight, 500);
|
|
11
|
+
background: var(--cc-sb-bg, #ffffff);
|
|
12
|
+
color: var(--cc-sb-color, #1f2937);
|
|
13
|
+
border: var(--cc-sb-border, 1px solid transparent);
|
|
14
|
+
min-width: var(--cc-sb-min-width, 300px);
|
|
15
|
+
|
|
16
|
+
&.snackbar-success {
|
|
17
|
+
background: var(--cc-sb-success-bg, #ecfdf5);
|
|
18
|
+
color: var(--cc-sb-success-color, #065f46);
|
|
19
|
+
border-color: var(--cc-sb-success-border, #a7f3d0);
|
|
20
|
+
.cc-snackbar-icon { color: var(--cc-sb-success-icon-color, #10b981); }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
&.snackbar-error {
|
|
24
|
+
background: var(--cc-sb-error-bg, #fef2f2);
|
|
25
|
+
color: var(--cc-sb-error-color, #991b1b);
|
|
26
|
+
border-color: var(--cc-sb-error-border, #fecaca);
|
|
27
|
+
.cc-snackbar-icon { color: var(--cc-sb-error-icon-color, #ef4444); }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
&.snackbar-warning {
|
|
31
|
+
background: var(--cc-sb-warning-bg, #fffbeb);
|
|
32
|
+
color: var(--cc-sb-warning-color, #92400e);
|
|
33
|
+
border-color: var(--cc-sb-warning-border, #fde68a);
|
|
34
|
+
.cc-snackbar-icon { color: var(--cc-sb-warning-icon-color, #f59e0b); }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&.snackbar-info {
|
|
38
|
+
background: var(--cc-sb-info-bg, #eff6ff);
|
|
39
|
+
color: var(--cc-sb-info-color, #1e40af);
|
|
40
|
+
border-color: var(--cc-sb-info-border, #bfdbfe);
|
|
41
|
+
.cc-snackbar-icon { color: var(--cc-sb-info-icon-color, #3b82f6); }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.cc-snackbar-icon {
|
|
45
|
+
display: flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
justify-content: center;
|
|
48
|
+
flex-shrink: 0;
|
|
49
|
+
|
|
50
|
+
svg {
|
|
51
|
+
width: var(--cc-sb-icon-size, 20px);
|
|
52
|
+
height: var(--cc-sb-icon-size, 20px);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.cc-snackbar-message {
|
|
57
|
+
flex-grow: 1;
|
|
58
|
+
line-height: 1.4;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.cc-snackbar-close {
|
|
62
|
+
background: transparent;
|
|
63
|
+
border: none;
|
|
64
|
+
padding: 0;
|
|
65
|
+
margin: 0;
|
|
66
|
+
cursor: pointer;
|
|
67
|
+
display: flex;
|
|
68
|
+
align-items: center;
|
|
69
|
+
justify-content: center;
|
|
70
|
+
color: currentcolor;
|
|
71
|
+
opacity: 0.7;
|
|
72
|
+
transition: opacity 0.2s;
|
|
73
|
+
|
|
74
|
+
&:hover {
|
|
75
|
+
opacity: 1;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
svg {
|
|
79
|
+
width: var(--cc-sb-close-icon-size, 16px);
|
|
80
|
+
height: var(--cc-sb-close-icon-size, 16px);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Override Angular Material default snackbar surface
|
|
86
|
+
::ng-deep .cc-snackbar-panel {
|
|
87
|
+
.mdc-snackbar__surface {
|
|
88
|
+
background: transparent !important;
|
|
89
|
+
box-shadow: none !important;
|
|
90
|
+
padding: 0 !important;
|
|
91
|
+
border-radius: 0 !important;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
&.mat-snack-bar-container {
|
|
95
|
+
background: transparent !important;
|
|
96
|
+
box-shadow: none !important;
|
|
97
|
+
padding: 0 !important;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Component, inject } from '@angular/core';
|
|
2
|
+
import { MAT_SNACK_BAR_DATA, MatSnackBarRef } from '@angular/material/snack-bar';
|
|
3
|
+
import { SnackbarConfig } from '../models/snackbar.models';
|
|
4
|
+
|
|
5
|
+
@Component({
|
|
6
|
+
selector: 'lib-snackbar',
|
|
7
|
+
templateUrl: './snackbar.component.html',
|
|
8
|
+
styleUrls: ['./snackbar.component.scss'],
|
|
9
|
+
standalone: false
|
|
10
|
+
})
|
|
11
|
+
export class SnackbarComponent {
|
|
12
|
+
public data: SnackbarConfig = inject(MAT_SNACK_BAR_DATA);
|
|
13
|
+
public snackBarRef: MatSnackBarRef<SnackbarComponent> = inject(MatSnackBarRef);
|
|
14
|
+
|
|
15
|
+
get variantClass(): string {
|
|
16
|
+
return `snackbar-${this.data.variant || 'info'}`;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type SnackbarVariant = 'success' | 'error' | 'warning' | 'info';
|
|
2
|
+
|
|
3
|
+
export interface SnackbarConfig {
|
|
4
|
+
message: string;
|
|
5
|
+
variant?: SnackbarVariant;
|
|
6
|
+
duration?: number;
|
|
7
|
+
horizontalPosition?: 'start' | 'center' | 'end' | 'left' | 'right';
|
|
8
|
+
verticalPosition?: 'top' | 'bottom';
|
|
9
|
+
showCloseButton?: boolean;
|
|
10
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import { MatSnackBar, MatSnackBarConfig } from '@angular/material/snack-bar';
|
|
3
|
+
import { SnackbarConfig } from '../models/snackbar.models';
|
|
4
|
+
import { SnackbarComponent } from '../components/snackbar.component';
|
|
5
|
+
|
|
6
|
+
@Injectable({
|
|
7
|
+
providedIn: 'root'
|
|
8
|
+
})
|
|
9
|
+
export class SnackbarService {
|
|
10
|
+
|
|
11
|
+
constructor(private snackBar: MatSnackBar) {}
|
|
12
|
+
|
|
13
|
+
show(config: SnackbarConfig): void {
|
|
14
|
+
const matConfig: MatSnackBarConfig = {
|
|
15
|
+
duration: config.duration ?? 5000,
|
|
16
|
+
horizontalPosition: config.horizontalPosition ?? 'right',
|
|
17
|
+
verticalPosition: config.verticalPosition ?? 'top',
|
|
18
|
+
panelClass: ['cc-snackbar-panel', `cc-snackbar-${config.variant || 'info'}`],
|
|
19
|
+
data: config // Pass the entire config down to the component
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
this.snackBar.openFromComponent(SnackbarComponent, matConfig);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
success(message: string, duration?: number): void {
|
|
26
|
+
this.show({ message, variant: 'success', duration });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
error(message: string, duration?: number): void {
|
|
30
|
+
this.show({ message, variant: 'error', duration });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
warning(message: string, duration?: number): void {
|
|
34
|
+
this.show({ message, variant: 'warning', duration });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
info(message: string, duration?: number): void {
|
|
38
|
+
this.show({ message, variant: 'info', duration });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { NgModule } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
|
4
|
+
import { SnackbarComponent } from './components/snackbar.component';
|
|
5
|
+
|
|
6
|
+
@NgModule({
|
|
7
|
+
declarations: [SnackbarComponent],
|
|
8
|
+
imports: [CommonModule, MatSnackBarModule],
|
|
9
|
+
exports: [SnackbarComponent]
|
|
10
|
+
})
|
|
11
|
+
export class SnackbarModule {}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<div class="cc-summary-card" (click)="onCardClick()">
|
|
2
|
+
<!-- Icon Section (Left Side) -->
|
|
3
|
+
<div class="icon-section" *ngIf="config.icon || config.iconImage" [ngClass]="config.iconClass"
|
|
4
|
+
[ngStyle]="iconStyles">
|
|
5
|
+
<mat-icon *ngIf="config.icon">{{ config.icon }}</mat-icon>
|
|
6
|
+
<img *ngIf="!config.icon && config.iconImage" [src]="config.iconImage" [alt]="labels.iconAlt">
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<!-- Right Section (Header + Value/Meta) -->
|
|
10
|
+
<div class="right-section">
|
|
11
|
+
<!-- Header (Full Width on Right) -->
|
|
12
|
+
<div class="header" [ngClass]="config.headerClass" [ngStyle]="headerStyles">
|
|
13
|
+
{{ config.header }}
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<!-- Value and Meta Row -->
|
|
17
|
+
<div class="value-meta-row">
|
|
18
|
+
<!-- Content Section -->
|
|
19
|
+
<div class="content-section">
|
|
20
|
+
<!-- Value Row (with optional inline description) -->
|
|
21
|
+
<div class="value-row" [class.inline-layout]="isDescriptionInline">
|
|
22
|
+
<div class="value-container">
|
|
23
|
+
<div class="value" [ngClass]="config.valueClass" [ngStyle]="valueStyles">
|
|
24
|
+
{{ config.value }}
|
|
25
|
+
<span *ngIf="config.valueSubtext" class="value-subtext">{{ config.valueSubtext }}</span>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<!-- Description (inline or bottom based on config) -->
|
|
30
|
+
<div class="description" *ngIf="config.description" [ngClass]="config.descriptionClass"
|
|
31
|
+
[ngStyle]="descriptionStyles">
|
|
32
|
+
{{ config.description }}
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<!-- Meta/Status Section (Aligned with Value) -->
|
|
38
|
+
<div class="meta-section" *ngIf="config.metaData && config.metaData.length > 0">
|
|
39
|
+
<div *ngFor="let meta of config.metaData" class="meta-item"
|
|
40
|
+
[ngClass]="[meta.type === 'pill' ? 'meta-pill' : 'meta-text', meta.cssClass || '']"
|
|
41
|
+
[ngStyle]="getMetaStyles(meta)">
|
|
42
|
+
{{ meta.text }}
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|