@sdcorejs/angular 21.1.6 → 21.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -0
- package/assets/scss/core/menu.scss +18 -0
- package/assets/scss/core/utilities/_misc.scss +15 -0
- package/assets/scss/sd-core.scss +1 -0
- package/fesm2022/sdcorejs-angular-components-anchor.mjs +37 -13
- package/fesm2022/sdcorejs-angular-components-anchor.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-autoid-inspector.mjs +2 -2
- package/fesm2022/sdcorejs-angular-components-autoid-inspector.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-badge.mjs +15 -2
- package/fesm2022/sdcorejs-angular-components-badge.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-button.mjs +2 -2
- package/fesm2022/sdcorejs-angular-components-button.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-ckeditor-styles.mjs +1 -1
- package/fesm2022/sdcorejs-angular-components-ckeditor-styles.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-code-editor.mjs +3 -3
- package/fesm2022/sdcorejs-angular-components-code-editor.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-data-state.mjs +3 -3
- package/fesm2022/sdcorejs-angular-components-data-state.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-editor.mjs +2 -2
- package/fesm2022/sdcorejs-angular-components-editor.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-form-generic.mjs +324 -192
- package/fesm2022/sdcorejs-angular-components-form-generic.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-history.mjs +4 -4
- package/fesm2022/sdcorejs-angular-components-history.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-import-excel.mjs +13 -5
- package/fesm2022/sdcorejs-angular-components-import-excel.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-inform.mjs +3 -3
- package/fesm2022/sdcorejs-angular-components-inform.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-modal-resizable.mjs +164 -8
- package/fesm2022/sdcorejs-angular-components-modal-resizable.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-modal.mjs +30 -18
- package/fesm2022/sdcorejs-angular-components-modal.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-org-chart.mjs +60 -13
- package/fesm2022/sdcorejs-angular-components-org-chart.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-preview.mjs +27 -17
- package/fesm2022/sdcorejs-angular-components-preview.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-query-bar.mjs +192 -30
- package/fesm2022/sdcorejs-angular-components-query-bar.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-query-builder.mjs +187 -127
- package/fesm2022/sdcorejs-angular-components-query-builder.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-section.mjs +16 -2
- package/fesm2022/sdcorejs-angular-components-section.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-side-drawer.mjs +83 -24
- package/fesm2022/sdcorejs-angular-components-side-drawer.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-splitter.mjs +57 -21
- package/fesm2022/sdcorejs-angular-components-splitter.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-stepper.mjs +2 -2
- package/fesm2022/sdcorejs-angular-components-stepper.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-tab-router.mjs +68 -20
- package/fesm2022/sdcorejs-angular-components-tab-router.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-tab.mjs +3 -2
- package/fesm2022/sdcorejs-angular-components-tab.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-table.mjs +542 -255
- package/fesm2022/sdcorejs-angular-components-table.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-tree.mjs +80 -17
- package/fesm2022/sdcorejs-angular-components-tree.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-upload-file.mjs +48 -13
- package/fesm2022/sdcorejs-angular-components-upload-file.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components.mjs +6 -1
- package/fesm2022/sdcorejs-angular-components.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-configurations.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-directives.mjs +45 -8
- package/fesm2022/sdcorejs-angular-directives.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs +40 -29
- package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-checkbox.mjs +5 -5
- package/fesm2022/sdcorejs-angular-forms-checkbox.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs +67 -50
- package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-chip.mjs +57 -43
- package/fesm2022/sdcorejs-angular-forms-chip.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-date-range.mjs +232 -61
- package/fesm2022/sdcorejs-angular-forms-date-range.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-date.mjs +96 -24
- package/fesm2022/sdcorejs-angular-forms-date.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-datetime.mjs +131 -27
- package/fesm2022/sdcorejs-angular-forms-datetime.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-entity-picker.mjs +40 -16
- package/fesm2022/sdcorejs-angular-forms-entity-picker.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-input-color.mjs +16 -5
- package/fesm2022/sdcorejs-angular-forms-input-color.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-input-number.mjs +24 -9
- package/fesm2022/sdcorejs-angular-forms-input-number.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-input.mjs +58 -10
- package/fesm2022/sdcorejs-angular-forms-input.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-models.mjs +227 -6
- package/fesm2022/sdcorejs-angular-forms-models.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-radio.mjs +4 -4
- package/fesm2022/sdcorejs-angular-forms-radio.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-select.mjs +136 -38
- package/fesm2022/sdcorejs-angular-forms-select.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-switch.mjs +18 -3
- package/fesm2022/sdcorejs-angular-forms-switch.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-textarea.mjs +51 -62
- package/fesm2022/sdcorejs-angular-forms-textarea.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-time-range.mjs +57 -12
- package/fesm2022/sdcorejs-angular-forms-time-range.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-time.mjs +16 -5
- package/fesm2022/sdcorejs-angular-forms-time.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-tree-select.mjs +100 -9
- package/fesm2022/sdcorejs-angular-forms-tree-select.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms.mjs +91 -46
- package/fesm2022/sdcorejs-angular-forms.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-handlers.mjs +18 -3
- package/fesm2022/sdcorejs-angular-handlers.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-i18n.mjs +490 -68
- package/fesm2022/sdcorejs-angular-i18n.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-interceptors.mjs +87 -29
- package/fesm2022/sdcorejs-angular-interceptors.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-modules-auth.mjs +25 -15
- package/fesm2022/sdcorejs-angular-modules-auth.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-modules-icon.mjs +2 -2
- package/fesm2022/sdcorejs-angular-modules-icon.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-modules-keycloak.mjs +32 -3
- package/fesm2022/sdcorejs-angular-modules-keycloak.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-modules-layout.mjs +332 -111
- package/fesm2022/sdcorejs-angular-modules-layout.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-modules-permission.mjs +177 -40
- package/fesm2022/sdcorejs-angular-modules-permission.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-pipes.mjs +62 -28
- package/fesm2022/sdcorejs-angular-pipes.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-api.mjs +123 -13
- package/fesm2022/sdcorejs-angular-services-api.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-cache.mjs +53 -3
- package/fesm2022/sdcorejs-angular-services-cache.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-confirm.mjs +25 -73
- package/fesm2022/sdcorejs-angular-services-confirm.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-excel.mjs +12 -10
- package/fesm2022/sdcorejs-angular-services-excel.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-loading.mjs +75 -84
- package/fesm2022/sdcorejs-angular-services-loading.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-notify.mjs +46 -5
- package/fesm2022/sdcorejs-angular-services-notify.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-storage.mjs +4 -0
- package/fesm2022/sdcorejs-angular-services-storage.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services.mjs +0 -1
- package/fesm2022/sdcorejs-angular-services.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-utilities-extensions.mjs +225 -80
- package/fesm2022/sdcorejs-angular-utilities-extensions.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-utilities-models.mjs +1 -63
- package/fesm2022/sdcorejs-angular-utilities-models.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular.mjs +17 -10
- package/fesm2022/sdcorejs-angular.mjs.map +1 -1
- package/package.json +32 -25
- package/types/sdcorejs-angular-components-anchor.d.ts +3 -1
- package/types/sdcorejs-angular-components-badge.d.ts +1 -0
- package/types/sdcorejs-angular-components-ckeditor-styles.d.ts +1 -1
- package/types/sdcorejs-angular-components-form-generic.d.ts +44 -33
- package/types/sdcorejs-angular-components-import-excel.d.ts +1 -0
- package/types/sdcorejs-angular-components-mini-editor.d.ts +1 -1
- package/types/sdcorejs-angular-components-modal-resizable.d.ts +92 -0
- package/types/sdcorejs-angular-components-modal.d.ts +3 -2
- package/types/sdcorejs-angular-components-org-chart.d.ts +6 -0
- package/types/sdcorejs-angular-components-preview.d.ts +1 -0
- package/types/sdcorejs-angular-components-query-bar.d.ts +55 -17
- package/types/sdcorejs-angular-components-query-builder.d.ts +150 -98
- package/types/sdcorejs-angular-components-section.d.ts +3 -0
- package/types/sdcorejs-angular-components-tab-router.d.ts +19 -19
- package/types/sdcorejs-angular-components-table.d.ts +251 -109
- package/types/sdcorejs-angular-components-tree.d.ts +48 -30
- package/types/sdcorejs-angular-components-upload-file.d.ts +6 -3
- package/types/sdcorejs-angular-components.d.ts +6 -1
- package/types/sdcorejs-angular-configurations.d.ts +1 -2
- package/types/sdcorejs-angular-forms-autocomplete.d.ts +5 -2
- package/types/sdcorejs-angular-forms-chip-calendar.d.ts +10 -0
- package/types/sdcorejs-angular-forms-date-range.d.ts +14 -2
- package/types/sdcorejs-angular-forms-date.d.ts +13 -2
- package/types/sdcorejs-angular-forms-datetime.d.ts +13 -2
- package/types/sdcorejs-angular-forms-entity-picker.d.ts +9 -3
- package/types/sdcorejs-angular-forms-input-color.d.ts +4 -0
- package/types/sdcorejs-angular-forms-input-number.d.ts +3 -0
- package/types/sdcorejs-angular-forms-input.d.ts +3 -0
- package/types/sdcorejs-angular-forms-models.d.ts +119 -4
- package/types/sdcorejs-angular-forms-select.d.ts +27 -4
- package/types/sdcorejs-angular-forms-switch.d.ts +7 -1
- package/types/sdcorejs-angular-forms-textarea.d.ts +5 -3
- package/types/sdcorejs-angular-forms-time-range.d.ts +22 -1
- package/types/sdcorejs-angular-forms-tree-select.d.ts +36 -5
- package/types/sdcorejs-angular-forms.d.ts +22 -13
- package/types/sdcorejs-angular-i18n.d.ts +95 -16
- package/types/sdcorejs-angular-interceptors.d.ts +13 -3
- package/types/sdcorejs-angular-modules-auth.d.ts +1 -1
- package/types/sdcorejs-angular-modules-keycloak.d.ts +1 -0
- package/types/sdcorejs-angular-modules-layout.d.ts +94 -28
- package/types/sdcorejs-angular-modules-permission.d.ts +66 -4
- package/types/sdcorejs-angular-pipes.d.ts +27 -5
- package/types/sdcorejs-angular-services-api.d.ts +21 -1
- package/types/sdcorejs-angular-services-cache.d.ts +11 -1
- package/types/sdcorejs-angular-services-notify.d.ts +1 -1
- package/types/sdcorejs-angular-services.d.ts +0 -1
- package/types/sdcorejs-angular-utilities-extensions.d.ts +83 -61
- package/types/sdcorejs-angular-utilities-models.d.ts +2 -76
- package/types/sdcorejs-angular.d.ts +11 -2
- package/fesm2022/sdcorejs-angular-components-base.mjs +0 -23
- package/fesm2022/sdcorejs-angular-components-base.mjs.map +0 -1
- package/fesm2022/sdcorejs-angular-components-document-builder.mjs +0 -5038
- package/fesm2022/sdcorejs-angular-components-document-builder.mjs.map +0 -1
- package/fesm2022/sdcorejs-angular-models.mjs +0 -6
- package/fesm2022/sdcorejs-angular-models.mjs.map +0 -1
- package/fesm2022/sdcorejs-angular-services-docx.mjs +0 -291
- package/fesm2022/sdcorejs-angular-services-docx.mjs.map +0 -1
- package/fesm2022/sdcorejs-angular-services-license.mjs +0 -97
- package/fesm2022/sdcorejs-angular-services-license.mjs.map +0 -1
- package/types/sdcorejs-angular-components-base.d.ts +0 -11
- package/types/sdcorejs-angular-components-document-builder.d.ts +0 -252
- package/types/sdcorejs-angular-models.d.ts +0 -2
- package/types/sdcorejs-angular-services-docx.d.ts +0 -27
- package/types/sdcorejs-angular-services-license.d.ts +0 -12
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { Language } from '@sdcorejs/
|
|
2
|
-
export { Language, SUPPORTED_LANGUAGES } from '@sdcorejs/angular/models';
|
|
1
|
+
import { Language } from '@sdcorejs/utils/models';
|
|
3
2
|
import * as i0 from '@angular/core';
|
|
4
3
|
import { Signal, PipeTransform } from '@angular/core';
|
|
5
4
|
|
|
@@ -85,9 +84,6 @@ declare const EN_MESSAGES: {
|
|
|
85
84
|
readonly 'core.interceptor.no-internet.restored': "Connection restored.";
|
|
86
85
|
readonly 'core.excel.cannot-read-file': "Could not read file content";
|
|
87
86
|
readonly 'core.excel.no-sheet': "Excel file has no data sheet";
|
|
88
|
-
readonly 'core.docx.invalid-format': "Invalid format. Please select a template in DOC or DOCX format";
|
|
89
|
-
readonly 'core.docx.size-exceeded': "Template file size exceeds the supported limit. Please try again";
|
|
90
|
-
readonly 'core.docx.convert-error': "An error occurred while converting the DOCX file";
|
|
91
87
|
readonly 'core.notify.type.success': "Success";
|
|
92
88
|
readonly 'core.notify.type.info': "Information";
|
|
93
89
|
readonly 'core.notify.type.warning': "Warning";
|
|
@@ -184,7 +180,6 @@ declare const EN_MESSAGES: {
|
|
|
184
180
|
readonly 'core.form.time-range.step': "Times must align to a {step}-minute interval";
|
|
185
181
|
readonly 'core.form.time-range.from': "From";
|
|
186
182
|
readonly 'core.form.time-range.to': "To";
|
|
187
|
-
readonly 'core.form.time-range.clear': "Clear time range";
|
|
188
183
|
readonly 'core.form.time-spinner.hour': "Hour";
|
|
189
184
|
readonly 'core.form.time-spinner.minute': "Minute";
|
|
190
185
|
readonly 'core.form.time-spinner.second': "Second";
|
|
@@ -203,6 +198,7 @@ declare const EN_MESSAGES: {
|
|
|
203
198
|
readonly 'core.form.checkbox.checked': "Yes";
|
|
204
199
|
readonly 'core.form.checkbox.unchecked': "No";
|
|
205
200
|
readonly 'core.form.select.required': "Please enter information";
|
|
201
|
+
readonly 'core.form.select.selectAll': "All";
|
|
206
202
|
readonly 'core.form.textarea.required': "Please enter information";
|
|
207
203
|
readonly 'core.form.textarea.maxlength': "Maximum characters: {max}";
|
|
208
204
|
readonly 'core.form.textarea.invalid-pattern': "Invalid format";
|
|
@@ -216,12 +212,6 @@ declare const EN_MESSAGES: {
|
|
|
216
212
|
readonly 'core.component.editor.image.max-width': "Image width {width}px exceeds the limit of {max}px";
|
|
217
213
|
readonly 'core.component.editor.image.max-height': "Image height {height}px exceeds the limit of {max}px";
|
|
218
214
|
readonly 'core.component.editor.image.max-per-selection': "You can select at most {max} images per selection";
|
|
219
|
-
readonly 'core.component.document-builder.page-number.current': "Current page number";
|
|
220
|
-
readonly 'core.component.document-builder.page-number.total': "Total pages";
|
|
221
|
-
readonly 'core.component.document-builder.ck-comment.label': "Comment";
|
|
222
|
-
readonly 'core.component.document-builder.ck-comment.text-too-long': "Text too long ({length} characters). Maximum {max} characters.";
|
|
223
|
-
readonly 'core.component.document-builder.variable.not-allowed': "Adding variable to the text is not allowed";
|
|
224
|
-
readonly 'core.component.document-builder.variable.invalid-data': "Invalid variable data";
|
|
225
215
|
readonly 'core.component.form-builder.field-key': "Field key";
|
|
226
216
|
readonly 'core.component.form-builder.display': "Display";
|
|
227
217
|
readonly 'core.component.form-builder.general': "General";
|
|
@@ -235,6 +225,7 @@ declare const EN_MESSAGES: {
|
|
|
235
225
|
readonly 'core.component.form-builder.required-when': "Required when";
|
|
236
226
|
readonly 'core.component.form-builder.confirm': "Confirm";
|
|
237
227
|
readonly 'core.component.form-builder.delete': "Delete";
|
|
228
|
+
readonly 'core.component.form-builder.select-item': "Select to edit";
|
|
238
229
|
readonly 'core.component.form-builder.save': "Save";
|
|
239
230
|
readonly 'core.component.form-builder.hint': "Hint";
|
|
240
231
|
readonly 'core.component.form-builder.parameter': "Parameters";
|
|
@@ -306,9 +297,13 @@ declare const EN_MESSAGES: {
|
|
|
306
297
|
readonly 'core.component.form-builder.display-label': "Display label";
|
|
307
298
|
readonly 'core.component.form-builder.attribute': "Attribute";
|
|
308
299
|
readonly 'core.component.form-builder.add-variable': "Add variable";
|
|
300
|
+
readonly 'core.component.form-builder.no-variable': "No variables yet. Add one to use it in condition expressions.";
|
|
301
|
+
readonly 'core.component.form-builder.no-validation': "No validations yet. Add one to show a warning or an error on a condition.";
|
|
309
302
|
readonly 'core.component.form-builder.add-new': "Add new";
|
|
310
303
|
readonly 'core.component.form-builder.detail': "Details";
|
|
311
304
|
readonly 'core.component.form-builder.create-update': "Create/update";
|
|
305
|
+
readonly 'core.component.form-builder.update-row': "Update row";
|
|
306
|
+
readonly 'core.component.form-builder.add-row': "Add row";
|
|
312
307
|
readonly 'core.component.form-builder.default': "Default";
|
|
313
308
|
readonly 'core.component.form-builder.show-more': "Show more";
|
|
314
309
|
readonly 'core.component.form-builder.show-less': "Show less";
|
|
@@ -477,6 +472,8 @@ declare const EN_MESSAGES: {
|
|
|
477
472
|
readonly 'core.component.table.error-occurred': "An error occurred";
|
|
478
473
|
readonly 'core.component.table.not-an-array': "Data is not an array";
|
|
479
474
|
readonly 'core.component.table.config.confirm-reset': "Confirm reset all settings to defaults";
|
|
475
|
+
readonly 'core.component.table.config.drag-hint': "Drag the ⠿ handle to reorder columns";
|
|
476
|
+
readonly 'core.component.table.config.drag-handle': "Drag to reorder column";
|
|
480
477
|
readonly 'core.component.table.popup-export.select-columns': "Please select columns to export";
|
|
481
478
|
readonly 'core.component.table.selector-action.default-msg': "items selected";
|
|
482
479
|
readonly 'core.component.tab-router.too-many-tabs': "You have opened too many tabs.";
|
|
@@ -505,6 +502,13 @@ declare const EN_MESSAGES: {
|
|
|
505
502
|
readonly 'core.module.layout.user.notification': "Notifications";
|
|
506
503
|
readonly 'core.module.layout.sidebar.search': "Search";
|
|
507
504
|
readonly 'core.module.layout.sidebar.toggle': "Toggle sidebar";
|
|
505
|
+
readonly 'core.module.layout.sidebar.menu-groups': "Menu groups";
|
|
506
|
+
readonly 'core.module.layout.sidebar.close-menu': "Close menu";
|
|
507
|
+
readonly 'core.module.layout.sidebar.search-in-group': "Search this group";
|
|
508
|
+
readonly 'core.module.layout.sidebar.primary-nav': "Primary navigation";
|
|
509
|
+
readonly 'core.module.layout.sidebar.more-menu': "More menus";
|
|
510
|
+
readonly 'core.module.layout.sidebar.more': "More";
|
|
511
|
+
readonly 'core.module.layout.sidebar.search-in-menu': "Search menus";
|
|
508
512
|
readonly 'core.module.layout.greeting.hello': "Hello, {name}";
|
|
509
513
|
readonly 'core.module.layout.weekday.0': "Sunday";
|
|
510
514
|
readonly 'core.module.layout.weekday.1': "Monday";
|
|
@@ -531,6 +535,81 @@ declare const EN_MESSAGES: {
|
|
|
531
535
|
readonly 'core.module.layout.home.feature.integration': "Integration";
|
|
532
536
|
readonly 'core.module.layout.mock.user.full-name': "Demo User";
|
|
533
537
|
readonly 'core.module.generic.generic-select.detail-link': "details";
|
|
538
|
+
readonly 'core.component.query-bar.search-placeholder': "Search...";
|
|
539
|
+
readonly 'core.component.query-bar.no-fields': "No fields configured";
|
|
540
|
+
readonly 'core.component.query-bar.add-filter': "Add filter";
|
|
541
|
+
readonly 'core.component.query-bar.clear-all': "Clear all ({count})";
|
|
542
|
+
readonly 'core.component.query-bar.search': "Search";
|
|
543
|
+
readonly 'core.component.query-bar.logic-operator': "Logic operator";
|
|
544
|
+
readonly 'core.component.query-bar.boolean.true': "Yes";
|
|
545
|
+
readonly 'core.component.query-bar.boolean.false': "No";
|
|
546
|
+
readonly 'core.component.query-bar.placeholder.value': "value";
|
|
547
|
+
readonly 'core.component.query-bar.placeholder.text': "type…";
|
|
548
|
+
readonly 'core.component.query-bar.placeholder.from-number': "From";
|
|
549
|
+
readonly 'core.component.query-bar.placeholder.to-number': "To";
|
|
550
|
+
readonly 'core.component.query-bar.placeholder.from-text': "from…";
|
|
551
|
+
readonly 'core.component.query-bar.placeholder.to-text': "to…";
|
|
552
|
+
readonly 'core.component.query-bar.swap-field': "Swap field";
|
|
553
|
+
readonly 'core.component.query-bar.placeholder.select-value': "Select value";
|
|
554
|
+
readonly 'core.component.query-bar.placeholder.enter-value': "Enter value";
|
|
555
|
+
readonly 'core.component.query-bar.loading-values': "Loading...";
|
|
556
|
+
readonly 'core.component.query-bar.field-empty': "No fields configured yet.";
|
|
557
|
+
readonly 'core.component.query-bar.saved-filters.tooltip': "Saved filters";
|
|
558
|
+
readonly 'core.component.query-bar.saved-filters.tooltip-disabled': "Requires [savedFiltersKey] to enable";
|
|
559
|
+
readonly 'core.component.query-bar.saved-filters.delete': "Delete filter";
|
|
560
|
+
readonly 'core.component.query-bar.saved-filters.empty': "No saved filters yet.";
|
|
561
|
+
readonly 'core.component.query-bar.saved-filters.save': "Save current filter";
|
|
562
|
+
readonly 'core.component.query-bar.saved-filters.name-label': "Filter name";
|
|
563
|
+
readonly 'core.component.query-builder.date-mode.absolute': "Specific date";
|
|
564
|
+
readonly 'core.component.query-builder.date-mode.now': "Today";
|
|
565
|
+
readonly 'core.component.query-builder.date-mode.relative': "Relative";
|
|
566
|
+
readonly 'core.component.query-builder.value-source.literal': "Enter a value";
|
|
567
|
+
readonly 'core.component.query-builder.value-source.field': "Compare with field";
|
|
568
|
+
readonly 'core.component.query-builder.relative.hour-previous': "hours ago";
|
|
569
|
+
readonly 'core.component.query-builder.relative.hour-next': "hours from now";
|
|
570
|
+
readonly 'core.component.query-builder.relative.day-previous': "days ago";
|
|
571
|
+
readonly 'core.component.query-builder.relative.day-next': "days from now";
|
|
572
|
+
readonly 'core.component.query-builder.relative.week-previous': "weeks ago";
|
|
573
|
+
readonly 'core.component.query-builder.relative.week-next': "weeks from now";
|
|
574
|
+
readonly 'core.component.query-builder.relative.month-previous': "months ago";
|
|
575
|
+
readonly 'core.component.query-builder.relative.month-next': "months from now";
|
|
576
|
+
readonly 'core.component.query-builder.relative.format': "{amount} {phrase}";
|
|
577
|
+
readonly 'core.component.query-builder.add': "Add";
|
|
578
|
+
readonly 'core.component.query-builder.add-node': "Add a condition or group";
|
|
579
|
+
readonly 'core.component.query-builder.condition': "Condition";
|
|
580
|
+
readonly 'core.component.query-builder.group': "Group";
|
|
581
|
+
readonly 'core.component.query-builder.remove-group': "Remove group";
|
|
582
|
+
readonly 'core.component.query-builder.remove-condition': "Remove condition";
|
|
583
|
+
readonly 'core.component.query-builder.empty': "No conditions yet";
|
|
584
|
+
readonly 'core.component.query-builder.select-field': "Select field";
|
|
585
|
+
readonly 'core.component.query-builder.value': "Value";
|
|
586
|
+
readonly 'core.component.query-builder.from': "From";
|
|
587
|
+
readonly 'core.component.query-builder.to': "To";
|
|
588
|
+
readonly 'core.component.query-builder.boolean.true': "Yes";
|
|
589
|
+
readonly 'core.component.query-builder.boolean.false': "No";
|
|
590
|
+
readonly 'core.component.tree.selected-count': "{count} item(s) selected";
|
|
591
|
+
readonly 'core.component.tree.expand': "Expand tree item";
|
|
592
|
+
readonly 'core.component.tree.collapse': "Collapse tree item";
|
|
593
|
+
readonly 'core.component.tree.retry-item': "Retry loading tree item";
|
|
594
|
+
readonly 'core.component.tree.load-error': "Unable to load tree data";
|
|
595
|
+
readonly 'core.directive.hover-copy.copied': "Copied";
|
|
596
|
+
readonly 'core.module.layout.sidebar.pinned': "Pinned";
|
|
597
|
+
readonly 'core.module.layout.sidebar.recent': "Recent";
|
|
598
|
+
readonly 'core.module.layout.sidebar.all-menu': "All menus";
|
|
599
|
+
readonly 'core.module.layout.menu.pin': "Pin {title}";
|
|
600
|
+
readonly 'core.module.layout.menu.unpin': "Unpin {title}";
|
|
601
|
+
readonly 'core.form.date.open-picker': "Open calendar";
|
|
602
|
+
readonly 'core.form.datetime.open-picker': "Open calendar";
|
|
603
|
+
readonly 'core.form.date-range.open-picker': "Open calendar";
|
|
604
|
+
readonly 'core.form.date-range.clear': "Clear date range";
|
|
605
|
+
readonly 'core.form.select.search': "Search";
|
|
606
|
+
readonly 'core.component.table.loading': "Loading table data";
|
|
607
|
+
readonly 'core.component.upload-file.loading': "Uploading file";
|
|
608
|
+
readonly 'core.component.import-excel.loading': "Loading data";
|
|
609
|
+
readonly 'core.component.upload-file.remove': "Remove file";
|
|
610
|
+
readonly 'core.component.upload-file.zoom': "Zoom image";
|
|
611
|
+
readonly 'core.component.upload-file.view-all': "View all images";
|
|
612
|
+
readonly 'core.component.form-builder.canvas': "Form design canvas";
|
|
534
613
|
};
|
|
535
614
|
|
|
536
615
|
type I18nKey = keyof typeof EN_MESSAGES;
|
|
@@ -575,12 +654,12 @@ declare class I18nService {
|
|
|
575
654
|
static ɵprov: i0.ɵɵInjectableDeclaration<I18nService>;
|
|
576
655
|
}
|
|
577
656
|
|
|
578
|
-
declare class
|
|
657
|
+
declare class SdTranslatePipe implements PipeTransform {
|
|
579
658
|
#private;
|
|
580
659
|
transform(key: string, params?: I18nParams): string;
|
|
581
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<
|
|
582
|
-
static ɵpipe: i0.ɵɵPipeDeclaration<
|
|
660
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SdTranslatePipe, never>;
|
|
661
|
+
static ɵpipe: i0.ɵɵPipeDeclaration<SdTranslatePipe, "sdTranslate", true>;
|
|
583
662
|
}
|
|
584
663
|
|
|
585
|
-
export { I18N_MESSAGES, I18N_STORAGE_KEY, I18nService,
|
|
664
|
+
export { I18N_MESSAGES, I18N_STORAGE_KEY, I18nService, SdTranslatePipe };
|
|
586
665
|
export type { CustomLanguageProvider, I18nCatalog, I18nKey, I18nParams };
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
|
|
2
|
-
import { Observable } from 'rxjs';
|
|
3
2
|
import * as i0 from '@angular/core';
|
|
3
|
+
import { InjectionToken } from '@angular/core';
|
|
4
|
+
import { Observable } from 'rxjs';
|
|
4
5
|
|
|
6
|
+
/**
|
|
7
|
+
* URL dùng để dò kết nối khi một request trả về status 0.
|
|
8
|
+
*
|
|
9
|
+
* why: bản cũ hard-code `https://jsonplaceholder.typicode.com/todos/1`, không override được. Mọi
|
|
10
|
+
* app tiêu dùng thư viện đều ping một bên thứ ba lạ mỗi 3 giây khi mất mạng, và vì probe đi qua
|
|
11
|
+
* NGUYÊN chuỗi interceptor của app nên bất kỳ interceptor nào gắn header auth vô điều kiện đều
|
|
12
|
+
* rò token ra ngoài origin. Mặc định giờ là một đường dẫn same-origin; app đổi bằng cách provide
|
|
13
|
+
* lại token này (nên trỏ tới endpoint tĩnh, rẻ, không cần auth).
|
|
14
|
+
*/
|
|
15
|
+
declare const SD_NO_INTERNET_PROBE_URL: InjectionToken<string>;
|
|
5
16
|
declare class SdNoInternetInterceptor implements HttpInterceptor {
|
|
6
17
|
#private;
|
|
7
18
|
private snackBar;
|
|
8
|
-
private injector;
|
|
9
19
|
/** Inserted by Angular inject() migration for backwards compatibility */
|
|
10
20
|
constructor(...args: unknown[]);
|
|
11
21
|
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>>;
|
|
@@ -23,4 +33,4 @@ declare class SdUnauthorizedInterceptor implements HttpInterceptor {
|
|
|
23
33
|
static ɵprov: i0.ɵɵInjectableDeclaration<SdUnauthorizedInterceptor>;
|
|
24
34
|
}
|
|
25
35
|
|
|
26
|
-
export { SdNoInternetInterceptor, SdUnauthorizedInterceptor };
|
|
36
|
+
export { SD_NO_INTERNET_PROBE_URL, SdNoInternetInterceptor, SdUnauthorizedInterceptor };
|
|
@@ -5,7 +5,7 @@ import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from
|
|
|
5
5
|
import { MaybeAsync } from '@sdcorejs/utils/models';
|
|
6
6
|
import { Observable } from 'rxjs';
|
|
7
7
|
|
|
8
|
-
interface SdAuthInfo<T =
|
|
8
|
+
interface SdAuthInfo<T = unknown> {
|
|
9
9
|
id?: string;
|
|
10
10
|
username?: string;
|
|
11
11
|
firstName?: string;
|
|
@@ -40,6 +40,7 @@ interface ISdKeycloakConfiguration {
|
|
|
40
40
|
declare const SD_KEYCLOAK_CONFIGURATION: InjectionToken<ISdKeycloakConfiguration>;
|
|
41
41
|
|
|
42
42
|
declare class SdKeycloakService {
|
|
43
|
+
#private;
|
|
43
44
|
keycloak: Keycloak;
|
|
44
45
|
config: SdKeycloakTenantConfig;
|
|
45
46
|
init(config: SdKeycloakTenantConfig): Promise<boolean>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _angular_core from '@angular/core';
|
|
2
|
-
import {
|
|
2
|
+
import { InjectionToken, Signal, PipeTransform } from '@angular/core';
|
|
3
3
|
import * as i1$1 from '@angular/common';
|
|
4
4
|
import * as i1 from '@angular/router';
|
|
5
5
|
import { Params } from '@angular/router';
|
|
@@ -57,15 +57,59 @@ interface SdLayoutChildrenMenu {
|
|
|
57
57
|
tooltipTitle?: string;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Namespace áp cho toàn bộ state layout được persist — hằng chuỗi, hoặc hàm resolve lại mỗi lần đọc
|
|
62
|
+
* (dùng cho danh tính chỉ biết được SAU khi đăng nhập, ví dụ id user hoặc tenant).
|
|
63
|
+
*/
|
|
64
|
+
type SdLayoutStorageNamespace = string | (() => string | null | undefined);
|
|
65
|
+
/**
|
|
66
|
+
* Namespace do consumer cung cấp cho toàn bộ state layout được persist (thường là id user hoặc tenant).
|
|
67
|
+
*
|
|
68
|
+
* why: các key dưới đây là UUID CỐ ĐỊNH, không gắn với ai cả. Trên máy dùng chung, user A đăng xuất
|
|
69
|
+
* rồi user B đăng nhập thì `pinnedMenuKeys` / `recentMenuKeys` / `lastActiveMenuGroupId` của A vẫn
|
|
70
|
+
* còn nguyên trong localStorage và B nhìn thấy đúng những module A đã ghim và vừa truy cập. Cấp
|
|
71
|
+
* namespace theo user/tenant sẽ tách hẳn không gian lưu trữ.
|
|
72
|
+
*
|
|
73
|
+
* ⚠️ `SdLayoutStorageService` là singleton `providedIn: 'root'`, thường được khởi tạo TRƯỚC khi biết
|
|
74
|
+
* người dùng là ai. Vì vậy hãy cấp một **hàm** — nó được gọi lại ở mỗi lần truy cập handle, nên khi
|
|
75
|
+
* danh tính đến (hoặc đổi) thì cả bảy handle tự dựng lại trên namespace mới:
|
|
76
|
+
*
|
|
77
|
+
* ```ts
|
|
78
|
+
* providers: [
|
|
79
|
+
* {
|
|
80
|
+
* provide: SD_LAYOUT_STORAGE_NAMESPACE,
|
|
81
|
+
* useFactory: () => {
|
|
82
|
+
* const auth = inject(SdAuthService);
|
|
83
|
+
* return () => auth.getAuthInfo?.()?.id;
|
|
84
|
+
* },
|
|
85
|
+
* },
|
|
86
|
+
* ];
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* Đây là biện pháp bổ sung chứ không thay thế `SdLayoutStorageService.clear()` lúc signout.
|
|
90
|
+
*/
|
|
91
|
+
declare const SD_LAYOUT_STORAGE_NAMESPACE: InjectionToken<SdLayoutStorageNamespace>;
|
|
60
92
|
declare class SdLayoutStorageService {
|
|
61
93
|
#private;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
94
|
+
get isShowSidebar(): SdStorage<boolean>;
|
|
95
|
+
get menuLockStatus(): SdStorage<boolean>;
|
|
96
|
+
get lastActiveMenuGroupId(): SdStorage<string>;
|
|
97
|
+
get pinnedMenuGroup(): SdStorage<SdLayoutChildrenMenu>;
|
|
98
|
+
get pinnedMenuKeys(): SdStorage<string[]>;
|
|
99
|
+
get recentMenuKeys(): SdStorage<string[]>;
|
|
100
|
+
get versionStates(): SdStorage<Record<string, SdLayoutVersionState>>;
|
|
101
|
+
/**
|
|
102
|
+
* Xoá toàn bộ state layout đã persist.
|
|
103
|
+
*
|
|
104
|
+
* **Consumer PHẢI gọi hàm này trong luồng signout, TRƯỚC khi danh tính bị xoá.** Nếu không,
|
|
105
|
+
* pinned/recent/last-active của user vừa đăng xuất sẽ còn lại trên trình duyệt và hiện ra cho người
|
|
106
|
+
* đăng nhập kế tiếp — rò rỉ tên module nội bộ mà người đó có thể không có quyền thấy.
|
|
107
|
+
*
|
|
108
|
+
* why: khi đã cấu hình `SD_LAYOUT_STORAGE_NAMESPACE` theo user, namespace được resolve NGAY LÚC GỌI.
|
|
109
|
+
* Gọi `clear()` sau khi auth info về `undefined` sẽ xoá nhầm partition không-namespace, còn dữ liệu
|
|
110
|
+
* của user vừa thoát thì vẫn nguyên.
|
|
111
|
+
*/
|
|
112
|
+
clear(): void;
|
|
69
113
|
readPinnedMenuKeys(menus: SdLayoutMenu[]): string[];
|
|
70
114
|
writePinnedMenuKeys(keys: string[]): void;
|
|
71
115
|
readRecentMenuKeys(menus: SdLayoutMenu[], maximum?: number): string[];
|
|
@@ -251,10 +295,30 @@ declare function selectPrimaryMenuGroups(menus: SdLayoutMenu[], requestedIds: st
|
|
|
251
295
|
declare function resolveMenuKeys(menus: SdLayoutMenu[], keys: string[]): (SdLayoutRootMenu | SdLayoutChildrenMenu)[];
|
|
252
296
|
declare function flattenMenuLeaves(menus: SdLayoutMenu[]): SdLayoutRootMenu[];
|
|
253
297
|
|
|
298
|
+
/**
|
|
299
|
+
* Bật fallback demo của `SdLayoutService` khi KHÔNG provide `SD_LAYOUT_CONFIGURATION`.
|
|
300
|
+
*
|
|
301
|
+
* why: fallback cũ chạy ngầm sau mỗi `console.warn`, nên một app cấu hình thiếu vẫn ship được UI có
|
|
302
|
+
* user "demo@example.com" đang đăng nhập cùng nút signout không làm gì — người dùng cuối tin là đã
|
|
303
|
+
* đăng nhập thật. Giờ mặc định là throw; ai thực sự cần demo/playground phải khai báo ý định:
|
|
304
|
+
*
|
|
305
|
+
* ```ts
|
|
306
|
+
* providers: [{ provide: SD_LAYOUT_DEMO_FALLBACK, useValue: true }]
|
|
307
|
+
* ```
|
|
308
|
+
*
|
|
309
|
+
* Cờ nằm ở token riêng chứ không phải field của `ISdLayoutConfiguration`, vì nó phải đọc được ĐÚNG
|
|
310
|
+
* lúc `SD_LAYOUT_CONFIGURATION` vắng mặt — khi đó không có object configuration nào để đọc field.
|
|
311
|
+
*/
|
|
312
|
+
declare const SD_LAYOUT_DEMO_FALLBACK: InjectionToken<boolean>;
|
|
254
313
|
declare class SdLayoutService {
|
|
255
314
|
#private;
|
|
256
315
|
userInfo: _angular_core.WritableSignal<SdLayoutUserInfo | undefined>;
|
|
257
316
|
sidebar: _angular_core.WritableSignal<ISdSidebarConfiguration | undefined>;
|
|
317
|
+
/**
|
|
318
|
+
* Route "về trang chủ" của consumer, lấy từ `ISdLayoutConfiguration.homeUrl`.
|
|
319
|
+
* why: các trang lỗi (forbidden / not-found) cần một đích điều hướng thật thay vì reload chính nó.
|
|
320
|
+
*/
|
|
321
|
+
readonly homeUrl: string;
|
|
258
322
|
constructor();
|
|
259
323
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdLayoutService, never>;
|
|
260
324
|
static ɵprov: _angular_core.ɵɵInjectableDeclaration<SdLayoutService>;
|
|
@@ -285,7 +349,7 @@ declare class SdLayoutComponent {
|
|
|
285
349
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SdLayoutComponent, "sd-layout", never, { "menusInput": { "alias": "menus"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
286
350
|
}
|
|
287
351
|
|
|
288
|
-
declare class
|
|
352
|
+
declare class SdSidebarMobileV1 {
|
|
289
353
|
#private;
|
|
290
354
|
menus: _angular_core.InputSignal<SdLayoutMenu[]>;
|
|
291
355
|
userInfo: _angular_core.InputSignal<SdLayoutUserInfo>;
|
|
@@ -300,11 +364,11 @@ declare class SidebarMobileV1Component {
|
|
|
300
364
|
onExpandSideBar: () => void;
|
|
301
365
|
onMouseleaveSideBar: () => void;
|
|
302
366
|
onTitleMenuGroupChanged: (title: string | undefined) => void;
|
|
303
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<
|
|
304
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<
|
|
367
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdSidebarMobileV1, never>;
|
|
368
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SdSidebarMobileV1, "sd-sidebar-mobile-v1", never, { "menus": { "alias": "menus"; "required": false; "isSignal": true; }; "userInfo": { "alias": "userInfo"; "required": true; "isSignal": true; }; "sidebar": { "alias": "sidebar"; "required": true; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
305
369
|
}
|
|
306
370
|
|
|
307
|
-
declare class
|
|
371
|
+
declare class SdSidebarMobileOverlay {
|
|
308
372
|
#private;
|
|
309
373
|
isShowSidebar: _angular_core.InputSignal<boolean>;
|
|
310
374
|
menus: _angular_core.InputSignal<SdLayoutMenu[]>;
|
|
@@ -332,8 +396,8 @@ declare class SidebarMobileOverlayComponent {
|
|
|
332
396
|
getQueryParams(menu: SdLayoutMenu): Params;
|
|
333
397
|
onUserMenuOpened: () => void;
|
|
334
398
|
onUserMenuClosed: () => void;
|
|
335
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<
|
|
336
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<
|
|
399
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdSidebarMobileOverlay, never>;
|
|
400
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SdSidebarMobileOverlay, "sd-sidebar-mobile-overlay", never, { "isShowSidebar": { "alias": "isShowSidebar"; "required": false; "isSignal": true; }; "menus": { "alias": "menus"; "required": true; "isSignal": true; }; "userInfo": { "alias": "userInfo"; "required": true; "isSignal": true; }; "sidebar": { "alias": "sidebar"; "required": true; "isSignal": true; }; }, { "showSideBar": "showSideBar"; "expandSideBar": "expandSideBar"; "popupUserMenuOpened": "popupUserMenuOpened"; "popupUserMenuClosed": "popupUserMenuClosed"; "titleMenuGroupChanged": "titleMenuGroupChanged"; }, never, never, true, never>;
|
|
337
401
|
}
|
|
338
402
|
|
|
339
403
|
interface SdLayoutMenuTreeNode {
|
|
@@ -346,6 +410,8 @@ interface SdLayoutMenuTreeNode {
|
|
|
346
410
|
isActive: boolean;
|
|
347
411
|
isPinned: boolean;
|
|
348
412
|
isPinVisible: boolean;
|
|
413
|
+
/** Accessible name of the pin toggle — already i18n-resolved with the menu title interpolated. */
|
|
414
|
+
pinLabel: string;
|
|
349
415
|
}
|
|
350
416
|
declare class SdLayoutMenuTreeComponent {
|
|
351
417
|
#private;
|
|
@@ -416,7 +482,7 @@ interface SidebarV2RailItem {
|
|
|
416
482
|
key: string;
|
|
417
483
|
title: string;
|
|
418
484
|
}
|
|
419
|
-
declare class
|
|
485
|
+
declare class SdSidebarV2 {
|
|
420
486
|
#private;
|
|
421
487
|
menus: _angular_core.InputSignal<SdLayoutMenu[]>;
|
|
422
488
|
userInfo: _angular_core.InputSignal<SdLayoutUserInfo>;
|
|
@@ -440,11 +506,11 @@ declare class SidebarV2Component {
|
|
|
440
506
|
closeFromNavigation(): void;
|
|
441
507
|
onNavigate(menu: SdLayoutMenu): void;
|
|
442
508
|
onTogglePinned(menu: SdLayoutMenu): void;
|
|
443
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<
|
|
444
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<
|
|
509
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdSidebarV2, never>;
|
|
510
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SdSidebarV2, "sd-sidebar-v2", never, { "menus": { "alias": "menus"; "required": false; "isSignal": true; }; "userInfo": { "alias": "userInfo"; "required": true; "isSignal": true; }; "sidebar": { "alias": "sidebar"; "required": true; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
445
511
|
}
|
|
446
512
|
|
|
447
|
-
declare class
|
|
513
|
+
declare class SdSidebarMobileV2 {
|
|
448
514
|
#private;
|
|
449
515
|
menus: _angular_core.InputSignal<SdLayoutMenu[]>;
|
|
450
516
|
userInfo: _angular_core.InputSignal<SdLayoutUserInfo>;
|
|
@@ -465,11 +531,11 @@ declare class SidebarMobileV2Component {
|
|
|
465
531
|
onSheetKeydown(event: KeyboardEvent): void;
|
|
466
532
|
onNavigate(menu: SdLayoutMenu): void;
|
|
467
533
|
onTogglePinned(menu: SdLayoutMenu): void;
|
|
468
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<
|
|
469
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<
|
|
534
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdSidebarMobileV2, never>;
|
|
535
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SdSidebarMobileV2, "sd-sidebar-mobile-v2", never, { "menus": { "alias": "menus"; "required": false; "isSignal": true; }; "userInfo": { "alias": "userInfo"; "required": true; "isSignal": true; }; "sidebar": { "alias": "sidebar"; "required": true; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
470
536
|
}
|
|
471
537
|
|
|
472
|
-
declare class
|
|
538
|
+
declare class SdSidebarV3 {
|
|
473
539
|
#private;
|
|
474
540
|
menus: _angular_core.InputSignal<SdLayoutMenu[]>;
|
|
475
541
|
userInfo: _angular_core.InputSignal<SdLayoutUserInfo>;
|
|
@@ -492,11 +558,11 @@ declare class SidebarV3Component {
|
|
|
492
558
|
activateCollapsedMenu(menu: SdLayoutMenu): void;
|
|
493
559
|
navigateMenu(menu: SdLayoutMenu): void;
|
|
494
560
|
onTogglePinned(menu: SdLayoutMenu): void;
|
|
495
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<
|
|
496
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<
|
|
561
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdSidebarV3, never>;
|
|
562
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SdSidebarV3, "sd-sidebar-v3", never, { "menus": { "alias": "menus"; "required": false; "isSignal": true; }; "userInfo": { "alias": "userInfo"; "required": true; "isSignal": true; }; "sidebar": { "alias": "sidebar"; "required": true; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
497
563
|
}
|
|
498
564
|
|
|
499
|
-
declare class
|
|
565
|
+
declare class SdSidebarMobileV3 {
|
|
500
566
|
#private;
|
|
501
567
|
private readonly trigger;
|
|
502
568
|
menus: _angular_core.InputSignal<SdLayoutMenu[]>;
|
|
@@ -518,8 +584,8 @@ declare class SidebarMobileV3Component {
|
|
|
518
584
|
onDrawerKeydown(event: KeyboardEvent): void;
|
|
519
585
|
navigateMenu(menu: SdLayoutMenu): void;
|
|
520
586
|
onTogglePinned(menu: SdLayoutMenu): void;
|
|
521
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<
|
|
522
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<
|
|
587
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdSidebarMobileV3, never>;
|
|
588
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SdSidebarMobileV3, "sd-sidebar-mobile-v3", never, { "menus": { "alias": "menus"; "required": false; "isSignal": true; }; "userInfo": { "alias": "userInfo"; "required": true; "isSignal": true; }; "sidebar": { "alias": "sidebar"; "required": true; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
523
589
|
}
|
|
524
590
|
|
|
525
591
|
/**
|
|
@@ -565,5 +631,5 @@ declare class SdLayoutModule {
|
|
|
565
631
|
static ɵinj: _angular_core.ɵɵInjectorDeclaration<SdLayoutModule>;
|
|
566
632
|
}
|
|
567
633
|
|
|
568
|
-
export { DEFAULT_LAYOUT_MOBILE_BREAKPOINT, ForbiddenModule, HighlightSearchPipe, HomeModule, MenuFocusPipe, MenuPipe, NotFoundModule, SD_LAYOUT_CONFIGURATION, SD_LAYOUT_VIEWPORT, SdLayoutComponent, SdLayoutMenuTreeComponent, SdLayoutModule, SdLayoutNavigationStateService, SdLayoutResponsiveService, SdLayoutService, SdLayoutStorageService, SdLayoutUserMenuComponent, SdPageComponent,
|
|
569
|
-
export type { ISdLayoutConfiguration, ISdSidebarConfiguration, Menus, ResolvedSidebarRecentConfiguration, SdLayoutAccountAction, SdLayoutChildrenMenu, SdLayoutMenu, SdLayoutNotificationConfiguration, SdLayoutRootMenu, SdLayoutUserInfo, SdLayoutUserRole, SdLayoutVersionState, SdLayoutViewport, SidebarConfigurationBase, SidebarConfigurationV1, SidebarConfigurationV2, SidebarConfigurationV3 };
|
|
634
|
+
export { DEFAULT_LAYOUT_MOBILE_BREAKPOINT, ForbiddenModule, HighlightSearchPipe, HomeModule, MenuFocusPipe, MenuPipe, NotFoundModule, SD_LAYOUT_CONFIGURATION, SD_LAYOUT_DEMO_FALLBACK, SD_LAYOUT_STORAGE_NAMESPACE, SD_LAYOUT_VIEWPORT, SdLayoutComponent, SdLayoutMenuTreeComponent, SdLayoutModule, SdLayoutNavigationStateService, SdLayoutResponsiveService, SdLayoutService, SdLayoutStorageService, SdLayoutUserMenuComponent, SdPageComponent, SdSidebarMobileOverlay, SdSidebarMobileV1, SdSidebarMobileV2, SdSidebarMobileV3, SdSidebarV2, SdSidebarV3, flattenMenuLeaves, getMenuStableKey, normalizeLayoutMobileBreakpoint, normalizeSidebarConfiguration, resolveMenuKeys, resolveSidebarV2Interaction, resolveSidebarV3Recent, resolveTabName, searchMenuLeaves, selectPrimaryMenuGroups };
|
|
635
|
+
export type { ISdLayoutConfiguration, ISdSidebarConfiguration, Menus, ResolvedSidebarRecentConfiguration, SdLayoutAccountAction, SdLayoutChildrenMenu, SdLayoutMenu, SdLayoutNotificationConfiguration, SdLayoutRootMenu, SdLayoutStorageNamespace, SdLayoutUserInfo, SdLayoutUserRole, SdLayoutVersionState, SdLayoutViewport, SidebarConfigurationBase, SidebarConfigurationV1, SidebarConfigurationV2, SidebarConfigurationV3 };
|
|
@@ -49,6 +49,17 @@ interface ISdPermissionConfiguration {
|
|
|
49
49
|
* Hỗ trợ trả về đồng bộ, Promise hoặc Observable.
|
|
50
50
|
*/
|
|
51
51
|
getToken?: () => MaybeAsync<string | undefined | null>;
|
|
52
|
+
/**
|
|
53
|
+
* Cho phép mirror danh sách mã quyền của key này xuống `sessionStorage` để sống qua reload.
|
|
54
|
+
*
|
|
55
|
+
* ⚠️ Mặc định `false` — danh sách quyền CHỈ nằm trong bộ nhớ.
|
|
56
|
+
*
|
|
57
|
+
* Bật cờ này nghĩa là chấp nhận: mọi script chạy trên cùng origin đều ĐỌC và GHI được danh sách đó.
|
|
58
|
+
* Cache KHÔNG phải một ranh giới phân quyền — nó chỉ tiết kiệm một lần gọi API khi reload; backend
|
|
59
|
+
* vẫn phải kiểm tra quyền cho từng request. Khi bật, nhớ gọi `SdPermissionService.reset()` lúc
|
|
60
|
+
* signout để xoá cả bản mirror.
|
|
61
|
+
*/
|
|
62
|
+
persistCache?: boolean;
|
|
52
63
|
}
|
|
53
64
|
/**
|
|
54
65
|
* InjectionToken cho cấu hình permission.
|
|
@@ -65,13 +76,64 @@ interface ISdPermissionConfiguration {
|
|
|
65
76
|
*/
|
|
66
77
|
declare const SD_PERMISSION_CONFIGURATION: InjectionToken<ISdPermissionConfiguration | ISdPermissionConfiguration[]>;
|
|
67
78
|
|
|
79
|
+
/**
|
|
80
|
+
* Opt-out TƯỜNG MINH: "chỗ này cố ý không yêu cầu quyền nào".
|
|
81
|
+
*
|
|
82
|
+
* Dùng cho `route.data.permission`, `[sdPermission]` hoặc `hasPermission(...)` khi một route/phần tử
|
|
83
|
+
* thật sự công khai. Mọi giá trị rỗng khác (`undefined`, `null`, `''`, `[]`) đều bị coi là CẤU HÌNH
|
|
84
|
+
* THIẾU và bị từ chối — xem `SdPermissionService.hasPermission`.
|
|
85
|
+
*/
|
|
86
|
+
declare const SD_PERMISSION_PUBLIC = "__SD_PERMISSION_PUBLIC__";
|
|
87
|
+
/** Kiểu đầu vào cho `hasPermission` / `[sdPermission]`. */
|
|
88
|
+
type SdPermissionInput = string | string[] | null | undefined;
|
|
68
89
|
declare class SdPermissionService {
|
|
69
90
|
#private;
|
|
70
91
|
constructor();
|
|
71
92
|
loadPermissions: (key?: string) => Promise<string[]>;
|
|
72
93
|
loadAllPermissions: () => Promise<void>;
|
|
73
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Xoá TOÀN BỘ quyền đã nạp (mọi key) — cả map trong bộ nhớ, cờ "đã nạp" lẫn bản mirror
|
|
96
|
+
* `sessionStorage` của các key bật `persistCache`.
|
|
97
|
+
*
|
|
98
|
+
* ⚠️ BẮT BUỘC gọi khi signout. Service là singleton `providedIn: 'root'`, nên trong một SPA
|
|
99
|
+
* signout → signin (không reload trang) mà không reset thì `loadPermissions()` sẽ short-circuit
|
|
100
|
+
* theo key đã cache và user MỚI thừa hưởng nguyên bộ quyền của user CŨ.
|
|
101
|
+
*
|
|
102
|
+
* ```ts
|
|
103
|
+
* auth.signout$?.subscribe(() => permissionService.reset());
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
reset: () => void;
|
|
107
|
+
/**
|
|
108
|
+
* Xoá quyền đã nạp của MỘT key (mặc định là key portal `undefined`), buộc lần
|
|
109
|
+
* `loadPermissions(key)` kế tiếp gọi lại loader. Dùng khi chỉ một profile/tenant đổi quyền;
|
|
110
|
+
* signout thì dùng {@link reset}.
|
|
111
|
+
*/
|
|
112
|
+
invalidate: (key?: string) => void;
|
|
113
|
+
/**
|
|
114
|
+
* Kiểm tra quyền (OR cho mảng).
|
|
115
|
+
*
|
|
116
|
+
* ⚠️ BREAKING: đầu vào rỗng (`undefined` / `null` / `''` / `[]`) giờ trả `false`.
|
|
117
|
+
* Muốn "không yêu cầu quyền" thì phải nói ra bằng {@link SD_PERMISSION_PUBLIC}.
|
|
118
|
+
*/
|
|
119
|
+
hasPermission: (permission: SdPermissionInput, key?: string) => boolean;
|
|
74
120
|
getToken: (key?: string) => Promise<string | null | undefined>;
|
|
121
|
+
/**
|
|
122
|
+
* Giải mã phần payload của JWT hiện tại và trả về claim **CHƯA ĐƯỢC XÁC THỰC**.
|
|
123
|
+
*
|
|
124
|
+
* ⚠️ KHÔNG kiểm chữ ký, KHÔNG kiểm `exp`/`nbf`/`aud`/`iss`. Đây thuần tuý là base64url-decode: bất
|
|
125
|
+
* kỳ ai cũng tự tạo được một token có claim tuỳ ý và hàm này sẽ vui vẻ trả về. Vì vậy kết quả CHỈ
|
|
126
|
+
* dùng cho mục đích hiển thị (tên, avatar, tenant đang chọn…) và TUYỆT ĐỐI không được dùng để ra
|
|
127
|
+
* quyết định phân quyền — quyền phải do backend xác thực chữ ký rồi trả về.
|
|
128
|
+
*
|
|
129
|
+
* Trả `null` khi không có token hoặc payload hỏng.
|
|
130
|
+
*/
|
|
131
|
+
readUnverifiedTokenClaims: <T>(key?: string) => Promise<T | null>;
|
|
132
|
+
/**
|
|
133
|
+
* @deprecated Tên `decodeToken` gợi ý một thao tác đã được kiểm chứng, trong khi thực tế payload
|
|
134
|
+
* hoàn toàn KHÔNG được xác thực. Dùng {@link readUnverifiedTokenClaims} — alias này chỉ còn để
|
|
135
|
+
* consumer cũ không vỡ và sẽ bị gỡ ở release sau.
|
|
136
|
+
*/
|
|
75
137
|
decodeToken: <T>(key?: string) => Promise<T | null>;
|
|
76
138
|
static ɵfac: i0.ɵɵFactoryDeclaration<SdPermissionService, never>;
|
|
77
139
|
static ɵprov: i0.ɵɵInjectableDeclaration<SdPermissionService>;
|
|
@@ -79,7 +141,7 @@ declare class SdPermissionService {
|
|
|
79
141
|
|
|
80
142
|
declare class SdPermissionDirective {
|
|
81
143
|
#private;
|
|
82
|
-
readonly sdPermission: i0.InputSignal<
|
|
144
|
+
readonly sdPermission: i0.InputSignal<SdPermissionInput>;
|
|
83
145
|
readonly sdPermissionKey: i0.InputSignal<string | undefined>;
|
|
84
146
|
constructor();
|
|
85
147
|
static ɵfac: i0.ɵɵFactoryDeclaration<SdPermissionDirective, never>;
|
|
@@ -96,5 +158,5 @@ declare class SdPermissionGuard implements CanActivate, CanActivateChild {
|
|
|
96
158
|
static ɵprov: i0.ɵɵInjectableDeclaration<SdPermissionGuard>;
|
|
97
159
|
}
|
|
98
160
|
|
|
99
|
-
export { SD_PERMISSION_CONFIGURATION, SdPermissionDirective, SdPermissionGuard, SdPermissionService };
|
|
100
|
-
export type { ISdPermissionConfiguration };
|
|
161
|
+
export { SD_PERMISSION_CONFIGURATION, SD_PERMISSION_PUBLIC, SdPermissionDirective, SdPermissionGuard, SdPermissionService };
|
|
162
|
+
export type { ISdPermissionConfiguration, SdPermissionInput };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { PipeTransform } from '@angular/core';
|
|
3
|
-
import
|
|
3
|
+
import { SafeHtml } from '@angular/platform-browser';
|
|
4
4
|
import { Observable } from 'rxjs';
|
|
5
5
|
|
|
6
6
|
declare class SdFormatDatePipe implements PipeTransform {
|
|
@@ -25,17 +25,39 @@ declare class SdFormatNumberPipe implements PipeTransform {
|
|
|
25
25
|
static ɵprov: i0.ɵɵInjectableDeclaration<SdFormatNumberPipe>;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Render an HTML string through `[innerHTML]`.
|
|
30
|
+
*
|
|
31
|
+
* why: this pipe used to call `bypassSecurityTrustHtml()` unconditionally, on every value, with no
|
|
32
|
+
* sanitize step. That turned every call site into a stored-XSS sink — and the library itself pipes
|
|
33
|
+
* server-supplied table cell data through it
|
|
34
|
+
* (`components/table/src/components/desktop-cell/view/view.component.html`), while
|
|
35
|
+
* `components/table/sd-table.md` already described the value as "sanitized via sdSafeHtml".
|
|
36
|
+
*
|
|
37
|
+
* Now it **sanitizes by default** and the bypass is an explicit, per-call-site opt-in:
|
|
38
|
+
*
|
|
39
|
+
* ```html
|
|
40
|
+
* <!-- untrusted / server-supplied: script, on* handlers and javascript: urls are stripped -->
|
|
41
|
+
* <div [innerHTML]="row.note | sdSafeHtml"></div>
|
|
42
|
+
*
|
|
43
|
+
* <!-- app-authored markup you control, e.g. an inline SVG sprite -->
|
|
44
|
+
* <span [innerHTML]="iconSvg | sdSafeHtml: true"></span>
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* This mirrors the decision already taken for the toast in `services/notify`: text-safe by default,
|
|
48
|
+
* opt-in HTML. Auto-detecting "this looks like HTML" is deliberately NOT done — it would escalate
|
|
49
|
+
* untrusted text that merely contains `<` straight back into the unsanitized sink.
|
|
50
|
+
*/
|
|
28
51
|
declare class SdSafeHtmlPipe implements PipeTransform {
|
|
29
|
-
private
|
|
30
|
-
|
|
31
|
-
constructor(...args: unknown[]);
|
|
32
|
-
transform(html: string | number | undefined | null): _angular_platform_browser.SafeHtml | undefined;
|
|
52
|
+
#private;
|
|
53
|
+
transform(html: string | number | undefined | null, trusted?: boolean): SafeHtml | string | number | undefined;
|
|
33
54
|
static ɵfac: i0.ɵɵFactoryDeclaration<SdSafeHtmlPipe, never>;
|
|
34
55
|
static ɵpipe: i0.ɵɵPipeDeclaration<SdSafeHtmlPipe, "sdSafeHtml", true>;
|
|
35
56
|
static ɵprov: i0.ɵɵInjectableDeclaration<SdSafeHtmlPipe>;
|
|
36
57
|
}
|
|
37
58
|
|
|
38
59
|
declare class SdTimeDifferentPipe implements PipeTransform {
|
|
60
|
+
#private;
|
|
39
61
|
private maxSecond;
|
|
40
62
|
private maxMinute;
|
|
41
63
|
private maxHour;
|