@tinya-code/gas-admin-ui 0.2.0-alpha.15 → 0.2.0-alpha.18
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/fesm2022/tinya-code-gas-admin-ui-badge-EeCA_l-o.mjs +84 -0
- package/fesm2022/tinya-code-gas-admin-ui-badge-EeCA_l-o.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-bar-chart-G7sEMSBY.mjs +140 -0
- package/fesm2022/tinya-code-gas-admin-ui-bar-chart-G7sEMSBY.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-boolean-B2ASKL0E.mjs +113 -0
- package/fesm2022/tinya-code-gas-admin-ui-boolean-B2ASKL0E.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-button-BQjNW8KB.mjs +163 -0
- package/fesm2022/tinya-code-gas-admin-ui-button-BQjNW8KB.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-calendar-view-DCY8bj2V.mjs +1027 -0
- package/fesm2022/tinya-code-gas-admin-ui-calendar-view-DCY8bj2V.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-chart-line-BjdlKHoH.mjs +278 -0
- package/fesm2022/tinya-code-gas-admin-ui-chart-line-BjdlKHoH.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-color-Dljh_By3.mjs +107 -0
- package/fesm2022/tinya-code-gas-admin-ui-color-Dljh_By3.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-condition-evaluator-DY2k1M3C.mjs +101 -0
- package/fesm2022/tinya-code-gas-admin-ui-condition-evaluator-DY2k1M3C.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-currency-BvuF3Z63.mjs +141 -0
- package/fesm2022/tinya-code-gas-admin-ui-currency-BvuF3Z63.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-data-source.service-96FSbN72.mjs +88 -0
- package/fesm2022/tinya-code-gas-admin-ui-data-source.service-96FSbN72.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-date-1SJGXZrd.mjs +107 -0
- package/fesm2022/tinya-code-gas-admin-ui-date-1SJGXZrd.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-display-badge-fwk6sDU7.mjs +140 -0
- package/fesm2022/tinya-code-gas-admin-ui-display-badge-fwk6sDU7.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-display-date-D7zLiDiG.mjs +119 -0
- package/fesm2022/tinya-code-gas-admin-ui-display-date-D7zLiDiG.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-display-file-BiIhqvQC.mjs +125 -0
- package/fesm2022/tinya-code-gas-admin-ui-display-file-BiIhqvQC.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-display-image-C1dhnZi1.mjs +152 -0
- package/fesm2022/tinya-code-gas-admin-ui-display-image-C1dhnZi1.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-display-list-DOEuUbGe.mjs +211 -0
- package/fesm2022/tinya-code-gas-admin-ui-display-list-DOEuUbGe.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-display-number-DDMzr4Hn.mjs +116 -0
- package/fesm2022/tinya-code-gas-admin-ui-display-number-DDMzr4Hn.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-display-text-B8CdVNpv.mjs +111 -0
- package/fesm2022/tinya-code-gas-admin-ui-display-text-B8CdVNpv.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-dropdown-C3blvmE1.mjs +122 -0
- package/fesm2022/tinya-code-gas-admin-ui-dropdown-C3blvmE1.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-email-CT_O5ihA.mjs +107 -0
- package/fesm2022/tinya-code-gas-admin-ui-email-CT_O5ihA.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-empty-state-BMc0QtoT.mjs +109 -0
- package/fesm2022/tinya-code-gas-admin-ui-empty-state-BMc0QtoT.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-error-mapper.service-DY5y1FjE.mjs +45 -0
- package/fesm2022/tinya-code-gas-admin-ui-error-mapper.service-DY5y1FjE.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-field-aria-BD1Wiggc.mjs +50 -0
- package/fesm2022/tinya-code-gas-admin-ui-field-aria-BD1Wiggc.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-field-node-CIK6KNN_.mjs +24 -0
- package/fesm2022/tinya-code-gas-admin-ui-field-node-CIK6KNN_.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-field-path-B4-FTBGZ.mjs +27 -0
- package/fesm2022/tinya-code-gas-admin-ui-field-path-B4-FTBGZ.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-file-Dmxioog7.mjs +408 -0
- package/fesm2022/tinya-code-gas-admin-ui-file-Dmxioog7.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-form-view-CEe7aZ4m.mjs +4516 -0
- package/fesm2022/tinya-code-gas-admin-ui-form-view-CEe7aZ4m.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-format-badge-CK8ct5Wk.mjs +82 -0
- package/fesm2022/tinya-code-gas-admin-ui-format-badge-CK8ct5Wk.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-format-boolean-ClzezZz-.mjs +105 -0
- package/fesm2022/tinya-code-gas-admin-ui-format-boolean-ClzezZz-.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-format-currency-CVmniKml.mjs +65 -0
- package/fesm2022/tinya-code-gas-admin-ui-format-currency-CVmniKml.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-format-date-Dr1YsDd_.mjs +65 -0
- package/fesm2022/tinya-code-gas-admin-ui-format-date-Dr1YsDd_.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-format-number-CWCjpI4n.mjs +65 -0
- package/fesm2022/tinya-code-gas-admin-ui-format-number-CWCjpI4n.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-format-text-DBOgJkH0.mjs +59 -0
- package/fesm2022/tinya-code-gas-admin-ui-format-text-DBOgJkH0.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-format-thumbnail-PCRvxWKt.mjs +94 -0
- package/fesm2022/tinya-code-gas-admin-ui-format-thumbnail-PCRvxWKt.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-gap-sorting-iTdy_DYG.mjs +72 -0
- package/fesm2022/tinya-code-gas-admin-ui-gap-sorting-iTdy_DYG.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-group-h7-O8tt4.mjs +238 -0
- package/fesm2022/tinya-code-gas-admin-ui-group-h7-O8tt4.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-image-7UhJ7nqI.mjs +416 -0
- package/fesm2022/tinya-code-gas-admin-ui-image-7UhJ7nqI.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-kanban-view-Dl0Ol5Kb.mjs +439 -0
- package/fesm2022/tinya-code-gas-admin-ui-kanban-view-Dl0Ol5Kb.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-key-value-nVdgg5at.mjs +513 -0
- package/fesm2022/tinya-code-gas-admin-ui-key-value-nVdgg5at.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-list-DTtCYS4d.mjs +637 -0
- package/fesm2022/tinya-code-gas-admin-ui-list-DTtCYS4d.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-metric-card-DnGMQL8l.mjs +127 -0
- package/fesm2022/tinya-code-gas-admin-ui-metric-card-DnGMQL8l.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-multiselect-PB28e-jl.mjs +251 -0
- package/fesm2022/tinya-code-gas-admin-ui-multiselect-PB28e-jl.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-notification.service-LjSULER6.mjs +66 -0
- package/fesm2022/tinya-code-gas-admin-ui-notification.service-LjSULER6.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-number-JNr7glc8.mjs +114 -0
- package/fesm2022/tinya-code-gas-admin-ui-number-JNr7glc8.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-phone-jR417hPf.mjs +116 -0
- package/fesm2022/tinya-code-gas-admin-ui-phone-jR417hPf.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-quick-actions-DCQ6emmF.mjs +235 -0
- package/fesm2022/tinya-code-gas-admin-ui-quick-actions-DCQ6emmF.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-radio-mode-DxvN07DY.mjs +8 -0
- package/fesm2022/tinya-code-gas-admin-ui-radio-mode-DxvN07DY.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-readonly-text-BL7-4qie.mjs +124 -0
- package/fesm2022/tinya-code-gas-admin-ui-readonly-text-BL7-4qie.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-record-list-BiZfnd_7.mjs +249 -0
- package/fesm2022/tinya-code-gas-admin-ui-record-list-BiZfnd_7.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-relation-drawer.service-B0kT8EiW.mjs +39 -0
- package/fesm2022/tinya-code-gas-admin-ui-relation-drawer.service-B0kT8EiW.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-relation-ykpJ3PYl.mjs +309 -0
- package/fesm2022/tinya-code-gas-admin-ui-relation-ykpJ3PYl.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-render-registry-B88Pme-y.mjs +576 -0
- package/fesm2022/tinya-code-gas-admin-ui-render-registry-B88Pme-y.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-rich-select-CIHaOrbU.mjs +161 -0
- package/fesm2022/tinya-code-gas-admin-ui-rich-select-CIHaOrbU.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-rolldown-runtime-DpJrqANO.mjs +11 -0
- package/fesm2022/tinya-code-gas-admin-ui-schema-catalog-D0Pk0wAN.mjs +685 -0
- package/fesm2022/tinya-code-gas-admin-ui-schema-catalog-D0Pk0wAN.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-seed-DkVZbxPP.mjs +80 -0
- package/fesm2022/tinya-code-gas-admin-ui-seed-DkVZbxPP.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-select-CDwX9yNO.mjs +296 -0
- package/fesm2022/tinya-code-gas-admin-ui-select-CDwX9yNO.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-skeleton-DnWK0tcZ.mjs +119 -0
- package/fesm2022/tinya-code-gas-admin-ui-skeleton-DnWK0tcZ.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-slug-DU58cbiY.mjs +158 -0
- package/fesm2022/tinya-code-gas-admin-ui-slug-DU58cbiY.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-source-options-B9R4mw8-.mjs +26 -0
- package/fesm2022/tinya-code-gas-admin-ui-source-options-B9R4mw8-.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-status-progress-DmeG8htE.mjs +205 -0
- package/fesm2022/tinya-code-gas-admin-ui-status-progress-DmeG8htE.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-string-list-gleasqzD.mjs +432 -0
- package/fesm2022/tinya-code-gas-admin-ui-string-list-gleasqzD.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-template-interpolator-ewv7CkNX.mjs +36 -0
- package/fesm2022/tinya-code-gas-admin-ui-template-interpolator-ewv7CkNX.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-text-CUPmL7W_.mjs +107 -0
- package/fesm2022/tinya-code-gas-admin-ui-text-CUPmL7W_.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-textarea-CGLSIW13.mjs +223 -0
- package/fesm2022/tinya-code-gas-admin-ui-textarea-CGLSIW13.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-time-BcHzsTWf.mjs +107 -0
- package/fesm2022/tinya-code-gas-admin-ui-time-BcHzsTWf.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-upload.service-CZPEPCeN.mjs +60 -0
- package/fesm2022/tinya-code-gas-admin-ui-upload.service-CZPEPCeN.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui-url-GO4LZi__.mjs +141 -0
- package/fesm2022/tinya-code-gas-admin-ui-url-GO4LZi__.mjs.map +1 -0
- package/fesm2022/tinya-code-gas-admin-ui.mjs +4738 -0
- package/fesm2022/tinya-code-gas-admin-ui.mjs.map +1 -0
- package/package.json +15 -3
- package/types/tinya-code-gas-admin-ui.d.ts +3634 -0
- package/ng-package.json +0 -7
- package/src/lib/actions/action-registry.spec.ts +0 -52
- package/src/lib/actions/action-registry.ts +0 -126
- package/src/lib/actions/action-service.spec.ts +0 -215
- package/src/lib/actions/action-service.ts +0 -87
- package/src/lib/actions/descriptors.spec.ts +0 -155
- package/src/lib/actions/descriptors.ts +0 -154
- package/src/lib/columns/column-cell.ts +0 -33
- package/src/lib/columns/column-defaults.spec.ts +0 -99
- package/src/lib/columns/column-defaults.ts +0 -84
- package/src/lib/columns/column-format.spec.ts +0 -274
- package/src/lib/columns/descriptors.ts +0 -113
- package/src/lib/columns/format-badge.ts +0 -51
- package/src/lib/columns/format-boolean.ts +0 -58
- package/src/lib/columns/format-currency.ts +0 -30
- package/src/lib/columns/format-date.ts +0 -35
- package/src/lib/columns/format-number.ts +0 -32
- package/src/lib/columns/format-text.ts +0 -23
- package/src/lib/columns/format-thumbnail.ts +0 -63
- package/src/lib/core/adapters/firebase-auth.adapter.ts +0 -6
- package/src/lib/core/guards/auth.guard.spec.ts +0 -88
- package/src/lib/core/guards/auth.guard.ts +0 -48
- package/src/lib/core/guards/unsaved-changes.guard.ts +0 -16
- package/src/lib/core/interceptors/api-error.interceptor.spec.ts +0 -182
- package/src/lib/core/interceptors/api-error.interceptor.ts +0 -87
- package/src/lib/core/models/api.model.ts +0 -104
- package/src/lib/core/models/schema-descriptions.ts +0 -118
- package/src/lib/core/models/schema.model.ts +0 -1097
- package/src/lib/core/registry/composition-validator.spec.ts +0 -358
- package/src/lib/core/registry/composition-validator.ts +0 -270
- package/src/lib/core/registry/field-validators.spec.ts +0 -199
- package/src/lib/core/registry/field-validators.ts +0 -440
- package/src/lib/core/registry/render-host.spec.ts +0 -208
- package/src/lib/core/registry/render-host.ts +0 -646
- package/src/lib/core/registry/render-registry.spec.ts +0 -96
- package/src/lib/core/registry/render-registry.ts +0 -312
- package/src/lib/core/registry/schema-catalog.ts +0 -156
- package/src/lib/core/services/api.service.spec.ts +0 -1142
- package/src/lib/core/services/api.service.ts +0 -371
- package/src/lib/core/services/auth.service.spec.ts +0 -653
- package/src/lib/core/services/auth.service.ts +0 -503
- package/src/lib/core/services/config.service.spec.ts +0 -121
- package/src/lib/core/services/config.service.ts +0 -119
- package/src/lib/core/services/data-source.service.spec.ts +0 -179
- package/src/lib/core/services/data-source.service.ts +0 -142
- package/src/lib/core/services/error-mapper.service.spec.ts +0 -50
- package/src/lib/core/services/error-mapper.service.ts +0 -49
- package/src/lib/core/services/notification.service.ts +0 -73
- package/src/lib/core/services/relation-drawer.service.ts +0 -41
- package/src/lib/core/services/theme.service.spec.ts +0 -106
- package/src/lib/core/services/theme.service.ts +0 -86
- package/src/lib/core/services/transport.spec.ts +0 -198
- package/src/lib/core/services/transport.ts +0 -164
- package/src/lib/core/services/upload.service.ts +0 -81
- package/src/lib/core/testing/categories.schema.ts +0 -125
- package/src/lib/core/testing/orders.schema.ts +0 -372
- package/src/lib/core/testing/products.schema.ts +0 -258
- package/src/lib/core/testing/site.schema.ts +0 -195
- package/src/lib/core/testing/test-catalog.ts +0 -21
- package/src/lib/core/tokens.ts +0 -112
- package/src/lib/core/utils/clipboard.spec.ts +0 -55
- package/src/lib/core/utils/clipboard.ts +0 -90
- package/src/lib/core/utils/context-resolver.spec.ts +0 -95
- package/src/lib/core/utils/context-resolver.ts +0 -101
- package/src/lib/core/utils/response-unwrapper.spec.ts +0 -70
- package/src/lib/core/utils/response-unwrapper.ts +0 -103
- package/src/lib/core/utils/source-options.spec.ts +0 -96
- package/src/lib/core/utils/source-options.ts +0 -54
- package/src/lib/core/utils/template-interpolator.spec.ts +0 -59
- package/src/lib/core/utils/template-interpolator.ts +0 -56
- package/src/lib/core/view-navigation/view-navigation.service.spec.ts +0 -207
- package/src/lib/core/view-navigation/view-navigation.service.ts +0 -132
- package/src/lib/fields/boolean/boolean.descriptor.ts +0 -11
- package/src/lib/fields/boolean/boolean.ts +0 -40
- package/src/lib/fields/color/color.descriptor.ts +0 -12
- package/src/lib/fields/color/color.ts +0 -34
- package/src/lib/fields/currency/currency.descriptor.ts +0 -12
- package/src/lib/fields/currency/currency.ts +0 -67
- package/src/lib/fields/date/date.descriptor.ts +0 -12
- package/src/lib/fields/date/date.ts +0 -36
- package/src/lib/fields/descriptors.ts +0 -122
- package/src/lib/fields/display/display-badge.ts +0 -65
- package/src/lib/fields/display/display-date.ts +0 -39
- package/src/lib/fields/display/display-defaults.ts +0 -84
- package/src/lib/fields/display/display-file.ts +0 -41
- package/src/lib/fields/display/display-image.ts +0 -54
- package/src/lib/fields/display/display-list.ts +0 -107
- package/src/lib/fields/display/display-number.ts +0 -41
- package/src/lib/fields/display/display-text.ts +0 -42
- package/src/lib/fields/display/display.spec.ts +0 -242
- package/src/lib/fields/dropdown/dropdown.descriptor.ts +0 -12
- package/src/lib/fields/dropdown/dropdown.ts +0 -45
- package/src/lib/fields/email/email.descriptor.ts +0 -12
- package/src/lib/fields/email/email.ts +0 -28
- package/src/lib/fields/field-aria.ts +0 -60
- package/src/lib/fields/field-host/field-host.spec.ts +0 -118
- package/src/lib/fields/field-host/field-host.ts +0 -47
- package/src/lib/fields/field-node.ts +0 -88
- package/src/lib/fields/file/file.descriptor.ts +0 -14
- package/src/lib/fields/file/file.spec.ts +0 -134
- package/src/lib/fields/file/file.ts +0 -281
- package/src/lib/fields/group/group.descriptor.ts +0 -21
- package/src/lib/fields/group/group.ts +0 -110
- package/src/lib/fields/image/image.descriptor.ts +0 -12
- package/src/lib/fields/image/image.spec.ts +0 -117
- package/src/lib/fields/image/image.ts +0 -281
- package/src/lib/fields/key-value/key-value.descriptor.ts +0 -11
- package/src/lib/fields/key-value/key-value.ts +0 -283
- package/src/lib/fields/list/list.descriptor.ts +0 -21
- package/src/lib/fields/list/list.ts +0 -376
- package/src/lib/fields/multiselect/multiselect.descriptor.ts +0 -11
- package/src/lib/fields/multiselect/multiselect.spec.ts +0 -142
- package/src/lib/fields/multiselect/multiselect.ts +0 -152
- package/src/lib/fields/number/number.descriptor.ts +0 -12
- package/src/lib/fields/number/number.ts +0 -40
- package/src/lib/fields/phone/phone.descriptor.ts +0 -12
- package/src/lib/fields/phone/phone.ts +0 -46
- package/src/lib/fields/readonly-text/readonly-text.descriptor.ts +0 -12
- package/src/lib/fields/readonly-text/readonly-text.ts +0 -58
- package/src/lib/fields/relation/relation.descriptor.ts +0 -12
- package/src/lib/fields/relation/relation.spec.ts +0 -193
- package/src/lib/fields/relation/relation.ts +0 -224
- package/src/lib/fields/rich-select/rich-select.descriptor.ts +0 -12
- package/src/lib/fields/rich-select/rich-select.ts +0 -175
- package/src/lib/fields/select/radio-mode.ts +0 -25
- package/src/lib/fields/select/select.descriptor.ts +0 -12
- package/src/lib/fields/select/select.spec.ts +0 -162
- package/src/lib/fields/select/select.ts +0 -210
- package/src/lib/fields/slug/slug.descriptor.ts +0 -19
- package/src/lib/fields/slug/slug.ts +0 -67
- package/src/lib/fields/string-list/string-list.descriptor.ts +0 -11
- package/src/lib/fields/string-list/string-list.ts +0 -222
- package/src/lib/fields/text/text.descriptor.ts +0 -12
- package/src/lib/fields/text/text.ts +0 -35
- package/src/lib/fields/textarea/textarea.descriptor.ts +0 -12
- package/src/lib/fields/textarea/textarea.spec.ts +0 -117
- package/src/lib/fields/textarea/textarea.ts +0 -126
- package/src/lib/fields/time/time.descriptor.ts +0 -12
- package/src/lib/fields/time/time.ts +0 -28
- package/src/lib/fields/unknown-render/unknown-render.ts +0 -49
- package/src/lib/fields/url/url.descriptor.ts +0 -12
- package/src/lib/fields/url/url.ts +0 -53
- package/src/lib/gas-admin-ui.spec.ts +0 -21
- package/src/lib/gas-admin-ui.ts +0 -9
- package/src/lib/layouts/descriptors.ts +0 -9
- package/src/lib/pages/dashboard/dashboard.ts +0 -167
- package/src/lib/pages/detail-view/detail-view.spec.ts +0 -333
- package/src/lib/pages/detail-view/detail-view.ts +0 -570
- package/src/lib/pages/drawer-form/drawer-form.ts +0 -228
- package/src/lib/pages/form-view/form-model.ts +0 -88
- package/src/lib/pages/form-view/form-schema.ts +0 -255
- package/src/lib/pages/form-view/form-view.ts +0 -1622
- package/src/lib/pages/list-view/list-view.formats.spec.ts +0 -214
- package/src/lib/pages/list-view/list-view.ts +0 -882
- package/src/lib/pages/login/login.spec.ts +0 -109
- package/src/lib/pages/login/login.ts +0 -227
- package/src/lib/pages/resource-page/resource-page.ts +0 -234
- package/src/lib/shared/components/badge/badge.ts +0 -35
- package/src/lib/shared/components/button/button.ts +0 -65
- package/src/lib/shared/components/confirm-dialog/confirm-dialog.ts +0 -48
- package/src/lib/shared/components/copy-button/copy-button.ts +0 -56
- package/src/lib/shared/components/copy-share/copy-share.spec.ts +0 -122
- package/src/lib/shared/components/copy-share/copy-share.ts +0 -107
- package/src/lib/shared/components/drawer/drawer.spec.ts +0 -127
- package/src/lib/shared/components/drawer/drawer.ts +0 -172
- package/src/lib/shared/components/empty-state/empty-state.ts +0 -30
- package/src/lib/shared/components/modal/modal.spec.ts +0 -149
- package/src/lib/shared/components/modal/modal.ts +0 -145
- package/src/lib/shared/components/post-create-modal/post-create-modal.spec.ts +0 -165
- package/src/lib/shared/components/post-create-modal/post-create-modal.ts +0 -159
- package/src/lib/shared/components/skeleton/skeleton.ts +0 -31
- package/src/lib/shared/components/toast/toast.ts +0 -58
- package/src/lib/shared/utils/col-span.ts +0 -25
- package/src/lib/shared/utils/condition-evaluator.ts +0 -53
- package/src/lib/shared/utils/depends-on.ts +0 -48
- package/src/lib/shared/utils/dialog-focus.ts +0 -28
- package/src/lib/shared/utils/field-path.ts +0 -49
- package/src/lib/shared/utils/gap-sorting.ts +0 -144
- package/src/lib/shared/utils/seed.spec.ts +0 -64
- package/src/lib/shared/utils/seed.ts +0 -149
- package/src/lib/shared/utils/slugify.ts +0 -13
- package/src/lib/shared/utils/validators.ts +0 -41
- package/src/lib/shell/layout/layout.ts +0 -63
- package/src/lib/shell/shell.routes.spec.ts +0 -59
- package/src/lib/shell/shell.routes.ts +0 -122
- package/src/lib/shell/sidebar/sidebar.ts +0 -139
- package/src/lib/shell/theme-toggle/theme-toggle.ts +0 -74
- package/src/lib/views/calendar-view/calendar-model.ts +0 -426
- package/src/lib/views/calendar-view/calendar-view.spec.ts +0 -557
- package/src/lib/views/calendar-view/calendar-view.ts +0 -568
- package/src/lib/views/composer/composer-host.spec.ts +0 -301
- package/src/lib/views/composer/composer-host.ts +0 -248
- package/src/lib/views/composer/composer-imports.spec.ts +0 -54
- package/src/lib/views/composer/view-context.spec.ts +0 -117
- package/src/lib/views/composer/view-context.ts +0 -109
- package/src/lib/views/composer/view-slot.spec.ts +0 -130
- package/src/lib/views/composer/view-slot.ts +0 -178
- package/src/lib/views/descriptors.ts +0 -46
- package/src/lib/views/kanban-view/kanban-model.ts +0 -173
- package/src/lib/views/kanban-view/kanban-view.spec.ts +0 -540
- package/src/lib/views/kanban-view/kanban-view.ts +0 -327
- package/src/lib/widgets/bar-chart/bar-chart.descriptor.ts +0 -17
- package/src/lib/widgets/bar-chart/bar-chart.spec.ts +0 -66
- package/src/lib/widgets/bar-chart/bar-chart.ts +0 -76
- package/src/lib/widgets/chart-line/chart-line.descriptor.ts +0 -17
- package/src/lib/widgets/chart-line/chart-line.spec.ts +0 -113
- package/src/lib/widgets/chart-line/chart-line.ts +0 -219
- package/src/lib/widgets/descriptors.ts +0 -29
- package/src/lib/widgets/metric-card/metric-card.descriptor.ts +0 -41
- package/src/lib/widgets/metric-card/metric-card.spec.ts +0 -52
- package/src/lib/widgets/metric-card/metric-card.ts +0 -48
- package/src/lib/widgets/quick-actions/quick-actions.descriptor.ts +0 -13
- package/src/lib/widgets/quick-actions/quick-actions.spec.ts +0 -61
- package/src/lib/widgets/quick-actions/quick-actions.ts +0 -100
- package/src/lib/widgets/record-list/record-list.descriptor.ts +0 -16
- package/src/lib/widgets/record-list/record-list.spec.ts +0 -79
- package/src/lib/widgets/record-list/record-list.ts +0 -115
- package/src/lib/widgets/series.spec.ts +0 -42
- package/src/lib/widgets/series.ts +0 -56
- package/src/lib/widgets/status-progress/status-progress.descriptor.ts +0 -19
- package/src/lib/widgets/status-progress/status-progress.spec.ts +0 -63
- package/src/lib/widgets/status-progress/status-progress.ts +0 -104
- package/src/lib/widgets/widget-host/widget-host.spec.ts +0 -179
- package/src/lib/widgets/widget-host/widget-host.ts +0 -99
- package/src/public-api.ts +0 -104
- package/tinya-code-gas-admin-ui-0.2.0-alpha.15.tgz +0 -0
- package/tsconfig.lib.json +0 -13
- package/tsconfig.lib.prod.json +0 -11
- package/tsconfig.spec.json +0 -10
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { TestBed } from '@angular/core/testing';
|
|
2
|
-
import { toSignal } from '@angular/core/rxjs-interop';
|
|
3
|
-
import type { ParamMap } from '@angular/router';
|
|
4
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
5
|
-
|
|
6
|
-
import type {
|
|
7
|
-
ResourceSchema,
|
|
8
|
-
SelectionBinding,
|
|
9
|
-
UiViewDescriptor,
|
|
10
|
-
} from '../../core/models/schema.model';
|
|
11
|
-
import { createViewContext, instanceIdFor, syntheticRoute, virtualSchemaFor } from './view-context';
|
|
12
|
-
|
|
13
|
-
const schemaBase: ResourceSchema = {
|
|
14
|
-
id: 'demo',
|
|
15
|
-
label: 'Demo',
|
|
16
|
-
labelPlural: 'Demos',
|
|
17
|
-
kind: 'collection',
|
|
18
|
-
endpoint: {},
|
|
19
|
-
keyField: 'id',
|
|
20
|
-
titleField: 'name',
|
|
21
|
-
listColumns: [],
|
|
22
|
-
fields: [],
|
|
23
|
-
uiViews: {
|
|
24
|
-
rows: { type: 'list' },
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const nodoHijo: UiViewDescriptor = {
|
|
29
|
-
type: 'kanban',
|
|
30
|
-
path: '',
|
|
31
|
-
config: { groupField: 'x', columns: [{ value: 'a', label: 'A' }] },
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
describe('instanceIdFor', () => {
|
|
35
|
-
it('concatena padre/hijo con separador estable', () => {
|
|
36
|
-
expect(instanceIdFor('panel', 'cal')).toBe('panel/cal');
|
|
37
|
-
expect(instanceIdFor('a/b', 'c')).toBe('a/b/c');
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
describe('virtualSchemaFor', () => {
|
|
42
|
-
it('añade uiViews[instanceId] sin mutar el schema original', () => {
|
|
43
|
-
const clon = virtualSchemaFor(schemaBase, 'panel/cal', nodoHijo);
|
|
44
|
-
expect(clon.uiViews?.['panel/cal']).toBe(nodoHijo);
|
|
45
|
-
expect(schemaBase.uiViews?.['panel/cal']).toBeUndefined();
|
|
46
|
-
expect(Object.keys(schemaBase.uiViews ?? {})).toEqual(['rows']);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('conserva las uiViews existentes (lookup estilo hoja sigue funcionando)', () => {
|
|
50
|
-
const clon = virtualSchemaFor(schemaBase, 'panel/cal', nodoHijo);
|
|
51
|
-
expect(clon.uiViews?.['rows']).toBe(schemaBase.uiViews?.['rows']);
|
|
52
|
-
expect(clon.id).toBe('demo');
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
describe('createViewContext / syntheticRoute', () => {
|
|
57
|
-
it('sin emit la clave queda ausente (comportamiento local inerte)', () => {
|
|
58
|
-
const ctx = createViewContext({ resourceId: 'demo', uiView: 'rows', viewType: 'list' });
|
|
59
|
-
expect('emit' in ctx).toBe(false);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('con emit la clave existe y es una función', () => {
|
|
63
|
-
const ctx = createViewContext(
|
|
64
|
-
{ resourceId: 'demo', uiView: 'rows', viewType: 'list' },
|
|
65
|
-
vi.fn(),
|
|
66
|
-
);
|
|
67
|
-
expect(typeof ctx.emit).toBe('function');
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
// R9.9.4: la hoja necesita ver el binding declarado (cualquier mode),
|
|
71
|
-
// no sólo el `emit` — sin `select` en el payload la decision table no
|
|
72
|
-
// puede distinguir «sin declaración» de `none`/`inline`.
|
|
73
|
-
it('con select declarado la clave viaja en el payload', () => {
|
|
74
|
-
const binding: SelectionBinding = { on: 'open', mode: 'inline' };
|
|
75
|
-
const ctx = createViewContext({
|
|
76
|
-
resourceId: 'demo',
|
|
77
|
-
uiView: 'rows',
|
|
78
|
-
viewType: 'list',
|
|
79
|
-
select: binding,
|
|
80
|
-
});
|
|
81
|
-
expect(ctx.select).toEqual(binding);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it('sin select declarado la clave queda ausente (comportamiento local inerte)', () => {
|
|
85
|
-
const ctx = createViewContext({ resourceId: 'demo', uiView: 'rows', viewType: 'list' });
|
|
86
|
-
expect('select' in ctx).toBe(false);
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
describe('syntheticRoute', () => {
|
|
91
|
-
it('emite síncrono: toSignal(..., requireSync) de la hoja lee el payload sin input bindings', () => {
|
|
92
|
-
const ctx = createViewContext(
|
|
93
|
-
{ resourceId: 'demo', uiView: 'panel/cal', viewType: 'kanban' },
|
|
94
|
-
vi.fn(),
|
|
95
|
-
);
|
|
96
|
-
const r = syntheticRoute(ctx);
|
|
97
|
-
const data = TestBed.runInInjectionContext(() => toSignal(r.data, { requireSync: true }));
|
|
98
|
-
expect(data()).toEqual(ctx);
|
|
99
|
-
expect(typeof data()['emit']).toBe('function');
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
// ── R9.9.3 · ruta sintética completa (hojas tipo ResourcePage) ──
|
|
104
|
-
|
|
105
|
-
describe('syntheticRoute', () => {
|
|
106
|
-
it('incluye paramMap síncrono además de data (ResourcePage lee ambos)', () => {
|
|
107
|
-
const ruta = syntheticRoute({ resourceId: 'orders', uiView: 'x', viewType: 'list' });
|
|
108
|
-
let params: ParamMap | null = null;
|
|
109
|
-
ruta.paramMap.subscribe((p) => (params = p));
|
|
110
|
-
expect(params).not.toBeNull();
|
|
111
|
-
expect(params!.get('key')).toBeNull();
|
|
112
|
-
|
|
113
|
-
let data: unknown = null;
|
|
114
|
-
ruta.data.subscribe((d) => (data = d));
|
|
115
|
-
expect(data).toMatchObject({ resourceId: 'orders', viewType: 'list' });
|
|
116
|
-
});
|
|
117
|
-
});
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { convertToParamMap, type ActivatedRoute } from '@angular/router';
|
|
2
|
-
import { of } from 'rxjs';
|
|
3
|
-
|
|
4
|
-
import type {
|
|
5
|
-
ResourceSchema,
|
|
6
|
-
SelectionBinding,
|
|
7
|
-
UiViewDescriptor,
|
|
8
|
-
} from '../../core/models/schema.model';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* R9.9 · D1 — Canal ViewContext.
|
|
12
|
-
*
|
|
13
|
-
* El shell monta hojas con `loadComponent` SIN bindings de input, así que el
|
|
14
|
-
* único canal que una hoja recibe es `route.data`. Este módulo es la fábrica
|
|
15
|
-
* ÚNICA de ese payload para ambos productores:
|
|
16
|
-
*
|
|
17
|
-
* - Lado embebido (`ViewSlot`, slice 3): `syntheticRoute(payload)` — una
|
|
18
|
-
* `ActivatedRoute` sintética cuyo `data` emite síncrono, de modo que
|
|
19
|
-
* `toSignal(route.data, {requireSync:true})` sigue funcionando igual.
|
|
20
|
-
* - Lado ruta (`shell.routes`): `resolve:{viewContext}` devuelve el mismo
|
|
21
|
-
* payload con el `emit` ligado en contexto de inyección.
|
|
22
|
-
*
|
|
23
|
-
* Cero reescritura en las hojas: leen `schema`/`resourceId`/`uiView` como
|
|
24
|
-
* siempre. Un `emit` ausente significa «sin comportamiento declarado ⇒ el
|
|
25
|
-
* comportamiento local sigue» — nunca es un error.
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
/** Evento de selección que una hoja emite cuando hay `select` declarado. */
|
|
29
|
-
export interface SelectionEvent {
|
|
30
|
-
/** Recurso del registro seleccionado. */
|
|
31
|
-
resource: string;
|
|
32
|
-
/** Clave estable del registro — la ÚNICA identidad que viaja al router. */
|
|
33
|
-
key: string;
|
|
34
|
-
/** Disparador que activó la transición (`on` del binding). */
|
|
35
|
-
action: string;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/** Callback de selección entregado a la hoja a través del canal. */
|
|
39
|
-
export type SelectionEmitter = (event: SelectionEvent) => void;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Payload del canal: las mismas claves planas que una hoja montada por ruta
|
|
43
|
-
* lee en `route.data`. `schema` explícito sólo existe en el lado embebido
|
|
44
|
-
* (schema virtual); montado por ruta la hoja lo resuelve vía `resourceId`.
|
|
45
|
-
*/
|
|
46
|
-
export interface ViewContextData {
|
|
47
|
-
schema?: ResourceSchema;
|
|
48
|
-
resourceId: string;
|
|
49
|
-
uiView: string;
|
|
50
|
-
viewType: string;
|
|
51
|
-
/**
|
|
52
|
-
* Profundidad de ESTA instancia (raíz ⇒ campo ausente ⇒ 0). El productor
|
|
53
|
-
* embebido (`ViewSlot`) la fija para que un contenedor anidado pase
|
|
54
|
-
* `depth + 1` a sus propios slots y el tope `MAX_DEPTH` se cumpla en
|
|
55
|
-
* runtime aunque el validador no llegue a correr (defensa en profundidad).
|
|
56
|
-
*/
|
|
57
|
-
depth?: number;
|
|
58
|
-
/**
|
|
59
|
-
* Binding `select` declarado por la vista (cualquier mode). El `emit`
|
|
60
|
-
* sólo existe para `mode:'route'`; la hoja necesita VER el binding para
|
|
61
|
-
* aplicar la decision table (R9.9.4): ausente ⇒ comportamiento local,
|
|
62
|
-
* `inline` ⇒ selección local, `none` ⇒ no-op explícito.
|
|
63
|
-
*/
|
|
64
|
-
select?: SelectionBinding;
|
|
65
|
-
emit?: SelectionEmitter;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/** Identidad estable de una instancia embebida: `parentId + '/' + childId`. */
|
|
69
|
-
export function instanceIdFor(parentId: string, childId: string): string {
|
|
70
|
-
return `${parentId}/${childId}`;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Schema virtual por instancia: clona el schema y expone la config del hijo
|
|
75
|
-
* bajo `uiViews[instanceId]`, de modo que la lookup existente
|
|
76
|
-
* `schema.uiViews[route.uiView]` de las hojas resuelve la config del nodo
|
|
77
|
-
* SIN tocar ninguna hoja. No muta el schema original.
|
|
78
|
-
*/
|
|
79
|
-
export function virtualSchemaFor(
|
|
80
|
-
schema: ResourceSchema,
|
|
81
|
-
instanceId: string,
|
|
82
|
-
view: UiViewDescriptor,
|
|
83
|
-
): ResourceSchema {
|
|
84
|
-
return { ...schema, uiViews: { ...schema.uiViews, [instanceId]: view } };
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* `ActivatedRoute` sintética para hijos embebidos. `of()` emite síncrono ⇒
|
|
89
|
-
* `toSignal(..., {requireSync:true})` no revienta. El cast es único y
|
|
90
|
-
* documentado (D1): sólo se consume `data`, igual que una ruta real.
|
|
91
|
-
*/
|
|
92
|
-
export function syntheticRoute(data: ViewContextData): ActivatedRoute {
|
|
93
|
-
// `paramMap` además de `data`: hojas tipo `ResourcePage` (list/detail/
|
|
94
|
-
// dashboard) hacen `toSignal(route.paramMap, {requireSync:true})` y
|
|
95
|
-
// `paramMap.subscribe(...)`. Vacío = embebido sin clave de registro
|
|
96
|
-
// (nunca un detail-key implícito); la clave real viaja en el payload.
|
|
97
|
-
return {
|
|
98
|
-
data: of(data),
|
|
99
|
-
paramMap: of(convertToParamMap({})),
|
|
100
|
-
} as unknown as ActivatedRoute;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/** Construye el payload; `emit` sólo se agrega si existe (clave ausente si no). */
|
|
104
|
-
export function createViewContext(
|
|
105
|
-
base: Omit<ViewContextData, 'emit'>,
|
|
106
|
-
emit?: SelectionEmitter,
|
|
107
|
-
): ViewContextData {
|
|
108
|
-
return emit === undefined ? { ...base } : { ...base, emit };
|
|
109
|
-
}
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import { Component } from '@angular/core';
|
|
2
|
-
import { TestBed } from '@angular/core/testing';
|
|
3
|
-
import { ActivatedRoute } from '@angular/router';
|
|
4
|
-
import { afterEach, describe, expect, it } from 'vitest';
|
|
5
|
-
|
|
6
|
-
import type { ResourceSchema, ViewChildNode } from '../../core/models/schema.model';
|
|
7
|
-
import { register, unregister } from '../../core/registry/render-registry';
|
|
8
|
-
import { ViewSlot } from './view-slot';
|
|
9
|
-
|
|
10
|
-
/** Hoja de prueba registrada dinámicamente: lee su canal como una hoja real. */
|
|
11
|
-
@Component({
|
|
12
|
-
standalone: true,
|
|
13
|
-
selector: 'app-hoja-prueba',
|
|
14
|
-
template: `<p data-hoja>{{ uiView }}</p>`,
|
|
15
|
-
})
|
|
16
|
-
class HojaPrueba {
|
|
17
|
-
readonly uiView: unknown;
|
|
18
|
-
constructor(route: ActivatedRoute) {
|
|
19
|
-
let valor: Record<string, unknown> = {};
|
|
20
|
-
route.data.subscribe((d) => (valor = d as Record<string, unknown>));
|
|
21
|
-
this.uiView = valor['uiView'];
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const schema: ResourceSchema = {
|
|
26
|
-
id: 'demo',
|
|
27
|
-
label: 'Demo',
|
|
28
|
-
labelPlural: 'Demos',
|
|
29
|
-
kind: 'collection',
|
|
30
|
-
endpoint: {},
|
|
31
|
-
keyField: 'id',
|
|
32
|
-
titleField: 'name',
|
|
33
|
-
listColumns: [],
|
|
34
|
-
fields: [],
|
|
35
|
-
uiViews: { rows: { type: 'list' } },
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
describe('ViewSlot', () => {
|
|
39
|
-
afterEach(() => unregister('view', 'hoja-test'));
|
|
40
|
-
|
|
41
|
-
async function montar(node: ViewChildNode, profundidad = 0) {
|
|
42
|
-
const fixture = TestBed.createComponent(ViewSlot);
|
|
43
|
-
fixture.componentRef.setInput('schema', schema);
|
|
44
|
-
fixture.componentRef.setInput('node', node);
|
|
45
|
-
fixture.componentRef.setInput('parentInstanceId', 'panel');
|
|
46
|
-
fixture.componentRef.setInput('depth', profundidad);
|
|
47
|
-
fixture.detectChanges();
|
|
48
|
-
await fixture.whenStable();
|
|
49
|
-
fixture.detectChanges();
|
|
50
|
-
return fixture;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
it('monta el hijo por descriptor del registro (load lazy) sin importar hojas', async () => {
|
|
54
|
-
register('view', {
|
|
55
|
-
kind: 'view',
|
|
56
|
-
type: 'hoja-test',
|
|
57
|
-
since: '9.9',
|
|
58
|
-
load: async () => HojaPrueba,
|
|
59
|
-
});
|
|
60
|
-
const fixture = await montar({ id: 'a', label: 'A', type: 'hoja-test' });
|
|
61
|
-
expect(fixture.nativeElement.querySelector('[data-hoja]')).toBeTruthy();
|
|
62
|
-
// uiView del payload = instanceId virtual (parentId + '/' + id)
|
|
63
|
-
expect(fixture.nativeElement.textContent).toContain('panel/a');
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('tipo sin descriptor ⇒ estado de error legible, sin fallback del registro', async () => {
|
|
67
|
-
const fixture = await montar({ id: 'x', label: 'X', type: 'no-existe' });
|
|
68
|
-
expect(fixture.nativeElement.textContent).toContain('descriptor');
|
|
69
|
-
expect(fixture.nativeElement.querySelector('[data-hoja]')).toBeFalsy();
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('load() rechaza ⇒ error explícito con el rechazo retenido para diagnóstico', async () => {
|
|
73
|
-
const rechazo = new Error('fallo de red');
|
|
74
|
-
register('view', {
|
|
75
|
-
kind: 'view',
|
|
76
|
-
type: 'hoja-test',
|
|
77
|
-
since: '9.9',
|
|
78
|
-
load: async () => {
|
|
79
|
-
throw rechazo;
|
|
80
|
-
},
|
|
81
|
-
});
|
|
82
|
-
const fixture = await montar({ id: 'a', label: 'A', type: 'hoja-test' });
|
|
83
|
-
expect(fixture.nativeElement.textContent).toContain('fallo de red');
|
|
84
|
-
expect(fixture.componentInstance.error()).toBe(rechazo);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('ref resuelve la uiView del schema y el payload expone su config bajo instanceId', async () => {
|
|
88
|
-
register('view', {
|
|
89
|
-
kind: 'view',
|
|
90
|
-
type: 'hoja-test',
|
|
91
|
-
since: '9.9',
|
|
92
|
-
load: async () => HojaPrueba,
|
|
93
|
-
});
|
|
94
|
-
const schemaConRef: ResourceSchema = {
|
|
95
|
-
...schema,
|
|
96
|
-
uiViews: { ...schema.uiViews, destino: { type: 'hoja-test' } },
|
|
97
|
-
};
|
|
98
|
-
const fixture = TestBed.createComponent(ViewSlot);
|
|
99
|
-
fixture.componentRef.setInput('schema', schemaConRef);
|
|
100
|
-
fixture.componentRef.setInput('node', { id: 'h', label: 'H', ref: 'destino' });
|
|
101
|
-
fixture.componentRef.setInput('parentInstanceId', 'panel');
|
|
102
|
-
fixture.detectChanges();
|
|
103
|
-
await fixture.whenStable();
|
|
104
|
-
fixture.detectChanges();
|
|
105
|
-
expect(fixture.nativeElement.textContent).toContain('panel/h');
|
|
106
|
-
expect(fixture.componentInstance.payload()?.['schema']).toBeDefined();
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it('el payload lleva `select` declarado para que la hoja conozca el binding', async () => {
|
|
110
|
-
register('view', {
|
|
111
|
-
kind: 'view',
|
|
112
|
-
type: 'hoja-test',
|
|
113
|
-
since: '9.9',
|
|
114
|
-
load: async () => HojaPrueba,
|
|
115
|
-
});
|
|
116
|
-
const fixture = await montar({
|
|
117
|
-
id: 'a',
|
|
118
|
-
label: 'A',
|
|
119
|
-
type: 'hoja-test',
|
|
120
|
-
select: { on: 'open', mode: 'none' },
|
|
121
|
-
});
|
|
122
|
-
expect(fixture.componentInstance.payload()?.['select']).toEqual({ on: 'open', mode: 'none' });
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it('profundidad sobre el límite ⇒ error antes de montar (guard del host)', async () => {
|
|
126
|
-
const fixture = await montar({ id: 'a', label: 'A', type: 'list' }, 4);
|
|
127
|
-
expect(fixture.nativeElement.textContent).toContain('profundidad');
|
|
128
|
-
expect(fixture.nativeElement.querySelector('[data-hoja]')).toBeFalsy();
|
|
129
|
-
});
|
|
130
|
-
});
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ChangeDetectionStrategy,
|
|
3
|
-
Component,
|
|
4
|
-
EnvironmentInjector,
|
|
5
|
-
Injector,
|
|
6
|
-
ViewContainerRef,
|
|
7
|
-
effect,
|
|
8
|
-
inject,
|
|
9
|
-
input,
|
|
10
|
-
signal,
|
|
11
|
-
viewChild,
|
|
12
|
-
} from '@angular/core';
|
|
13
|
-
import { ActivatedRoute } from '@angular/router';
|
|
14
|
-
|
|
15
|
-
import type { ResourceSchema, ViewChildNode } from '../../core/models/schema.model';
|
|
16
|
-
import { MAX_DEPTH } from '../../core/registry/composition-validator';
|
|
17
|
-
import { get } from '../../core/registry/render-registry';
|
|
18
|
-
import { ViewNavigationService } from '../../core/view-navigation/view-navigation.service';
|
|
19
|
-
import { EmptyState } from '../../shared/components/empty-state/empty-state';
|
|
20
|
-
import { createViewContext, instanceIdFor, syntheticRoute, virtualSchemaFor } from './view-context';
|
|
21
|
-
import type { ViewContextData } from './view-context';
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* R9.9 · slice 3 — Slot de instancia embebida.
|
|
25
|
-
*
|
|
26
|
-
* Monta UN hijo de composición resolviéndolo SOLO por `(kind:'view', type)`
|
|
27
|
-
* en el registro (`get`, nunca `resolve` ⇒ el fallback silencioso del
|
|
28
|
-
* registro es inalcanzable, D2) y entregándole un canal ViewContext
|
|
29
|
-
* sintético (D1). Cada slot es una isla: carga/error/estado se aíslan por
|
|
30
|
-
* `instanceId`, y el rechazo de `load()` queda retenido en `error()` para
|
|
31
|
-
* diagnóstico sin tumbar a los hermanos.
|
|
32
|
-
*/
|
|
33
|
-
@Component({
|
|
34
|
-
selector: 'app-view-slot',
|
|
35
|
-
standalone: true,
|
|
36
|
-
imports: [EmptyState],
|
|
37
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
38
|
-
template: `
|
|
39
|
-
@if (status() === 'loading') {
|
|
40
|
-
<div role="status" class="p-3 text-sm text-neutral">Cargando…</div>
|
|
41
|
-
} @else if (status() === 'error') {
|
|
42
|
-
<app-empty-state title="No se pudo mostrar esta vista" [message]="mensaje()" />
|
|
43
|
-
} @else {
|
|
44
|
-
<div #host></div>
|
|
45
|
-
}
|
|
46
|
-
`,
|
|
47
|
-
})
|
|
48
|
-
export class ViewSlot {
|
|
49
|
-
/** Schema del recurso padre (el host le pasa el schema real). */
|
|
50
|
-
readonly schema = input.required<ResourceSchema>();
|
|
51
|
-
/** Nodo declarado (inline con `type` o por `ref`). */
|
|
52
|
-
readonly node = input.required<ViewChildNode>();
|
|
53
|
-
/** instanceId del contenedor padre (raíz ⇒ nombre de la uiView de ruta). */
|
|
54
|
-
readonly parentInstanceId = input.required<string>();
|
|
55
|
-
/** Profundidad del propio slot (hijo de raíz ⇒ 1). */
|
|
56
|
-
readonly depth = input(0);
|
|
57
|
-
|
|
58
|
-
/** Estado de ESTE slot — aislado por instancia, jamás compartido con hermanos. */
|
|
59
|
-
readonly status = signal<'loading' | 'ready' | 'error'>('loading');
|
|
60
|
-
/** Rechazo original retenido para diagnóstico (el display usa `mensaje()`). */
|
|
61
|
-
readonly error = signal<unknown>(null);
|
|
62
|
-
/** Payload entregado al hijo (público para tests/diagnóstico). */
|
|
63
|
-
readonly payload = signal<ViewContextData | null>(null);
|
|
64
|
-
|
|
65
|
-
private readonly nav = inject(ViewNavigationService);
|
|
66
|
-
private readonly envInjector = inject(EnvironmentInjector);
|
|
67
|
-
private readonly ancla = viewChild('host', { read: ViewContainerRef });
|
|
68
|
-
|
|
69
|
-
private epoch = 0;
|
|
70
|
-
private pendiente: { tipo: unknown; injector: Injector } | null = null;
|
|
71
|
-
|
|
72
|
-
constructor() {
|
|
73
|
-
// Fase 1: montaje/reactivo — cualquier cambio de inputs re-monta el slot.
|
|
74
|
-
effect(() => this.monar());
|
|
75
|
-
// Fase 2: cuando el ancla #host existe (status ready), crear el hijo.
|
|
76
|
-
effect(() => {
|
|
77
|
-
if (this.status() !== 'ready') return;
|
|
78
|
-
const pend = this.pendiente;
|
|
79
|
-
let ancla: ViewContainerRef | undefined;
|
|
80
|
-
try {
|
|
81
|
-
ancla = this.ancla();
|
|
82
|
-
} catch {
|
|
83
|
-
ancla = undefined; // ancla aún no materializada; el effect re-corre al aparecer
|
|
84
|
-
}
|
|
85
|
-
if (!pend || !ancla) return;
|
|
86
|
-
this.pendiente = null;
|
|
87
|
-
ancla.clear();
|
|
88
|
-
ancla.createComponent(pend.tipo as never, { injector: pend.injector });
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
private async monar(): Promise<void> {
|
|
93
|
-
const esquema = this.schema();
|
|
94
|
-
const nodo = this.node();
|
|
95
|
-
if (!esquema || !nodo) return;
|
|
96
|
-
const turno = ++this.epoch;
|
|
97
|
-
this.pendiente = null;
|
|
98
|
-
|
|
99
|
-
if (this.depth() > MAX_DEPTH) {
|
|
100
|
-
this.error.set(
|
|
101
|
-
new Error(
|
|
102
|
-
`Límite de profundidad de composición excedido (${MAX_DEPTH}) en ${esquema.id}.${nodo.id}`,
|
|
103
|
-
),
|
|
104
|
-
);
|
|
105
|
-
this.status.set('error');
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Referencia por uiView del mismo schema o nodo inline.
|
|
110
|
-
const resuelto = 'ref' in nodo ? esquema.uiViews?.[nodo.ref] : nodo;
|
|
111
|
-
if (resuelto === undefined) {
|
|
112
|
-
const ref = 'ref' in nodo ? nodo.ref : nodo.id;
|
|
113
|
-
this.error.set(new Error(`Referencia '${ref}' inexistente en ${esquema.id}`));
|
|
114
|
-
this.status.set('error');
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const descriptor = get('view', resuelto.type);
|
|
119
|
-
if (!descriptor) {
|
|
120
|
-
// Sin fallback: error legible, nunca pantalla de reserva (D2).
|
|
121
|
-
this.error.set(
|
|
122
|
-
new Error(`No existe descriptor kind:view type '${resuelto.type}' en ${esquema.id}`),
|
|
123
|
-
);
|
|
124
|
-
this.status.set('error');
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const instanceId = instanceIdFor(this.parentInstanceId(), nodo.id);
|
|
129
|
-
const select = 'ref' in nodo ? resuelto.select : nodo.select;
|
|
130
|
-
const virtual = virtualSchemaFor(esquema, instanceId, resuelto);
|
|
131
|
-
// D4: el emisor va a `dispatch` (target resuelto, segmentos, guards);
|
|
132
|
-
// sólo un binding `mode:'route'` lleva `emit`, pero el payload declara
|
|
133
|
-
// `select` SIEMPRE para que la hoja aplique la decision table.
|
|
134
|
-
const emit =
|
|
135
|
-
select?.mode === 'route'
|
|
136
|
-
? (event: Parameters<NonNullable<ViewContextData['emit']>>[0]): void => {
|
|
137
|
-
void this.nav.dispatch(select, event);
|
|
138
|
-
}
|
|
139
|
-
: undefined;
|
|
140
|
-
this.payload.set(
|
|
141
|
-
createViewContext(
|
|
142
|
-
{
|
|
143
|
-
schema: virtual,
|
|
144
|
-
resourceId: esquema.id,
|
|
145
|
-
uiView: instanceId,
|
|
146
|
-
viewType: resuelto.type,
|
|
147
|
-
depth: this.depth(),
|
|
148
|
-
...(select !== undefined ? { select } : {}),
|
|
149
|
-
},
|
|
150
|
-
emit,
|
|
151
|
-
),
|
|
152
|
-
);
|
|
153
|
-
|
|
154
|
-
this.error.set(null);
|
|
155
|
-
this.status.set('loading');
|
|
156
|
-
const injector = Injector.create({
|
|
157
|
-
providers: [{ provide: ActivatedRoute, useValue: syntheticRoute(this.payload()!) }],
|
|
158
|
-
parent: this.envInjector,
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
try {
|
|
162
|
-
const tipo = await descriptor.load();
|
|
163
|
-
if (turno !== this.epoch) return; // inputs cambiaron: descartar
|
|
164
|
-
this.pendiente = { tipo, injector };
|
|
165
|
-
this.status.set('ready');
|
|
166
|
-
} catch (e) {
|
|
167
|
-
if (turno !== this.epoch) return;
|
|
168
|
-
this.error.set(e);
|
|
169
|
-
this.status.set('error');
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/** Mensaje mostrado (el error original queda en `error()`). */
|
|
174
|
-
mensaje(): string {
|
|
175
|
-
const e = this.error();
|
|
176
|
-
return e instanceof Error ? e.message : String(e);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import type { RenderDescriptor } from '../core/registry/render-registry';
|
|
2
|
-
|
|
3
|
-
export const viewDescriptors: readonly RenderDescriptor[] = [
|
|
4
|
-
{
|
|
5
|
-
kind: 'view',
|
|
6
|
-
type: 'list',
|
|
7
|
-
since: '9.1',
|
|
8
|
-
load: async () => (await import('../pages/resource-page/resource-page')).ResourcePage,
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
kind: 'view',
|
|
12
|
-
type: 'detail',
|
|
13
|
-
since: '9.1',
|
|
14
|
-
load: async () => (await import('../pages/resource-page/resource-page')).ResourcePage,
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
kind: 'view',
|
|
18
|
-
type: 'form',
|
|
19
|
-
since: '9.1',
|
|
20
|
-
load: async () => (await import('../pages/form-view/form-view')).FormView,
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
kind: 'view',
|
|
24
|
-
type: 'dashboard',
|
|
25
|
-
since: '9.1',
|
|
26
|
-
load: async () => (await import('../pages/resource-page/resource-page')).ResourcePage,
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
kind: 'view',
|
|
30
|
-
type: 'calendar',
|
|
31
|
-
since: '9.8',
|
|
32
|
-
load: async () => (await import('./calendar-view/calendar-view')).CalendarView,
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
kind: 'view',
|
|
36
|
-
type: 'kanban',
|
|
37
|
-
since: '9.8',
|
|
38
|
-
load: async () => (await import('./kanban-view/kanban-view')).KanbanView,
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
kind: 'view',
|
|
42
|
-
type: 'tabs',
|
|
43
|
-
since: '9.9',
|
|
44
|
-
load: async () => (await import('./composer/composer-host')).ComposerHost,
|
|
45
|
-
},
|
|
46
|
-
];
|