@things-factory/kpi 10.1.248 → 10.1.249
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/dist-client/bootstrap.d.ts +2 -0
- package/dist-client/bootstrap.js +7 -0
- package/dist-client/bootstrap.js.map +1 -0
- package/dist-client/charts/kpi-boxplot-chart.d.ts +24 -0
- package/dist-client/charts/kpi-boxplot-chart.js +324 -0
- package/dist-client/charts/kpi-boxplot-chart.js.map +1 -0
- package/dist-client/charts/kpi-mini-trend-chart.d.ts +14 -0
- package/dist-client/charts/kpi-mini-trend-chart.js +148 -0
- package/dist-client/charts/kpi-mini-trend-chart.js.map +1 -0
- package/dist-client/charts/kpi-radar-chart.d.ts +16 -0
- package/dist-client/charts/kpi-radar-chart.js +138 -0
- package/dist-client/charts/kpi-radar-chart.js.map +1 -0
- package/dist-client/charts/kpi-trend-chart.d.ts +25 -0
- package/dist-client/charts/kpi-trend-chart.js +186 -0
- package/dist-client/charts/kpi-trend-chart.js.map +1 -0
- package/dist-client/google-map/common-google-map.d.ts +34 -0
- package/dist-client/google-map/common-google-map.js +333 -0
- package/dist-client/google-map/common-google-map.js.map +1 -0
- package/dist-client/google-map/google-map-loader.d.ts +8 -0
- package/dist-client/google-map/google-map-loader.js +22 -0
- package/dist-client/google-map/google-map-loader.js.map +1 -0
- package/dist-client/index.d.ts +1 -0
- package/dist-client/index.js +2 -0
- package/dist-client/index.js.map +1 -0
- package/dist-client/pages/kpi/kpi-grade-editor.d.ts +35 -0
- package/dist-client/pages/kpi/kpi-grade-editor.js +165 -0
- package/dist-client/pages/kpi/kpi-grade-editor.js.map +1 -0
- package/dist-client/pages/kpi/kpi-importer.d.ts +23 -0
- package/dist-client/pages/kpi/kpi-importer.js +92 -0
- package/dist-client/pages/kpi/kpi-importer.js.map +1 -0
- package/dist-client/pages/kpi/kpi-list-page.d.ts +136 -0
- package/dist-client/pages/kpi/kpi-list-page.js +948 -0
- package/dist-client/pages/kpi/kpi-list-page.js.map +1 -0
- package/dist-client/pages/kpi/kpi-overview-sample.d.ts +36 -0
- package/dist-client/pages/kpi/kpi-overview-sample.js +264 -0
- package/dist-client/pages/kpi/kpi-overview-sample.js.map +1 -0
- package/dist-client/pages/kpi/kpi-overview.d.ts +14 -0
- package/dist-client/pages/kpi/kpi-overview.js +361 -0
- package/dist-client/pages/kpi/kpi-overview.js.map +1 -0
- package/dist-client/pages/kpi/kpi-tree-page.d.ts +51 -0
- package/dist-client/pages/kpi/kpi-tree-page.js +355 -0
- package/dist-client/pages/kpi/kpi-tree-page.js.map +1 -0
- package/dist-client/pages/kpi/kpi-view.d.ts +12 -0
- package/dist-client/pages/kpi/kpi-view.js +193 -0
- package/dist-client/pages/kpi/kpi-view.js.map +1 -0
- package/dist-client/pages/kpi/kpi-viz-editor.d.ts +19 -0
- package/dist-client/pages/kpi/kpi-viz-editor.js +562 -0
- package/dist-client/pages/kpi/kpi-viz-editor.js.map +1 -0
- package/dist-client/pages/kpi-dashboard/cards/kpi-level1-card.d.ts +17 -0
- package/dist-client/pages/kpi-dashboard/cards/kpi-level1-card.js +279 -0
- package/dist-client/pages/kpi-dashboard/cards/kpi-level1-card.js.map +1 -0
- package/dist-client/pages/kpi-dashboard/cards/kpi-level2-comparison.d.ts +19 -0
- package/dist-client/pages/kpi-dashboard/cards/kpi-level2-comparison.js +385 -0
- package/dist-client/pages/kpi-dashboard/cards/kpi-level2-comparison.js.map +1 -0
- package/dist-client/pages/kpi-dashboard/cards/kpi-level3-comparison.d.ts +23 -0
- package/dist-client/pages/kpi-dashboard/cards/kpi-level3-comparison.js +465 -0
- package/dist-client/pages/kpi-dashboard/cards/kpi-level3-comparison.js.map +1 -0
- package/dist-client/pages/kpi-dashboard/components/kpi-chart-toggle.d.ts +8 -0
- package/dist-client/pages/kpi-dashboard/components/kpi-chart-toggle.js +78 -0
- package/dist-client/pages/kpi-dashboard/components/kpi-chart-toggle.js.map +1 -0
- package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.d.ts +24 -0
- package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.js +440 -0
- package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.js.map +1 -0
- package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.d.ts +33 -0
- package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js +444 -0
- package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js.map +1 -0
- package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.d.ts +23 -0
- package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.js +369 -0
- package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.js.map +1 -0
- package/dist-client/pages/kpi-dashboard/kpi-alert-panel.d.ts +18 -0
- package/dist-client/pages/kpi-dashboard/kpi-alert-panel.js +128 -0
- package/dist-client/pages/kpi-dashboard/kpi-alert-panel.js.map +1 -0
- package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.d.ts +31 -0
- package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js +493 -0
- package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js.map +1 -0
- package/dist-client/pages/kpi-dashboard/kpi-dashboard.d.ts +50 -0
- package/dist-client/pages/kpi-dashboard/kpi-dashboard.js +884 -0
- package/dist-client/pages/kpi-dashboard/kpi-dashboard.js.map +1 -0
- package/dist-client/pages/kpi-dashboard/kpi-grade-visualization.d.ts +12 -0
- package/dist-client/pages/kpi-dashboard/kpi-grade-visualization.js +82 -0
- package/dist-client/pages/kpi-dashboard/kpi-grade-visualization.js.map +1 -0
- package/dist-client/pages/kpi-dashboard/kpi-history-viewer.d.ts +11 -0
- package/dist-client/pages/kpi-dashboard/kpi-history-viewer.js +65 -0
- package/dist-client/pages/kpi-dashboard/kpi-history-viewer.js.map +1 -0
- package/dist-client/pages/kpi-dashboard/kpi-list-summary.d.ts +13 -0
- package/dist-client/pages/kpi-dashboard/kpi-list-summary.js +115 -0
- package/dist-client/pages/kpi-dashboard/kpi-list-summary.js.map +1 -0
- package/dist-client/pages/kpi-dashboard/kpi-performance-summary.d.ts +15 -0
- package/dist-client/pages/kpi-dashboard/kpi-performance-summary.js +146 -0
- package/dist-client/pages/kpi-dashboard/kpi-performance-summary.js.map +1 -0
- package/dist-client/pages/kpi-dashboard/kpi-value-entry.d.ts +7 -0
- package/dist-client/pages/kpi-dashboard/kpi-value-entry.js +86 -0
- package/dist-client/pages/kpi-dashboard/kpi-value-entry.js.map +1 -0
- package/dist-client/pages/kpi-history/kpi-history-list-page.d.ts +21 -0
- package/dist-client/pages/kpi-history/kpi-history-list-page.js +160 -0
- package/dist-client/pages/kpi-history/kpi-history-list-page.js.map +1 -0
- package/dist-client/pages/kpi-metric/kpi-metric-importer.d.ts +23 -0
- package/dist-client/pages/kpi-metric/kpi-metric-importer.js +92 -0
- package/dist-client/pages/kpi-metric/kpi-metric-importer.js.map +1 -0
- package/dist-client/pages/kpi-metric/kpi-metric-list-page.d.ts +65 -0
- package/dist-client/pages/kpi-metric/kpi-metric-list-page.js +415 -0
- package/dist-client/pages/kpi-metric/kpi-metric-list-page.js.map +1 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.d.ts +52 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.js +678 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.js.map +1 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.d.ts +23 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.js +75 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.js.map +1 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.d.ts +64 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js +311 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js.map +1 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.d.ts +12 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.js +175 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.js.map +1 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.d.ts +35 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.js +161 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.js.map +1 -0
- package/dist-client/pages/kpi-statistic/kpi-statistic-editor-page.d.ts +47 -0
- package/dist-client/pages/kpi-statistic/kpi-statistic-editor-page.js +655 -0
- package/dist-client/pages/kpi-statistic/kpi-statistic-editor-page.js.map +1 -0
- package/dist-client/pages/kpi-statistic/kpi-statistic-importer.d.ts +23 -0
- package/dist-client/pages/kpi-statistic/kpi-statistic-importer.js +92 -0
- package/dist-client/pages/kpi-statistic/kpi-statistic-importer.js.map +1 -0
- package/dist-client/pages/kpi-statistic/kpi-statistic-list-page.d.ts +65 -0
- package/dist-client/pages/kpi-statistic/kpi-statistic-list-page.js +416 -0
- package/dist-client/pages/kpi-statistic/kpi-statistic-list-page.js.map +1 -0
- package/dist-client/pages/kpi-value/kpi-value-editor-page.d.ts +50 -0
- package/dist-client/pages/kpi-value/kpi-value-editor-page.js +700 -0
- package/dist-client/pages/kpi-value/kpi-value-editor-page.js.map +1 -0
- package/dist-client/pages/kpi-value/kpi-value-importer.d.ts +23 -0
- package/dist-client/pages/kpi-value/kpi-value-importer.js +92 -0
- package/dist-client/pages/kpi-value/kpi-value-importer.js.map +1 -0
- package/dist-client/pages/kpi-value/kpi-value-list-page.d.ts +73 -0
- package/dist-client/pages/kpi-value/kpi-value-list-page.js +403 -0
- package/dist-client/pages/kpi-value/kpi-value-list-page.js.map +1 -0
- package/dist-client/route.d.ts +1 -0
- package/dist-client/route.js +47 -0
- package/dist-client/route.js.map +1 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -0
- package/dist-client/viewparts/kpi-metric-input.d.ts +23 -0
- package/dist-client/viewparts/kpi-metric-input.js +140 -0
- package/dist-client/viewparts/kpi-metric-input.js.map +1 -0
- package/dist-client/viewparts/kpi-metric-meta-editor.d.ts +36 -0
- package/dist-client/viewparts/kpi-metric-meta-editor.js +321 -0
- package/dist-client/viewparts/kpi-metric-meta-editor.js.map +1 -0
- package/dist-client/viewparts/metric-input-hint.d.ts +26 -0
- package/dist-client/viewparts/metric-input-hint.js +19 -0
- package/dist-client/viewparts/metric-input-hint.js.map +1 -0
- package/dist-client/viewparts/metric-input.test.d.ts +1 -0
- package/dist-client/viewparts/metric-input.test.js +43 -0
- package/dist-client/viewparts/metric-input.test.js.map +1 -0
- package/dist-client/viewparts/metric-renderer-registry.d.ts +18 -0
- package/dist-client/viewparts/metric-renderer-registry.js +29 -0
- package/dist-client/viewparts/metric-renderer-registry.js.map +1 -0
- package/dist-client/viewparts/ox-grist-editor-metric-input-hint.d.ts +19 -0
- package/dist-client/viewparts/ox-grist-editor-metric-input-hint.js +76 -0
- package/dist-client/viewparts/ox-grist-editor-metric-input-hint.js.map +1 -0
- package/dist-server/calculator/calculator.test.d.ts +1 -0
- package/dist-server/calculator/calculator.test.js +126 -0
- package/dist-server/calculator/calculator.test.js.map +1 -0
- package/dist-server/calculator/evaluator.d.ts +8 -0
- package/dist-server/calculator/evaluator.js +42 -0
- package/dist-server/calculator/evaluator.js.map +1 -0
- package/dist-server/calculator/functions.d.ts +3 -0
- package/dist-server/calculator/functions.js +62 -0
- package/dist-server/calculator/functions.js.map +1 -0
- package/dist-server/calculator/index.d.ts +6 -0
- package/dist-server/calculator/index.js +10 -0
- package/dist-server/calculator/index.js.map +1 -0
- package/dist-server/calculator/parser.d.ts +34 -0
- package/dist-server/calculator/parser.js +185 -0
- package/dist-server/calculator/parser.js.map +1 -0
- package/dist-server/calculator/provider.d.ts +8 -0
- package/dist-server/calculator/provider.js +13 -0
- package/dist-server/calculator/provider.js.map +1 -0
- package/dist-server/calculator/score.d.ts +21 -0
- package/dist-server/calculator/score.js +36 -0
- package/dist-server/calculator/score.js.map +1 -0
- package/dist-server/calculator/score.test.d.ts +1 -0
- package/dist-server/calculator/score.test.js +47 -0
- package/dist-server/calculator/score.test.js.map +1 -0
- package/dist-server/calculator/validate.d.ts +15 -0
- package/dist-server/calculator/validate.js +30 -0
- package/dist-server/calculator/validate.js.map +1 -0
- package/dist-server/calculator/validate.test.d.ts +1 -0
- package/dist-server/calculator/validate.test.js +45 -0
- package/dist-server/calculator/validate.test.js.map +1 -0
- package/dist-server/controllers/index.d.ts +2 -0
- package/dist-server/controllers/index.js +6 -0
- package/dist-server/controllers/index.js.map +1 -0
- package/dist-server/controllers/kpi-metric-value-provider.d.ts +11 -0
- package/dist-server/controllers/kpi-metric-value-provider.js +97 -0
- package/dist-server/controllers/kpi-metric-value-provider.js.map +1 -0
- package/dist-server/controllers/kpi-value-provider.d.ts +11 -0
- package/dist-server/controllers/kpi-value-provider.js +50 -0
- package/dist-server/controllers/kpi-value-provider.js.map +1 -0
- package/dist-server/index.d.ts +5 -0
- package/dist-server/index.js +9 -0
- package/dist-server/index.js.map +1 -0
- package/dist-server/migrations/1752190849680-seed-kpi-metrics.d.ts +6 -0
- package/dist-server/migrations/1752190849680-seed-kpi-metrics.js +102 -0
- package/dist-server/migrations/1752190849680-seed-kpi-metrics.js.map +1 -0
- package/dist-server/migrations/1752190849681-seed-kpi.d.ts +5 -0
- package/dist-server/migrations/1752190849681-seed-kpi.js +315 -0
- package/dist-server/migrations/1752190849681-seed-kpi.js.map +1 -0
- package/dist-server/migrations/1752192090123-add-grades-to-kpi.d.ts +7 -0
- package/dist-server/migrations/1752192090123-add-grades-to-kpi.js +51 -0
- package/dist-server/migrations/1752192090123-add-grades-to-kpi.js.map +1 -0
- package/dist-server/migrations/1752192090124-add-kpi-statistics.d.ts +5 -0
- package/dist-server/migrations/1752192090124-add-kpi-statistics.js +710 -0
- package/dist-server/migrations/1752192090124-add-kpi-statistics.js.map +1 -0
- package/dist-server/migrations/1752192090128-seed-kpi-org-scope.d.ts +6 -0
- package/dist-server/migrations/1752192090128-seed-kpi-org-scope.js +111 -0
- package/dist-server/migrations/1752192090128-seed-kpi-org-scope.js.map +1 -0
- package/dist-server/migrations/1752192090129-seed-kpi-values.d.ts +6 -0
- package/dist-server/migrations/1752192090129-seed-kpi-values.js +187 -0
- package/dist-server/migrations/1752192090129-seed-kpi-values.js.map +1 -0
- package/dist-server/migrations/1752192090200-add-meta-to-kpi-metric.d.ts +10 -0
- package/dist-server/migrations/1752192090200-add-meta-to-kpi-metric.js +26 -0
- package/dist-server/migrations/1752192090200-add-meta-to-kpi-metric.js.map +1 -0
- package/dist-server/migrations/1752192090201-backfill-kpi-metric-meta.d.ts +11 -0
- package/dist-server/migrations/1752192090201-backfill-kpi-metric-meta.js +54 -0
- package/dist-server/migrations/1752192090201-backfill-kpi-metric-meta.js.map +1 -0
- package/dist-server/migrations/grade-data/x11-performance-table.json +962 -0
- package/dist-server/migrations/grade-data/x12-performance-table.json +611 -0
- package/dist-server/migrations/grade-data/x14-performance-table.json +42 -0
- package/dist-server/migrations/grade-data/x21-performance-table.json +889 -0
- package/dist-server/migrations/grade-data/x22-performance-table.json +1064 -0
- package/dist-server/migrations/grade-data/x23-performance-table.json +42 -0
- package/dist-server/migrations/grade-data/x31-performance-table.json +644 -0
- package/dist-server/migrations/grade-data/x32-performance-table.json +993 -0
- package/dist-server/migrations/grade-data/x33-performance-table.json +195 -0
- package/dist-server/migrations/grade-data/x34-performance-table.json +12 -0
- package/dist-server/migrations/grade-data/x35-performance-table.json +42 -0
- package/dist-server/migrations/grade-data/x41-performance-table.json +825 -0
- package/dist-server/migrations/grade-data/x42-performance-table.json +786 -0
- package/dist-server/migrations/grade-data/x43-performance-table.json +12 -0
- package/dist-server/migrations/grade-data/x44-performance-table.json +42 -0
- package/dist-server/migrations/grade-data/x51-performance-table.json +924 -0
- package/dist-server/migrations/grade-data/x52-performance-table.json +42 -0
- package/dist-server/migrations/grade-data/x61-performance-table.json +261 -0
- package/dist-server/migrations/grade-data/x62-performance-table.json +42 -0
- package/dist-server/migrations/index.d.ts +1 -0
- package/dist-server/migrations/index.js +12 -0
- package/dist-server/migrations/index.js.map +1 -0
- package/dist-server/migrations/seed-data/kpi-metrics-seed.json +517 -0
- package/dist-server/migrations/seed-data/kpi-org-scope-seed.json +1676 -0
- package/dist-server/migrations/seed-data/kpi-scopes-seed.json +121 -0
- package/dist-server/migrations/seed-data/kpi-values-seed.json +402 -0
- package/dist-server/migrations/seed-data/kpis-seed.json +488 -0
- package/dist-server/migrations/seed-data/scope-definitions-seed.json +90 -0
- package/dist-server/routes.d.ts +1 -0
- package/dist-server/routes.js +72 -0
- package/dist-server/routes.js.map +1 -0
- package/dist-server/service/index.d.ts +15 -0
- package/dist-server/service/index.js +49 -0
- package/dist-server/service/index.js.map +1 -0
- package/dist-server/service/kpi/aggregate-kpi.d.ts +8 -0
- package/dist-server/service/kpi/aggregate-kpi.js +123 -0
- package/dist-server/service/kpi/aggregate-kpi.js.map +1 -0
- package/dist-server/service/kpi/event-subscriber.d.ts +9 -0
- package/dist-server/service/kpi/event-subscriber.js +31 -0
- package/dist-server/service/kpi/event-subscriber.js.map +1 -0
- package/dist-server/service/kpi/index.d.ts +8 -0
- package/dist-server/service/kpi/index.js +12 -0
- package/dist-server/service/kpi/index.js.map +1 -0
- package/dist-server/service/kpi/kpi-formula.service.d.ts +49 -0
- package/dist-server/service/kpi/kpi-formula.service.js +165 -0
- package/dist-server/service/kpi/kpi-formula.service.js.map +1 -0
- package/dist-server/service/kpi/kpi-grade.types.d.ts +22 -0
- package/dist-server/service/kpi/kpi-grade.types.js +3 -0
- package/dist-server/service/kpi/kpi-grade.types.js.map +1 -0
- package/dist-server/service/kpi/kpi-history.d.ts +29 -0
- package/dist-server/service/kpi/kpi-history.js +148 -0
- package/dist-server/service/kpi/kpi-history.js.map +1 -0
- package/dist-server/service/kpi/kpi-mutation.d.ts +14 -0
- package/dist-server/service/kpi/kpi-mutation.js +553 -0
- package/dist-server/service/kpi/kpi-mutation.js.map +1 -0
- package/dist-server/service/kpi/kpi-query.d.ts +24 -0
- package/dist-server/service/kpi/kpi-query.js +309 -0
- package/dist-server/service/kpi/kpi-query.js.map +1 -0
- package/dist-server/service/kpi/kpi-type.d.ts +48 -0
- package/dist-server/service/kpi/kpi-type.js +221 -0
- package/dist-server/service/kpi/kpi-type.js.map +1 -0
- package/dist-server/service/kpi/kpi.d.ts +130 -0
- package/dist-server/service/kpi/kpi.js +356 -0
- package/dist-server/service/kpi/kpi.js.map +1 -0
- package/dist-server/service/kpi-alert/index.d.ts +2 -0
- package/dist-server/service/kpi-alert/index.js +6 -0
- package/dist-server/service/kpi-alert/index.js.map +1 -0
- package/dist-server/service/kpi-alert/kpi-alert-query.d.ts +4 -0
- package/dist-server/service/kpi-alert/kpi-alert-query.js +72 -0
- package/dist-server/service/kpi-alert/kpi-alert-query.js.map +1 -0
- package/dist-server/service/kpi-alert/kpi-alert-type.d.ts +8 -0
- package/dist-server/service/kpi-alert/kpi-alert-type.js +33 -0
- package/dist-server/service/kpi-alert/kpi-alert-type.js.map +1 -0
- package/dist-server/service/kpi-metric/aggregate-kpi-metric.d.ts +8 -0
- package/dist-server/service/kpi-metric/aggregate-kpi-metric.js +126 -0
- package/dist-server/service/kpi-metric/aggregate-kpi-metric.js.map +1 -0
- package/dist-server/service/kpi-metric/index.d.ts +6 -0
- package/dist-server/service/kpi-metric/index.js +10 -0
- package/dist-server/service/kpi-metric/index.js.map +1 -0
- package/dist-server/service/kpi-metric/kpi-metric-meta.d.ts +46 -0
- package/dist-server/service/kpi-metric/kpi-metric-meta.js +27 -0
- package/dist-server/service/kpi-metric/kpi-metric-meta.js.map +1 -0
- package/dist-server/service/kpi-metric/kpi-metric-meta.test.d.ts +1 -0
- package/dist-server/service/kpi-metric/kpi-metric-meta.test.js +43 -0
- package/dist-server/service/kpi-metric/kpi-metric-meta.test.js.map +1 -0
- package/dist-server/service/kpi-metric/kpi-metric-mutation.d.ts +10 -0
- package/dist-server/service/kpi-metric/kpi-metric-mutation.js +296 -0
- package/dist-server/service/kpi-metric/kpi-metric-mutation.js.map +1 -0
- package/dist-server/service/kpi-metric/kpi-metric-query.d.ts +14 -0
- package/dist-server/service/kpi-metric/kpi-metric-query.js +126 -0
- package/dist-server/service/kpi-metric/kpi-metric-query.js.map +1 -0
- package/dist-server/service/kpi-metric/kpi-metric-type.d.ts +45 -0
- package/dist-server/service/kpi-metric/kpi-metric-type.js +177 -0
- package/dist-server/service/kpi-metric/kpi-metric-type.js.map +1 -0
- package/dist-server/service/kpi-metric/kpi-metric.d.ts +39 -0
- package/dist-server/service/kpi-metric/kpi-metric.js +174 -0
- package/dist-server/service/kpi-metric/kpi-metric.js.map +1 -0
- package/dist-server/service/kpi-metric-value/index.d.ts +6 -0
- package/dist-server/service/kpi-metric-value/index.js +10 -0
- package/dist-server/service/kpi-metric-value/index.js.map +1 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.d.ts +11 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js +283 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js.map +1 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-query.d.ts +13 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-query.js +106 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-query.js.map +1 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-type.d.ts +26 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-type.js +112 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-type.js.map +1 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value.d.ts +23 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value.js +107 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value.js.map +1 -0
- package/dist-server/service/kpi-org-scope/index.d.ts +5 -0
- package/dist-server/service/kpi-org-scope/index.js +9 -0
- package/dist-server/service/kpi-org-scope/index.js.map +1 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope-mutation.d.ts +8 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope-mutation.js +170 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope-mutation.js.map +1 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope-query.d.ts +14 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope-query.js +152 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope-query.js.map +1 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope-type.d.ts +26 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope-type.js +101 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope-type.js.map +1 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope.d.ts +26 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope.js +135 -0
- package/dist-server/service/kpi-org-scope/kpi-org-scope.js.map +1 -0
- package/dist-server/service/kpi-scope/index.d.ts +9 -0
- package/dist-server/service/kpi-scope/index.js +14 -0
- package/dist-server/service/kpi-scope/index.js.map +1 -0
- package/dist-server/service/kpi-scope/kpi-scope-mutation.d.ts +9 -0
- package/dist-server/service/kpi-scope/kpi-scope-mutation.js +140 -0
- package/dist-server/service/kpi-scope/kpi-scope-mutation.js.map +1 -0
- package/dist-server/service/kpi-scope/kpi-scope-query.d.ts +11 -0
- package/dist-server/service/kpi-scope/kpi-scope-query.js +89 -0
- package/dist-server/service/kpi-scope/kpi-scope-query.js.map +1 -0
- package/dist-server/service/kpi-scope/kpi-scope-type.d.ts +35 -0
- package/dist-server/service/kpi-scope/kpi-scope-type.js +138 -0
- package/dist-server/service/kpi-scope/kpi-scope-type.js.map +1 -0
- package/dist-server/service/kpi-scope/kpi-scope.d.ts +38 -0
- package/dist-server/service/kpi-scope/kpi-scope.js +144 -0
- package/dist-server/service/kpi-scope/kpi-scope.js.map +1 -0
- package/dist-server/service/kpi-statistic/index.d.ts +6 -0
- package/dist-server/service/kpi-statistic/index.js +10 -0
- package/dist-server/service/kpi-statistic/index.js.map +1 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-batch.service.d.ts +43 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-batch.service.js +181 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-batch.service.js.map +1 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-calculation.service.d.ts +50 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-calculation.service.js +324 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-calculation.service.js.map +1 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-mutation.d.ts +14 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-mutation.js +279 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-mutation.js.map +1 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-query.d.ts +17 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-query.js +183 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-query.js.map +1 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-type.d.ts +59 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-type.js +200 -0
- package/dist-server/service/kpi-statistic/kpi-statistic-type.js.map +1 -0
- package/dist-server/service/kpi-statistic/kpi-statistic.d.ts +42 -0
- package/dist-server/service/kpi-statistic/kpi-statistic.js +210 -0
- package/dist-server/service/kpi-statistic/kpi-statistic.js.map +1 -0
- package/dist-server/service/kpi-value/index.d.ts +6 -0
- package/dist-server/service/kpi-value/index.js +10 -0
- package/dist-server/service/kpi-value/index.js.map +1 -0
- package/dist-server/service/kpi-value/kpi-value-mutation.d.ts +13 -0
- package/dist-server/service/kpi-value/kpi-value-mutation.js +447 -0
- package/dist-server/service/kpi-value/kpi-value-mutation.js.map +1 -0
- package/dist-server/service/kpi-value/kpi-value-query.d.ts +22 -0
- package/dist-server/service/kpi-value/kpi-value-query.js +149 -0
- package/dist-server/service/kpi-value/kpi-value-query.js.map +1 -0
- package/dist-server/service/kpi-value/kpi-value-score.service.d.ts +24 -0
- package/dist-server/service/kpi-value/kpi-value-score.service.js +61 -0
- package/dist-server/service/kpi-value/kpi-value-score.service.js.map +1 -0
- package/dist-server/service/kpi-value/kpi-value-type.d.ts +33 -0
- package/dist-server/service/kpi-value/kpi-value-type.js +156 -0
- package/dist-server/service/kpi-value/kpi-value-type.js.map +1 -0
- package/dist-server/service/kpi-value/kpi-value.d.ts +32 -0
- package/dist-server/service/kpi-value/kpi-value.js +175 -0
- package/dist-server/service/kpi-value/kpi-value.js.map +1 -0
- package/dist-server/service/utils/value-date-util.d.ts +4 -0
- package/dist-server/service/utils/value-date-util.js +117 -0
- package/dist-server/service/utils/value-date-util.js.map +1 -0
- package/dist-server/tsconfig.tsbuildinfo +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { __decorate, __metadata } from "tslib";
|
|
2
|
+
import { html, css, LitElement, nothing } from 'lit';
|
|
3
|
+
import { customElement, property } from 'lit/decorators.js';
|
|
4
|
+
import { resolveInputHint } from './metric-input-hint';
|
|
5
|
+
import { MetricRendererRegistry } from './metric-renderer-registry';
|
|
6
|
+
/**
|
|
7
|
+
* metric 정의(meta.input)에 따라 입력 위젯을 **선언적으로 자동 렌더**하는 제네릭 컴포넌트.
|
|
8
|
+
* 이름 추측(isRating 등) 없이 `resolveInputHint` 로 위젯을 결정한다.
|
|
9
|
+
*
|
|
10
|
+
* <kpi-metric-input .metric=${metric} .value=${v}
|
|
11
|
+
* @metric-input-change=${e => (v = e.detail.value)}></kpi-metric-input>
|
|
12
|
+
*
|
|
13
|
+
* 예외 UI 는 MetricRendererRegistry 로 등록(제네릭 우선순위보다 먼저 적용).
|
|
14
|
+
*/
|
|
15
|
+
let KpiMetricInput = class KpiMetricInput extends LitElement {
|
|
16
|
+
constructor() {
|
|
17
|
+
super(...arguments);
|
|
18
|
+
this.metric = {};
|
|
19
|
+
/** 상위에서 강제 비활성화(권한 등). readonly 힌트와 별개. */
|
|
20
|
+
this.disabled = false;
|
|
21
|
+
}
|
|
22
|
+
static { this.styles = css `
|
|
23
|
+
:host {
|
|
24
|
+
display: inline-flex;
|
|
25
|
+
align-items: baseline;
|
|
26
|
+
gap: 2px;
|
|
27
|
+
font: 13px/18px var(--theme-font, sans-serif);
|
|
28
|
+
}
|
|
29
|
+
input,
|
|
30
|
+
select {
|
|
31
|
+
background-color: var(--input-field-background, var(--md-sys-color-surface-container-highest));
|
|
32
|
+
color: var(--input-field-color, var(--md-sys-color-on-surface));
|
|
33
|
+
font: inherit;
|
|
34
|
+
padding: 2px 4px;
|
|
35
|
+
}
|
|
36
|
+
input[type='number'] {
|
|
37
|
+
width: 5em;
|
|
38
|
+
text-align: right;
|
|
39
|
+
}
|
|
40
|
+
.stars {
|
|
41
|
+
display: inline-flex;
|
|
42
|
+
cursor: pointer;
|
|
43
|
+
font-size: 18px;
|
|
44
|
+
line-height: 1;
|
|
45
|
+
color: var(--md-sys-color-primary, #2e79be);
|
|
46
|
+
}
|
|
47
|
+
.stars[readonly] {
|
|
48
|
+
cursor: default;
|
|
49
|
+
opacity: 0.85;
|
|
50
|
+
}
|
|
51
|
+
.star {
|
|
52
|
+
width: 1em;
|
|
53
|
+
}
|
|
54
|
+
.unit {
|
|
55
|
+
color: var(--md-sys-color-on-surface-variant, #888);
|
|
56
|
+
font-size: 11px;
|
|
57
|
+
}
|
|
58
|
+
`; }
|
|
59
|
+
_emit(value) {
|
|
60
|
+
this.value = value;
|
|
61
|
+
this.dispatchEvent(new CustomEvent('metric-input-change', { detail: { value }, bubbles: true, composed: true }));
|
|
62
|
+
}
|
|
63
|
+
render() {
|
|
64
|
+
const custom = MetricRendererRegistry.resolve(this.metric);
|
|
65
|
+
if (custom)
|
|
66
|
+
return custom(this.metric, this.value, v => this._emit(v));
|
|
67
|
+
const hint = resolveInputHint(this.metric);
|
|
68
|
+
const ro = this.disabled || !!hint.readonly;
|
|
69
|
+
const unit = this.metric?.unit;
|
|
70
|
+
// 값(우측정렬) 바로 옆에 단위 — 값이 단위에 붙어 자연스럽게. (rating/toggle 등엔 unit 보통 없음)
|
|
71
|
+
return html `
|
|
72
|
+
${this._renderWidget(hint, ro)}${unit ? html `<span class="unit">${unit}</span>` : nothing}
|
|
73
|
+
`;
|
|
74
|
+
}
|
|
75
|
+
_renderWidget(hint, ro) {
|
|
76
|
+
switch (hint.widget) {
|
|
77
|
+
case 'rating':
|
|
78
|
+
return this._renderRating(hint, ro);
|
|
79
|
+
case 'select':
|
|
80
|
+
return this._renderSelect(hint, ro);
|
|
81
|
+
case 'date':
|
|
82
|
+
return html `<input type="date" .value=${this.value ?? ''} ?disabled=${ro}
|
|
83
|
+
@change=${(e) => this._emit(e.target.value)} />`;
|
|
84
|
+
case 'toggle':
|
|
85
|
+
return html `<input type="checkbox" .checked=${!!this.value} ?disabled=${ro}
|
|
86
|
+
@change=${(e) => this._emit(e.target.checked)} />`;
|
|
87
|
+
case 'text':
|
|
88
|
+
return html `<input type="text" .value=${this.value ?? ''} ?disabled=${ro}
|
|
89
|
+
placeholder=${hint.placeholder ?? ''} @input=${(e) => this._emit(e.target.value)} />`;
|
|
90
|
+
case 'number':
|
|
91
|
+
default:
|
|
92
|
+
return html `<input type="number" .value=${this.value ?? ''} ?disabled=${ro}
|
|
93
|
+
min=${hint.min ?? nothing} max=${hint.max ?? nothing} step=${hint.step ?? nothing}
|
|
94
|
+
placeholder=${hint.placeholder ?? ''}
|
|
95
|
+
@input=${(e) => {
|
|
96
|
+
const raw = e.target.value;
|
|
97
|
+
this._emit(raw === '' ? null : Number(raw));
|
|
98
|
+
}} />`;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
_renderRating(hint, ro) {
|
|
102
|
+
const max = hint.max ?? 5;
|
|
103
|
+
const score = Number(this.value ?? 0);
|
|
104
|
+
const stars = Array.from({ length: max }, (_, idx) => {
|
|
105
|
+
const i = idx + 1;
|
|
106
|
+
const filled = i <= Math.round(score);
|
|
107
|
+
return html `<span class="star" @click=${() => (ro ? null : this._emit(i))}>${filled ? '★' : '☆'}</span>`;
|
|
108
|
+
});
|
|
109
|
+
return html `<span class="stars" ?readonly=${ro} title=${`${score}/${max}`}>${stars}</span>`;
|
|
110
|
+
}
|
|
111
|
+
_renderSelect(hint, ro) {
|
|
112
|
+
const options = hint.options ?? [];
|
|
113
|
+
return html `<select ?disabled=${ro} @change=${(e) => {
|
|
114
|
+
const raw = e.target.value;
|
|
115
|
+
// 옵션의 원래 타입(숫자 등)을 보존해 방출 — 문자열 강제 방지.
|
|
116
|
+
const opt = options.find(o => String(o.value) === raw);
|
|
117
|
+
this._emit(raw === '' ? null : opt ? opt.value : raw);
|
|
118
|
+
}}>
|
|
119
|
+
<option value="" ?selected=${this.value == null || this.value === ''}>-</option>
|
|
120
|
+
${options.map(o => html `<option value=${o.value} ?selected=${String(this.value) === String(o.value)}>${o.label}</option>`)}
|
|
121
|
+
</select>`;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
__decorate([
|
|
125
|
+
property({ type: Object }),
|
|
126
|
+
__metadata("design:type", Object)
|
|
127
|
+
], KpiMetricInput.prototype, "metric", void 0);
|
|
128
|
+
__decorate([
|
|
129
|
+
property(),
|
|
130
|
+
__metadata("design:type", Object)
|
|
131
|
+
], KpiMetricInput.prototype, "value", void 0);
|
|
132
|
+
__decorate([
|
|
133
|
+
property({ type: Boolean }),
|
|
134
|
+
__metadata("design:type", Object)
|
|
135
|
+
], KpiMetricInput.prototype, "disabled", void 0);
|
|
136
|
+
KpiMetricInput = __decorate([
|
|
137
|
+
customElement('kpi-metric-input')
|
|
138
|
+
], KpiMetricInput);
|
|
139
|
+
export { KpiMetricInput };
|
|
140
|
+
//# sourceMappingURL=kpi-metric-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kpi-metric-input.js","sourceRoot":"","sources":["../../client/viewparts/kpi-metric-input.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,KAAK,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE3D,OAAO,EAAE,gBAAgB,EAA4B,MAAM,qBAAqB,CAAA;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AAEnE;;;;;;;;GAQG;AAEI,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,UAAU;IAAvC;;QAuCuB,WAAM,GAAkB,EAAE,CAAA;QAEtD,2CAA2C;QACd,aAAQ,GAAG,KAAK,CAAA;IAyE/C,CAAC;aAlHQ,WAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoClB,AApCY,CAoCZ;IAOO,KAAK,CAAC,KAAU;QACtB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;QAClB,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,qBAAqB,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IAClH,CAAC;IAED,MAAM;QACJ,MAAM,MAAM,GAAG,sBAAsB,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC1D,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;QAEtE,MAAM,IAAI,GAAG,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC1C,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAA;QAC3C,MAAM,IAAI,GAAI,IAAI,CAAC,MAAc,EAAE,IAAI,CAAA;QAEvC,oEAAoE;QACpE,OAAO,IAAI,CAAA;QACP,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA,sBAAsB,IAAI,SAAS,CAAC,CAAC,CAAC,OAAO;KAC1F,CAAA;IACH,CAAC;IAEO,aAAa,CAAC,IAAe,EAAE,EAAW;QAChD,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;YACpB,KAAK,QAAQ;gBACX,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;YACrC,KAAK,QAAQ;gBACX,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;YACrC,KAAK,MAAM;gBACT,OAAO,IAAI,CAAA,6BAA6B,IAAI,CAAC,KAAK,IAAI,EAAE,cAAc,EAAE;oBAC5D,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAE,CAAC,CAAC,MAA2B,CAAC,KAAK,CAAC,KAAK,CAAA;YACjF,KAAK,QAAQ;gBACX,OAAO,IAAI,CAAA,mCAAmC,CAAC,CAAC,IAAI,CAAC,KAAK,cAAc,EAAE;oBAC9D,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAE,CAAC,CAAC,MAA2B,CAAC,OAAO,CAAC,KAAK,CAAA;YACnF,KAAK,MAAM;gBACT,OAAO,IAAI,CAAA,6BAA6B,IAAI,CAAC,KAAK,IAAI,EAAE,cAAc,EAAE;wBACxD,IAAI,CAAC,WAAW,IAAI,EAAE,WAAW,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAE,CAAC,CAAC,MAA2B,CAAC,KAAK,CAAC,KAAK,CAAA;YACtH,KAAK,QAAQ,CAAC;YACd;gBACE,OAAO,IAAI,CAAA,+BAA+B,IAAI,CAAC,KAAK,IAAI,EAAE,cAAc,EAAE;gBAClE,IAAI,CAAC,GAAG,IAAI,OAAO,QAAQ,IAAI,CAAC,GAAG,IAAI,OAAO,SAAS,IAAI,CAAC,IAAI,IAAI,OAAO;wBACnE,IAAI,CAAC,WAAW,IAAI,EAAE;mBAC3B,CAAC,CAAQ,EAAE,EAAE;oBACpB,MAAM,GAAG,GAAI,CAAC,CAAC,MAA2B,CAAC,KAAK,CAAA;oBAChD,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;gBAC7C,CAAC,KAAK,CAAA;QACZ,CAAC;IACH,CAAC;IAEO,aAAa,CAAC,IAAe,EAAE,EAAW;QAChD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAA;QACzB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAA;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE;YACnD,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC,CAAA;YACjB,MAAM,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YACrC,OAAO,IAAI,CAAA,6BAA6B,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,SAAS,CAAA;QAC1G,CAAC,CAAC,CAAA;QACF,OAAO,IAAI,CAAA,iCAAiC,EAAE,UAAU,GAAG,KAAK,IAAI,GAAG,EAAE,IAAI,KAAK,SAAS,CAAA;IAC7F,CAAC;IAEO,aAAa,CAAC,IAAe,EAAE,EAAW;QAChD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAA;QAClC,OAAO,IAAI,CAAA,qBAAqB,EAAE,YAAY,CAAC,CAAQ,EAAE,EAAE;YACzD,MAAM,GAAG,GAAI,CAAC,CAAC,MAA4B,CAAC,KAAK,CAAA;YACjD,uCAAuC;YACvC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAA;YACtD,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QACvD,CAAC;mCAC8B,IAAI,CAAC,KAAK,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,EAAE;QAClE,OAAO,CAAC,GAAG,CACX,CAAC,CAAC,EAAE,CAAC,IAAI,CAAA,iBAAiB,CAAC,CAAC,KAAK,cAAc,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,WAAW,CAC5G;cACO,CAAA;IACZ,CAAC;;AA3E2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;8CAA2B;AAC1C;IAAX,QAAQ,EAAE;;6CAAW;AAEO;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;;gDAAiB;AA1ClC,cAAc;IAD1B,aAAa,CAAC,kBAAkB,CAAC;GACrB,cAAc,CAmH1B","sourcesContent":["import { html, css, LitElement, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { resolveInputHint, InputHint, KpiMetricLike } from './metric-input-hint'\nimport { MetricRendererRegistry } from './metric-renderer-registry'\n\n/**\n * metric 정의(meta.input)에 따라 입력 위젯을 **선언적으로 자동 렌더**하는 제네릭 컴포넌트.\n * 이름 추측(isRating 등) 없이 `resolveInputHint` 로 위젯을 결정한다.\n *\n * <kpi-metric-input .metric=${metric} .value=${v}\n * @metric-input-change=${e => (v = e.detail.value)}></kpi-metric-input>\n *\n * 예외 UI 는 MetricRendererRegistry 로 등록(제네릭 우선순위보다 먼저 적용).\n */\n@customElement('kpi-metric-input')\nexport class KpiMetricInput extends LitElement {\n static styles = css`\n :host {\n display: inline-flex;\n align-items: baseline;\n gap: 2px;\n font: 13px/18px var(--theme-font, sans-serif);\n }\n input,\n select {\n background-color: var(--input-field-background, var(--md-sys-color-surface-container-highest));\n color: var(--input-field-color, var(--md-sys-color-on-surface));\n font: inherit;\n padding: 2px 4px;\n }\n input[type='number'] {\n width: 5em;\n text-align: right;\n }\n .stars {\n display: inline-flex;\n cursor: pointer;\n font-size: 18px;\n line-height: 1;\n color: var(--md-sys-color-primary, #2e79be);\n }\n .stars[readonly] {\n cursor: default;\n opacity: 0.85;\n }\n .star {\n width: 1em;\n }\n .unit {\n color: var(--md-sys-color-on-surface-variant, #888);\n font-size: 11px;\n }\n `\n\n @property({ type: Object }) metric: KpiMetricLike = {}\n @property() value: any\n /** 상위에서 강제 비활성화(권한 등). readonly 힌트와 별개. */\n @property({ type: Boolean }) disabled = false\n\n private _emit(value: any) {\n this.value = value\n this.dispatchEvent(new CustomEvent('metric-input-change', { detail: { value }, bubbles: true, composed: true }))\n }\n\n render() {\n const custom = MetricRendererRegistry.resolve(this.metric)\n if (custom) return custom(this.metric, this.value, v => this._emit(v))\n\n const hint = resolveInputHint(this.metric)\n const ro = this.disabled || !!hint.readonly\n const unit = (this.metric as any)?.unit\n\n // 값(우측정렬) 바로 옆에 단위 — 값이 단위에 붙어 자연스럽게. (rating/toggle 등엔 unit 보통 없음)\n return html`\n ${this._renderWidget(hint, ro)}${unit ? html`<span class=\"unit\">${unit}</span>` : nothing}\n `\n }\n\n private _renderWidget(hint: InputHint, ro: boolean) {\n switch (hint.widget) {\n case 'rating':\n return this._renderRating(hint, ro)\n case 'select':\n return this._renderSelect(hint, ro)\n case 'date':\n return html`<input type=\"date\" .value=${this.value ?? ''} ?disabled=${ro}\n @change=${(e: Event) => this._emit((e.target as HTMLInputElement).value)} />`\n case 'toggle':\n return html`<input type=\"checkbox\" .checked=${!!this.value} ?disabled=${ro}\n @change=${(e: Event) => this._emit((e.target as HTMLInputElement).checked)} />`\n case 'text':\n return html`<input type=\"text\" .value=${this.value ?? ''} ?disabled=${ro}\n placeholder=${hint.placeholder ?? ''} @input=${(e: Event) => this._emit((e.target as HTMLInputElement).value)} />`\n case 'number':\n default:\n return html`<input type=\"number\" .value=${this.value ?? ''} ?disabled=${ro}\n min=${hint.min ?? nothing} max=${hint.max ?? nothing} step=${hint.step ?? nothing}\n placeholder=${hint.placeholder ?? ''}\n @input=${(e: Event) => {\n const raw = (e.target as HTMLInputElement).value\n this._emit(raw === '' ? null : Number(raw))\n }} />`\n }\n }\n\n private _renderRating(hint: InputHint, ro: boolean) {\n const max = hint.max ?? 5\n const score = Number(this.value ?? 0)\n const stars = Array.from({ length: max }, (_, idx) => {\n const i = idx + 1\n const filled = i <= Math.round(score)\n return html`<span class=\"star\" @click=${() => (ro ? null : this._emit(i))}>${filled ? '★' : '☆'}</span>`\n })\n return html`<span class=\"stars\" ?readonly=${ro} title=${`${score}/${max}`}>${stars}</span>`\n }\n\n private _renderSelect(hint: InputHint, ro: boolean) {\n const options = hint.options ?? []\n return html`<select ?disabled=${ro} @change=${(e: Event) => {\n const raw = (e.target as HTMLSelectElement).value\n // 옵션의 원래 타입(숫자 등)을 보존해 방출 — 문자열 강제 방지.\n const opt = options.find(o => String(o.value) === raw)\n this._emit(raw === '' ? null : opt ? opt.value : raw)\n }}>\n <option value=\"\" ?selected=${this.value == null || this.value === ''}>-</option>\n ${options.map(\n o => html`<option value=${o.value} ?selected=${String(this.value) === String(o.value)}>${o.label}</option>`\n )}\n </select>`\n }\n}\n"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import '@material/web/icon/icon.js';
|
|
2
|
+
import { LitElement } from 'lit';
|
|
3
|
+
/**
|
|
4
|
+
* KpiMetric.meta.input(입력 위젯 힌트) 구조화 에디터.
|
|
5
|
+
*
|
|
6
|
+
* metric 관리 화면(kpi-metric-list-page)에서 팝업으로 열려 meta.input 을 편집한다.
|
|
7
|
+
* raw JSON 을 직접 만지지 않고 위젯/필드를 폼으로 구성 → 내부적으로 meta 객체 생성.
|
|
8
|
+
* meta 의 다른 키(kind/source…)는 보존하고 input 만 교체/삭제한다.
|
|
9
|
+
*
|
|
10
|
+
* - `metric-meta-save` detail:{ meta } — 저장 (widget 미선택 시 input 제거된 meta)
|
|
11
|
+
* - `metric-meta-cancel` — 취소
|
|
12
|
+
*/
|
|
13
|
+
export declare class KpiMetricMetaEditor extends LitElement {
|
|
14
|
+
static styles: import("lit").CSSResult[];
|
|
15
|
+
/** { name, meta, collectType } */
|
|
16
|
+
metric: any;
|
|
17
|
+
widget: string;
|
|
18
|
+
min: string;
|
|
19
|
+
max: string;
|
|
20
|
+
step: string;
|
|
21
|
+
decimals: string;
|
|
22
|
+
placeholder: string;
|
|
23
|
+
optionsText: string;
|
|
24
|
+
readonly: boolean;
|
|
25
|
+
required: boolean;
|
|
26
|
+
hasPlan: boolean;
|
|
27
|
+
connectedCallback(): void;
|
|
28
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
29
|
+
private _num;
|
|
30
|
+
private _buildInput;
|
|
31
|
+
/** 기존 meta 는 보존하고 input 만 교체(또는 삭제). */
|
|
32
|
+
private _buildMeta;
|
|
33
|
+
private _save;
|
|
34
|
+
private _clear;
|
|
35
|
+
private _cancel;
|
|
36
|
+
}
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import { __decorate, __metadata } from "tslib";
|
|
2
|
+
import '@material/web/icon/icon.js';
|
|
3
|
+
import { css, html, LitElement } from 'lit';
|
|
4
|
+
import { customElement, property, state } from 'lit/decorators.js';
|
|
5
|
+
import { CommonHeaderStyles } from '@operato/styles';
|
|
6
|
+
/**
|
|
7
|
+
* KpiMetric.meta.input(입력 위젯 힌트) 구조화 에디터.
|
|
8
|
+
*
|
|
9
|
+
* metric 관리 화면(kpi-metric-list-page)에서 팝업으로 열려 meta.input 을 편집한다.
|
|
10
|
+
* raw JSON 을 직접 만지지 않고 위젯/필드를 폼으로 구성 → 내부적으로 meta 객체 생성.
|
|
11
|
+
* meta 의 다른 키(kind/source…)는 보존하고 input 만 교체/삭제한다.
|
|
12
|
+
*
|
|
13
|
+
* - `metric-meta-save` detail:{ meta } — 저장 (widget 미선택 시 input 제거된 meta)
|
|
14
|
+
* - `metric-meta-cancel` — 취소
|
|
15
|
+
*/
|
|
16
|
+
let KpiMetricMetaEditor = class KpiMetricMetaEditor extends LitElement {
|
|
17
|
+
constructor() {
|
|
18
|
+
super(...arguments);
|
|
19
|
+
/** { name, meta, collectType } */
|
|
20
|
+
this.metric = {};
|
|
21
|
+
this.widget = '';
|
|
22
|
+
this.min = '';
|
|
23
|
+
this.max = '';
|
|
24
|
+
this.step = '';
|
|
25
|
+
this.decimals = '';
|
|
26
|
+
this.placeholder = '';
|
|
27
|
+
this.optionsText = '';
|
|
28
|
+
this.readonly = false;
|
|
29
|
+
this.required = false;
|
|
30
|
+
this.hasPlan = false;
|
|
31
|
+
}
|
|
32
|
+
static { this.styles = [
|
|
33
|
+
CommonHeaderStyles,
|
|
34
|
+
css `
|
|
35
|
+
:host {
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
height: 100%;
|
|
39
|
+
box-sizing: border-box;
|
|
40
|
+
width: 100%;
|
|
41
|
+
min-width: 520px;
|
|
42
|
+
font-size: 14px;
|
|
43
|
+
color: #212529;
|
|
44
|
+
}
|
|
45
|
+
/* 스크롤되는 내용부 — 버튼은 아래에 고정 (kpi-metric-value-manual-entry-form 패턴) */
|
|
46
|
+
.content {
|
|
47
|
+
flex: 1;
|
|
48
|
+
overflow-y: auto;
|
|
49
|
+
padding: 20px 24px 8px 24px;
|
|
50
|
+
}
|
|
51
|
+
h3 {
|
|
52
|
+
margin: 0 0 4px 0;
|
|
53
|
+
font-size: 15px;
|
|
54
|
+
}
|
|
55
|
+
.sub {
|
|
56
|
+
color: #6b7684;
|
|
57
|
+
margin-bottom: 14px;
|
|
58
|
+
}
|
|
59
|
+
.field {
|
|
60
|
+
display: grid;
|
|
61
|
+
grid-template-columns: 96px 1fr;
|
|
62
|
+
align-items: center;
|
|
63
|
+
gap: 8px 10px;
|
|
64
|
+
margin-bottom: 10px;
|
|
65
|
+
}
|
|
66
|
+
label {
|
|
67
|
+
color: #35618e;
|
|
68
|
+
font-weight: 500;
|
|
69
|
+
}
|
|
70
|
+
input[type='text'],
|
|
71
|
+
input[type='number'],
|
|
72
|
+
select,
|
|
73
|
+
textarea {
|
|
74
|
+
background-color: var(--input-field-background, var(--md-sys-color-surface-container-highest));
|
|
75
|
+
color: var(--input-field-color, var(--md-sys-color-on-surface));
|
|
76
|
+
width: 100%;
|
|
77
|
+
box-sizing: border-box;
|
|
78
|
+
padding: 6px 8px;
|
|
79
|
+
border: 1px solid #cdd5df;
|
|
80
|
+
border-radius: 5px;
|
|
81
|
+
font-size: 13px;
|
|
82
|
+
}
|
|
83
|
+
textarea {
|
|
84
|
+
min-height: 72px;
|
|
85
|
+
resize: vertical;
|
|
86
|
+
font-family: monospace;
|
|
87
|
+
}
|
|
88
|
+
.checks {
|
|
89
|
+
display: flex;
|
|
90
|
+
gap: 16px;
|
|
91
|
+
flex-wrap: wrap;
|
|
92
|
+
margin: 4px 0 12px 0;
|
|
93
|
+
}
|
|
94
|
+
.checks label {
|
|
95
|
+
display: inline-flex;
|
|
96
|
+
align-items: center;
|
|
97
|
+
gap: 5px;
|
|
98
|
+
color: #212529;
|
|
99
|
+
font-weight: 400;
|
|
100
|
+
}
|
|
101
|
+
.hint {
|
|
102
|
+
color: #8b95a1;
|
|
103
|
+
font-size: 11px;
|
|
104
|
+
grid-column: 2;
|
|
105
|
+
margin-top: -4px;
|
|
106
|
+
}
|
|
107
|
+
`
|
|
108
|
+
]; }
|
|
109
|
+
connectedCallback() {
|
|
110
|
+
super.connectedCallback();
|
|
111
|
+
const input = this.metric?.meta?.input || {};
|
|
112
|
+
this.widget = input.widget || '';
|
|
113
|
+
this.min = input.min !== undefined ? String(input.min) : '';
|
|
114
|
+
this.max = input.max !== undefined ? String(input.max) : '';
|
|
115
|
+
this.step = input.step !== undefined ? String(input.step) : '';
|
|
116
|
+
this.decimals = input.decimals !== undefined ? String(input.decimals) : '';
|
|
117
|
+
this.placeholder = input.placeholder || '';
|
|
118
|
+
this.optionsText = (input.options || []).map((o) => `${o.value}|${o.label ?? o.value}`).join('\n');
|
|
119
|
+
this.readonly = !!input.readonly;
|
|
120
|
+
this.required = !!input.required;
|
|
121
|
+
this.hasPlan = !!input.hasPlan;
|
|
122
|
+
}
|
|
123
|
+
render() {
|
|
124
|
+
const w = this.widget;
|
|
125
|
+
return html `
|
|
126
|
+
<div class="content">
|
|
127
|
+
<h3>입력 힌트 · ${this.metric?.name || ''}</h3>
|
|
128
|
+
<div class="sub">값 입력 화면(월별/완료평가 등)이 이 힌트로 위젯을 그립니다. 위젯을 비우면 힌트가 제거되어 숫자 입력으로 폴백합니다.</div>
|
|
129
|
+
|
|
130
|
+
<div class="field">
|
|
131
|
+
<label>위젯</label>
|
|
132
|
+
<select .value=${w} @change=${(e) => (this.widget = e.target.value)}>
|
|
133
|
+
<option value="">(자동/폴백 — 숫자)</option>
|
|
134
|
+
<option value="number" ?selected=${w === 'number'}>number — 숫자</option>
|
|
135
|
+
<option value="rating" ?selected=${w === 'rating'}>rating — 별점</option>
|
|
136
|
+
<option value="select" ?selected=${w === 'select'}>select — 선택목록</option>
|
|
137
|
+
<option value="toggle" ?selected=${w === 'toggle'}>toggle — 스위치</option>
|
|
138
|
+
<option value="text" ?selected=${w === 'text'}>text — 텍스트</option>
|
|
139
|
+
<option value="date" ?selected=${w === 'date'}>date — 날짜</option>
|
|
140
|
+
</select>
|
|
141
|
+
</div>
|
|
142
|
+
|
|
143
|
+
${w === 'number' || w === 'rating'
|
|
144
|
+
? html `
|
|
145
|
+
${w === 'number'
|
|
146
|
+
? html `<div class="field">
|
|
147
|
+
<label>최소</label>
|
|
148
|
+
<input type="number" .value=${this.min} @input=${(e) => (this.min = e.target.value)} />
|
|
149
|
+
</div>`
|
|
150
|
+
: ''}
|
|
151
|
+
<div class="field">
|
|
152
|
+
<label>최대</label>
|
|
153
|
+
<input type="number" .value=${this.max} @input=${(e) => (this.max = e.target.value)} />
|
|
154
|
+
${w === 'rating' ? html `<span class="hint">별 개수 (기본 5)</span>` : ''}
|
|
155
|
+
</div>
|
|
156
|
+
<div class="field">
|
|
157
|
+
<label>스텝</label>
|
|
158
|
+
<input type="number" .value=${this.step} @input=${(e) => (this.step = e.target.value)} />
|
|
159
|
+
${w === 'rating' ? html `<span class="hint">1=정수, 0.5=반별 (기본 1)</span>` : ''}
|
|
160
|
+
</div>
|
|
161
|
+
${w === 'number'
|
|
162
|
+
? html `<div class="field">
|
|
163
|
+
<label>소수자리</label>
|
|
164
|
+
<input type="number" .value=${this.decimals} @input=${(e) => (this.decimals = e.target.value)} />
|
|
165
|
+
</div>`
|
|
166
|
+
: ''}
|
|
167
|
+
`
|
|
168
|
+
: ''}
|
|
169
|
+
${w === 'select'
|
|
170
|
+
? html `
|
|
171
|
+
<div class="field">
|
|
172
|
+
<label>옵션</label>
|
|
173
|
+
<textarea
|
|
174
|
+
.value=${this.optionsText}
|
|
175
|
+
placeholder="한 줄에 하나: 값|표시라벨 예) 1|양호 2|보통"
|
|
176
|
+
@input=${(e) => (this.optionsText = e.target.value)}
|
|
177
|
+
></textarea>
|
|
178
|
+
<span class="hint">한 줄당 <code>값|라벨</code> (라벨 생략 시 값 사용)</span>
|
|
179
|
+
</div>
|
|
180
|
+
`
|
|
181
|
+
: ''}
|
|
182
|
+
${w === 'text'
|
|
183
|
+
? html `<div class="field">
|
|
184
|
+
<label>placeholder</label>
|
|
185
|
+
<input type="text" .value=${this.placeholder} @input=${(e) => (this.placeholder = e.target.value)} />
|
|
186
|
+
</div>`
|
|
187
|
+
: ''}
|
|
188
|
+
|
|
189
|
+
${w
|
|
190
|
+
? html `<div class="checks">
|
|
191
|
+
<label><input type="checkbox" .checked=${this.readonly} @change=${(e) => (this.readonly = e.target.checked)} /> 읽기전용</label>
|
|
192
|
+
<label><input type="checkbox" .checked=${this.required} @change=${(e) => (this.required = e.target.checked)} /> 필수</label>
|
|
193
|
+
<label><input type="checkbox" .checked=${this.hasPlan} @change=${(e) => (this.hasPlan = e.target.checked)} /> 계획/실제 2열</label>
|
|
194
|
+
</div>`
|
|
195
|
+
: ''}
|
|
196
|
+
</div>
|
|
197
|
+
|
|
198
|
+
<div class="footer">
|
|
199
|
+
${this.metric?.meta?.input
|
|
200
|
+
? html `<button danger @click=${this._clear}><md-icon>delete</md-icon>힌트 삭제</button>`
|
|
201
|
+
: ''}
|
|
202
|
+
<div filler></div>
|
|
203
|
+
<button @click=${this._cancel}><md-icon>cancel</md-icon>취소</button>
|
|
204
|
+
<button done @click=${this._save}><md-icon>done</md-icon>저장</button>
|
|
205
|
+
</div>
|
|
206
|
+
`;
|
|
207
|
+
}
|
|
208
|
+
_num(v) {
|
|
209
|
+
if (v === '' || v === null || v === undefined)
|
|
210
|
+
return undefined;
|
|
211
|
+
const n = Number(v);
|
|
212
|
+
return Number.isNaN(n) ? undefined : n;
|
|
213
|
+
}
|
|
214
|
+
_buildInput() {
|
|
215
|
+
if (!this.widget)
|
|
216
|
+
return undefined;
|
|
217
|
+
const input = { widget: this.widget };
|
|
218
|
+
if (this.widget === 'number' || this.widget === 'rating') {
|
|
219
|
+
const min = this._num(this.min);
|
|
220
|
+
const max = this._num(this.max);
|
|
221
|
+
const step = this._num(this.step);
|
|
222
|
+
const decimals = this._num(this.decimals);
|
|
223
|
+
if (this.widget === 'number' && min !== undefined)
|
|
224
|
+
input.min = min;
|
|
225
|
+
if (max !== undefined)
|
|
226
|
+
input.max = max;
|
|
227
|
+
if (step !== undefined)
|
|
228
|
+
input.step = step;
|
|
229
|
+
if (this.widget === 'number' && decimals !== undefined)
|
|
230
|
+
input.decimals = decimals;
|
|
231
|
+
}
|
|
232
|
+
if (this.widget === 'select') {
|
|
233
|
+
const options = this.optionsText
|
|
234
|
+
.split('\n')
|
|
235
|
+
.map(line => line.trim())
|
|
236
|
+
.filter(Boolean)
|
|
237
|
+
.map(line => {
|
|
238
|
+
const [value, label] = line.split('|').map(s => s.trim());
|
|
239
|
+
return { value, label: label || value };
|
|
240
|
+
});
|
|
241
|
+
if (options.length)
|
|
242
|
+
input.options = options;
|
|
243
|
+
}
|
|
244
|
+
if (this.widget === 'text' && this.placeholder)
|
|
245
|
+
input.placeholder = this.placeholder;
|
|
246
|
+
if (this.readonly)
|
|
247
|
+
input.readonly = true;
|
|
248
|
+
if (this.required)
|
|
249
|
+
input.required = true;
|
|
250
|
+
if (this.hasPlan)
|
|
251
|
+
input.hasPlan = true;
|
|
252
|
+
return input;
|
|
253
|
+
}
|
|
254
|
+
/** 기존 meta 는 보존하고 input 만 교체(또는 삭제). */
|
|
255
|
+
_buildMeta() {
|
|
256
|
+
const rest = { ...(this.metric?.meta || {}) };
|
|
257
|
+
delete rest.input;
|
|
258
|
+
const input = this._buildInput();
|
|
259
|
+
const meta = input ? { ...rest, input } : rest;
|
|
260
|
+
return Object.keys(meta).length ? meta : null;
|
|
261
|
+
}
|
|
262
|
+
_save() {
|
|
263
|
+
this.dispatchEvent(new CustomEvent('metric-meta-save', { detail: { meta: this._buildMeta() }, bubbles: true, composed: true }));
|
|
264
|
+
}
|
|
265
|
+
_clear() {
|
|
266
|
+
this.widget = '';
|
|
267
|
+
this.dispatchEvent(new CustomEvent('metric-meta-save', { detail: { meta: this._buildMeta() }, bubbles: true, composed: true }));
|
|
268
|
+
}
|
|
269
|
+
_cancel() {
|
|
270
|
+
this.dispatchEvent(new CustomEvent('metric-meta-cancel', { bubbles: true, composed: true }));
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
__decorate([
|
|
274
|
+
property({ type: Object }),
|
|
275
|
+
__metadata("design:type", Object)
|
|
276
|
+
], KpiMetricMetaEditor.prototype, "metric", void 0);
|
|
277
|
+
__decorate([
|
|
278
|
+
state(),
|
|
279
|
+
__metadata("design:type", Object)
|
|
280
|
+
], KpiMetricMetaEditor.prototype, "widget", void 0);
|
|
281
|
+
__decorate([
|
|
282
|
+
state(),
|
|
283
|
+
__metadata("design:type", Object)
|
|
284
|
+
], KpiMetricMetaEditor.prototype, "min", void 0);
|
|
285
|
+
__decorate([
|
|
286
|
+
state(),
|
|
287
|
+
__metadata("design:type", Object)
|
|
288
|
+
], KpiMetricMetaEditor.prototype, "max", void 0);
|
|
289
|
+
__decorate([
|
|
290
|
+
state(),
|
|
291
|
+
__metadata("design:type", Object)
|
|
292
|
+
], KpiMetricMetaEditor.prototype, "step", void 0);
|
|
293
|
+
__decorate([
|
|
294
|
+
state(),
|
|
295
|
+
__metadata("design:type", Object)
|
|
296
|
+
], KpiMetricMetaEditor.prototype, "decimals", void 0);
|
|
297
|
+
__decorate([
|
|
298
|
+
state(),
|
|
299
|
+
__metadata("design:type", Object)
|
|
300
|
+
], KpiMetricMetaEditor.prototype, "placeholder", void 0);
|
|
301
|
+
__decorate([
|
|
302
|
+
state(),
|
|
303
|
+
__metadata("design:type", Object)
|
|
304
|
+
], KpiMetricMetaEditor.prototype, "optionsText", void 0);
|
|
305
|
+
__decorate([
|
|
306
|
+
state(),
|
|
307
|
+
__metadata("design:type", Object)
|
|
308
|
+
], KpiMetricMetaEditor.prototype, "readonly", void 0);
|
|
309
|
+
__decorate([
|
|
310
|
+
state(),
|
|
311
|
+
__metadata("design:type", Object)
|
|
312
|
+
], KpiMetricMetaEditor.prototype, "required", void 0);
|
|
313
|
+
__decorate([
|
|
314
|
+
state(),
|
|
315
|
+
__metadata("design:type", Object)
|
|
316
|
+
], KpiMetricMetaEditor.prototype, "hasPlan", void 0);
|
|
317
|
+
KpiMetricMetaEditor = __decorate([
|
|
318
|
+
customElement('kpi-metric-meta-editor')
|
|
319
|
+
], KpiMetricMetaEditor);
|
|
320
|
+
export { KpiMetricMetaEditor };
|
|
321
|
+
//# sourceMappingURL=kpi-metric-meta-editor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kpi-metric-meta-editor.js","sourceRoot":"","sources":["../../client/viewparts/kpi-metric-meta-editor.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { CommonHeaderStyles } from '@operato/styles'\n\n/**\n * KpiMetric.meta.input(입력 위젯 힌트) 구조화 에디터.\n *\n * metric 관리 화면(kpi-metric-list-page)에서 팝업으로 열려 meta.input 을 편집한다.\n * raw JSON 을 직접 만지지 않고 위젯/필드를 폼으로 구성 → 내부적으로 meta 객체 생성.\n * meta 의 다른 키(kind/source…)는 보존하고 input 만 교체/삭제한다.\n *\n * - `metric-meta-save` detail:{ meta } — 저장 (widget 미선택 시 input 제거된 meta)\n * - `metric-meta-cancel` — 취소\n */\n@customElement('kpi-metric-meta-editor')\nexport class KpiMetricMetaEditor extends LitElement {\n static styles = [\n CommonHeaderStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n box-sizing: border-box;\n width: 100%;\n min-width: 520px;\n font-size: 14px;\n color: #212529;\n }\n /* 스크롤되는 내용부 — 버튼은 아래에 고정 (kpi-metric-value-manual-entry-form 패턴) */\n .content {\n flex: 1;\n overflow-y: auto;\n padding: 20px 24px 8px 24px;\n }\n h3 {\n margin: 0 0 4px 0;\n font-size: 15px;\n }\n .sub {\n color: #6b7684;\n margin-bottom: 14px;\n }\n .field {\n display: grid;\n grid-template-columns: 96px 1fr;\n align-items: center;\n gap: 8px 10px;\n margin-bottom: 10px;\n }\n label {\n color: #35618e;\n font-weight: 500;\n }\n input[type='text'],\n input[type='number'],\n select,\n textarea {\n background-color: var(--input-field-background, var(--md-sys-color-surface-container-highest));\n color: var(--input-field-color, var(--md-sys-color-on-surface));\n width: 100%;\n box-sizing: border-box;\n padding: 6px 8px;\n border: 1px solid #cdd5df;\n border-radius: 5px;\n font-size: 13px;\n }\n textarea {\n min-height: 72px;\n resize: vertical;\n font-family: monospace;\n }\n .checks {\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n margin: 4px 0 12px 0;\n }\n .checks label {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n color: #212529;\n font-weight: 400;\n }\n .hint {\n color: #8b95a1;\n font-size: 11px;\n grid-column: 2;\n margin-top: -4px;\n }\n `\n ]\n\n /** { name, meta, collectType } */\n @property({ type: Object }) metric: any = {}\n\n @state() widget = ''\n @state() min = ''\n @state() max = ''\n @state() step = ''\n @state() decimals = ''\n @state() placeholder = ''\n @state() optionsText = ''\n @state() readonly = false\n @state() required = false\n @state() hasPlan = false\n\n connectedCallback() {\n super.connectedCallback()\n const input = this.metric?.meta?.input || {}\n this.widget = input.widget || ''\n this.min = input.min !== undefined ? String(input.min) : ''\n this.max = input.max !== undefined ? String(input.max) : ''\n this.step = input.step !== undefined ? String(input.step) : ''\n this.decimals = input.decimals !== undefined ? String(input.decimals) : ''\n this.placeholder = input.placeholder || ''\n this.optionsText = (input.options || []).map((o: any) => `${o.value}|${o.label ?? o.value}`).join('\\n')\n this.readonly = !!input.readonly\n this.required = !!input.required\n this.hasPlan = !!input.hasPlan\n }\n\n render() {\n const w = this.widget\n return html`\n <div class=\"content\">\n <h3>입력 힌트 · ${this.metric?.name || ''}</h3>\n <div class=\"sub\">값 입력 화면(월별/완료평가 등)이 이 힌트로 위젯을 그립니다. 위젯을 비우면 힌트가 제거되어 숫자 입력으로 폴백합니다.</div>\n\n <div class=\"field\">\n <label>위젯</label>\n <select .value=${w} @change=${(e: any) => (this.widget = e.target.value)}>\n <option value=\"\">(자동/폴백 — 숫자)</option>\n <option value=\"number\" ?selected=${w === 'number'}>number — 숫자</option>\n <option value=\"rating\" ?selected=${w === 'rating'}>rating — 별점</option>\n <option value=\"select\" ?selected=${w === 'select'}>select — 선택목록</option>\n <option value=\"toggle\" ?selected=${w === 'toggle'}>toggle — 스위치</option>\n <option value=\"text\" ?selected=${w === 'text'}>text — 텍스트</option>\n <option value=\"date\" ?selected=${w === 'date'}>date — 날짜</option>\n </select>\n </div>\n\n ${w === 'number' || w === 'rating'\n ? html`\n ${w === 'number'\n ? html`<div class=\"field\">\n <label>최소</label>\n <input type=\"number\" .value=${this.min} @input=${(e: any) => (this.min = e.target.value)} />\n </div>`\n : ''}\n <div class=\"field\">\n <label>최대</label>\n <input type=\"number\" .value=${this.max} @input=${(e: any) => (this.max = e.target.value)} />\n ${w === 'rating' ? html`<span class=\"hint\">별 개수 (기본 5)</span>` : ''}\n </div>\n <div class=\"field\">\n <label>스텝</label>\n <input type=\"number\" .value=${this.step} @input=${(e: any) => (this.step = e.target.value)} />\n ${w === 'rating' ? html`<span class=\"hint\">1=정수, 0.5=반별 (기본 1)</span>` : ''}\n </div>\n ${w === 'number'\n ? html`<div class=\"field\">\n <label>소수자리</label>\n <input type=\"number\" .value=${this.decimals} @input=${(e: any) => (this.decimals = e.target.value)} />\n </div>`\n : ''}\n `\n : ''}\n ${w === 'select'\n ? html`\n <div class=\"field\">\n <label>옵션</label>\n <textarea\n .value=${this.optionsText}\n placeholder=\"한 줄에 하나: 값|표시라벨 예) 1|양호 2|보통\"\n @input=${(e: any) => (this.optionsText = e.target.value)}\n ></textarea>\n <span class=\"hint\">한 줄당 <code>값|라벨</code> (라벨 생략 시 값 사용)</span>\n </div>\n `\n : ''}\n ${w === 'text'\n ? html`<div class=\"field\">\n <label>placeholder</label>\n <input type=\"text\" .value=${this.placeholder} @input=${(e: any) => (this.placeholder = e.target.value)} />\n </div>`\n : ''}\n\n ${w\n ? html`<div class=\"checks\">\n <label><input type=\"checkbox\" .checked=${this.readonly} @change=${(e: any) => (this.readonly = e.target.checked)} /> 읽기전용</label>\n <label><input type=\"checkbox\" .checked=${this.required} @change=${(e: any) => (this.required = e.target.checked)} /> 필수</label>\n <label><input type=\"checkbox\" .checked=${this.hasPlan} @change=${(e: any) => (this.hasPlan = e.target.checked)} /> 계획/실제 2열</label>\n </div>`\n : ''}\n </div>\n\n <div class=\"footer\">\n ${this.metric?.meta?.input\n ? html`<button danger @click=${this._clear}><md-icon>delete</md-icon>힌트 삭제</button>`\n : ''}\n <div filler></div>\n <button @click=${this._cancel}><md-icon>cancel</md-icon>취소</button>\n <button done @click=${this._save}><md-icon>done</md-icon>저장</button>\n </div>\n `\n }\n\n private _num(v: string): number | undefined {\n if (v === '' || v === null || v === undefined) return undefined\n const n = Number(v)\n return Number.isNaN(n) ? undefined : n\n }\n\n private _buildInput(): any {\n if (!this.widget) return undefined\n const input: any = { widget: this.widget }\n\n if (this.widget === 'number' || this.widget === 'rating') {\n const min = this._num(this.min)\n const max = this._num(this.max)\n const step = this._num(this.step)\n const decimals = this._num(this.decimals)\n if (this.widget === 'number' && min !== undefined) input.min = min\n if (max !== undefined) input.max = max\n if (step !== undefined) input.step = step\n if (this.widget === 'number' && decimals !== undefined) input.decimals = decimals\n }\n\n if (this.widget === 'select') {\n const options = this.optionsText\n .split('\\n')\n .map(line => line.trim())\n .filter(Boolean)\n .map(line => {\n const [value, label] = line.split('|').map(s => s.trim())\n return { value, label: label || value }\n })\n if (options.length) input.options = options\n }\n\n if (this.widget === 'text' && this.placeholder) input.placeholder = this.placeholder\n\n if (this.readonly) input.readonly = true\n if (this.required) input.required = true\n if (this.hasPlan) input.hasPlan = true\n\n return input\n }\n\n /** 기존 meta 는 보존하고 input 만 교체(또는 삭제). */\n private _buildMeta(): any {\n const rest = { ...(this.metric?.meta || {}) }\n delete rest.input\n const input = this._buildInput()\n const meta = input ? { ...rest, input } : rest\n return Object.keys(meta).length ? meta : null\n }\n\n private _save() {\n this.dispatchEvent(\n new CustomEvent('metric-meta-save', { detail: { meta: this._buildMeta() }, bubbles: true, composed: true })\n )\n }\n\n private _clear() {\n this.widget = ''\n this.dispatchEvent(\n new CustomEvent('metric-meta-save', { detail: { meta: this._buildMeta() }, bubbles: true, composed: true })\n )\n }\n\n private _cancel() {\n this.dispatchEvent(new CustomEvent('metric-meta-cancel', { bubbles: true, composed: true }))\n }\n}\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type InputWidget = 'number' | 'rating' | 'select' | 'date' | 'text' | 'toggle';
|
|
2
|
+
export interface InputHint {
|
|
3
|
+
widget: InputWidget;
|
|
4
|
+
min?: number;
|
|
5
|
+
max?: number;
|
|
6
|
+
step?: number;
|
|
7
|
+
options?: {
|
|
8
|
+
value: string | number;
|
|
9
|
+
label: string;
|
|
10
|
+
}[];
|
|
11
|
+
required?: boolean;
|
|
12
|
+
decimals?: number;
|
|
13
|
+
readonly?: boolean;
|
|
14
|
+
hasPlan?: boolean;
|
|
15
|
+
placeholder?: string;
|
|
16
|
+
default?: any;
|
|
17
|
+
}
|
|
18
|
+
export interface KpiMetricLike {
|
|
19
|
+
meta?: {
|
|
20
|
+
input?: InputHint;
|
|
21
|
+
[k: string]: any;
|
|
22
|
+
} | null;
|
|
23
|
+
collectType?: string;
|
|
24
|
+
}
|
|
25
|
+
/** meta.input 우선, 없으면 number 폴백(이름추측 금지). readonly 는 명시값 우선, 미지정+AUTO 면 true. */
|
|
26
|
+
export declare function resolveInputHint(metric: KpiMetricLike | null | undefined): InputHint;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// 클라이언트용 InputHint 타입 + resolveInputHint.
|
|
2
|
+
//
|
|
3
|
+
// ⚠️ 원본(진실의 원천): server/service/kpi-metric/kpi-metric-meta.ts
|
|
4
|
+
// client/server tsconfig 가 분리되어 server 를 import 할 수 없어 동형 복제한다.
|
|
5
|
+
// 변경 시 양쪽을 함께 수정할 것.
|
|
6
|
+
/** meta.input 우선, 없으면 number 폴백(이름추측 금지). readonly 는 명시값 우선, 미지정+AUTO 면 true. */
|
|
7
|
+
export function resolveInputHint(metric) {
|
|
8
|
+
const isAuto = metric?.collectType === 'AUTO';
|
|
9
|
+
const hint = metric?.meta?.input;
|
|
10
|
+
if (hint?.widget) {
|
|
11
|
+
const readonly = hint.readonly ?? isAuto;
|
|
12
|
+
if (hint.widget === 'rating') {
|
|
13
|
+
return { ...hint, max: hint.max ?? 5, step: hint.step ?? 1, readonly };
|
|
14
|
+
}
|
|
15
|
+
return { ...hint, readonly };
|
|
16
|
+
}
|
|
17
|
+
return { widget: 'number', readonly: isAuto };
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=metric-input-hint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metric-input-hint.js","sourceRoot":"","sources":["../../client/viewparts/metric-input-hint.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,EAAE;AACF,8DAA8D;AAC9D,mEAAmE;AACnE,wBAAwB;AAuBxB,iFAAiF;AACjF,MAAM,UAAU,gBAAgB,CAAC,MAAwC;IACvE,MAAM,MAAM,GAAG,MAAM,EAAE,WAAW,KAAK,MAAM,CAAA;IAC7C,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,EAAE,KAAK,CAAA;IAEhC,IAAI,IAAI,EAAE,MAAM,EAAE,CAAC;QACjB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAA;QACxC,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC7B,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAA;QACxE,CAAC;QACD,OAAO,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAA;IAC9B,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAA;AAC/C,CAAC","sourcesContent":["// 클라이언트용 InputHint 타입 + resolveInputHint.\n//\n// ⚠️ 원본(진실의 원천): server/service/kpi-metric/kpi-metric-meta.ts\n// client/server tsconfig 가 분리되어 server 를 import 할 수 없어 동형 복제한다.\n// 변경 시 양쪽을 함께 수정할 것.\n\nexport type InputWidget = 'number' | 'rating' | 'select' | 'date' | 'text' | 'toggle'\n\nexport interface InputHint {\n widget: InputWidget\n min?: number\n max?: number\n step?: number\n options?: { value: string | number; label: string }[]\n required?: boolean\n decimals?: number\n readonly?: boolean\n hasPlan?: boolean\n placeholder?: string\n default?: any\n}\n\nexport interface KpiMetricLike {\n meta?: { input?: InputHint; [k: string]: any } | null\n collectType?: string\n}\n\n/** meta.input 우선, 없으면 number 폴백(이름추측 금지). readonly 는 명시값 우선, 미지정+AUTO 면 true. */\nexport function resolveInputHint(metric: KpiMetricLike | null | undefined): InputHint {\n const isAuto = metric?.collectType === 'AUTO'\n const hint = metric?.meta?.input\n\n if (hint?.widget) {\n const readonly = hint.readonly ?? isAuto\n if (hint.widget === 'rating') {\n return { ...hint, max: hint.max ?? 5, step: hint.step ?? 1, readonly }\n }\n return { ...hint, readonly }\n }\n return { widget: 'number', readonly: isAuto }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { resolveInputHint } from './metric-input-hint';
|
|
2
|
+
import { MetricRendererRegistry } from './metric-renderer-registry';
|
|
3
|
+
describe('resolveInputHint (client copy)', () => {
|
|
4
|
+
it('meta 없음 → number 폴백', () => {
|
|
5
|
+
expect(resolveInputHint(null)).toEqual({ widget: 'number', readonly: false });
|
|
6
|
+
expect(resolveInputHint({ collectType: 'AUTO' })).toEqual({ widget: 'number', readonly: true });
|
|
7
|
+
});
|
|
8
|
+
it('rating 기본값(max 5, step 1)', () => {
|
|
9
|
+
expect(resolveInputHint({ meta: { input: { widget: 'rating' } } })).toEqual({
|
|
10
|
+
widget: 'rating',
|
|
11
|
+
max: 5,
|
|
12
|
+
step: 1,
|
|
13
|
+
readonly: false
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
it('readonly 명시 false 는 AUTO 라도 존중', () => {
|
|
17
|
+
expect(resolveInputHint({ collectType: 'AUTO', meta: { input: { widget: 'number', readonly: false } } }).readonly).toBe(false);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
describe('MetricRendererRegistry', () => {
|
|
21
|
+
const dummy = () => null;
|
|
22
|
+
beforeEach(() => MetricRendererRegistry.clear());
|
|
23
|
+
it('매칭 없으면 undefined (→ 제네릭)', () => {
|
|
24
|
+
expect(MetricRendererRegistry.resolve({ meta: {} })).toBeUndefined();
|
|
25
|
+
});
|
|
26
|
+
it('predicate 매칭 시 렌더러 반환, 먼저 등록된 것 우선', () => {
|
|
27
|
+
const r1 = () => 'r1';
|
|
28
|
+
const r2 = () => 'r2';
|
|
29
|
+
MetricRendererRegistry.register((m) => m.name === 'X', r1);
|
|
30
|
+
MetricRendererRegistry.register((m) => m.name === 'X', r2);
|
|
31
|
+
expect(MetricRendererRegistry.resolve({ name: 'X' })).toBe(r1);
|
|
32
|
+
expect(MetricRendererRegistry.resolve({ name: 'Y' })).toBeUndefined();
|
|
33
|
+
});
|
|
34
|
+
it('predicate 예외는 매칭 실패로 처리(다음으로 진행)', () => {
|
|
35
|
+
MetricRendererRegistry.register(() => {
|
|
36
|
+
throw new Error('boom');
|
|
37
|
+
}, dummy);
|
|
38
|
+
const ok = () => 'ok';
|
|
39
|
+
MetricRendererRegistry.register((m) => m.name === 'Z', ok);
|
|
40
|
+
expect(MetricRendererRegistry.resolve({ name: 'Z' })).toBe(ok);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
//# sourceMappingURL=metric-input.test.js.map
|