@things-factory/kpi 9.0.31 → 9.0.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- package/client/charts/kpi-boxplot-chart.ts +182 -42
- package/client/charts/kpi-radar-chart.ts +9 -9
- package/client/pages/kpi/kpi-list-page.ts +196 -32
- package/client/pages/kpi/kpi-overview.ts +9 -11
- package/client/pages/kpi/kpi-tree-page.ts +409 -0
- package/client/pages/kpi/kpi-view.ts +187 -0
- package/client/pages/kpi-dashboard/cards/kpi-level1-card.ts +1 -1
- package/client/pages/kpi-dashboard/cards/kpi-level2-comparison.ts +1 -1
- package/client/pages/kpi-dashboard/cards/kpi-level3-comparison.ts +1 -1
- package/client/pages/kpi-dashboard/components/kpi-left-panel.ts +198 -160
- package/client/pages/kpi-dashboard/components/kpi-map-panel.ts +133 -0
- package/client/pages/kpi-dashboard/components/kpi-region-popup.ts +3 -2
- package/client/pages/kpi-dashboard/kpi-dashboard-map.ts +4 -3
- package/client/pages/kpi-dashboard/kpi-dashboard.ts +28 -30
- package/client/pages/kpi-history/kpi-history-list-page.ts +11 -11
- package/client/pages/kpi-metric/kpi-metric-list-page.ts +10 -2
- package/client/pages/kpi-metric-value/kpi-metric-value-editor-page.ts +7 -7
- package/client/pages/kpi-metric-value/kpi-metric-value-importer.ts +2 -2
- package/client/pages/kpi-metric-value/kpi-metric-value-list-page.ts +16 -8
- package/client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.ts +5 -5
- package/client/pages/kpi-statistic/kpi-statistic-editor-page.ts +1 -2
- package/client/pages/kpi-statistic/kpi-statistic-list-page.ts +10 -2
- package/client/pages/kpi-value/kpi-value-editor-page.ts +11 -7
- package/client/pages/kpi-value/kpi-value-list-page.ts +31 -7
- package/client/route.ts +2 -9
- package/design-entities.md +8 -12
- package/dist-client/charts/kpi-boxplot-chart.d.ts +2 -0
- package/dist-client/charts/kpi-boxplot-chart.js +168 -42
- package/dist-client/charts/kpi-boxplot-chart.js.map +1 -1
- package/dist-client/charts/kpi-radar-chart.js +9 -9
- package/dist-client/charts/kpi-radar-chart.js.map +1 -1
- package/dist-client/pages/kpi/kpi-list-page.d.ts +19 -3
- package/dist-client/pages/kpi/kpi-list-page.js +188 -32
- package/dist-client/pages/kpi/kpi-list-page.js.map +1 -1
- package/dist-client/pages/kpi/kpi-overview.js +9 -11
- package/dist-client/pages/kpi/kpi-overview.js.map +1 -1
- package/dist-client/pages/kpi/kpi-tree-page.d.ts +59 -0
- package/dist-client/pages/kpi/kpi-tree-page.js +403 -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 +191 -0
- package/dist-client/pages/kpi/kpi-view.js.map +1 -0
- package/dist-client/pages/kpi-dashboard/cards/kpi-level1-card.js +1 -1
- package/dist-client/pages/kpi-dashboard/cards/kpi-level1-card.js.map +1 -1
- package/dist-client/pages/kpi-dashboard/cards/kpi-level2-comparison.js +1 -1
- package/dist-client/pages/kpi-dashboard/cards/kpi-level2-comparison.js.map +1 -1
- package/dist-client/pages/kpi-dashboard/cards/kpi-level3-comparison.js +1 -1
- package/dist-client/pages/kpi-dashboard/cards/kpi-level3-comparison.js.map +1 -1
- package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.d.ts +3 -1
- package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.js +197 -161
- package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.js.map +1 -1
- package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.d.ts +5 -0
- package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js +146 -0
- package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js.map +1 -1
- package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.js +3 -2
- package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.js.map +1 -1
- package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js +4 -3
- package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js.map +1 -1
- package/dist-client/pages/kpi-dashboard/kpi-dashboard.js +28 -30
- package/dist-client/pages/kpi-dashboard/kpi-dashboard.js.map +1 -1
- package/dist-client/pages/kpi-history/kpi-history-list-page.d.ts +6 -1
- package/dist-client/pages/kpi-history/kpi-history-list-page.js +11 -11
- package/dist-client/pages/kpi-history/kpi-history-list-page.js.map +1 -1
- package/dist-client/pages/kpi-metric/kpi-metric-list-page.d.ts +5 -0
- package/dist-client/pages/kpi-metric/kpi-metric-list-page.js +10 -2
- package/dist-client/pages/kpi-metric/kpi-metric-list-page.js.map +1 -1
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.d.ts +1 -1
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.js +8 -8
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.js.map +1 -1
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.js +2 -2
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.js.map +1 -1
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.d.ts +5 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js +16 -8
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js.map +1 -1
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.d.ts +1 -1
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.js +6 -6
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.js.map +1 -1
- package/dist-client/pages/kpi-statistic/kpi-statistic-editor-page.js +1 -2
- package/dist-client/pages/kpi-statistic/kpi-statistic-editor-page.js.map +1 -1
- package/dist-client/pages/kpi-statistic/kpi-statistic-list-page.d.ts +5 -0
- package/dist-client/pages/kpi-statistic/kpi-statistic-list-page.js +10 -2
- package/dist-client/pages/kpi-statistic/kpi-statistic-list-page.js.map +1 -1
- package/dist-client/pages/kpi-value/kpi-value-editor-page.d.ts +2 -1
- package/dist-client/pages/kpi-value/kpi-value-editor-page.js +16 -8
- package/dist-client/pages/kpi-value/kpi-value-editor-page.js.map +1 -1
- package/dist-client/pages/kpi-value/kpi-value-list-page.d.ts +5 -0
- package/dist-client/pages/kpi-value/kpi-value-list-page.js +31 -7
- package/dist-client/pages/kpi-value/kpi-value-list-page.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/route.js +2 -8
- package/dist-client/route.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/controllers/kpi-metric-value-provider.d.ts +1 -1
- package/dist-server/controllers/kpi-metric-value-provider.js +4 -4
- package/dist-server/controllers/kpi-metric-value-provider.js.map +1 -1
- package/dist-server/controllers/kpi-value-provider.d.ts +1 -1
- package/dist-server/controllers/kpi-value-provider.js +3 -3
- package/dist-server/controllers/kpi-value-provider.js.map +1 -1
- package/dist-server/migrations/1752190849680-seed-kpi-metrics.d.ts +6 -0
- package/dist-server/migrations/1752190849680-seed-kpi-metrics.js +101 -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/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/seed-data/kpi-metrics-seed.json +454 -0
- package/dist-server/migrations/seed-data/kpi-org-scope-seed.json +1676 -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/service/index.d.ts +3 -7
- package/dist-server/service/index.js +5 -12
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/kpi/aggregate-kpi.js +30 -13
- package/dist-server/service/kpi/aggregate-kpi.js.map +1 -1
- package/dist-server/service/kpi/kpi-formula.service.d.ts +15 -0
- package/dist-server/service/kpi/kpi-formula.service.js +90 -0
- package/dist-server/service/kpi/kpi-formula.service.js.map +1 -1
- package/dist-server/service/kpi/kpi-history.d.ts +0 -3
- package/dist-server/service/kpi/kpi-history.js +0 -10
- package/dist-server/service/kpi/kpi-history.js.map +1 -1
- package/dist-server/service/kpi/kpi-mutation.d.ts +1 -1
- package/dist-server/service/kpi/kpi-mutation.js +57 -20
- package/dist-server/service/kpi/kpi-mutation.js.map +1 -1
- package/dist-server/service/kpi/kpi-query.d.ts +7 -3
- package/dist-server/service/kpi/kpi-query.js +126 -10
- package/dist-server/service/kpi/kpi-query.js.map +1 -1
- package/dist-server/service/kpi/kpi-type.d.ts +4 -2
- package/dist-server/service/kpi/kpi-type.js +12 -4
- package/dist-server/service/kpi/kpi-type.js.map +1 -1
- package/dist-server/service/kpi/kpi.d.ts +4 -3
- package/dist-server/service/kpi/kpi.js +20 -8
- package/dist-server/service/kpi/kpi.js.map +1 -1
- package/dist-server/service/kpi-metric/aggregate-kpi-metric.js +46 -11
- package/dist-server/service/kpi-metric/aggregate-kpi-metric.js.map +1 -1
- package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.d.ts +1 -1
- package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js +6 -6
- package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js.map +1 -1
- package/dist-server/service/kpi-metric-value/kpi-metric-value-type.d.ts +2 -2
- package/dist-server/service/kpi-metric-value/kpi-metric-value-type.js +4 -4
- package/dist-server/service/kpi-metric-value/kpi-metric-value-type.js.map +1 -1
- package/dist-server/service/kpi-metric-value/kpi-metric-value.d.ts +1 -1
- package/dist-server/service/kpi-metric-value/kpi-metric-value.js +3 -3
- package/dist-server/service/kpi-metric-value/kpi-metric-value.js.map +1 -1
- package/dist-server/service/kpi-org-scope/index.d.ts +9 -0
- package/dist-server/service/kpi-org-scope/index.js +14 -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-statistic/kpi-statistic.d.ts +1 -0
- package/dist-server/service/kpi-statistic/kpi-statistic.js +11 -0
- package/dist-server/service/kpi-statistic/kpi-statistic.js.map +1 -1
- package/dist-server/service/kpi-value/kpi-value-mutation.js +71 -7
- package/dist-server/service/kpi-value/kpi-value-mutation.js.map +1 -1
- package/dist-server/service/kpi-value/kpi-value-type.d.ts +4 -2
- package/dist-server/service/kpi-value/kpi-value-type.js +12 -4
- package/dist-server/service/kpi-value/kpi-value-type.js.map +1 -1
- package/dist-server/service/kpi-value/kpi-value.d.ts +3 -1
- package/dist-server/service/kpi-value/kpi-value.js +11 -5
- package/dist-server/service/kpi-value/kpi-value.js.map +1 -1
- package/dist-server/service/utils/value-date-util.d.ts +1 -0
- package/dist-server/service/utils/value-date-util.js +41 -0
- package/dist-server/service/utils/value-date-util.js.map +1 -1
- package/dist-server/tsconfig.json +10 -0
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -6
- package/server/@types/index.d.ts +11 -0
- package/server/controllers/kpi-metric-value-provider.ts +5 -5
- package/server/controllers/kpi-value-provider.ts +4 -4
- package/server/migrations/1752190849680-seed-kpi-metrics.ts +124 -0
- package/server/migrations/1752190849681-seed-kpi.ts +356 -0
- package/server/migrations/1752192090123-add-grades-to-kpi.ts +67 -0
- package/server/migrations/1752192090124-add-kpi-statistics.ts +719 -0
- package/server/migrations/1752192090128-seed-kpi-org-scope.ts +132 -0
- package/server/migrations/1752192090129-seed-kpi-values.ts +207 -0
- package/server/migrations/grade-data/x11-performance-table.json +962 -0
- package/server/migrations/grade-data/x12-performance-table.json +611 -0
- package/server/migrations/grade-data/x14-performance-table.json +42 -0
- package/server/migrations/grade-data/x21-performance-table.json +889 -0
- package/server/migrations/grade-data/x22-performance-table.json +1064 -0
- package/server/migrations/grade-data/x23-performance-table.json +42 -0
- package/server/migrations/grade-data/x31-performance-table.json +644 -0
- package/server/migrations/grade-data/x32-performance-table.json +993 -0
- package/server/migrations/grade-data/x33-performance-table.json +195 -0
- package/server/migrations/grade-data/x34-performance-table.json +12 -0
- package/server/migrations/grade-data/x35-performance-table.json +42 -0
- package/server/migrations/grade-data/x41-performance-table.json +825 -0
- package/server/migrations/grade-data/x42-performance-table.json +786 -0
- package/server/migrations/grade-data/x43-performance-table.json +12 -0
- package/server/migrations/grade-data/x44-performance-table.json +42 -0
- package/server/migrations/grade-data/x51-performance-table.json +924 -0
- package/server/migrations/grade-data/x52-performance-table.json +42 -0
- package/server/migrations/grade-data/x61-performance-table.json +261 -0
- package/server/migrations/grade-data/x62-performance-table.json +42 -0
- package/server/migrations/seed-data/kpi-metrics-seed.json +454 -0
- package/server/migrations/seed-data/kpi-org-scope-seed.json +1676 -0
- package/server/migrations/seed-data/kpi-values-seed.json +402 -0
- package/server/migrations/seed-data/kpis-seed.json +488 -0
- package/server/service/index.ts +5 -12
- package/server/service/kpi/aggregate-kpi.ts +31 -13
- package/server/service/kpi/kpi-formula.service.ts +101 -0
- package/server/service/kpi/kpi-history.ts +0 -8
- package/server/service/kpi/kpi-mutation.ts +59 -19
- package/server/service/kpi/kpi-query.ts +118 -8
- package/server/service/kpi/kpi-type.ts +10 -4
- package/server/service/kpi/kpi.ts +17 -7
- package/server/service/kpi-metric/aggregate-kpi-metric.ts +55 -11
- package/server/service/kpi-metric-value/kpi-metric-value-mutation.ts +6 -6
- package/server/service/kpi-metric-value/kpi-metric-value-type.ts +4 -4
- package/server/service/kpi-metric-value/kpi-metric-value.ts +3 -3
- package/server/service/kpi-org-scope/index.ts +11 -0
- package/server/service/kpi-org-scope/kpi-org-scope-mutation.ts +173 -0
- package/server/service/kpi-org-scope/kpi-org-scope-query.ts +127 -0
- package/server/service/kpi-org-scope/kpi-org-scope-type.ts +68 -0
- package/server/service/kpi-org-scope/kpi-org-scope.ts +123 -0
- package/server/service/kpi-statistic/kpi-statistic.ts +10 -0
- package/server/service/kpi-value/kpi-value-mutation.ts +73 -7
- package/server/service/kpi-value/kpi-value-type.ts +10 -4
- package/server/service/kpi-value/kpi-value.ts +10 -5
- package/server/service/utils/value-date-util.ts +47 -0
- package/server/types/global.d.ts +8 -0
- package/things-factory.config.js +1 -0
- package/translations/en.json +15 -3
- package/translations/ja.json +13 -3
- package/translations/ko.json +15 -3
- package/translations/ms.json +13 -3
- package/translations/zh.json +13 -3
- package/client/pages/kpi-category/kpi-category-importer.ts +0 -90
- package/client/pages/kpi-category/kpi-category-list-page.ts +0 -537
- package/client/pages/kpi-category/kpi-category-value-calculator.ts +0 -233
- package/client/pages/kpi-category-value/kpi-category-value-list-page.ts +0 -404
- package/dist-client/pages/kpi-category/kpi-category-importer.d.ts +0 -23
- package/dist-client/pages/kpi-category/kpi-category-importer.js +0 -92
- package/dist-client/pages/kpi-category/kpi-category-importer.js.map +0 -1
- package/dist-client/pages/kpi-category/kpi-category-list-page.d.ts +0 -74
- package/dist-client/pages/kpi-category/kpi-category-list-page.js +0 -517
- package/dist-client/pages/kpi-category/kpi-category-list-page.js.map +0 -1
- package/dist-client/pages/kpi-category/kpi-category-value-calculator.d.ts +0 -13
- package/dist-client/pages/kpi-category/kpi-category-value-calculator.js +0 -256
- package/dist-client/pages/kpi-category/kpi-category-value-calculator.js.map +0 -1
- package/dist-client/pages/kpi-category-value/kpi-category-value-list-page.d.ts +0 -63
- package/dist-client/pages/kpi-category-value/kpi-category-value-list-page.js +0 -393
- package/dist-client/pages/kpi-category-value/kpi-category-value-list-page.js.map +0 -1
- package/dist-server/service/kpi-category/index.d.ts +0 -6
- package/dist-server/service/kpi-category/index.js +0 -10
- package/dist-server/service/kpi-category/index.js.map +0 -1
- package/dist-server/service/kpi-category/kpi-category-mutation.d.ts +0 -9
- package/dist-server/service/kpi-category/kpi-category-mutation.js +0 -221
- package/dist-server/service/kpi-category/kpi-category-mutation.js.map +0 -1
- package/dist-server/service/kpi-category/kpi-category-query.d.ts +0 -18
- package/dist-server/service/kpi-category/kpi-category-query.js +0 -115
- package/dist-server/service/kpi-category/kpi-category-query.js.map +0 -1
- package/dist-server/service/kpi-category/kpi-category-type.d.ts +0 -24
- package/dist-server/service/kpi-category/kpi-category-type.js +0 -100
- package/dist-server/service/kpi-category/kpi-category-type.js.map +0 -1
- package/dist-server/service/kpi-category/kpi-category.d.ts +0 -22
- package/dist-server/service/kpi-category/kpi-category.js +0 -106
- package/dist-server/service/kpi-category/kpi-category.js.map +0 -1
- package/dist-server/service/kpi-category-value/index.d.ts +0 -6
- package/dist-server/service/kpi-category-value/index.js +0 -10
- package/dist-server/service/kpi-category-value/index.js.map +0 -1
- package/dist-server/service/kpi-category-value/kpi-category-value-mutation.d.ts +0 -8
- package/dist-server/service/kpi-category-value/kpi-category-value-mutation.js +0 -102
- package/dist-server/service/kpi-category-value/kpi-category-value-mutation.js.map +0 -1
- package/dist-server/service/kpi-category-value/kpi-category-value-query.d.ts +0 -13
- package/dist-server/service/kpi-category-value/kpi-category-value-query.js +0 -91
- package/dist-server/service/kpi-category-value/kpi-category-value-query.js.map +0 -1
- package/dist-server/service/kpi-category-value/kpi-category-value-type.d.ts +0 -19
- package/dist-server/service/kpi-category-value/kpi-category-value-type.js +0 -73
- package/dist-server/service/kpi-category-value/kpi-category-value-type.js.map +0 -1
- package/dist-server/service/kpi-category-value/kpi-category-value.d.ts +0 -19
- package/dist-server/service/kpi-category-value/kpi-category-value.js +0 -91
- package/dist-server/service/kpi-category-value/kpi-category-value.js.map +0 -1
- package/helps/kpi/kpi-category.md +0 -160
- package/server/service/kpi-category/index.ts +0 -7
- package/server/service/kpi-category/kpi-category-mutation.ts +0 -217
- package/server/service/kpi-category/kpi-category-query.ts +0 -87
- package/server/service/kpi-category/kpi-category-type.ts +0 -73
- package/server/service/kpi-category/kpi-category.ts +0 -95
- package/server/service/kpi-category-value/index.ts +0 -7
- package/server/service/kpi-category-value/kpi-category-value-mutation.ts +0 -88
- package/server/service/kpi-category-value/kpi-category-value-query.ts +0 -62
- package/server/service/kpi-category-value/kpi-category-value-type.ts +0 -48
- package/server/service/kpi-category-value/kpi-category-value.ts +0 -79
package/README.md
CHANGED
|
@@ -3,14 +3,13 @@
|
|
|
3
3
|
## 1. KPI란?
|
|
4
4
|
|
|
5
5
|
- KPI(Key Performance Indicator)는 조직의 목표 달성도를 수치로 측정/관리하는 핵심 지표입니다.
|
|
6
|
-
- KPI는 산식(formula), 목표값(target),
|
|
6
|
+
- KPI는 산식(formula), 목표값(target), 버전(version), 상태(state) 등 다양한 속성을 가집니다.
|
|
7
7
|
- KPI의 실적값(Performance Value)은 특정 시점/조직/프로젝트별로 기록됩니다.
|
|
8
8
|
|
|
9
9
|
## 2. KPI 모듈의 주요 엔티티
|
|
10
10
|
|
|
11
11
|
- **Kpi**: KPI 정의(이름, 산식, 카테고리, 상태, 버전 등)
|
|
12
12
|
- **KpiValue**: KPI별 실적값(날짜, 값, 입력방식, 소스 등)
|
|
13
|
-
- **KpiCategory**: KPI 분류(트리 구조 가능)
|
|
14
13
|
- **KpiMetric**: KPI 산식에 사용되는 원천 데이터 항목(코드, 단위, 데이터셋 등)
|
|
15
14
|
- **KpiGrade**: KPI별 등급/구간(구간별 점수, 색상 등)
|
|
16
15
|
- **KpiHistory**: KPI의 버전별 이력(스냅샷)
|
|
@@ -5,7 +5,7 @@ import * as d3 from 'd3'
|
|
|
5
5
|
@customElement('kpi-boxplot-chart')
|
|
6
6
|
export class KpiBoxplotChart extends LitElement {
|
|
7
7
|
@property({ type: Array }) data: any[] = []
|
|
8
|
-
@property({ type: Array }) groups: string[] = []
|
|
8
|
+
@property({ type: Array }) groups: string[] = [] // 조직 단위 목록 (빈 배열이면 데이터에서 자동 추출)
|
|
9
9
|
@property({ type: String }) minKey: string = 'min'
|
|
10
10
|
@property({ type: String }) maxKey: string = 'max'
|
|
11
11
|
@property({ type: String }) meanKey: string = 'mean'
|
|
@@ -14,6 +14,7 @@ export class KpiBoxplotChart extends LitElement {
|
|
|
14
14
|
@property({ type: String }) q3Key: string = 'q3'
|
|
15
15
|
@property({ type: String }) valueKey: string = 'value'
|
|
16
16
|
@property({ type: String }) currentGroup: string = ''
|
|
17
|
+
@property({ type: Boolean }) independentScale: boolean = false
|
|
17
18
|
|
|
18
19
|
static styles = css`
|
|
19
20
|
:host {
|
|
@@ -64,32 +65,83 @@ export class KpiBoxplotChart extends LitElement {
|
|
|
64
65
|
this.drawBoxplot()
|
|
65
66
|
}
|
|
66
67
|
|
|
68
|
+
private getOrgValue = (d: any) => d.org || d.group
|
|
69
|
+
|
|
67
70
|
drawBoxplot() {
|
|
68
71
|
const svg = d3.select(this.renderRoot.querySelector('#boxplot'))
|
|
69
72
|
svg.selectAll('*').remove()
|
|
73
|
+
|
|
74
|
+
// 데이터 검증
|
|
75
|
+
if (!this.data || this.data.length === 0) {
|
|
76
|
+
return
|
|
77
|
+
}
|
|
70
78
|
const w = this.chartWidth || 300
|
|
71
79
|
const h = this.chartHeight || 300
|
|
72
|
-
const margin = {
|
|
80
|
+
const margin = {
|
|
81
|
+
top: 20,
|
|
82
|
+
right: 20,
|
|
83
|
+
bottom: 40,
|
|
84
|
+
left: this.independentScale ? 20 : 40
|
|
85
|
+
}
|
|
73
86
|
const plotW = w - margin.left - margin.right
|
|
74
87
|
const plotH = h - margin.top - margin.bottom
|
|
75
88
|
|
|
76
|
-
// x축: 그룹
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
// x축: 조직 단위 (그룹) - org 또는 group 필드 지원
|
|
90
|
+
const groups = this.groups.length > 0 ? this.groups : [...new Set(this.data.map(d => this.getOrgValue(d)).filter(org => org != null))]
|
|
91
|
+
if (groups.length === 0) {
|
|
92
|
+
console.warn('No valid groups found in data:', this.data)
|
|
93
|
+
return // 유효한 그룹이 없으면 차트를 그리지 않음
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
console.log('Boxplot groups:', groups)
|
|
97
|
+
console.log('Data org values:', this.data.map(d => this.getOrgValue(d)))
|
|
98
|
+
console.log('Full data:', this.data)
|
|
99
|
+
console.log('Chart dimensions:', { w, h, plotW, plotH })
|
|
100
|
+
|
|
101
|
+
const x = d3.scaleBand().domain(groups).range([0, plotW]).padding(0.4)
|
|
102
|
+
|
|
103
|
+
// y축 스케일 설정
|
|
104
|
+
let y: d3.ScaleLinear<number, number>
|
|
105
|
+
|
|
106
|
+
if (this.independentScale) {
|
|
107
|
+
// 독립 스케일: 각 시리즈별로 개별 스케일 생성
|
|
108
|
+
const yScales = this.data.map(d => {
|
|
109
|
+
const values = [
|
|
110
|
+
d[this.minKey],
|
|
111
|
+
d[this.maxKey],
|
|
112
|
+
d[this.q1Key],
|
|
113
|
+
d[this.q3Key],
|
|
114
|
+
d[this.medianKey],
|
|
115
|
+
d[this.meanKey],
|
|
116
|
+
d[this.valueKey]
|
|
117
|
+
]
|
|
118
|
+
const min = d3.min(values) ?? 0
|
|
119
|
+
const max = d3.max(values) ?? 1
|
|
120
|
+
return {
|
|
121
|
+
org: d.org,
|
|
122
|
+
scale: d3.scaleLinear().domain([min, max]).nice().range([plotH, 0])
|
|
123
|
+
}
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
// 기본 y축은 첫 번째 스케일 사용
|
|
127
|
+
y = yScales[0]?.scale || d3.scaleLinear().domain([0, 1]).range([plotH, 0])
|
|
128
|
+
} else {
|
|
129
|
+
// 통합 스케일: 모든 데이터를 하나의 스케일에 맞춤
|
|
130
|
+
const allValues = this.data.flatMap(d => [
|
|
131
|
+
d[this.minKey],
|
|
132
|
+
d[this.maxKey],
|
|
133
|
+
d[this.q1Key],
|
|
134
|
+
d[this.q3Key],
|
|
135
|
+
d[this.medianKey],
|
|
136
|
+
d[this.meanKey],
|
|
137
|
+
d[this.valueKey]
|
|
138
|
+
])
|
|
139
|
+
y = d3
|
|
140
|
+
.scaleLinear()
|
|
141
|
+
.domain([d3.min(allValues) ?? 0, d3.max(allValues) ?? 1])
|
|
142
|
+
.nice()
|
|
143
|
+
.range([plotH, 0])
|
|
144
|
+
}
|
|
93
145
|
|
|
94
146
|
const g = svg
|
|
95
147
|
.attr('width', w)
|
|
@@ -98,66 +150,154 @@ export class KpiBoxplotChart extends LitElement {
|
|
|
98
150
|
.attr('transform', `translate(${margin.left},${margin.top})`)
|
|
99
151
|
|
|
100
152
|
// 축
|
|
101
|
-
|
|
153
|
+
if (!this.independentScale) {
|
|
154
|
+
g.append('g').call(d3.axisLeft(y))
|
|
155
|
+
}
|
|
102
156
|
g.append('g').attr('transform', `translate(0,${plotH})`).call(d3.axisBottom(x))
|
|
103
157
|
|
|
104
|
-
// 박스플롯
|
|
105
|
-
|
|
106
|
-
|
|
158
|
+
// 박스플롯 - 각 그룹별로 박스 생성
|
|
159
|
+
groups.forEach(groupName => {
|
|
160
|
+
// 해당 그룹의 데이터 찾기
|
|
161
|
+
const groupData = this.data.find(d => this.getOrgValue(d) === groupName)
|
|
162
|
+
console.log(`Searching for group: ${groupName}, found:`, groupData)
|
|
163
|
+
if (!groupData) {
|
|
164
|
+
console.warn(`No data found for group: ${groupName}. Available data:`, this.data.map(d => ({ org: d.org, keys: Object.keys(d) })))
|
|
165
|
+
return
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// 필수 필드 검증
|
|
169
|
+
const requiredFields = [this.minKey, this.maxKey, this.q1Key, this.q3Key, this.medianKey, this.meanKey]
|
|
170
|
+
const missingFields = requiredFields.filter(field => groupData[field] == null)
|
|
171
|
+
if (missingFields.length > 0) {
|
|
172
|
+
console.warn(`Missing required fields for group ${groupName}:`, missingFields)
|
|
173
|
+
console.log('Group data:', groupData)
|
|
174
|
+
return
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const gx = x(groupName) ?? 0
|
|
178
|
+
console.log(`Drawing box for ${groupName} at x=${gx}, bandwidth=${x.bandwidth()}`)
|
|
179
|
+
|
|
180
|
+
// 독립 스케일 사용 시 해당 그룹의 스케일 찾기
|
|
181
|
+
let currentY = y
|
|
182
|
+
if (this.independentScale) {
|
|
183
|
+
const values = [
|
|
184
|
+
groupData[this.minKey],
|
|
185
|
+
groupData[this.maxKey],
|
|
186
|
+
groupData[this.q1Key],
|
|
187
|
+
groupData[this.q3Key],
|
|
188
|
+
groupData[this.medianKey],
|
|
189
|
+
groupData[this.meanKey],
|
|
190
|
+
groupData[this.valueKey]
|
|
191
|
+
]
|
|
192
|
+
const min = d3.min(values) ?? 0
|
|
193
|
+
const max = d3.max(values) ?? 1
|
|
194
|
+
currentY = d3.scaleLinear().domain([min, max]).nice().range([plotH, 0])
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Outlier 계산 (1.5 * IQR 규칙)
|
|
198
|
+
const iqr = groupData[this.q3Key] - groupData[this.q1Key]
|
|
199
|
+
const lowerFence = groupData[this.q1Key] - 1.5 * iqr
|
|
200
|
+
const upperFence = groupData[this.q3Key] + 1.5 * iqr
|
|
201
|
+
|
|
202
|
+
// 실제 min/max 값 (fence 내부)
|
|
203
|
+
const actualMin = Math.max(groupData[this.minKey], lowerFence)
|
|
204
|
+
const actualMax = Math.min(groupData[this.maxKey], upperFence)
|
|
205
|
+
|
|
107
206
|
// 박스
|
|
108
207
|
g.append('rect')
|
|
109
208
|
.attr('x', gx)
|
|
110
|
-
.attr('y',
|
|
209
|
+
.attr('y', currentY(groupData[this.q3Key]))
|
|
111
210
|
.attr('width', x.bandwidth())
|
|
112
|
-
.attr('height',
|
|
113
|
-
.attr('fill',
|
|
211
|
+
.attr('height', currentY(groupData[this.q1Key]) - currentY(groupData[this.q3Key]))
|
|
212
|
+
.attr('fill', this.getOrgValue(groupData) === this.currentGroup ? '#2196f3' : '#bbb')
|
|
114
213
|
.attr('opacity', 0.5)
|
|
214
|
+
|
|
115
215
|
// 중앙선(중앙값)
|
|
116
216
|
g.append('line')
|
|
117
217
|
.attr('x1', gx)
|
|
118
218
|
.attr('x2', gx + x.bandwidth())
|
|
119
|
-
.attr('y1',
|
|
120
|
-
.attr('y2',
|
|
219
|
+
.attr('y1', currentY(groupData[this.medianKey]))
|
|
220
|
+
.attr('y2', currentY(groupData[this.medianKey]))
|
|
121
221
|
.attr('stroke', '#333')
|
|
122
222
|
.attr('stroke-width', 2)
|
|
123
|
-
|
|
223
|
+
|
|
224
|
+
// 수염 (fence 내부의 min-max)
|
|
124
225
|
g.append('line')
|
|
125
226
|
.attr('x1', gx + x.bandwidth() / 2)
|
|
126
227
|
.attr('x2', gx + x.bandwidth() / 2)
|
|
127
|
-
.attr('y1',
|
|
128
|
-
.attr('y2',
|
|
228
|
+
.attr('y1', currentY(actualMin))
|
|
229
|
+
.attr('y2', currentY(actualMax))
|
|
129
230
|
.attr('stroke', '#333')
|
|
130
|
-
|
|
231
|
+
|
|
232
|
+
// min/max 선 (fence 내부)
|
|
131
233
|
g.append('line')
|
|
132
234
|
.attr('x1', gx + x.bandwidth() / 4)
|
|
133
235
|
.attr('x2', gx + (x.bandwidth() * 3) / 4)
|
|
134
|
-
.attr('y1',
|
|
135
|
-
.attr('y2',
|
|
236
|
+
.attr('y1', currentY(actualMin))
|
|
237
|
+
.attr('y2', currentY(actualMin))
|
|
136
238
|
.attr('stroke', '#333')
|
|
137
239
|
g.append('line')
|
|
138
240
|
.attr('x1', gx + x.bandwidth() / 4)
|
|
139
241
|
.attr('x2', gx + (x.bandwidth() * 3) / 4)
|
|
140
|
-
.attr('y1',
|
|
141
|
-
.attr('y2',
|
|
242
|
+
.attr('y1', currentY(actualMax))
|
|
243
|
+
.attr('y2', currentY(actualMax))
|
|
142
244
|
.attr('stroke', '#333')
|
|
245
|
+
|
|
246
|
+
// Outlier 표시 (fence 외부의 값들)
|
|
247
|
+
if (groupData[this.minKey] < lowerFence) {
|
|
248
|
+
g.append('circle')
|
|
249
|
+
.attr('cx', gx + x.bandwidth() / 2)
|
|
250
|
+
.attr('cy', currentY(groupData[this.minKey]))
|
|
251
|
+
.attr('r', 3)
|
|
252
|
+
.attr('fill', '#ff4444')
|
|
253
|
+
.attr('stroke', '#333')
|
|
254
|
+
.attr('stroke-width', 1)
|
|
255
|
+
}
|
|
256
|
+
if (groupData[this.maxKey] > upperFence) {
|
|
257
|
+
g.append('circle')
|
|
258
|
+
.attr('cx', gx + x.bandwidth() / 2)
|
|
259
|
+
.attr('cy', currentY(groupData[this.maxKey]))
|
|
260
|
+
.attr('r', 3)
|
|
261
|
+
.attr('fill', '#ff4444')
|
|
262
|
+
.attr('stroke', '#333')
|
|
263
|
+
.attr('stroke-width', 1)
|
|
264
|
+
}
|
|
265
|
+
|
|
143
266
|
// 평균값
|
|
144
267
|
g.append('circle')
|
|
145
268
|
.attr('cx', gx + x.bandwidth() / 2)
|
|
146
|
-
.attr('cy',
|
|
269
|
+
.attr('cy', currentY(groupData[this.meanKey]))
|
|
147
270
|
.attr('r', 4)
|
|
148
271
|
.attr('fill', 'orange')
|
|
149
272
|
})
|
|
150
273
|
// 현재 그룹 값 강조
|
|
151
|
-
this.
|
|
152
|
-
|
|
274
|
+
if (this.currentGroup && groups.includes(this.currentGroup)) {
|
|
275
|
+
const currentGroupData = this.data.find(d => this.getOrgValue(d) === this.currentGroup)
|
|
276
|
+
if (currentGroupData) {
|
|
277
|
+
let currentY = y
|
|
278
|
+
if (this.independentScale) {
|
|
279
|
+
const values = [
|
|
280
|
+
currentGroupData[this.minKey],
|
|
281
|
+
currentGroupData[this.maxKey],
|
|
282
|
+
currentGroupData[this.q1Key],
|
|
283
|
+
currentGroupData[this.q3Key],
|
|
284
|
+
currentGroupData[this.medianKey],
|
|
285
|
+
currentGroupData[this.meanKey],
|
|
286
|
+
currentGroupData[this.valueKey]
|
|
287
|
+
]
|
|
288
|
+
const min = d3.min(values) ?? 0
|
|
289
|
+
const max = d3.max(values) ?? 1
|
|
290
|
+
currentY = d3.scaleLinear().domain([min, max]).nice().range([plotH, 0])
|
|
291
|
+
}
|
|
292
|
+
|
|
153
293
|
g.append('circle')
|
|
154
|
-
.attr('cx', x(
|
|
155
|
-
.attr('cy',
|
|
294
|
+
.attr('cx', x(this.currentGroup) + x.bandwidth() / 2)
|
|
295
|
+
.attr('cy', currentY(currentGroupData[this.valueKey]))
|
|
156
296
|
.attr('r', 6)
|
|
157
297
|
.attr('fill', '#e91e63')
|
|
158
298
|
.attr('stroke', '#fff')
|
|
159
299
|
.attr('stroke-width', 2)
|
|
160
300
|
}
|
|
161
|
-
}
|
|
301
|
+
}
|
|
162
302
|
}
|
|
163
303
|
}
|
|
@@ -66,11 +66,11 @@ export class KpiRadarChart extends LitElement {
|
|
|
66
66
|
const r = Math.min(w, h) / 2 - 40
|
|
67
67
|
const angleSlice = (2 * Math.PI) / (this.categories.length || 1)
|
|
68
68
|
|
|
69
|
-
// 데이터 변환: {
|
|
70
|
-
const
|
|
71
|
-
.groups(this.data, d => d.
|
|
72
|
-
.map(([
|
|
73
|
-
|
|
69
|
+
// 데이터 변환: { org, values: [ {category, value} ... ] }
|
|
70
|
+
const orgData = d3
|
|
71
|
+
.groups(this.data, d => d.org)
|
|
72
|
+
.map(([org, values]) => ({
|
|
73
|
+
org,
|
|
74
74
|
values: this.categories.map((cat, i) => {
|
|
75
75
|
const found = values.find(v => v.category === cat)
|
|
76
76
|
return { category: cat, value: found ? found[this.valueKey] : 0 }
|
|
@@ -110,7 +110,7 @@ export class KpiRadarChart extends LitElement {
|
|
|
110
110
|
})
|
|
111
111
|
|
|
112
112
|
// 그룹별 폴리곤
|
|
113
|
-
|
|
113
|
+
orgData.forEach(gd => {
|
|
114
114
|
// 마지막에 첫 점을 한 번 더 추가
|
|
115
115
|
const closedValues = [...gd.values, gd.values[0]]
|
|
116
116
|
const line = d3
|
|
@@ -120,9 +120,9 @@ export class KpiRadarChart extends LitElement {
|
|
|
120
120
|
g.append('path')
|
|
121
121
|
.datum(closedValues)
|
|
122
122
|
.attr('d', line as any)
|
|
123
|
-
.attr('fill', gd.
|
|
124
|
-
.attr('stroke', gd.
|
|
125
|
-
.attr('stroke-width', gd.
|
|
123
|
+
.attr('fill', gd.org === this.currentGroup ? 'rgba(33,150,243,0.4)' : 'rgba(200,200,200,0.2)')
|
|
124
|
+
.attr('stroke', gd.org === this.currentGroup ? '#2196f3' : '#aaa')
|
|
125
|
+
.attr('stroke-width', gd.org === this.currentGroup ? 3 : 1)
|
|
126
126
|
})
|
|
127
127
|
}
|
|
128
128
|
}
|
|
@@ -17,6 +17,7 @@ import { i18next, localize } from '@operato/i18n'
|
|
|
17
17
|
import { notify, openPopup } from '@operato/layout'
|
|
18
18
|
import { OxPopup, OxPrompt } from '@operato/popup'
|
|
19
19
|
import { isMobileDevice } from '@operato/utils'
|
|
20
|
+
import { p13n } from '@operato/p13n'
|
|
20
21
|
|
|
21
22
|
import { connect } from 'pwa-helpers/connect-mixin'
|
|
22
23
|
import gql from 'graphql-tag'
|
|
@@ -26,7 +27,7 @@ import { KpiGradeEditor } from './kpi-grade-editor'
|
|
|
26
27
|
import { KpiVizEditor } from './kpi-viz-editor'
|
|
27
28
|
|
|
28
29
|
@customElement('kpi-list-page')
|
|
29
|
-
export class KpiListPage extends connect(store)(localize(i18next)(ScopedElementsMixin(PageView))) {
|
|
30
|
+
export class KpiListPage extends connect(store)(p13n(localize(i18next)(ScopedElementsMixin(PageView)))) {
|
|
30
31
|
static styles = [
|
|
31
32
|
ScrollbarStyles,
|
|
32
33
|
CommonGristStyles,
|
|
@@ -67,32 +68,65 @@ export class KpiListPage extends connect(store)(localize(i18next)(ScopedElements
|
|
|
67
68
|
|
|
68
69
|
@state() availableVariables: any[] = []
|
|
69
70
|
@state() availableVariablesLoaded = false
|
|
71
|
+
@state() hierarchicalView = false
|
|
70
72
|
|
|
71
|
-
async getAvailableKpiMetricVariables() {
|
|
72
|
-
|
|
73
|
+
async getAvailableKpiMetricVariables(currentKpi?: any) {
|
|
74
|
+
// Leaf KPI인 경우: kpi-metric을 변수로 사용
|
|
75
|
+
if (!currentKpi || currentKpi.isLeaf) {
|
|
76
|
+
if (this.availableVariablesLoaded) {
|
|
77
|
+
return this.availableVariables
|
|
78
|
+
}
|
|
79
|
+
const response = await client.query({
|
|
80
|
+
query: gql`
|
|
81
|
+
query {
|
|
82
|
+
kpiMetrics {
|
|
83
|
+
items {
|
|
84
|
+
name
|
|
85
|
+
description
|
|
86
|
+
unit
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
`
|
|
91
|
+
})
|
|
92
|
+
this.availableVariables = (response.data.kpiMetrics.items || []).map(metric => ({
|
|
93
|
+
name: metric.name,
|
|
94
|
+
description: metric.description,
|
|
95
|
+
type: 'kpi-metric',
|
|
96
|
+
unit: metric.unit
|
|
97
|
+
}))
|
|
98
|
+
this.availableVariablesLoaded = true
|
|
73
99
|
return this.availableVariables
|
|
74
100
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
101
|
+
|
|
102
|
+
// 부모 KPI인 경우: 자식 KPI를 변수로 사용
|
|
103
|
+
try {
|
|
104
|
+
const response = await client.query({
|
|
105
|
+
query: gql`
|
|
106
|
+
query ($id: String!) {
|
|
107
|
+
kpi(id: $id) {
|
|
108
|
+
children {
|
|
109
|
+
id
|
|
110
|
+
name
|
|
111
|
+
description
|
|
112
|
+
}
|
|
83
113
|
}
|
|
84
114
|
}
|
|
115
|
+
`,
|
|
116
|
+
variables: {
|
|
117
|
+
id: currentKpi.id
|
|
85
118
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
return (response.data.kpi.children || []).map(childKpi => ({
|
|
122
|
+
name: childKpi.name,
|
|
123
|
+
description: childKpi.description,
|
|
124
|
+
type: 'child-kpi'
|
|
125
|
+
}))
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error('Failed to fetch child KPIs:', error)
|
|
128
|
+
return []
|
|
129
|
+
}
|
|
96
130
|
}
|
|
97
131
|
|
|
98
132
|
get context() {
|
|
@@ -111,6 +145,11 @@ export class KpiListPage extends connect(store)(localize(i18next)(ScopedElements
|
|
|
111
145
|
},
|
|
112
146
|
help: 'kpi/kpi',
|
|
113
147
|
actions: [
|
|
148
|
+
{
|
|
149
|
+
title: this.hierarchicalView ? 'List View' : 'Tree View',
|
|
150
|
+
action: this._toggleHierarchicalView.bind(this),
|
|
151
|
+
icon: this.hierarchicalView ? 'list' : 'account_tree'
|
|
152
|
+
},
|
|
114
153
|
{
|
|
115
154
|
title: i18next.t('button.save'),
|
|
116
155
|
action: this._updateKpi.bind(this),
|
|
@@ -136,7 +175,12 @@ export class KpiListPage extends connect(store)(localize(i18next)(ScopedElements
|
|
|
136
175
|
const mode = this.mode || (isMobileDevice() ? 'CARD' : 'GRID')
|
|
137
176
|
|
|
138
177
|
return html`
|
|
139
|
-
<ox-grist
|
|
178
|
+
<ox-grist
|
|
179
|
+
.mode=${mode}
|
|
180
|
+
.config=${this.gristConfig}
|
|
181
|
+
.fetchHandler=${this.fetchHandler.bind(this)}
|
|
182
|
+
.personalConfigProvider=${this.getPagePreferenceProvider('ox-grist')!}
|
|
183
|
+
>
|
|
140
184
|
<div slot="headroom" class="header">
|
|
141
185
|
<div class="filters">
|
|
142
186
|
<ox-filters-form autofocus without-search></ox-filters-form>
|
|
@@ -154,6 +198,8 @@ export class KpiListPage extends connect(store)(localize(i18next)(ScopedElements
|
|
|
154
198
|
</ox-record-creator>
|
|
155
199
|
</div>
|
|
156
200
|
</div>
|
|
201
|
+
|
|
202
|
+
<ox-grist-personalizer slot="setting"></ox-grist-personalizer>
|
|
157
203
|
</ox-grist>
|
|
158
204
|
`
|
|
159
205
|
}
|
|
@@ -170,7 +216,6 @@ export class KpiListPage extends connect(store)(localize(i18next)(ScopedElements
|
|
|
170
216
|
details: [
|
|
171
217
|
'name',
|
|
172
218
|
'description',
|
|
173
|
-
'category',
|
|
174
219
|
'formula',
|
|
175
220
|
'active',
|
|
176
221
|
'state',
|
|
@@ -220,26 +265,36 @@ export class KpiListPage extends connect(store)(localize(i18next)(ScopedElements
|
|
|
220
265
|
},
|
|
221
266
|
{
|
|
222
267
|
type: 'resource-object',
|
|
223
|
-
name: '
|
|
268
|
+
name: 'parent',
|
|
224
269
|
label: true,
|
|
225
|
-
header: '
|
|
270
|
+
header: '상위 KPI',
|
|
226
271
|
record: {
|
|
227
272
|
editable: true,
|
|
228
273
|
options: {
|
|
229
|
-
title: i18next.t('title.lookup
|
|
230
|
-
queryName: '
|
|
274
|
+
title: i18next.t('title.lookup KPI'),
|
|
275
|
+
queryName: 'kpis',
|
|
276
|
+
basicArgs: {
|
|
277
|
+
filters: [{ name: 'isLeaf', operator: 'eq', value: false }]
|
|
278
|
+
}
|
|
231
279
|
}
|
|
232
280
|
},
|
|
233
281
|
width: 200
|
|
234
282
|
},
|
|
283
|
+
{
|
|
284
|
+
type: 'boolean',
|
|
285
|
+
name: 'isLeaf',
|
|
286
|
+
header: '리프 KPI',
|
|
287
|
+
record: { editable: true },
|
|
288
|
+
width: 100
|
|
289
|
+
},
|
|
235
290
|
{
|
|
236
291
|
type: 'formula',
|
|
237
292
|
name: 'formula',
|
|
238
293
|
header: '산식',
|
|
239
294
|
record: {
|
|
240
295
|
editable: true,
|
|
241
|
-
availableVariables: async () => {
|
|
242
|
-
return await this.getAvailableKpiMetricVariables()
|
|
296
|
+
availableVariables: async (value: string, column: ColumnConfig, record: any) => {
|
|
297
|
+
return await this.getAvailableKpiMetricVariables(record)
|
|
243
298
|
}
|
|
244
299
|
},
|
|
245
300
|
width: 320
|
|
@@ -490,6 +545,10 @@ export class KpiListPage extends connect(store)(localize(i18next)(ScopedElements
|
|
|
490
545
|
}
|
|
491
546
|
|
|
492
547
|
async fetchHandler({ page = 1, limit = 100, sortings = [], filters = [] }: FetchOption) {
|
|
548
|
+
if (this.hierarchicalView) {
|
|
549
|
+
return this.fetchHierarchicalData()
|
|
550
|
+
}
|
|
551
|
+
|
|
493
552
|
const response = await client.query({
|
|
494
553
|
query: gql`
|
|
495
554
|
query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
|
|
@@ -510,11 +569,15 @@ export class KpiListPage extends connect(store)(localize(i18next)(ScopedElements
|
|
|
510
569
|
scheduleId
|
|
511
570
|
timezone
|
|
512
571
|
version
|
|
513
|
-
|
|
572
|
+
parent {
|
|
573
|
+
id
|
|
574
|
+
name
|
|
575
|
+
}
|
|
576
|
+
children {
|
|
514
577
|
id
|
|
515
578
|
name
|
|
516
|
-
description
|
|
517
579
|
}
|
|
580
|
+
isLeaf
|
|
518
581
|
updater {
|
|
519
582
|
id
|
|
520
583
|
name
|
|
@@ -790,7 +853,7 @@ export class KpiListPage extends connect(store)(localize(i18next)(ScopedElements
|
|
|
790
853
|
id
|
|
791
854
|
value
|
|
792
855
|
valueDate
|
|
793
|
-
|
|
856
|
+
org
|
|
794
857
|
}
|
|
795
858
|
}
|
|
796
859
|
`,
|
|
@@ -806,4 +869,105 @@ export class KpiListPage extends connect(store)(localize(i18next)(ScopedElements
|
|
|
806
869
|
notify({ message: 'KPI 실적값 계산 중 오류가 발생했습니다.' })
|
|
807
870
|
}
|
|
808
871
|
}
|
|
872
|
+
|
|
873
|
+
_toggleHierarchicalView() {
|
|
874
|
+
this.hierarchicalView = !this.hierarchicalView
|
|
875
|
+
this.grist.fetch()
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
async fetchHierarchicalData() {
|
|
879
|
+
const response = await client.query({
|
|
880
|
+
query: gql`
|
|
881
|
+
query {
|
|
882
|
+
kpiTree {
|
|
883
|
+
id
|
|
884
|
+
name
|
|
885
|
+
description
|
|
886
|
+
active
|
|
887
|
+
formula
|
|
888
|
+
periodType
|
|
889
|
+
scoreFormula
|
|
890
|
+
grades
|
|
891
|
+
vizType
|
|
892
|
+
vizMeta
|
|
893
|
+
weight
|
|
894
|
+
schedule
|
|
895
|
+
scheduleId
|
|
896
|
+
timezone
|
|
897
|
+
version
|
|
898
|
+
parent {
|
|
899
|
+
id
|
|
900
|
+
name
|
|
901
|
+
}
|
|
902
|
+
children {
|
|
903
|
+
id
|
|
904
|
+
name
|
|
905
|
+
description
|
|
906
|
+
active
|
|
907
|
+
isLeaf
|
|
908
|
+
weight
|
|
909
|
+
children {
|
|
910
|
+
id
|
|
911
|
+
name
|
|
912
|
+
description
|
|
913
|
+
active
|
|
914
|
+
isLeaf
|
|
915
|
+
weight
|
|
916
|
+
children {
|
|
917
|
+
id
|
|
918
|
+
name
|
|
919
|
+
description
|
|
920
|
+
active
|
|
921
|
+
isLeaf
|
|
922
|
+
weight
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
isLeaf
|
|
927
|
+
updater {
|
|
928
|
+
id
|
|
929
|
+
name
|
|
930
|
+
}
|
|
931
|
+
updatedAt
|
|
932
|
+
creator {
|
|
933
|
+
id
|
|
934
|
+
name
|
|
935
|
+
}
|
|
936
|
+
createdAt
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
`
|
|
940
|
+
})
|
|
941
|
+
|
|
942
|
+
const flattenedRecords = this.flattenTreeData(response.data.kpiTree)
|
|
943
|
+
|
|
944
|
+
return {
|
|
945
|
+
total: flattenedRecords.length,
|
|
946
|
+
records: flattenedRecords
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
flattenTreeData(treeData: any[], level = 0): any[] {
|
|
951
|
+
const flattened: any[] = []
|
|
952
|
+
|
|
953
|
+
for (const item of treeData) {
|
|
954
|
+
const flattenedItem = {
|
|
955
|
+
...item,
|
|
956
|
+
__level: level,
|
|
957
|
+
__hasChildren: item.children && item.children.length > 0,
|
|
958
|
+
__expanded: true
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
// Add indentation to name for visual hierarchy
|
|
962
|
+
flattenedItem.name = ' '.repeat(level) + (level > 0 ? '└ ' : '') + item.name
|
|
963
|
+
|
|
964
|
+
flattened.push(flattenedItem)
|
|
965
|
+
|
|
966
|
+
if (item.children && item.children.length > 0) {
|
|
967
|
+
flattened.push(...this.flattenTreeData(item.children, level + 1))
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
return flattened
|
|
972
|
+
}
|
|
809
973
|
}
|