@openmrs/esm-report-builder 0.1.1-pre.87
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/.eslintignore +5 -0
- package/.eslintrc.js +19 -0
- package/.prettierrc +8 -0
- package/.tx/config +12 -0
- package/LICENSE +401 -0
- package/README.md +336 -0
- package/__mocks__/react-i18next.js +12 -0
- package/dist/162.js +1 -0
- package/dist/162.js.map +1 -0
- package/dist/184.js +2 -0
- package/dist/184.js.LICENSE.txt +14 -0
- package/dist/184.js.map +1 -0
- package/dist/242.js +2 -0
- package/dist/242.js.LICENSE.txt +21 -0
- package/dist/242.js.map +1 -0
- package/dist/253.js +1 -0
- package/dist/253.js.map +1 -0
- package/dist/300.js +1 -0
- package/dist/311.js +1 -0
- package/dist/311.js.map +1 -0
- package/dist/469.js +2 -0
- package/dist/469.js.LICENSE.txt +45 -0
- package/dist/469.js.map +1 -0
- package/dist/478.js +2 -0
- package/dist/478.js.LICENSE.txt +9 -0
- package/dist/478.js.map +1 -0
- package/dist/539.js +1 -0
- package/dist/539.js.map +1 -0
- package/dist/540.js +2 -0
- package/dist/540.js.LICENSE.txt +9 -0
- package/dist/540.js.map +1 -0
- package/dist/669.js +1 -0
- package/dist/669.js.map +1 -0
- package/dist/710.js +1 -0
- package/dist/710.js.map +1 -0
- package/dist/729.js +1 -0
- package/dist/729.js.map +1 -0
- package/dist/838.js +2 -0
- package/dist/838.js.LICENSE.txt +9 -0
- package/dist/838.js.map +1 -0
- package/dist/917.js +1 -0
- package/dist/917.js.map +1 -0
- package/dist/961.js +2 -0
- package/dist/961.js.LICENSE.txt +19 -0
- package/dist/961.js.map +1 -0
- package/dist/main.js +1 -0
- package/dist/main.js.map +1 -0
- package/dist/openmrs-esm-report-builder.js +1 -0
- package/dist/openmrs-esm-report-builder.js.buildmanifest.json +530 -0
- package/dist/openmrs-esm-report-builder.js.map +1 -0
- package/dist/routes.json +1 -0
- package/e2e/core/env.ts +5 -0
- package/e2e/core/global-setup.ts +34 -0
- package/e2e/core/test.ts +21 -0
- package/e2e/pages/app-shell.page.ts +34 -0
- package/e2e/pages/etl-sources.page.ts +35 -0
- package/e2e/pages/report-sections.page.ts +20 -0
- package/e2e/pages/section-preview.modal.ts +29 -0
- package/e2e/specs/etl-sources.spec.ts +51 -0
- package/e2e/specs/navigation.spec.ts +13 -0
- package/e2e/specs/section-preview-validation.spec.ts +38 -0
- package/e2e/specs/section-preview.spec.ts +94 -0
- package/e2e/support/github/Dockerfile +22 -0
- package/e2e/support/github/Dockerfile.dockerignore +13 -0
- package/e2e/support/github/docker-compose.yml +31 -0
- package/e2e/support/github/run-e2e-docker-env.sh +131 -0
- package/e2e/support/github/spa-assemble-config.json +9 -0
- package/e2e/tsconfig.json +11 -0
- package/example.env +5 -0
- package/jest.config.js +28 -0
- package/linelist_report_builder_design_spec.md +816 -0
- package/package.json +111 -0
- package/playwright.config.ts +28 -0
- package/routes.json +22 -0
- package/src/__debug__/all-designs.test.tsx +30 -0
- package/src/admin-card-link.extension.module.scss +55 -0
- package/src/admin-card-link.extension.tsx +24 -0
- package/src/components/admin/admin-page.component.tsx +75 -0
- package/src/components/admin/age-categories-page.component.tsx +109 -0
- package/src/components/admin/age-groups-page.component.tsx +146 -0
- package/src/components/admin/etl-browser/columns-tab.component.tsx +80 -0
- package/src/components/admin/etl-browser/etl-browser-page.component.tsx +309 -0
- package/src/components/admin/etl-browser/etl-browser.component.scss +424 -0
- package/src/components/admin/etl-browser/metadata-tab.component.tsx +65 -0
- package/src/components/admin/etl-browser/preview-grid.component.tsx +189 -0
- package/src/components/admin/etl-browser/relationships-tab.component.tsx +21 -0
- package/src/components/admin/etl-browser/sources-tree.component.tsx +118 -0
- package/src/components/admin/etl-browser/table-detail.component.tsx +124 -0
- package/src/components/admin/etl-browser/table-info-strip.component.tsx +51 -0
- package/src/components/admin/etl-browser/table-list.component.tsx +136 -0
- package/src/components/admin/etl-browser/use-table-preview.ts +47 -0
- package/src/components/admin/etl-sources-page.component.tsx +355 -0
- package/src/components/admin/etl-tasks-page.component.scss +370 -0
- package/src/components/admin/etl-tasks-page.component.tsx +768 -0
- package/src/components/admin/report-categories-page.component.tsx +267 -0
- package/src/components/admin/report-library-page.component.tsx +551 -0
- package/src/components/ai-support/ai-assist-button.component.tsx +30 -0
- package/src/components/ai-support/ai-assist-modal.component.tsx +81 -0
- package/src/components/ai-support/ai.service.ts +21 -0
- package/src/components/ai-support/ai.types.ts +12 -0
- package/src/components/app-shell/report-builder-shell.component.tsx +242 -0
- package/src/components/app-shell/report-builder-shell.scss +18 -0
- package/src/components/dashboards/dashboard-config.schema.ts +97 -0
- package/src/components/dashboards/dashboard-form-modal.component.tsx +150 -0
- package/src/components/dashboards/dashboards-admin.scss +62 -0
- package/src/components/dashboards/dashboards-page.component.tsx +153 -0
- package/src/components/dashboards/dashboards-table.component.tsx +130 -0
- package/src/components/dashboards/sections/dashboard-autoinclude.section.tsx +75 -0
- package/src/components/dashboards/sections/dashboard-basics.section.tsx +80 -0
- package/src/components/dashboards/sections/dashboard-json.section.tsx +79 -0
- package/src/components/dashboards/sections/dashboard-sections-editor.section.tsx +130 -0
- package/src/components/dashboards/sections/dashboard-widgets-editor.section.tsx +184 -0
- package/src/components/data-themes/data-theme-form.component.tsx +59 -0
- package/src/components/data-themes/data-theme-modal.component.tsx +349 -0
- package/src/components/data-themes/data-themes-page.component.tsx +139 -0
- package/src/components/data-themes/data-themes-table.component.tsx +98 -0
- package/src/components/data-themes/icon-registry.ts +35 -0
- package/src/components/data-themes/sections/data-theme-basics.section.tsx +63 -0
- package/src/components/data-themes/sections/data-theme-condition-columns.section.tsx +397 -0
- package/src/components/data-themes/sections/data-theme-fields-editor.section.tsx +125 -0
- package/src/components/data-themes/sections/data-theme-metadata.section.tsx +245 -0
- package/src/components/data-themes/sections/data-theme-preview.section.tsx +115 -0
- package/src/components/data-themes/sections/data-theme-source.section.tsx +184 -0
- package/src/components/data-visualizer/components/cqi-components/cqi-data-table.component.tsx +214 -0
- package/src/components/data-visualizer/components/cqi-components/cqi-elements.ts +203 -0
- package/src/components/data-visualizer/components/cqi-components/detail.component.tsx +110 -0
- package/src/components/data-visualizer/components/cqi-components/detail.scss +22 -0
- package/src/components/data-visualizer/components/data-table/data-table.component.tsx +208 -0
- package/src/components/data-visualizer/components/data-table/data-tables.scss +206 -0
- package/src/components/data-visualizer/components/empty-state/empty-state-illustration.component.tsx +53 -0
- package/src/components/data-visualizer/components/header/header.component.tsx +43 -0
- package/src/components/data-visualizer/components/header/header.scss +71 -0
- package/src/components/data-visualizer/components/model/confirm.component.tsx +40 -0
- package/src/components/data-visualizer/components/panel/panel.component.tsx +20 -0
- package/src/components/data-visualizer/components/panel/panel.scss +25 -0
- package/src/components/data-visualizer/components/popover/modifier-panel.tsx +53 -0
- package/src/components/data-visualizer/constants.ts +445 -0
- package/src/components/data-visualizer/data-visualizer-illustration.component.tsx +31 -0
- package/src/components/data-visualizer/data-visualizer.component.tsx +1935 -0
- package/src/components/data-visualizer/data-visualizer.resource.ts +462 -0
- package/src/components/data-visualizer/data-visualizer.scss +449 -0
- package/src/components/data-visualizer/declarations.d.ts +131 -0
- package/src/components/data-visualizer/parameter-inputs/boolean-parameter-input.component.tsx +34 -0
- package/src/components/data-visualizer/parameter-inputs/concept-parameter-input.component.tsx +81 -0
- package/src/components/data-visualizer/parameter-inputs/date-parameter-input.component.tsx +110 -0
- package/src/components/data-visualizer/parameter-inputs/date-range-input.component.scss +47 -0
- package/src/components/data-visualizer/parameter-inputs/date-range-input.component.tsx +228 -0
- package/src/components/data-visualizer/parameter-inputs/identifier-type-parameter-input.component.tsx +69 -0
- package/src/components/data-visualizer/parameter-inputs/list-parameter-input.component.tsx +73 -0
- package/src/components/data-visualizer/parameter-inputs/location-parameter-input.component.tsx +81 -0
- package/src/components/data-visualizer/parameter-inputs/number-parameter-input.component.tsx +40 -0
- package/src/components/data-visualizer/parameter-inputs/person-attribute-parameter-input.component.tsx +71 -0
- package/src/components/data-visualizer/parameter-inputs/text-parameter-input.component.tsx +52 -0
- package/src/components/data-visualizer/report-parameter-modal.component.tsx +383 -0
- package/src/components/data-visualizer/types.ts +206 -0
- package/src/components/etl-monitor/builder/builder-state-machine.ts +381 -0
- package/src/components/etl-monitor/builder/design-registry.tsx +139 -0
- package/src/components/etl-monitor/builder/etl-monitor-builder-context.tsx +702 -0
- package/src/components/etl-monitor/builder/etl-monitor-builder-modal.component.tsx +461 -0
- package/src/components/etl-monitor/builder/etl-monitor-builder-modal.scss +256 -0
- package/src/components/etl-monitor/builder/etl-monitor-builder-page.component.tsx +387 -0
- package/src/components/etl-monitor/builder/etl-monitor-builder-page.scss +976 -0
- package/src/components/etl-monitor/builder/generated-config-panel.component.tsx +168 -0
- package/src/components/etl-monitor/builder/generated-config-panel.scss +198 -0
- package/src/components/etl-monitor/builder/index.ts +5 -0
- package/src/components/etl-monitor/builder/monitor-preview.tsx +124 -0
- package/src/components/etl-monitor/builder/steps/data-source-step.component.tsx +667 -0
- package/src/components/etl-monitor/builder/steps/data-source-step.scss +284 -0
- package/src/components/etl-monitor/builder/steps/design-samples.ts +278 -0
- package/src/components/etl-monitor/builder/steps/design-step.component.tsx +299 -0
- package/src/components/etl-monitor/builder/steps/design-step.scss +479 -0
- package/src/components/etl-monitor/builder/steps/fields-step.component.tsx +859 -0
- package/src/components/etl-monitor/builder/steps/fields-step.scss +459 -0
- package/src/components/etl-monitor/builder/steps/general-step.component.tsx +288 -0
- package/src/components/etl-monitor/builder/steps/general-step.scss +103 -0
- package/src/components/etl-monitor/builder/steps/index.ts +5 -0
- package/src/components/etl-monitor/builder/steps/preview-step.component.tsx +245 -0
- package/src/components/etl-monitor/builder/steps/preview-step.scss +236 -0
- package/src/components/etl-monitor/etl-monitor-card-shell.component.tsx +154 -0
- package/src/components/etl-monitor/etl-monitor-card-shell.scss +103 -0
- package/src/components/etl-monitor/etl-monitor-dashboard.component.tsx +227 -0
- package/src/components/etl-monitor/etl-monitor-dashboard.scss +148 -0
- package/src/components/etl-monitor/etl-monitor-status-card.component.tsx +192 -0
- package/src/components/etl-monitor/etl-monitors-page.component.tsx +621 -0
- package/src/components/etl-monitor/renderers/DetailsRenderer.tsx +2 -0
- package/src/components/etl-monitor/renderers/ErrorLogRenderer.tsx +2 -0
- package/src/components/etl-monitor/renderers/EtlMonitorWidget.tsx +97 -0
- package/src/components/etl-monitor/renderers/MetricsGridRenderer.tsx +2 -0
- package/src/components/etl-monitor/renderers/MonitorRenderer.tsx +175 -0
- package/src/components/etl-monitor/renderers/ProgressRenderer.tsx +2 -0
- package/src/components/etl-monitor/renderers/StatusCardRenderer.tsx +2 -0
- package/src/components/etl-monitor/renderers/SummaryCardRenderer.tsx +2 -0
- package/src/components/etl-monitor/renderers/TableRenderer.tsx +2 -0
- package/src/components/etl-monitor/renderers/component-icons.tsx +33 -0
- package/src/components/etl-monitor/renderers/components/details-renderer.tsx +195 -0
- package/src/components/etl-monitor/renderers/components/error-log-renderer.tsx +104 -0
- package/src/components/etl-monitor/renderers/components/index.ts +6 -0
- package/src/components/etl-monitor/renderers/components/log-renderer.tsx +86 -0
- package/src/components/etl-monitor/renderers/components/metrics-grid-renderer.tsx +133 -0
- package/src/components/etl-monitor/renderers/components/progress-renderer.tsx +188 -0
- package/src/components/etl-monitor/renderers/components/status-card-renderer.tsx +247 -0
- package/src/components/etl-monitor/renderers/components/summary-card-renderer.tsx +160 -0
- package/src/components/etl-monitor/renderers/components/table-renderer.tsx +175 -0
- package/src/components/etl-monitor/renderers/components/time-series-renderer.tsx +310 -0
- package/src/components/etl-monitor/renderers/data-transformer.ts +361 -0
- package/src/components/etl-monitor/renderers/index.ts +11 -0
- package/src/components/etl-monitor/renderers/legacy-monitor-renderer.tsx +69 -0
- package/src/components/etl-monitor/renderers/monitor-renderer.tsx +6 -0
- package/src/components/etl-monitor/renderers/monitor-renderers.scss +1621 -0
- package/src/components/etl-monitor/renderers/monitor-widget-card.component.tsx +54 -0
- package/src/components/etl-monitor/renderers/monitor-widget-card.scss +16 -0
- package/src/components/etl-monitor/renderers/v2-monitor-renderer.tsx +227 -0
- package/src/components/import-export/artifact-groups.ts +153 -0
- package/src/components/import-export/export-report-modal.component.tsx +265 -0
- package/src/components/import-export/import-export-page.component.tsx +610 -0
- package/src/components/import-export/import-export.styles.scss +825 -0
- package/src/components/import-export/import-package-modal.component.tsx +401 -0
- package/src/components/import-export/index.ts +3 -0
- package/src/components/indicators/README.md +24 -0
- package/src/components/indicators/base-indicator-basic-fields.component.tsx +18 -0
- package/src/components/indicators/base-indicator-basics.section.tsx +54 -0
- package/src/components/indicators/base-indicator-countby.section.tsx +25 -0
- package/src/components/indicators/base-indicator-criteria.section.tsx +83 -0
- package/src/components/indicators/base-indicator-details-form.component.tsx +80 -0
- package/src/components/indicators/base-indicator-theme-unit-fields.component.tsx +39 -0
- package/src/components/indicators/create-base-indicator-modal.component.tsx +623 -0
- package/src/components/indicators/create-composite-base-indicator-modal.component.tsx +295 -0
- package/src/components/indicators/create-custom-indicator-modal.component.tsx +548 -0
- package/src/components/indicators/create-final-indicator-modal.component.tsx +285 -0
- package/src/components/indicators/custom-condition-input.component.tsx +310 -0
- package/src/components/indicators/diagnosis-filters-form.component.tsx +101 -0
- package/src/components/indicators/disaggregation-panel.component.tsx +93 -0
- package/src/components/indicators/handler/concept-search-multiselect.component.tsx +153 -0
- package/src/components/indicators/handler/question-answer-concept-search.component.tsx +336 -0
- package/src/components/indicators/indicator-run-preview-modal.component.tsx +391 -0
- package/src/components/indicators/indicator-search-select.component.tsx +297 -0
- package/src/components/indicators/indicator-status-tag.component.tsx +9 -0
- package/src/components/indicators/indicators-page.component.tsx +673 -0
- package/src/components/indicators/indicators-page.scss +121 -0
- package/src/components/indicators/indicators-table.component.tsx +188 -0
- package/src/components/indicators/preview-table.component.tsx +31 -0
- package/src/components/indicators/sections/composite-indicator-basics.section.tsx +36 -0
- package/src/components/indicators/sections/composite-indicator-picker.section.tsx +116 -0
- package/src/components/indicators/sections/composite-indicator-sql-preview.section.tsx +31 -0
- package/src/components/indicators/sections/custom-indicator-basics.section.tsx +65 -0
- package/src/components/indicators/sections/custom-indicator-disaggregation.section.tsx +93 -0
- package/src/components/indicators/sections/custom-indicator-filters.section.tsx +203 -0
- package/src/components/indicators/sections/custom-indicator-population.section.tsx +107 -0
- package/src/components/indicators/sections/custom-indicator-sql-preview.section.tsx +108 -0
- package/src/components/indicators/sections/final-indicator-basics.section.tsx +46 -0
- package/src/components/indicators/sections/final-indicator-disaggregation.section.tsx +47 -0
- package/src/components/indicators/sections/final-indicator-picker.section.tsx +60 -0
- package/src/components/indicators/sections/final-indicator-preview.section.tsx +20 -0
- package/src/components/indicators/sections/final-indicator-results-preview.section.tsx +65 -0
- package/src/components/indicators/sections/indicator-basics.section.tsx +40 -0
- package/src/components/indicators/sections/indicator-conditions.section.tsx +279 -0
- package/src/components/indicators/sections/indicator-sql-preview.section.tsx +63 -0
- package/src/components/indicators/sections/indicator-theme.section.tsx +48 -0
- package/src/components/indicators/sql-preview.component.tsx +19 -0
- package/src/components/indicators/tag-input.component.tsx +177 -0
- package/src/components/indicators/types/base-indicator-form.types.ts +17 -0
- package/src/components/indicators/types/base-indicator-theme.constants.ts +8 -0
- package/src/components/indicators/types/composite-indicator.types.ts +27 -0
- package/src/components/indicators/types/condition-ui.types.ts +11 -0
- package/src/components/indicators/types/custom-indicator.types.ts +161 -0
- package/src/components/indicators/types/data-theme-config.types.ts +88 -0
- package/src/components/indicators/types/indicator-types.ts +57 -0
- package/src/components/indicators/types/sql-builders.ts +43 -0
- package/src/components/indicators/utils/composite-indicator-sql.utils.test.ts +143 -0
- package/src/components/indicators/utils/composite-indicator-sql.utils.ts +426 -0
- package/src/components/indicators/utils/concept-preload.utils.ts +21 -0
- package/src/components/indicators/utils/custom-indicator-interpreter.test.ts +493 -0
- package/src/components/indicators/utils/custom-indicator-interpreter.ts +702 -0
- package/src/components/indicators/utils/final-indicator-sql.utils.ts +190 -0
- package/src/components/indicators/utils/indicator-conditions-hydration.utils.ts +254 -0
- package/src/components/indicators/utils/indicator-sql-resolution.utils.ts +204 -0
- package/src/components/indicators/utils/indicator-sql.utils.ts +721 -0
- package/src/components/indicators/utils/population-sql.compiler.test.ts +999 -0
- package/src/components/indicators/utils/population-sql.compiler.ts +858 -0
- package/src/components/landing/landing-action-item.component.tsx +50 -0
- package/src/components/landing/landing-action-list.component.tsx +12 -0
- package/src/components/landing/landing-activity-list.component.tsx +47 -0
- package/src/components/landing/landing-footer-grid.component.tsx +45 -0
- package/src/components/landing/landing-hero.component.tsx +18 -0
- package/src/components/landing/landing-section-card.component.tsx +33 -0
- package/src/components/landing/report-builder-landing-page.component.tsx +186 -0
- package/src/components/landing/report-builder-landing-page.scss +131 -0
- package/src/components/legacy-reports/legacy-report-detail-page.component.tsx +300 -0
- package/src/components/legacy-reports/legacy-report-editor-page.component.tsx +324 -0
- package/src/components/legacy-reports/legacy-report-upload-modal.component.tsx +307 -0
- package/src/components/legacy-reports/legacy-reports-page.component.tsx +206 -0
- package/src/components/legacy-reports/legacy-reports-table.component.tsx +154 -0
- package/src/components/legacy-reports/tabs/legacy-report-datasets-tab.component.tsx +344 -0
- package/src/components/legacy-reports/tabs/legacy-report-dimensions-tab.component.tsx +590 -0
- package/src/components/legacy-reports/tabs/legacy-report-indicators-tab.component.tsx +490 -0
- package/src/components/legacy-reports/tabs/legacy-report-json-preview-tab.component.tsx +272 -0
- package/src/components/legacy-reports/tabs/legacy-report-overview-tab.component.tsx +218 -0
- package/src/components/legacy-reports/tabs/legacy-report-parameters-tab.component.tsx +279 -0
- package/src/components/linelist/definition/indicator-to-sql.utils.ts +281 -0
- package/src/components/linelist/definition/linelist-definition-editor.component.tsx +1676 -0
- package/src/components/linelist/definition/linelist-definition-editor.scss +461 -0
- package/src/components/linelist/definition/linelist-definition.types.ts +108 -0
- package/src/components/linelist/definition/panels/column-properties-panel.component.tsx +328 -0
- package/src/components/linelist/definition/panels/column-selector-panel.component.tsx +1082 -0
- package/src/components/linelist/definition/panels/column-selector-panel.scss +100 -0
- package/src/components/linelist/definition/panels/custom-sql-column-modal.component.tsx +248 -0
- package/src/components/linelist/definition/panels/encounter-diagnosis-column-modal.component.tsx +300 -0
- package/src/components/linelist/definition/panels/encounter-diagnosis-column-modal.scss +21 -0
- package/src/components/linelist/definition/panels/multi-datasource-selector.component.tsx +332 -0
- package/src/components/linelist/definition/panels/multi-datasource-selector.scss +161 -0
- package/src/components/linelist/definition/panels/observation-column-modal.component.tsx +450 -0
- package/src/components/linelist/definition/panels/observation-column-modal.scss +29 -0
- package/src/components/linelist/definition/panels/parameter-panel.component.tsx +659 -0
- package/src/components/linelist/definition/panels/parameter-panel.scss +64 -0
- package/src/components/linelist/definition/panels/population-source-selector.component.tsx +407 -0
- package/src/components/linelist/definition/panels/population-source-selector.scss +187 -0
- package/src/components/linelist/design/panels/column-category-selector.component.tsx +433 -0
- package/src/components/linelist/design/panels/column-category-selector.scss +329 -0
- package/src/components/linelist/design/panels/column-debug-panel.component.tsx +197 -0
- package/src/components/linelist/design/panels/column-debug-panel.scss +141 -0
- package/src/components/linelist/design/panels/data-catalogue.component.tsx +1062 -0
- package/src/components/linelist/design/panels/data-catalogue.scss +263 -0
- package/src/components/linelist/design/panels/display-settings-panel.component.tsx +405 -0
- package/src/components/linelist/design/panels/display-settings-panel.scss +78 -0
- package/src/components/linelist/design/panels/filtermap-editor.component.tsx +434 -0
- package/src/components/linelist/design/panels/filtermap-editor.scss +176 -0
- package/src/components/linelist/design/panels/json-preview.component.tsx +114 -0
- package/src/components/linelist/design/panels/json-preview.scss +85 -0
- package/src/components/linelist/design/panels/query-config-panel.component.tsx +1137 -0
- package/src/components/linelist/design/panels/query-config-panel.scss +342 -0
- package/src/components/linelist/design/panels/sort-config-panel.component.tsx +330 -0
- package/src/components/linelist/design/panels/sort-config-panel.scss +77 -0
- package/src/components/linelist/design/panels/sql-builder-panel.component.tsx +475 -0
- package/src/components/linelist/design/panels/sql-builder-panel.scss +226 -0
- package/src/components/linelist/design/panels/transformation-panel.component.tsx +687 -0
- package/src/components/linelist/design/panels/transformation-panel.scss +81 -0
- package/src/components/linelist/design/panels/visual-filter-panel.component.tsx +595 -0
- package/src/components/linelist/design/panels/visual-filter-panel.scss +76 -0
- package/src/components/linelist/linelist-dashboard.page.component.tsx +756 -0
- package/src/components/linelist/linelist-dashboard.page.scss +240 -0
- package/src/components/linelist/linelist-editor.page.component.tsx +134 -0
- package/src/components/linelist/linelist-editor.page.scss +28 -0
- package/src/components/linelist/linelist-run-report.page.component.tsx +715 -0
- package/src/components/linelist/linelist-run-report.page.scss +136 -0
- package/src/components/linelist/modals/linelist-report-builder-modal.component.tsx +1454 -0
- package/src/components/linelist/modals/linelist-report-builder-modal.scss +164 -0
- package/src/components/linelist/modals/preview-parameter-modal.component.tsx +361 -0
- package/src/components/report/dashboard/reports-table.component.tsx +186 -0
- package/src/components/report/definition/panels/properties-panel.component.tsx +38 -0
- package/src/components/report/definition/panels/report-structure-panel.component.tsx +61 -0
- package/src/components/report/definition/panels/selection-panel.component.tsx +58 -0
- package/src/components/report/definition/report-definition-editor.component.tsx +99 -0
- package/src/components/report/definition/report-definition.types.ts +66 -0
- package/src/components/report/design/panels/IndicatorPropertiesPanel.scss +33 -0
- package/src/components/report/design/panels/IndicatorPropertiesPanel.tsx +389 -0
- package/src/components/report/design/panels/JsonPreviewPanel.scss +32 -0
- package/src/components/report/design/panels/JsonPreviewPanel.tsx +104 -0
- package/src/components/report/design/panels/mapping-preview-panel.component.tsx +82 -0
- package/src/components/report/design/panels/mapping-preview-panel.scss +55 -0
- package/src/components/report/design/panels/template-structure-panel.component.tsx +296 -0
- package/src/components/report/design/panels/template-structure-panel.scss +81 -0
- package/src/components/report/design/report-design-editor.component.tsx +1170 -0
- package/src/components/report/design/report-design.types.ts +48 -0
- package/src/components/report/design/report-design.utils.ts +86 -0
- package/src/components/report/panels/report-detail.component.tsx +71 -0
- package/src/components/report/panels/report-panel-shell.component.tsx +60 -0
- package/src/components/report/report-dashboard.page.component.tsx +554 -0
- package/src/components/report/report-editor.page.component.tsx +590 -0
- package/src/components/report/report.routes.tsx +32 -0
- package/src/components/report-sections/create-report-section-modal.component.tsx +388 -0
- package/src/components/report-sections/hooks/useAgeCategories.ts +25 -0
- package/src/components/report-sections/hooks/useSectionEditorState.ts +449 -0
- package/src/components/report-sections/panels/Dhis2MappingPanel.tsx +157 -0
- package/src/components/report-sections/panels/DisaggregationPanel.tsx +97 -0
- package/src/components/report-sections/panels/IndicatorPickerPanel.tsx +201 -0
- package/src/components/report-sections/panels/SectionBasicsPanel.tsx +27 -0
- package/src/components/report-sections/report-section-preview-modal.component.tsx +548 -0
- package/src/components/report-sections/report-sections-page.component.tsx +325 -0
- package/src/components/report-sections/section-disaggregation.utils.ts +637 -0
- package/src/components/report-sections/section-types.ts +55 -0
- package/src/components/report-sections/section-utils.ts +50 -0
- package/src/components/report-sections/sections-page.scss +79 -0
- package/src/components/run-reports/run-reports-page.component.tsx +8 -0
- package/src/components/security/access-denied-page.component.tsx +69 -0
- package/src/components/security/access-denied-page.scss +39 -0
- package/src/components/security/privilege-route.component.test.tsx +79 -0
- package/src/components/security/privilege-route.component.tsx +39 -0
- package/src/components/shared/compile-setup-modal.component.tsx +182 -0
- package/src/components/shared/concept-selector.component.tsx +245 -0
- package/src/components/shared/concept-selector.scss +121 -0
- package/src/components/shared/header/builder-header-actions.component.tsx +38 -0
- package/src/components/shared/header/header.component.tsx +85 -0
- package/src/components/shared/header/header.scss +150 -0
- package/src/components/shared/header/illustration.component.tsx +34 -0
- package/src/components/shared/indicator-properties-panel/IndicatorPropertiesPanel.scss +33 -0
- package/src/components/shared/indicator-properties-panel/IndicatorPropertiesPanel.tsx +389 -0
- package/src/components/shared/json-preview-panel/JsonPreviewPanel.scss +32 -0
- package/src/components/shared/json-preview-panel/JsonPreviewPanel.tsx +104 -0
- package/src/components/shared/mapping-preview-panel/mapping-preview-panel.component.tsx +82 -0
- package/src/components/shared/mapping-preview-panel/mapping-preview-panel.scss +55 -0
- package/src/components/shared/preview/query-results-preview.component.tsx +204 -0
- package/src/components/shared/template-structure-panel/template-structure-panel.component.tsx +296 -0
- package/src/components/shared/template-structure-panel/template-structure-panel.scss +81 -0
- package/src/config-schema.ts +43 -0
- package/src/constants/privileges.test.ts +53 -0
- package/src/constants/privileges.ts +118 -0
- package/src/features/dashboards/DashboardRendererPage.tsx +174 -0
- package/src/features/dashboards/DashboardsPage.tsx +164 -0
- package/src/features/dashboards/EtlDashboardPage.tsx +32 -0
- package/src/features/dashboards/components/DashboardEmptyState.tsx +41 -0
- package/src/features/dashboards/components/DashboardGrid.tsx +48 -0
- package/src/features/dashboards/components/DashboardHeader.tsx +58 -0
- package/src/features/dashboards/components/DashboardSection.tsx +46 -0
- package/src/features/dashboards/components/ReportLaunchCard.tsx +51 -0
- package/src/features/dashboards/components/WidgetSlotDispatcher.tsx +61 -0
- package/src/features/dashboards/components/WidgetUnavailableCard.tsx +36 -0
- package/src/features/dashboards/dashboards.scss +196 -0
- package/src/features/dashboards/hooks/useDashboard.ts +61 -0
- package/src/features/dashboards/hooks/useDashboardWidgets.ts +74 -0
- package/src/features/dashboards/hooks/useDashboards.ts +56 -0
- package/src/features/dashboards/hooks/useMonitorDataMap.ts +84 -0
- package/src/features/dashboards/index.ts +11 -0
- package/src/features/dashboards/utils/dashboard-config.util.test.ts +255 -0
- package/src/features/dashboards/utils/dashboard-config.util.ts +382 -0
- package/src/features/report-visualizer/ReportVisualizerPage.tsx +448 -0
- package/src/features/report-visualizer/components/Export/ExportMenu.tsx +141 -0
- package/src/features/report-visualizer/components/Export/index.ts +2 -0
- package/src/features/report-visualizer/components/ReportExplorer/QuickFilters.tsx +152 -0
- package/src/features/report-visualizer/components/ReportExplorer/ReportCategoryFilter.tsx +54 -0
- package/src/features/report-visualizer/components/ReportExplorer/ReportExplorerPanel.tsx +201 -0
- package/src/features/report-visualizer/components/ReportExplorer/ReportExplorerRail.tsx +202 -0
- package/src/features/report-visualizer/components/ReportExplorer/ReportList.tsx +287 -0
- package/src/features/report-visualizer/components/ReportExplorer/ReportSearch.tsx +151 -0
- package/src/features/report-visualizer/components/ReportExplorer/ReportTagFilter.tsx +100 -0
- package/src/features/report-visualizer/components/ReportExplorer/RunReportButton.tsx +42 -0
- package/src/features/report-visualizer/components/ReportExplorer/RuntimeParameterForm.tsx +259 -0
- package/src/features/report-visualizer/components/ReportExplorer/index.ts +8 -0
- package/src/features/report-visualizer/components/ReportWorkspace/ReportLayer.tsx +33 -0
- package/src/features/report-visualizer/components/ReportWorkspace/ReportSummary.tsx +88 -0
- package/src/features/report-visualizer/components/ReportWorkspace/ReportViewTabs.tsx +72 -0
- package/src/features/report-visualizer/components/ReportWorkspace/ReportWorkspaceHeader.tsx +92 -0
- package/src/features/report-visualizer/components/ReportWorkspace/ReportWorkspacePanel.tsx +242 -0
- package/src/features/report-visualizer/components/ReportWorkspace/index.ts +5 -0
- package/src/features/report-visualizer/components/TableView/ColumnVisibilityMenu.tsx +206 -0
- package/src/features/report-visualizer/components/TableView/ReportTable.tsx +253 -0
- package/src/features/report-visualizer/components/TableView/index.ts +2 -0
- package/src/features/report-visualizer/hooks/index.ts +4 -0
- package/src/features/report-visualizer/hooks/useExplorerPreferences.ts +103 -0
- package/src/features/report-visualizer/hooks/useReportCapabilities.ts +112 -0
- package/src/features/report-visualizer/hooks/useReportParameters.ts +152 -0
- package/src/features/report-visualizer/hooks/useReports.ts +135 -0
- package/src/features/report-visualizer/index.ts +6 -0
- package/src/features/report-visualizer/report-visualizer.scss +593 -0
- package/src/features/report-visualizer/types/index.ts +1 -0
- package/src/features/report-visualizer/types/report-visualizer.types.ts +104 -0
- package/src/features/report-visualizer/utils/status-colors.ts +117 -0
- package/src/globals.d.ts +14 -0
- package/src/hooks/address-template.ts +86 -0
- package/src/hooks/concept.ts +112 -0
- package/src/hooks/indicator/index.ts +1 -0
- package/src/hooks/indicator/useIndicatorsByTheme.ts +41 -0
- package/src/hooks/openmrs-reference-data.ts +432 -0
- package/src/hooks/theme/index.ts +4 -0
- package/src/hooks/theme/useDataTheme.ts +61 -0
- package/src/hooks/theme/useDataThemes.ts +28 -0
- package/src/hooks/theme/useMambaTableMeta.ts +34 -0
- package/src/hooks/theme/useMambaTables.ts +95 -0
- package/src/hooks/use-report-builder-privileges.test.tsx +98 -0
- package/src/hooks/use-report-builder-privileges.ts +58 -0
- package/src/index.ts +29 -0
- package/src/resources/address-template/address-template.api.ts +180 -0
- package/src/resources/agegroup/agegroups.api.ts +58 -0
- package/src/resources/concept/concept.api.ts +116 -0
- package/src/resources/concepts/concept-mapper.ts +21 -0
- package/src/resources/concepts/concept-types.ts +31 -0
- package/src/resources/concepts/concepts.resource.ts +44 -0
- package/src/resources/concepts/useConceptSearch.ts +41 -0
- package/src/resources/dashboard/dashboard.api.ts +107 -0
- package/src/resources/etl-monitor/etl-monitor-test.api.ts +409 -0
- package/src/resources/etl-monitor/etl-monitor.api.ts +381 -0
- package/src/resources/etl-source/etl-source.api.ts +65 -0
- package/src/resources/etl-task/etl-task.api.ts +96 -0
- package/src/resources/etl-task/etl-task.types.ts +31 -0
- package/src/resources/indicator/indicators.api.ts +125 -0
- package/src/resources/legacy-reports/legacy-reports.api.ts +144 -0
- package/src/resources/linelist/linelist-reports.api.ts +616 -0
- package/src/resources/location/location.api.ts +135 -0
- package/src/resources/openmrs-api.ts +40 -0
- package/src/resources/patient-identifier-type/patient-identifier-type.api.ts +65 -0
- package/src/resources/person-attribute-type/person-attribute-type.api.ts +71 -0
- package/src/resources/preview/sql-preview.api.ts +54 -0
- package/src/resources/report/reports.api.ts +140 -0
- package/src/resources/report-category/report-category.api.ts +41 -0
- package/src/resources/report-import-export/import-export-api.ts +164 -0
- package/src/resources/report-library/report-library.api.ts +63 -0
- package/src/resources/report-section/report-sections.api.ts +73 -0
- package/src/resources/report-section/section-preview.api.ts +25 -0
- package/src/resources/theme/data-theme.api.ts +88 -0
- package/src/resources/theme/etl-schema.api.ts +101 -0
- package/src/resources/theme/etl-table-meta.api.ts +45 -0
- package/src/root.component.tsx +20 -0
- package/src/routes/report-builder.routes.tsx +160 -0
- package/src/routes/report-builder.scss +56 -0
- package/src/routes.json +28 -0
- package/src/sample-template.ts +121 -0
- package/src/template-utils.ts +110 -0
- package/src/types/carbon-react-inert.d.ts +13 -0
- package/src/types/condition-operators.ts +63 -0
- package/src/types/dashboard/dashboard.types.ts +137 -0
- package/src/types/dashboard/index.ts +4 -0
- package/src/types/etl/etl-types.ts +238 -0
- package/src/types/etl-monitor/etl-monitor-builder.types.ts +555 -0
- package/src/types/etl-monitor/etl-monitor-v2.types.ts +397 -0
- package/src/types/etl-monitor/etl-monitor.types.ts +188 -0
- package/src/types/etl-monitor/index.ts +6 -0
- package/src/types/linelist/compile-config.ts +455 -0
- package/src/types/linelist-types.ts +2059 -0
- package/src/types/theme/data-theme.types.ts +88 -0
- package/src/utils/api-error.utils.test.ts +151 -0
- package/src/utils/api-error.utils.ts +131 -0
- package/src/utils/config-enhancer.ts +62 -0
- package/src/utils/etl-browser/etl-browser.util.test.ts +145 -0
- package/src/utils/etl-browser/export-csv.util.ts +43 -0
- package/src/utils/etl-browser/group-tables.util.ts +84 -0
- package/src/utils/etl-browser/index.ts +4 -0
- package/src/utils/etl-browser/summarize-columns.util.ts +27 -0
- package/src/utils/etl-browser/table-sql.util.ts +20 -0
- package/src/utils/etl-monitor/config-v2-adapter.util.ts +460 -0
- package/src/utils/etl-monitor/endpoint-config-normalizer.util.ts +383 -0
- package/src/utils/etl-monitor/index.ts +10 -0
- package/src/utils/etl-monitor/jsonpath-resolver.util.ts +118 -0
- package/src/utils/etl-monitor/normalization-examples.ts +0 -0
- package/src/utils/etl-monitor/schema-inspector.util.ts +76 -0
- package/src/utils/etl-monitor/semantic-type-detector.util.ts +76 -0
- package/src/utils/etl-monitor/status-mapper.util.ts +105 -0
- package/src/utils/etl-monitor/value-formatters.util.ts +167 -0
- package/src/utils/etl-task/etl-task-card.util.test.ts +239 -0
- package/src/utils/etl-task/etl-task-card.util.ts +276 -0
- package/src/utils/etl-task/index.ts +1 -0
- package/src/utils/html-entities.utils.ts +34 -0
- package/src/utils/parameter-resolution.ts +218 -0
- package/src/views/etl-monitor-builder/add-monitor-modal.component.scss +0 -0
- package/src/views/etl-monitor-builder/add-monitor-modal.component.tsx +210 -0
- package/src/views/etl-monitor-builder/etl-monitor-builder.component.scss +157 -0
- package/src/views/etl-monitor-builder/etl-monitor-builder.component.tsx +252 -0
- package/src/views/etl-monitor-builder/etl-monitor-builder.store.ts +126 -0
- package/tools/scss-stub.js +12 -0
- package/tools/setup-tests.ts +1 -0
- package/translations/en.json +65 -0
- package/tsconfig.json +43 -0
- package/webpack.config.js +30 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SelectedConcept } from '../handler/concept-search-multiselect.component';
|
|
2
|
+
|
|
3
|
+
export type QAUiState = {
|
|
4
|
+
/** Selected question concepts (multi-select) */
|
|
5
|
+
questions: SelectedConcept[];
|
|
6
|
+
answers: SelectedConcept[];
|
|
7
|
+
error?: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type ConceptUiMap = Record<string, SelectedConcept[]>;
|
|
11
|
+
export type QaUiMap = Record<string, QAUiState>;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom Indicator Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* Custom indicators are complex indicators that don't fit into BASE/COMPOSITE/FINAL categories.
|
|
5
|
+
* They have their own complex SQL logic with multiple JOINs, subqueries, and business rules.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Patient identification column types
|
|
10
|
+
*/
|
|
11
|
+
export type PatientIdColumn = 'client_id' | 'patient_id' | 'person_id';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Population query extraction methods
|
|
15
|
+
*/
|
|
16
|
+
export type PopulationExtractionMethod = 'sqlTemplate' | 'configJson' | 'auto' | 'custom';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Re-disaggregation strategies for custom indicators
|
|
20
|
+
*/
|
|
21
|
+
export type RedisaggregationStrategy = 'population-extraction' | 'query-rewriting' | 'custom' | 'none';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Filter preservation rule - defines which filters should be preserved during disaggregation
|
|
25
|
+
*/
|
|
26
|
+
export type FilterPreservationRule = {
|
|
27
|
+
/** Filter identifier */
|
|
28
|
+
name: string;
|
|
29
|
+
/** Human-readable description */
|
|
30
|
+
description: string;
|
|
31
|
+
/** Regex pattern to identify the JOIN clause for this filter */
|
|
32
|
+
joinPattern: string;
|
|
33
|
+
/** Regex pattern to identify the WHERE clause for this filter */
|
|
34
|
+
wherePattern: string;
|
|
35
|
+
/** Whether this filter is required for the indicator to work correctly */
|
|
36
|
+
required: boolean;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Custom indicator configuration
|
|
41
|
+
*/
|
|
42
|
+
export type CustomIndicatorConfig = {
|
|
43
|
+
version: 1;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Patient identification column
|
|
47
|
+
* Custom indicators define their own patient ID column instead of using theme config
|
|
48
|
+
*/
|
|
49
|
+
patientIdColumn: PatientIdColumn;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Population SQL preview
|
|
53
|
+
* The extracted population SQL used for section disaggregation
|
|
54
|
+
*/
|
|
55
|
+
sqlPreview?: string;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Full SQL template
|
|
59
|
+
* The complete indicator SQL with COUNT, JOINs, and business logic
|
|
60
|
+
* Included for consistency with BASE/COMPOSITE/FINAL indicators
|
|
61
|
+
*/
|
|
62
|
+
sqlTemplate?: string;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Population query extraction configuration
|
|
66
|
+
*/
|
|
67
|
+
populationQuery: {
|
|
68
|
+
/** How to extract population SQL from the indicator */
|
|
69
|
+
extractFrom: PopulationExtractionMethod;
|
|
70
|
+
/** Path in configJson if extractFrom is 'configJson' */
|
|
71
|
+
configPath?: string;
|
|
72
|
+
/** Custom extraction function if extractFrom is 'custom' */
|
|
73
|
+
customExtractor?: string;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Filter preservation rules
|
|
78
|
+
* Defines which filters should be preserved during section disaggregation
|
|
79
|
+
*/
|
|
80
|
+
preserveFilters?: FilterPreservationRule[];
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Re-disaggregation support
|
|
84
|
+
*/
|
|
85
|
+
supportsRedisaggregation: boolean;
|
|
86
|
+
/** Strategy for re-disaggregation */
|
|
87
|
+
redisaggregationStrategy: RedisaggregationStrategy;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Theme independence
|
|
91
|
+
* Custom indicators don't require theme configuration
|
|
92
|
+
*/
|
|
93
|
+
themeIndependent: boolean;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Business logic description
|
|
97
|
+
* Helps users understand what the indicator does
|
|
98
|
+
*/
|
|
99
|
+
businessLogic?: string;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Expected data sources
|
|
103
|
+
* Lists the tables/views this indicator queries
|
|
104
|
+
*/
|
|
105
|
+
dataSources?: string[];
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Query structure analysis result
|
|
110
|
+
*/
|
|
111
|
+
export type QueryStructureAnalysis = {
|
|
112
|
+
/** Patient ID column used in the query */
|
|
113
|
+
patientIdColumn: PatientIdColumn;
|
|
114
|
+
/** Whether the query contains a population subquery */
|
|
115
|
+
hasPopulationQuery: boolean;
|
|
116
|
+
/** Extracted population SQL */
|
|
117
|
+
populationSql?: string;
|
|
118
|
+
/** Filters identified in the query */
|
|
119
|
+
filters: Array<{
|
|
120
|
+
name: string;
|
|
121
|
+
type: 'LEFT JOIN' | 'INNER JOIN' | 'WHERE';
|
|
122
|
+
pattern: string;
|
|
123
|
+
}>;
|
|
124
|
+
/** JOIN structure */
|
|
125
|
+
joinStructure: Array<{
|
|
126
|
+
type: 'LEFT JOIN' | 'INNER JOIN' | 'CROSS JOIN';
|
|
127
|
+
table: string;
|
|
128
|
+
alias: string;
|
|
129
|
+
condition: string;
|
|
130
|
+
}>;
|
|
131
|
+
/** Whether this query can be re-disaggregated */
|
|
132
|
+
redisaggregatable: boolean;
|
|
133
|
+
/** Confidence score for the analysis (0-1) */
|
|
134
|
+
confidence: number;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Custom indicator authoring metadata
|
|
139
|
+
* Used when creating/editing custom indicators
|
|
140
|
+
*/
|
|
141
|
+
export type CustomIndicatorAuthoring = {
|
|
142
|
+
version: 1;
|
|
143
|
+
/** Indicator category */
|
|
144
|
+
category: string;
|
|
145
|
+
/** Business purpose */
|
|
146
|
+
purpose: string;
|
|
147
|
+
/** Expected output format */
|
|
148
|
+
outputFormat: 'count' | 'table' | 'list';
|
|
149
|
+
/** Configuration for UI */
|
|
150
|
+
uiConfig?: {
|
|
151
|
+
/** Whether to show advanced options */
|
|
152
|
+
showAdvanced: boolean;
|
|
153
|
+
/** Available parameters */
|
|
154
|
+
parameters?: Array<{
|
|
155
|
+
name: string;
|
|
156
|
+
type: 'date' | 'string' | 'number' | 'boolean';
|
|
157
|
+
required: boolean;
|
|
158
|
+
defaultValue?: any;
|
|
159
|
+
}>;
|
|
160
|
+
};
|
|
161
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// src/report-builder/types/theme/data-theme.types.ts
|
|
2
|
+
|
|
3
|
+
export type MainDataDomain =
|
|
4
|
+
| 'OBSERVATIONS'
|
|
5
|
+
| 'TEST_ORDERS'
|
|
6
|
+
| 'MEDICATION_ORDERS'
|
|
7
|
+
| 'APPOINTMENTS'
|
|
8
|
+
| 'MEDICATION_DISPENSE'
|
|
9
|
+
| 'DIAGNOSIS';
|
|
10
|
+
|
|
11
|
+
export type FieldType = 'string' | 'number' | 'date' | 'datetime' | 'boolean' | 'coded' | 'json';
|
|
12
|
+
|
|
13
|
+
export type ThemeField = {
|
|
14
|
+
key: string;
|
|
15
|
+
label: string;
|
|
16
|
+
expr: string;
|
|
17
|
+
type: FieldType;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type ConditionHandler =
|
|
21
|
+
| 'CONCEPT_SEARCH'
|
|
22
|
+
| 'QUESTION_ANSWER_CONCEPT_SEARCH'
|
|
23
|
+
| 'TEXT'
|
|
24
|
+
| 'NUMBER'
|
|
25
|
+
| 'DATE_RANGE'
|
|
26
|
+
| 'BOOLEAN'
|
|
27
|
+
| 'LOCATION_PICKER'
|
|
28
|
+
| 'CODED_LIST';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Theme-side operator tokens (legacy + UI-friendly).
|
|
32
|
+
* NOTE: SQL generation will normalize these to real SQL operators.
|
|
33
|
+
*/
|
|
34
|
+
export type ConditionOperator = 'EQUALS' | 'IN' | 'NOT_IN' | 'LIKE' | 'BETWEEN' | 'GTE' | 'LTE' | 'IS_NULL' | 'IS_NOT_NULL';
|
|
35
|
+
|
|
36
|
+
export type ConditionValueType =
|
|
37
|
+
| 'conceptUuid'
|
|
38
|
+
| 'conceptId'
|
|
39
|
+
| 'string'
|
|
40
|
+
| 'number'
|
|
41
|
+
| 'date'
|
|
42
|
+
| 'datetime'
|
|
43
|
+
| 'boolean';
|
|
44
|
+
|
|
45
|
+
export type ThemeCondition = {
|
|
46
|
+
key: string;
|
|
47
|
+
label: string;
|
|
48
|
+
handler: ConditionHandler;
|
|
49
|
+
column: string;
|
|
50
|
+
operator: ConditionOperator;
|
|
51
|
+
valueType: ConditionValueType;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type DataThemeConfig = {
|
|
55
|
+
sourceTable: string;
|
|
56
|
+
patientIdColumn: string;
|
|
57
|
+
dateColumn: string;
|
|
58
|
+
locationColumn?: string;
|
|
59
|
+
|
|
60
|
+
joins?: Array<{ alias: string; joinSql: string }>;
|
|
61
|
+
defaultFilters?: string[];
|
|
62
|
+
|
|
63
|
+
fields: ThemeField[];
|
|
64
|
+
|
|
65
|
+
conditions?: ThemeCondition[];
|
|
66
|
+
|
|
67
|
+
conditionColumns?: Record<string, string>;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export type DataTheme = {
|
|
71
|
+
uuid?: string;
|
|
72
|
+
name: string;
|
|
73
|
+
description?: string;
|
|
74
|
+
code: string;
|
|
75
|
+
domain: MainDataDomain;
|
|
76
|
+
configJson: string;
|
|
77
|
+
metaJson?: string;
|
|
78
|
+
retired?: boolean;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export type DataThemeRow = {
|
|
82
|
+
uuid: string;
|
|
83
|
+
name: string;
|
|
84
|
+
code: string;
|
|
85
|
+
domain: MainDataDomain;
|
|
86
|
+
description?: string;
|
|
87
|
+
retired?: boolean;
|
|
88
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { DataThemeConfig, ThemeCondition } from './data-theme-config.types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* What the indicator builder saves/uses.
|
|
5
|
+
* Keep it flexible because you already have a backend model.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type IndicatorKind = 'BASE' | 'FINAL' | 'CUSTOM';
|
|
9
|
+
|
|
10
|
+
export type IndicatorConditionValue =
|
|
11
|
+
| string
|
|
12
|
+
| number
|
|
13
|
+
| boolean
|
|
14
|
+
| Array<string | number>
|
|
15
|
+
| { start?: string; end?: string }
|
|
16
|
+
| null;
|
|
17
|
+
|
|
18
|
+
export type IndicatorCondition = {
|
|
19
|
+
key: string; // matches ThemeCondition.key
|
|
20
|
+
operator?: ThemeCondition['operator'];
|
|
21
|
+
valueType?: ThemeCondition['valueType'];
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Actual chosen value(s).
|
|
25
|
+
* - concept search returns ids/uuids depending on your handler config
|
|
26
|
+
*/
|
|
27
|
+
value: IndicatorConditionValue;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type BaseIndicatorDraft = {
|
|
31
|
+
uuid?: string;
|
|
32
|
+
name: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
code?: string;
|
|
35
|
+
|
|
36
|
+
kind: IndicatorKind;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The selected data theme
|
|
40
|
+
*/
|
|
41
|
+
themeUuid: string;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Optional snapshot of theme config at save time (good for debugging / auditing)
|
|
45
|
+
*/
|
|
46
|
+
themeConfig?: DataThemeConfig;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* User-picked conditions (values), keys should match theme config conditions
|
|
50
|
+
*/
|
|
51
|
+
conditions?: IndicatorCondition[];
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Optional SQL preview used by UI
|
|
55
|
+
*/
|
|
56
|
+
sqlPreview?: string;
|
|
57
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
import type { DiagnosisBaseConfig } from './indicator-types';
|
|
3
|
+
|
|
4
|
+
function normalizeCsvToSqlInList(csv: string) {
|
|
5
|
+
const cleaned = (csv ?? '')
|
|
6
|
+
.split(',')
|
|
7
|
+
.map((x) => x.trim())
|
|
8
|
+
.filter(Boolean)
|
|
9
|
+
.map((x) => String(Number(x)))
|
|
10
|
+
.filter((x) => x !== 'NaN');
|
|
11
|
+
|
|
12
|
+
return cleaned.length ? cleaned.join(',') : '1';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function diagnosisClause(ids: number[]) {
|
|
16
|
+
if (!ids || ids.length === 0) {
|
|
17
|
+
return `-- AND a.diagnosis_coded = <select a concept>`;
|
|
18
|
+
}
|
|
19
|
+
if (ids.length === 1) {
|
|
20
|
+
return `AND a.diagnosis_coded = ${ids[0]}`;
|
|
21
|
+
}
|
|
22
|
+
return `AND a.diagnosis_coded IN (${ids.join(',')})`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function buildDiagnosisBaseSql(cfg: DiagnosisBaseConfig) {
|
|
26
|
+
const ranks = normalizeCsvToSqlInList(cfg.dxRanksCsv);
|
|
27
|
+
|
|
28
|
+
return `
|
|
29
|
+
SELECT
|
|
30
|
+
COUNT(*) AS total
|
|
31
|
+
FROM mamba_fact_encounter_diagnosis a
|
|
32
|
+
JOIN mamba_fact_patients_latest_patient_demographics mdp
|
|
33
|
+
ON mdp.client_id = a.client_id
|
|
34
|
+
WHERE a.date_created >= :startDate
|
|
35
|
+
AND a.date_created < :endDate
|
|
36
|
+
${diagnosisClause(cfg.conceptIds)}
|
|
37
|
+
AND a.certainty = '${cfg.certainty}'
|
|
38
|
+
AND a.dx_rank IN (${ranks})
|
|
39
|
+
${cfg.onlyNotVoided ? 'AND a.voided = 0' : ''}
|
|
40
|
+
${cfg.requireNonNullBirthdate ? 'AND mdp.birthdate IS NOT NULL' : ''}
|
|
41
|
+
${cfg.requireNonNullGender ? 'AND mdp.gender IS NOT NULL' : ''}
|
|
42
|
+
;`.trim();
|
|
43
|
+
}*/
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for composite-indicator-sql.utils
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, it, expect } from '@jest/globals';
|
|
6
|
+
import { countSqlToPopulationSql } from './composite-indicator-sql.utils';
|
|
7
|
+
|
|
8
|
+
describe('countSqlToPopulationSql', () => {
|
|
9
|
+
describe('Case 0: COUNT DISTINCT SQL', () => {
|
|
10
|
+
it('should preserve FROM and WHERE clauses when converting COUNT DISTINCT', () => {
|
|
11
|
+
const input = 'SELECT COUNT(DISTINCT a.client_id) AS total FROM patients a WHERE a.active = 1';
|
|
12
|
+
const result = countSqlToPopulationSql(input, 'client_id', 'Patients');
|
|
13
|
+
|
|
14
|
+
// Should preserve the FROM and WHERE clauses
|
|
15
|
+
expect(result).toContain('FROM patients a');
|
|
16
|
+
expect(result).toContain('WHERE a.active = 1');
|
|
17
|
+
expect(result).toContain('SELECT DISTINCT a.client_id AS client_id');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should handle unqualified column references', () => {
|
|
21
|
+
const input = 'SELECT COUNT(DISTINCT client_id) AS total FROM patients a';
|
|
22
|
+
const result = countSqlToPopulationSql(input, 'client_id', 'Patients');
|
|
23
|
+
|
|
24
|
+
// Should add table alias 'a.' to unqualified column
|
|
25
|
+
expect(result).toContain('SELECT DISTINCT a.client_id AS client_id');
|
|
26
|
+
expect(result).toContain('FROM patients a');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should preserve JOIN clauses', () => {
|
|
30
|
+
const input =
|
|
31
|
+
'SELECT COUNT(DISTINCT a.client_id) AS total FROM patients a JOIN demographics d ON d.client_id = a.client_id';
|
|
32
|
+
const result = countSqlToPopulationSql(input, 'client_id', 'Patients');
|
|
33
|
+
|
|
34
|
+
expect(result).toContain('FROM patients a');
|
|
35
|
+
expect(result).toContain('JOIN demographics d');
|
|
36
|
+
expect(result).toContain('SELECT DISTINCT a.client_id AS client_id');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should handle multi-line queries', () => {
|
|
40
|
+
const input = `SELECT COUNT(DISTINCT a.client_id) AS total
|
|
41
|
+
FROM patients a
|
|
42
|
+
WHERE a.date >= :startDate
|
|
43
|
+
AND a.active = 1`;
|
|
44
|
+
const result = countSqlToPopulationSql(input, 'client_id', 'Patients');
|
|
45
|
+
|
|
46
|
+
expect(result).toContain('FROM patients a');
|
|
47
|
+
expect(result).toContain('WHERE a.date >= :startDate');
|
|
48
|
+
expect(result).toContain('AND a.active = 1');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('Case 1: Composite COUNT SQL with WITH clauses', () => {
|
|
53
|
+
it('should preserve WITH CTEs and extract inner query', () => {
|
|
54
|
+
const input = `WITH A AS (SELECT client_id FROM table_a WHERE x = 1),
|
|
55
|
+
B AS (SELECT client_id FROM table_b WHERE y = 2)
|
|
56
|
+
SELECT COUNT(*) AS total
|
|
57
|
+
FROM (SELECT A.client_id FROM A) X`;
|
|
58
|
+
const result = countSqlToPopulationSql(input, 'client_id', 'Patients');
|
|
59
|
+
|
|
60
|
+
expect(result).toContain('WITH');
|
|
61
|
+
expect(result).toContain('A AS (');
|
|
62
|
+
expect(result).toContain('B AS (');
|
|
63
|
+
expect(result).toContain('SELECT DISTINCT pop.client_id');
|
|
64
|
+
expect(result).toContain('FROM (');
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe('Case 2: Base COUNT SQL', () => {
|
|
69
|
+
it('should convert COUNT(*) to DISTINCT select', () => {
|
|
70
|
+
const input = 'SELECT COUNT(*) AS total FROM patients a WHERE a.active = 1';
|
|
71
|
+
const result = countSqlToPopulationSql(input, 'client_id', 'Patients');
|
|
72
|
+
|
|
73
|
+
expect(result).toContain('SELECT DISTINCT a.client_id AS client_id');
|
|
74
|
+
expect(result).toContain('FROM patients a');
|
|
75
|
+
expect(result).toContain('WHERE a.active = 1');
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
describe('Edge cases', () => {
|
|
80
|
+
it('should handle empty input', () => {
|
|
81
|
+
const result = countSqlToPopulationSql('', 'client_id', 'Patients');
|
|
82
|
+
expect(result).toBe('');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should handle input with trailing semicolon', () => {
|
|
86
|
+
const input = 'SELECT COUNT(DISTINCT a.client_id) AS total FROM patients a;';
|
|
87
|
+
const result = countSqlToPopulationSql(input, 'client_id', 'Patients');
|
|
88
|
+
|
|
89
|
+
expect(result).not.toContain(';');
|
|
90
|
+
expect(result).toContain('FROM patients a');
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('should use patient_id for Encounters unit', () => {
|
|
94
|
+
const input = 'SELECT COUNT(DISTINCT a.encounter_id) AS total FROM encounters a';
|
|
95
|
+
const result = countSqlToPopulationSql(input, 'encounter_id', 'Encounters');
|
|
96
|
+
|
|
97
|
+
expect(result).toContain('SELECT DISTINCT a.encounter_id AS encounter_id');
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
describe('Improved: COUNT DISTINCT with different table aliases', () => {
|
|
102
|
+
it('should handle table alias "p" instead of "a"', () => {
|
|
103
|
+
const input = 'SELECT COUNT(DISTINCT p.patient_id) AS cnt FROM patients p WHERE active = 1';
|
|
104
|
+
const result = countSqlToPopulationSql(input, 'patient_id', 'Patients');
|
|
105
|
+
|
|
106
|
+
expect(result).toContain('SELECT DISTINCT p.patient_id AS patient_id');
|
|
107
|
+
expect(result).toContain('FROM patients p');
|
|
108
|
+
expect(result).toContain('WHERE active = 1');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('should handle unqualified column with alias "t"', () => {
|
|
112
|
+
const input = 'SELECT COUNT(DISTINCT client_id) AS count FROM my_table t';
|
|
113
|
+
const result = countSqlToPopulationSql(input, 'client_id', 'Patients');
|
|
114
|
+
|
|
115
|
+
expect(result).toContain('SELECT DISTINCT t.client_id AS client_id');
|
|
116
|
+
expect(result).toContain('FROM my_table t');
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should handle AS keyword in FROM clause', () => {
|
|
120
|
+
const input = 'SELECT COUNT(DISTINCT client_id) AS total FROM patients AS p';
|
|
121
|
+
const result = countSqlToPopulationSql(input, 'client_id', 'Patients');
|
|
122
|
+
|
|
123
|
+
expect(result).toContain('SELECT DISTINCT p.client_id AS client_id');
|
|
124
|
+
expect(result).toContain('FROM patients AS p');
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('should handle alias "base" for composite CTEs', () => {
|
|
128
|
+
const input = 'SELECT COUNT(DISTINCT base.client_id) AS total FROM population base WHERE base.date >= :startDate';
|
|
129
|
+
const result = countSqlToPopulationSql(input, 'client_id', 'Patients');
|
|
130
|
+
|
|
131
|
+
expect(result).toContain('SELECT DISTINCT base.client_id AS client_id');
|
|
132
|
+
expect(result).toContain('FROM population base');
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('should handle COUNT(*) with different table alias', () => {
|
|
136
|
+
const input = 'SELECT COUNT(*) AS total FROM encounters e WHERE e.status = "completed"';
|
|
137
|
+
const result = countSqlToPopulationSql(input, 'encounter_id', 'Encounters');
|
|
138
|
+
|
|
139
|
+
expect(result).toContain('SELECT DISTINCT e.encounter_id AS encounter_id');
|
|
140
|
+
expect(result).toContain('FROM encounters e');
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
});
|