@things-factory/kpi 9.1.19 → 10.0.0-beta.2
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/client/pages/kpi/kpi-list-page.ts +339 -525
- package/client/pages/kpi/kpi-tree-page.ts +135 -207
- package/client/pages/kpi-metric/kpi-metric-list-page.ts +146 -226
- package/client/pages/kpi-metric-value/kpi-metric-value-editor-page.ts +187 -295
- package/client/pages/kpi-metric-value/kpi-metric-value-list-page.ts +123 -194
- package/client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.ts +57 -91
- package/client/pages/kpi-statistic/kpi-statistic-editor-page.ts +180 -278
- package/client/pages/kpi-statistic/kpi-statistic-list-page.ts +186 -286
- package/client/pages/kpi-value/kpi-value-editor-page.ts +189 -292
- package/client/pages/kpi-value/kpi-value-list-page.ts +170 -264
- package/dist-client/pages/kpi/kpi-list-page.d.ts +0 -6
- package/dist-client/pages/kpi/kpi-list-page.js +150 -282
- package/dist-client/pages/kpi/kpi-list-page.js.map +1 -1
- package/dist-client/pages/kpi/kpi-tree-page.d.ts +1 -7
- package/dist-client/pages/kpi/kpi-tree-page.js +76 -127
- package/dist-client/pages/kpi/kpi-tree-page.js.map +1 -1
- package/dist-client/pages/kpi-metric/kpi-metric-list-page.d.ts +0 -6
- package/dist-client/pages/kpi-metric/kpi-metric-list-page.js +62 -116
- 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 -7
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.js +82 -140
- 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-list-page.d.ts +0 -6
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js +54 -98
- 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-page.d.ts +1 -7
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.js +30 -57
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.js.map +1 -1
- package/dist-client/pages/kpi-statistic/kpi-statistic-editor-page.d.ts +1 -7
- package/dist-client/pages/kpi-statistic/kpi-statistic-editor-page.js +91 -153
- 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 +0 -6
- package/dist-client/pages/kpi-statistic/kpi-statistic-list-page.js +81 -155
- 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 +1 -7
- package/dist-client/pages/kpi-value/kpi-value-editor-page.js +80 -136
- 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 +0 -6
- package/dist-client/pages/kpi-value/kpi-value-list-page.js +73 -134
- package/dist-client/pages/kpi-value/kpi-value-list-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/service/index.d.ts +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +18 -18
- package/client/tsconfig.json +0 -11
- package/dist-server/tsconfig.json +0 -10
- package/server/@types/index.d.ts +0 -11
- package/server/calculator/evaluator.ts +0 -45
- package/server/calculator/functions.ts +0 -67
- package/server/calculator/index.ts +0 -4
- package/server/calculator/parser.ts +0 -137
- package/server/calculator/provider.ts +0 -10
- package/server/controllers/index.ts +0 -2
- package/server/controllers/kpi-metric-value-provider.ts +0 -79
- package/server/controllers/kpi-value-provider.ts +0 -51
- package/server/index.ts +0 -6
- package/server/migrations/1752190849680-seed-kpi-metrics.ts +0 -124
- package/server/migrations/1752190849681-seed-kpi.ts +0 -356
- package/server/migrations/1752192090123-add-grades-to-kpi.ts +0 -67
- package/server/migrations/1752192090124-add-kpi-statistics.ts +0 -719
- package/server/migrations/1752192090128-seed-kpi-org-scope.ts +0 -132
- package/server/migrations/1752192090129-seed-kpi-values.ts +0 -207
- package/server/migrations/grade-data/x11-performance-table.json +0 -962
- package/server/migrations/grade-data/x12-performance-table.json +0 -611
- package/server/migrations/grade-data/x14-performance-table.json +0 -42
- package/server/migrations/grade-data/x21-performance-table.json +0 -889
- package/server/migrations/grade-data/x22-performance-table.json +0 -1064
- package/server/migrations/grade-data/x23-performance-table.json +0 -42
- package/server/migrations/grade-data/x31-performance-table.json +0 -644
- package/server/migrations/grade-data/x32-performance-table.json +0 -993
- package/server/migrations/grade-data/x33-performance-table.json +0 -195
- package/server/migrations/grade-data/x34-performance-table.json +0 -12
- package/server/migrations/grade-data/x35-performance-table.json +0 -42
- package/server/migrations/grade-data/x41-performance-table.json +0 -825
- package/server/migrations/grade-data/x42-performance-table.json +0 -786
- package/server/migrations/grade-data/x43-performance-table.json +0 -12
- package/server/migrations/grade-data/x44-performance-table.json +0 -42
- package/server/migrations/grade-data/x51-performance-table.json +0 -924
- package/server/migrations/grade-data/x52-performance-table.json +0 -42
- package/server/migrations/grade-data/x61-performance-table.json +0 -261
- package/server/migrations/grade-data/x62-performance-table.json +0 -42
- package/server/migrations/index.ts +0 -9
- package/server/migrations/seed-data/kpi-metrics-seed.json +0 -454
- package/server/migrations/seed-data/kpi-org-scope-seed.json +0 -1676
- package/server/migrations/seed-data/kpi-scopes-seed.json +0 -121
- package/server/migrations/seed-data/kpi-values-seed.json +0 -402
- package/server/migrations/seed-data/kpis-seed.json +0 -488
- package/server/migrations/seed-data/scope-definitions-seed.json +0 -90
- package/server/routes.ts +0 -81
- package/server/service/index.ts +0 -51
- package/server/service/kpi/aggregate-kpi.ts +0 -103
- package/server/service/kpi/event-subscriber.ts +0 -29
- package/server/service/kpi/index.ts +0 -9
- package/server/service/kpi/kpi-formula.service.ts +0 -164
- package/server/service/kpi/kpi-grade.types.ts +0 -28
- package/server/service/kpi/kpi-history.ts +0 -126
- package/server/service/kpi/kpi-mutation.ts +0 -553
- package/server/service/kpi/kpi-query.ts +0 -224
- package/server/service/kpi/kpi-type.ts +0 -151
- package/server/service/kpi/kpi.ts +0 -254
- package/server/service/kpi-alert/index.ts +0 -3
- package/server/service/kpi-alert/kpi-alert-query.ts +0 -59
- package/server/service/kpi-alert/kpi-alert-type.ts +0 -20
- package/server/service/kpi-metric/aggregate-kpi-metric.ts +0 -132
- package/server/service/kpi-metric/index.ts +0 -7
- package/server/service/kpi-metric/kpi-metric-mutation.ts +0 -309
- package/server/service/kpi-metric/kpi-metric-query.ts +0 -70
- package/server/service/kpi-metric/kpi-metric-type.ts +0 -111
- package/server/service/kpi-metric/kpi-metric.ts +0 -134
- package/server/service/kpi-metric-value/index.ts +0 -7
- package/server/service/kpi-metric-value/kpi-metric-value-mutation.ts +0 -270
- package/server/service/kpi-metric-value/kpi-metric-value-query.ts +0 -62
- package/server/service/kpi-metric-value/kpi-metric-value-type.ts +0 -82
- package/server/service/kpi-metric-value/kpi-metric-value.ts +0 -93
- package/server/service/kpi-org-scope/index.ts +0 -6
- package/server/service/kpi-org-scope/kpi-org-scope-mutation.ts +0 -173
- package/server/service/kpi-org-scope/kpi-org-scope-query.ts +0 -127
- package/server/service/kpi-org-scope/kpi-org-scope-type.ts +0 -68
- package/server/service/kpi-org-scope/kpi-org-scope.ts +0 -123
- package/server/service/kpi-scope/index.ts +0 -11
- package/server/service/kpi-scope/kpi-scope-mutation.ts +0 -129
- package/server/service/kpi-scope/kpi-scope-query.ts +0 -63
- package/server/service/kpi-scope/kpi-scope-type.ts +0 -96
- package/server/service/kpi-scope/kpi-scope.ts +0 -143
- package/server/service/kpi-statistic/index.ts +0 -7
- package/server/service/kpi-statistic/kpi-statistic-batch.service.ts +0 -231
- package/server/service/kpi-statistic/kpi-statistic-calculation.service.ts +0 -410
- package/server/service/kpi-statistic/kpi-statistic-mutation.ts +0 -291
- package/server/service/kpi-statistic/kpi-statistic-query.ts +0 -146
- package/server/service/kpi-statistic/kpi-statistic-type.ts +0 -152
- package/server/service/kpi-statistic/kpi-statistic.ts +0 -199
- package/server/service/kpi-value/index.ts +0 -7
- package/server/service/kpi-value/kpi-value-mutation.ts +0 -432
- package/server/service/kpi-value/kpi-value-query.ts +0 -61
- package/server/service/kpi-value/kpi-value-score.service.ts +0 -106
- package/server/service/kpi-value/kpi-value-type.ts +0 -122
- package/server/service/kpi-value/kpi-value.ts +0 -160
- package/server/service/utils/value-date-util.ts +0 -119
- package/server/tsconfig.json +0 -10
- package/server/types/global.d.ts +0 -8
|
@@ -7,7 +7,7 @@ import './kpi-viz-editor.js'
|
|
|
7
7
|
import './kpi-grade-editor.js'
|
|
8
8
|
|
|
9
9
|
import { CommonButtonStyles, CommonHeaderStyles, CommonGristStyles, ScrollbarStyles } from '@operato/styles'
|
|
10
|
-
import { PageView
|
|
10
|
+
import { PageView } from '@operato/shell'
|
|
11
11
|
import { css, html } from 'lit'
|
|
12
12
|
import { customElement, property, query, state } from 'lit/decorators.js'
|
|
13
13
|
import { ScopedElementsMixin } from '@open-wc/scoped-elements'
|
|
@@ -19,7 +19,6 @@ import { OxPopup, OxPrompt } from '@operato/popup'
|
|
|
19
19
|
import { isMobileDevice } from '@operato/utils'
|
|
20
20
|
import { p13n } from '@operato/p13n'
|
|
21
21
|
|
|
22
|
-
import { connect } from 'pwa-helpers/connect-mixin'
|
|
23
22
|
import gql from 'graphql-tag'
|
|
24
23
|
|
|
25
24
|
import { KpiImporter } from './kpi-importer'
|
|
@@ -27,39 +26,33 @@ import { KpiGradeEditor } from './kpi-grade-editor'
|
|
|
27
26
|
import { KpiVizEditor } from './kpi-viz-editor'
|
|
28
27
|
|
|
29
28
|
@customElement('kpi-list-page')
|
|
30
|
-
export class KpiListPage extends
|
|
31
|
-
static styles = [
|
|
29
|
+
export class KpiListPage extends p13n(localize(i18next)(ScopedElementsMixin(PageView))) { static styles = [
|
|
32
30
|
ScrollbarStyles,
|
|
33
31
|
CommonGristStyles,
|
|
34
32
|
CommonHeaderStyles,
|
|
35
33
|
css`
|
|
36
|
-
:host {
|
|
37
|
-
display: flex;
|
|
34
|
+
:host { display: flex;
|
|
38
35
|
|
|
39
36
|
width: 100%;
|
|
40
37
|
|
|
41
38
|
--grid-record-emphasized-background-color: #8b0000;
|
|
42
39
|
--grid-record-emphasized-color: #ff6b6b;
|
|
43
|
-
|
|
40
|
+
}
|
|
44
41
|
|
|
45
|
-
ox-grist {
|
|
46
|
-
overflow-y: auto;
|
|
42
|
+
ox-grist { overflow-y: auto;
|
|
47
43
|
flex: 1;
|
|
48
|
-
|
|
44
|
+
}
|
|
49
45
|
|
|
50
|
-
ox-filters-form {
|
|
51
|
-
|
|
52
|
-
}
|
|
46
|
+
ox-filters-form { flex: 1;
|
|
47
|
+
}
|
|
53
48
|
`
|
|
54
49
|
]
|
|
55
50
|
|
|
56
|
-
static get scopedElements() {
|
|
57
|
-
return {
|
|
58
|
-
'kpi-importer': KpiImporter,
|
|
51
|
+
static get scopedElements() { return { 'kpi-importer': KpiImporter,
|
|
59
52
|
'kpi-grade-editor': KpiGradeEditor,
|
|
60
53
|
'kpi-viz-editor': KpiVizEditor
|
|
61
|
-
|
|
62
|
-
|
|
54
|
+
}
|
|
55
|
+
}
|
|
63
56
|
|
|
64
57
|
@property({ type: Object }) gristConfig: any
|
|
65
58
|
@property({ type: String }) mode: 'CARD' | 'GRID' | 'LIST' = isMobileDevice() ? 'CARD' : 'GRID'
|
|
@@ -70,109 +63,81 @@ export class KpiListPage extends connect(store)(p13n(localize(i18next)(ScopedEle
|
|
|
70
63
|
@state() availableVariablesLoaded = false
|
|
71
64
|
@state() hierarchicalView = false
|
|
72
65
|
|
|
73
|
-
async getAvailableKpiMetricVariables(currentKpi?: any) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
const response = await client.query({
|
|
80
|
-
query: gql`
|
|
81
|
-
query {
|
|
82
|
-
kpiMetrics {
|
|
83
|
-
items {
|
|
84
|
-
name
|
|
66
|
+
async getAvailableKpiMetricVariables(currentKpi?: any) { // Leaf KPI인 경우: kpi-metric을 변수로 사용
|
|
67
|
+
if (!currentKpi || currentKpi.isLeaf) { if (this.availableVariablesLoaded) { return this.availableVariables
|
|
68
|
+
}
|
|
69
|
+
const response = await client.query({ query: gql`
|
|
70
|
+
query { kpiMetrics { items { name
|
|
85
71
|
description
|
|
86
72
|
unit
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
90
76
|
`
|
|
91
|
-
|
|
92
|
-
this.availableVariables = (response.data.kpiMetrics.items || []).map(metric => ({
|
|
93
|
-
name: metric.name,
|
|
77
|
+
})
|
|
78
|
+
this.availableVariables = (response.data.kpiMetrics.items || []).map(metric => ({ name: metric.name,
|
|
94
79
|
description: metric.description,
|
|
95
80
|
type: 'kpi-metric',
|
|
96
81
|
unit: metric.unit
|
|
97
|
-
|
|
82
|
+
}))
|
|
98
83
|
this.availableVariablesLoaded = true
|
|
99
84
|
return this.availableVariables
|
|
100
|
-
|
|
85
|
+
}
|
|
101
86
|
|
|
102
87
|
// 부모 KPI인 경우: 자식 KPI를 변수로 사용
|
|
103
|
-
try {
|
|
104
|
-
|
|
105
|
-
query: gql`
|
|
106
|
-
query ($id: String!) {
|
|
107
|
-
kpi(id: $id) {
|
|
108
|
-
children {
|
|
109
|
-
id
|
|
88
|
+
try { const response = await client.query({ query: gql`
|
|
89
|
+
query ($id: String!) { kpi(id: $id) { children { id
|
|
110
90
|
name
|
|
111
91
|
description
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
115
95
|
`,
|
|
116
|
-
variables: {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
})
|
|
96
|
+
variables: { id: currentKpi.id
|
|
97
|
+
}
|
|
98
|
+
})
|
|
120
99
|
|
|
121
|
-
return (response.data.kpi.children || []).map(childKpi => ({
|
|
122
|
-
name: childKpi.name,
|
|
100
|
+
return (response.data.kpi.children || []).map(childKpi => ({ name: childKpi.name,
|
|
123
101
|
description: childKpi.description,
|
|
124
102
|
type: 'child-kpi'
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
console.error('Failed to fetch child KPIs:', error)
|
|
103
|
+
}))
|
|
104
|
+
} catch (error) { console.error('Failed to fetch child KPIs:', error)
|
|
128
105
|
return []
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
get context() {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
search: {
|
|
136
|
-
handler: (search: string) => {
|
|
137
|
-
this.grist.searchText = search
|
|
138
|
-
},
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
get context() { return { title: i18next.t('title.kpi list'),
|
|
110
|
+
search: { handler: (search: string) => { this.grist.searchText = search
|
|
111
|
+
},
|
|
139
112
|
value: this.grist.searchText
|
|
140
|
-
|
|
141
|
-
filter: {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
},
|
|
113
|
+
},
|
|
114
|
+
filter: { handler: () => { this.grist.toggleHeadroom()
|
|
115
|
+
}
|
|
116
|
+
},
|
|
146
117
|
help: 'kpi/kpi',
|
|
147
118
|
actions: [
|
|
148
|
-
{
|
|
149
|
-
title: this.hierarchicalView ? 'List View' : 'Tree View',
|
|
119
|
+
{ title: this.hierarchicalView ? 'List View' : 'Tree View',
|
|
150
120
|
action: this._toggleHierarchicalView.bind(this),
|
|
151
121
|
icon: this.hierarchicalView ? 'list' : 'account_tree'
|
|
152
|
-
|
|
153
|
-
{
|
|
154
|
-
title: i18next.t('button.save'),
|
|
122
|
+
},
|
|
123
|
+
{ title: i18next.t('button.save'),
|
|
155
124
|
action: this._updateKpi.bind(this),
|
|
156
125
|
...CommonButtonStyles.save
|
|
157
|
-
|
|
158
|
-
{
|
|
159
|
-
title: i18next.t('button.delete'),
|
|
126
|
+
},
|
|
127
|
+
{ title: i18next.t('button.delete'),
|
|
160
128
|
action: this._deleteKpi.bind(this),
|
|
161
129
|
...CommonButtonStyles.delete
|
|
162
|
-
|
|
130
|
+
}
|
|
163
131
|
],
|
|
164
|
-
exportable: {
|
|
165
|
-
name: i18next.t('title.kpi list'),
|
|
132
|
+
exportable: { name: i18next.t('title.kpi list'),
|
|
166
133
|
data: this.exportHandler.bind(this)
|
|
167
|
-
|
|
168
|
-
importable: {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
134
|
+
},
|
|
135
|
+
importable: { handler: this.importHandler.bind(this)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
173
139
|
|
|
174
|
-
render() {
|
|
175
|
-
const mode = this.mode || (isMobileDevice() ? 'CARD' : 'GRID')
|
|
140
|
+
render() { const mode = this.mode || (isMobileDevice() ? 'CARD' : 'GRID')
|
|
176
141
|
|
|
177
142
|
return html`
|
|
178
143
|
<ox-grist
|
|
@@ -202,17 +167,13 @@ export class KpiListPage extends connect(store)(p13n(localize(i18next)(ScopedEle
|
|
|
202
167
|
<ox-grist-personalizer slot="setting"></ox-grist-personalizer>
|
|
203
168
|
</ox-grist>
|
|
204
169
|
`
|
|
205
|
-
|
|
170
|
+
}
|
|
206
171
|
|
|
207
|
-
connectedCallback() {
|
|
208
|
-
super.connectedCallback()
|
|
172
|
+
connectedCallback() { super.connectedCallback()
|
|
209
173
|
this.fetchKpiMetrics()
|
|
210
|
-
|
|
174
|
+
}
|
|
211
175
|
|
|
212
|
-
async pageInitialized(lifecycle: any) {
|
|
213
|
-
this.gristConfig = {
|
|
214
|
-
list: {
|
|
215
|
-
fields: ['name', 'description'],
|
|
176
|
+
async pageInitialized(lifecycle: any) { this.gristConfig = { list: { fields: ['name', 'description'],
|
|
216
177
|
details: [
|
|
217
178
|
'name',
|
|
218
179
|
'description',
|
|
@@ -230,91 +191,74 @@ export class KpiListPage extends connect(store)(p13n(localize(i18next)(ScopedEle
|
|
|
230
191
|
'updater',
|
|
231
192
|
'thumbnail'
|
|
232
193
|
]
|
|
233
|
-
|
|
194
|
+
},
|
|
234
195
|
columns: [
|
|
235
196
|
{ type: 'gutter', gutterName: 'sequence' },
|
|
236
197
|
{ type: 'gutter', gutterName: 'row-selector', multiple: true },
|
|
237
198
|
// KPI 실적값 계산 버튼 추가
|
|
238
|
-
{
|
|
239
|
-
type: 'gutter',
|
|
199
|
+
{ type: 'gutter',
|
|
240
200
|
gutterName: 'button',
|
|
241
201
|
icon: 'calculate',
|
|
242
202
|
title: '실적값 계산',
|
|
243
|
-
handlers: {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
},
|
|
249
|
-
{
|
|
250
|
-
type: 'string',
|
|
203
|
+
handlers: { click: (columns, data, column, record, rowIndex) => { this._calculateKpiValue(record)
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
{ type: 'string',
|
|
251
208
|
name: 'name',
|
|
252
209
|
header: '이름',
|
|
253
210
|
record: { editable: true },
|
|
254
211
|
filter: 'search',
|
|
255
212
|
sortable: true,
|
|
256
213
|
width: 120
|
|
257
|
-
|
|
258
|
-
{
|
|
259
|
-
type: 'string',
|
|
214
|
+
},
|
|
215
|
+
{ type: 'string',
|
|
260
216
|
name: 'description',
|
|
261
217
|
header: i18next.t('field.description'),
|
|
262
218
|
record: { editable: true },
|
|
263
219
|
filter: 'search',
|
|
264
220
|
width: 200
|
|
265
|
-
|
|
266
|
-
{
|
|
267
|
-
type: 'resource-object',
|
|
221
|
+
},
|
|
222
|
+
{ type: 'resource-object',
|
|
268
223
|
name: 'parent',
|
|
269
224
|
label: true,
|
|
270
225
|
header: '상위 KPI',
|
|
271
|
-
record: {
|
|
272
|
-
|
|
273
|
-
options: {
|
|
274
|
-
title: i18next.t('title.lookup KPI'),
|
|
226
|
+
record: { editable: true,
|
|
227
|
+
options: { title: i18next.t('title.lookup KPI'),
|
|
275
228
|
queryName: 'kpis',
|
|
276
|
-
basicArgs: {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
},
|
|
229
|
+
basicArgs: { filters: [{ name: 'isLeaf', operator: 'eq', value: false }]
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
},
|
|
281
233
|
width: 200
|
|
282
|
-
|
|
283
|
-
{
|
|
284
|
-
type: 'boolean',
|
|
234
|
+
},
|
|
235
|
+
{ type: 'boolean',
|
|
285
236
|
name: 'isLeaf',
|
|
286
237
|
header: '리프 KPI',
|
|
287
238
|
record: { editable: true },
|
|
288
239
|
width: 100
|
|
289
|
-
|
|
290
|
-
{
|
|
291
|
-
type: 'formula',
|
|
240
|
+
},
|
|
241
|
+
{ type: 'formula',
|
|
292
242
|
name: 'formula',
|
|
293
243
|
header: '산식',
|
|
294
|
-
record: {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
if (!record || record.isLeaf) {
|
|
299
|
-
return await this.getAvailableKpiMetricVariables(record)
|
|
300
|
-
}
|
|
244
|
+
record: { editable: true,
|
|
245
|
+
availableVariables: async (value: string, column: ColumnConfig, record: any) => { // Leaf KPI인 경우: kpi-metric을 변수로 사용
|
|
246
|
+
if (!record || record.isLeaf) { return await this.getAvailableKpiMetricVariables(record)
|
|
247
|
+
}
|
|
301
248
|
// 부모 KPI인 경우: 자식 KPI를 변수로 사용
|
|
302
|
-
return (record.children || []).map(child => ({
|
|
303
|
-
name: child.name,
|
|
249
|
+
return (record.children || []).map(child => ({ name: child.name,
|
|
304
250
|
description: child.description || child.name,
|
|
305
251
|
type: 'child-kpi',
|
|
306
252
|
unit: ''
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
253
|
+
}))
|
|
254
|
+
}
|
|
255
|
+
},
|
|
310
256
|
width: 320
|
|
311
|
-
|
|
312
|
-
{
|
|
313
|
-
type: 'select',
|
|
257
|
+
},
|
|
258
|
+
{ type: 'select',
|
|
314
259
|
name: 'periodType',
|
|
315
260
|
header: '계산주기',
|
|
316
|
-
record: {
|
|
317
|
-
editable: true,
|
|
261
|
+
record: { editable: true,
|
|
318
262
|
options: [
|
|
319
263
|
{ value: '', display: '' },
|
|
320
264
|
{ value: 'DAY', display: '일' },
|
|
@@ -325,39 +269,32 @@ export class KpiListPage extends connect(store)(p13n(localize(i18next)(ScopedEle
|
|
|
325
269
|
{ value: 'RANGE', display: '범위' },
|
|
326
270
|
{ value: 'ALLTIME', display: '전체' }
|
|
327
271
|
]
|
|
328
|
-
|
|
272
|
+
},
|
|
329
273
|
width: 80
|
|
330
|
-
|
|
331
|
-
{
|
|
332
|
-
type: 'formula',
|
|
274
|
+
},
|
|
275
|
+
{ type: 'formula',
|
|
333
276
|
name: 'scoreFormula',
|
|
334
277
|
header: '성과점수수식',
|
|
335
|
-
record: {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
if (record.isLeaf) {
|
|
340
|
-
return [
|
|
341
|
-
{
|
|
342
|
-
name: 'value',
|
|
278
|
+
record: { editable: true,
|
|
279
|
+
availableVariables: async (value: string, column: ColumnConfig, record: any) => { // leaf 이면 value를 사용
|
|
280
|
+
if (record.isLeaf) { return [
|
|
281
|
+
{ name: 'value',
|
|
343
282
|
description: 'KPI 실적값',
|
|
344
283
|
type: 'kpi-value',
|
|
345
284
|
unit: ''
|
|
346
|
-
|
|
285
|
+
}
|
|
347
286
|
]
|
|
348
|
-
|
|
287
|
+
}
|
|
349
288
|
// 부모 이면 자식 KPI들을 변수로 사용
|
|
350
|
-
return record.children.map(child => ({
|
|
351
|
-
name: child.name,
|
|
289
|
+
return record.children.map(child => ({ name: child.name,
|
|
352
290
|
description: child.description || child.name,
|
|
353
291
|
type: 'kpi-score',
|
|
354
292
|
unit: ''
|
|
355
|
-
|
|
356
|
-
|
|
293
|
+
}))
|
|
294
|
+
},
|
|
357
295
|
includeDefaultFunctions: false,
|
|
358
296
|
availableFunctions: [
|
|
359
|
-
{
|
|
360
|
-
name: 'INTEGRATE()',
|
|
297
|
+
{ name: 'INTEGRATE()',
|
|
361
298
|
description: '수치 적분',
|
|
362
299
|
template: 'INTEGRATE({func}, {a}, {b}, {n})',
|
|
363
300
|
syntax: 'INTEGRATE(func, a, b, n)',
|
|
@@ -365,9 +302,8 @@ export class KpiListPage extends connect(store)(p13n(localize(i18next)(ScopedEle
|
|
|
365
302
|
returnType: 'number',
|
|
366
303
|
help: '사다리꼴 적분법을 사용하여 수치 적분을 계산합니다.',
|
|
367
304
|
examples: ['INTEGRATE(x => x*x, 0, 1, 1000)', 'INTEGRATE([효율성], 0, 1)']
|
|
368
|
-
|
|
369
|
-
{
|
|
370
|
-
name: 'BETA_FUNCTION()',
|
|
305
|
+
},
|
|
306
|
+
{ name: 'BETA_FUNCTION()',
|
|
371
307
|
description: '베타 함수',
|
|
372
308
|
template: 'BETA_FUNCTION({x}, {alpha}, {beta})',
|
|
373
309
|
syntax: 'BETA_FUNCTION(x, alpha, beta)',
|
|
@@ -375,9 +311,8 @@ export class KpiListPage extends connect(store)(p13n(localize(i18next)(ScopedEle
|
|
|
375
311
|
returnType: 'number',
|
|
376
312
|
help: '베타 분포 함수를 계산합니다. t^(α-1) × (1-t)^(β-1)',
|
|
377
313
|
examples: ['BETA_FUNCTION(0.5, 2, 3)', 'BETA_FUNCTION([품질지수], 3, 2)']
|
|
378
|
-
|
|
379
|
-
{
|
|
380
|
-
name: 'INCOMPLETE_BETA()',
|
|
314
|
+
},
|
|
315
|
+
{ name: 'INCOMPLETE_BETA()',
|
|
381
316
|
description: '불완전 베타 함수',
|
|
382
317
|
template: 'INCOMPLETE_BETA({x}, {alpha}, {beta})',
|
|
383
318
|
syntax: 'INCOMPLETE_BETA(x, alpha, beta)',
|
|
@@ -385,9 +320,8 @@ export class KpiListPage extends connect(store)(p13n(localize(i18next)(ScopedEle
|
|
|
385
320
|
returnType: 'number',
|
|
386
321
|
help: '불완전 베타 함수를 수치 적분으로 계산합니다.',
|
|
387
322
|
examples: ['INCOMPLETE_BETA(0.7, 2, 3)', 'INCOMPLETE_BETA([목표달성률]/100, 2, 3)']
|
|
388
|
-
|
|
389
|
-
{
|
|
390
|
-
name: 'COMPLETE_BETA()',
|
|
323
|
+
},
|
|
324
|
+
{ name: 'COMPLETE_BETA()',
|
|
391
325
|
description: '완전 베타 함수',
|
|
392
326
|
template: 'COMPLETE_BETA({alpha}, {beta})',
|
|
393
327
|
syntax: 'COMPLETE_BETA(alpha, beta)',
|
|
@@ -395,9 +329,8 @@ export class KpiListPage extends connect(store)(p13n(localize(i18next)(ScopedEle
|
|
|
395
329
|
returnType: 'number',
|
|
396
330
|
help: '완전 베타 함수 B(α,β)를 계산합니다.',
|
|
397
331
|
examples: ['COMPLETE_BETA(2, 3)', 'COMPLETE_BETA(3, 2)']
|
|
398
|
-
|
|
399
|
-
{
|
|
400
|
-
name: 'PERFORMANCE_INDEX()',
|
|
332
|
+
},
|
|
333
|
+
{ name: 'PERFORMANCE_INDEX()',
|
|
401
334
|
description: '성과 지수',
|
|
402
335
|
template: 'PERFORMANCE_INDEX({x}, {alpha1}, {beta1}, {alpha2}, {beta2})',
|
|
403
336
|
syntax: 'PERFORMANCE_INDEX(x, alpha1, beta1, alpha2, beta2)',
|
|
@@ -409,9 +342,8 @@ export class KpiListPage extends connect(store)(p13n(localize(i18next)(ScopedEle
|
|
|
409
342
|
returnType: 'number',
|
|
410
343
|
help: '성과 지수를 계산합니다: 1 - (불완전 베타 / 완전 베타)',
|
|
411
344
|
examples: ['PERFORMANCE_INDEX(0.8, 2, 3, 2, 3)', 'PERFORMANCE_INDEX([성과점수]/100, 2, 3, 2, 3)']
|
|
412
|
-
|
|
413
|
-
{
|
|
414
|
-
name: 'EXP()',
|
|
345
|
+
},
|
|
346
|
+
{ name: 'EXP()',
|
|
415
347
|
description: '지수 함수',
|
|
416
348
|
template: 'EXP({x})',
|
|
417
349
|
syntax: 'EXP(x)',
|
|
@@ -419,9 +351,8 @@ export class KpiListPage extends connect(store)(p13n(localize(i18next)(ScopedEle
|
|
|
419
351
|
returnType: 'number',
|
|
420
352
|
help: '자연상수 e의 x제곱을 계산합니다.',
|
|
421
353
|
examples: ['EXP(1)', 'EXP([효율성])']
|
|
422
|
-
|
|
423
|
-
{
|
|
424
|
-
name: 'LOG()',
|
|
354
|
+
},
|
|
355
|
+
{ name: 'LOG()',
|
|
425
356
|
description: '자연 로그',
|
|
426
357
|
template: 'LOG({x})',
|
|
427
358
|
syntax: 'LOG(x)',
|
|
@@ -429,9 +360,8 @@ export class KpiListPage extends connect(store)(p13n(localize(i18next)(ScopedEle
|
|
|
429
360
|
returnType: 'number',
|
|
430
361
|
help: '자연 로그 ln(x)를 계산합니다.',
|
|
431
362
|
examples: ['LOG(2.718)', 'LOG([성과점수])']
|
|
432
|
-
|
|
433
|
-
{
|
|
434
|
-
name: 'POW()',
|
|
363
|
+
},
|
|
364
|
+
{ name: 'POW()',
|
|
435
365
|
description: '거듭제곱',
|
|
436
366
|
template: 'POW({x}, {y})',
|
|
437
367
|
syntax: 'POW(x, y)',
|
|
@@ -439,9 +369,8 @@ export class KpiListPage extends connect(store)(p13n(localize(i18next)(ScopedEle
|
|
|
439
369
|
returnType: 'number',
|
|
440
370
|
help: 'x의 y제곱을 계산합니다.',
|
|
441
371
|
examples: ['POW(2, 3)', 'POW([효율성], 2)']
|
|
442
|
-
|
|
443
|
-
{
|
|
444
|
-
name: 'EXPONENTIAL_DECAY()',
|
|
372
|
+
},
|
|
373
|
+
{ name: 'EXPONENTIAL_DECAY()',
|
|
445
374
|
description: '지수 감쇠',
|
|
446
375
|
template: 'EXPONENTIAL_DECAY({value}, {scale}, {power})',
|
|
447
376
|
syntax: 'EXPONENTIAL_DECAY(value, scale, power)',
|
|
@@ -449,42 +378,35 @@ export class KpiListPage extends connect(store)(p13n(localize(i18next)(ScopedEle
|
|
|
449
378
|
returnType: 'number',
|
|
450
379
|
help: '지수 감쇠 함수 exp(-(value/scale)^power)를 계산합니다.',
|
|
451
380
|
examples: ['EXPONENTIAL_DECAY(50, 100, 2)', 'EXPONENTIAL_DECAY([목표달성률], 50, 2)']
|
|
452
|
-
|
|
381
|
+
}
|
|
453
382
|
]
|
|
454
|
-
|
|
383
|
+
},
|
|
455
384
|
width: 200
|
|
456
|
-
|
|
457
|
-
{
|
|
458
|
-
type: 'string',
|
|
385
|
+
},
|
|
386
|
+
{ type: 'string',
|
|
459
387
|
name: 'grades',
|
|
460
388
|
header: '성과지수 Lookup',
|
|
461
|
-
record: {
|
|
462
|
-
|
|
463
|
-
renderer: (v, c, r) => {
|
|
464
|
-
if (r.grades && r.grades.length > 0) {
|
|
465
|
-
return html`<span style="color: #4caf50; cursor: pointer;" @click=${() => this._editGrades(r)}>
|
|
389
|
+
record: { editable: false,
|
|
390
|
+
renderer: (v, c, r) => { if (r.grades && r.grades.length > 0) { return html`<span style="color: #4caf50; cursor: pointer;" @click=${() => this._editGrades(r)}>
|
|
466
391
|
${r.grades.length}개 등급 설정됨
|
|
467
392
|
</span>`
|
|
468
|
-
|
|
469
|
-
return html`<span style="color: #999; cursor: pointer;" @click=${() => this._editGrades(r)}>
|
|
393
|
+
} else { return html`<span style="color: #999; cursor: pointer;" @click=${() => this._editGrades(r)}>
|
|
470
394
|
등급 설정 없음
|
|
471
395
|
</span>`
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
},
|
|
475
399
|
width: 150
|
|
476
|
-
|
|
477
|
-
{
|
|
478
|
-
type: 'number',
|
|
400
|
+
},
|
|
401
|
+
{ type: 'number',
|
|
479
402
|
name: 'weight',
|
|
480
403
|
header: '가중치',
|
|
481
404
|
record: { editable: true },
|
|
482
405
|
filter: true,
|
|
483
406
|
sortable: true,
|
|
484
407
|
width: 80
|
|
485
|
-
|
|
486
|
-
{
|
|
487
|
-
type: 'checkbox',
|
|
408
|
+
},
|
|
409
|
+
{ type: 'checkbox',
|
|
488
410
|
name: 'active',
|
|
489
411
|
label: true,
|
|
490
412
|
header: i18next.t('field.active'),
|
|
@@ -492,17 +414,14 @@ export class KpiListPage extends connect(store)(p13n(localize(i18next)(ScopedEle
|
|
|
492
414
|
filter: true,
|
|
493
415
|
sortable: true,
|
|
494
416
|
width: 60
|
|
495
|
-
|
|
417
|
+
},
|
|
496
418
|
{ type: 'string', name: 'state', header: '상태', record: { editable: false }, width: 100 },
|
|
497
|
-
{
|
|
498
|
-
type: 'string',
|
|
419
|
+
{ type: 'string',
|
|
499
420
|
name: 'vizType',
|
|
500
421
|
hidden: true,
|
|
501
422
|
header: '시각화 설정',
|
|
502
|
-
record: {
|
|
503
|
-
|
|
504
|
-
renderer: (v, c, r) => {
|
|
505
|
-
const vizType = r.vizType || 'CARD'
|
|
423
|
+
record: { editable: false,
|
|
424
|
+
renderer: (v, c, r) => { const vizType = r.vizType || 'CARD'
|
|
506
425
|
const vizMeta = r.vizMeta || {}
|
|
507
426
|
const color = vizMeta.color || '#2196f3'
|
|
508
427
|
const icon = vizMeta.icon || 'dashboard'
|
|
@@ -515,67 +434,54 @@ export class KpiListPage extends connect(store)(p13n(localize(i18next)(ScopedEle
|
|
|
515
434
|
</md-icon>
|
|
516
435
|
</div>
|
|
517
436
|
`
|
|
518
|
-
|
|
519
|
-
|
|
437
|
+
}
|
|
438
|
+
},
|
|
520
439
|
width: 150
|
|
521
|
-
|
|
440
|
+
},
|
|
522
441
|
{ type: 'crontab', name: 'schedule', header: '스케줄', record: { editable: true }, width: 120 },
|
|
523
442
|
{ type: 'string', name: 'scheduleId', header: '스케줄ID', record: { editable: false }, width: 120 },
|
|
524
443
|
{ type: 'timezone', name: 'timezone', header: '타임존', record: { editable: true }, width: 120 },
|
|
525
444
|
{ type: 'number', name: 'version', header: '버전', record: { editable: false }, width: 80 },
|
|
526
445
|
{ type: 'datetime', name: 'createdAt', header: '생성일', record: { editable: false }, width: 180 },
|
|
527
|
-
{
|
|
528
|
-
type: 'datetime',
|
|
446
|
+
{ type: 'datetime',
|
|
529
447
|
name: 'updatedAt',
|
|
530
448
|
header: i18next.t('field.updated_at'),
|
|
531
449
|
record: { editable: false },
|
|
532
450
|
sortable: true,
|
|
533
451
|
width: 180
|
|
534
|
-
|
|
535
|
-
{
|
|
536
|
-
type: 'resource-object',
|
|
452
|
+
},
|
|
453
|
+
{ type: 'resource-object',
|
|
537
454
|
name: 'creator',
|
|
538
455
|
header: '생성자',
|
|
539
456
|
record: { editable: false, renderer: (v, c, r) => r.creator?.name },
|
|
540
457
|
width: 120
|
|
541
|
-
|
|
542
|
-
{
|
|
543
|
-
type: 'resource-object',
|
|
458
|
+
},
|
|
459
|
+
{ type: 'resource-object',
|
|
544
460
|
name: 'updater',
|
|
545
461
|
header: i18next.t('field.updater'),
|
|
546
462
|
record: { editable: false, renderer: (v, c, r) => r.updater?.name },
|
|
547
463
|
sortable: true,
|
|
548
464
|
width: 120
|
|
549
|
-
|
|
465
|
+
},
|
|
550
466
|
{ type: 'string', name: 'thumbnail', header: '썸네일', record: { editable: false }, width: 120 }
|
|
551
467
|
],
|
|
552
|
-
rows: {
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
}
|
|
557
|
-
},
|
|
468
|
+
rows: { appendable: false,
|
|
469
|
+
selectable: { multiple: true
|
|
470
|
+
}
|
|
471
|
+
},
|
|
558
472
|
sorters: [{ name: 'name' }]
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
async pageUpdated(changes: any, lifecycle: any) {
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
const response = await client.query({
|
|
574
|
-
query: gql`
|
|
575
|
-
query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
|
|
576
|
-
responses: kpis(filters: $filters, pagination: $pagination, sortings: $sortings) {
|
|
577
|
-
items {
|
|
578
|
-
id
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
async pageUpdated(changes: any, lifecycle: any) { if (this.active) { // do something here when this page just became as active
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
async fetchHandler({ page = 1, limit = 100, sortings = [], filters = [] }: FetchOption) { if (this.hierarchicalView) { return this.fetchHierarchicalData()
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const response = await client.query({ query: gql`
|
|
484
|
+
query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) { responses: kpis(filters: $filters, pagination: $pagination, sortings: $sortings) { items { id
|
|
579
485
|
name
|
|
580
486
|
description
|
|
581
487
|
active
|
|
@@ -590,236 +496,179 @@ export class KpiListPage extends connect(store)(p13n(localize(i18next)(ScopedEle
|
|
|
590
496
|
scheduleId
|
|
591
497
|
timezone
|
|
592
498
|
version
|
|
593
|
-
parent {
|
|
594
|
-
id
|
|
499
|
+
parent { id
|
|
595
500
|
name
|
|
596
|
-
|
|
597
|
-
children {
|
|
598
|
-
id
|
|
501
|
+
}
|
|
502
|
+
children { id
|
|
599
503
|
name
|
|
600
504
|
description
|
|
601
|
-
|
|
505
|
+
}
|
|
602
506
|
isLeaf
|
|
603
|
-
updater {
|
|
604
|
-
id
|
|
507
|
+
updater { id
|
|
605
508
|
name
|
|
606
|
-
|
|
509
|
+
}
|
|
607
510
|
updatedAt
|
|
608
|
-
creator {
|
|
609
|
-
id
|
|
511
|
+
creator { id
|
|
610
512
|
name
|
|
611
|
-
|
|
513
|
+
}
|
|
612
514
|
createdAt
|
|
613
|
-
|
|
515
|
+
}
|
|
614
516
|
total
|
|
615
|
-
|
|
616
|
-
|
|
517
|
+
}
|
|
518
|
+
}
|
|
617
519
|
`,
|
|
618
|
-
variables: {
|
|
619
|
-
filters,
|
|
520
|
+
variables: { filters,
|
|
620
521
|
pagination: { page, limit },
|
|
621
522
|
sortings
|
|
622
|
-
|
|
623
|
-
|
|
523
|
+
}
|
|
524
|
+
})
|
|
624
525
|
|
|
625
|
-
return {
|
|
626
|
-
total: response.data.responses.total || 0,
|
|
526
|
+
return { total: response.data.responses.total || 0,
|
|
627
527
|
records: response.data.responses.items || []
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
async fetchKpiMetrics() {
|
|
632
|
-
|
|
633
|
-
query: gql`
|
|
634
|
-
query {
|
|
635
|
-
kpiMetrics {
|
|
636
|
-
items {
|
|
637
|
-
name
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
async fetchKpiMetrics() { const response = await client.query({ query: gql`
|
|
532
|
+
query { kpiMetrics { items { name
|
|
638
533
|
description
|
|
639
534
|
unit
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
643
538
|
`
|
|
644
|
-
|
|
539
|
+
})
|
|
645
540
|
|
|
646
|
-
if (!response.errors) {
|
|
647
|
-
this.availableVariables = (response.data.kpiMetrics.items || []).map(metric => ({
|
|
648
|
-
name: metric.name,
|
|
541
|
+
if (!response.errors) { this.availableVariables = (response.data.kpiMetrics.items || []).map(metric => ({ name: metric.name,
|
|
649
542
|
description: metric.description,
|
|
650
543
|
type: 'kpi-metric',
|
|
651
544
|
unit: metric.unit
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
async _deleteKpi() {
|
|
657
|
-
|
|
658
|
-
await OxPrompt.open({
|
|
659
|
-
title: i18next.t('text.are_you_sure'),
|
|
545
|
+
}))
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
async _deleteKpi() { if (
|
|
550
|
+
await OxPrompt.open({ title: i18next.t('text.are_you_sure'),
|
|
660
551
|
text: i18next.t('text.sure_to_x', { x: i18next.t('text.delete') }),
|
|
661
552
|
confirmButton: { text: i18next.t('button.confirm') },
|
|
662
553
|
cancelButton: { text: i18next.t('button.cancel') }
|
|
663
|
-
|
|
664
|
-
) {
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
mutation: gql`
|
|
669
|
-
mutation ($ids: [String!]!) {
|
|
670
|
-
deleteKpis(ids: $ids)
|
|
671
|
-
}
|
|
554
|
+
})
|
|
555
|
+
) { const ids = this.grist.selected.map(record => record.id)
|
|
556
|
+
if (ids && ids.length > 0) { const response = await client.mutate({ mutation: gql`
|
|
557
|
+
mutation ($ids: [String!]!) { deleteKpis(ids: $ids)
|
|
558
|
+
}
|
|
672
559
|
`,
|
|
673
|
-
variables: {
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
async _updateKpi() {
|
|
689
|
-
let patches = this.grist.dirtyRecords
|
|
690
|
-
if (patches && patches.length) {
|
|
691
|
-
patches = patches.map(patch => {
|
|
692
|
-
let patchField: any = patch.id ? { id: patch.id } : {}
|
|
560
|
+
variables: { ids
|
|
561
|
+
}
|
|
562
|
+
})
|
|
563
|
+
|
|
564
|
+
if (!response.errors) { this.grist.fetch()
|
|
565
|
+
notify({ message: i18next.t('text.info_x_successfully', { x: i18next.t('text.delete') })
|
|
566
|
+
})
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
async _updateKpi() { let patches = this.grist.dirtyRecords
|
|
573
|
+
if (patches && patches.length) { patches = patches.map(patch => { let patchField: any = patch.id ? { id: patch.id } : {}
|
|
693
574
|
const dirtyFields = patch.__dirtyfields__
|
|
694
|
-
for (let key in dirtyFields) {
|
|
695
|
-
|
|
696
|
-
}
|
|
575
|
+
for (let key in dirtyFields) { patchField[key] = dirtyFields[key].after
|
|
576
|
+
}
|
|
697
577
|
patchField.cuFlag = patch.__dirty__
|
|
698
578
|
|
|
699
579
|
return patchField
|
|
700
|
-
|
|
580
|
+
})
|
|
701
581
|
|
|
702
|
-
const response = await client.mutate({
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
name
|
|
707
|
-
}
|
|
708
|
-
}
|
|
582
|
+
const response = await client.mutate({ mutation: gql`
|
|
583
|
+
mutation ($patches: [KpiPatch!]!) { updateMultipleKpi(patches: $patches) { name
|
|
584
|
+
}
|
|
585
|
+
}
|
|
709
586
|
`,
|
|
710
|
-
variables: {
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
const response = await client.query({
|
|
724
|
-
query: gql`
|
|
725
|
-
mutation ($kpi: NewKpi!) {
|
|
726
|
-
createKpi(kpi: $kpi) {
|
|
727
|
-
id
|
|
728
|
-
}
|
|
729
|
-
}
|
|
587
|
+
variables: { patches
|
|
588
|
+
}
|
|
589
|
+
})
|
|
590
|
+
|
|
591
|
+
if (!response.errors) { this.grist.fetch()
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
async creationCallback(kpi) { try { const response = await client.query({ query: gql`
|
|
597
|
+
mutation ($kpi: NewKpi!) { createKpi(kpi: $kpi) { id
|
|
598
|
+
}
|
|
599
|
+
}
|
|
730
600
|
`,
|
|
731
|
-
variables: {
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
if (!response.errors) {
|
|
740
|
-
this.grist.fetch()
|
|
601
|
+
variables: { kpi
|
|
602
|
+
},
|
|
603
|
+
context: { hasUpload: true
|
|
604
|
+
}
|
|
605
|
+
})
|
|
606
|
+
|
|
607
|
+
if (!response.errors) { this.grist.fetch()
|
|
741
608
|
document.dispatchEvent(
|
|
742
|
-
new CustomEvent('notify', {
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
}
|
|
746
|
-
})
|
|
609
|
+
new CustomEvent('notify', { detail: { message: i18next.t('text.data_created_successfully')
|
|
610
|
+
}
|
|
611
|
+
})
|
|
747
612
|
)
|
|
748
|
-
|
|
613
|
+
}
|
|
749
614
|
|
|
750
615
|
return true
|
|
751
|
-
|
|
752
|
-
console.error(ex)
|
|
616
|
+
} catch (ex) { console.error(ex)
|
|
753
617
|
document.dispatchEvent(
|
|
754
|
-
new CustomEvent('notify', {
|
|
755
|
-
detail: {
|
|
756
|
-
type: 'error',
|
|
618
|
+
new CustomEvent('notify', { detail: { type: 'error',
|
|
757
619
|
message: i18next.t('text.error')
|
|
758
|
-
|
|
759
|
-
|
|
620
|
+
}
|
|
621
|
+
})
|
|
760
622
|
)
|
|
761
623
|
return false
|
|
762
|
-
|
|
763
|
-
|
|
624
|
+
}
|
|
625
|
+
}
|
|
764
626
|
|
|
765
|
-
async exportHandler() {
|
|
766
|
-
const exportTargets = this.grist.selected.length ? this.grist.selected : this.grist.dirtyData.records
|
|
627
|
+
async exportHandler() { const exportTargets = this.grist.selected.length ? this.grist.selected : this.grist.dirtyData.records
|
|
767
628
|
const targetFieldSet = new Set(['id', 'name', 'description', 'active'])
|
|
768
629
|
|
|
769
|
-
return exportTargets.map(kpi => {
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
tempObj[field] = kpi[field]
|
|
773
|
-
}
|
|
630
|
+
return exportTargets.map(kpi => { let tempObj = {}
|
|
631
|
+
for (const field of targetFieldSet) { tempObj[field] = kpi[field]
|
|
632
|
+
}
|
|
774
633
|
|
|
775
634
|
return tempObj
|
|
776
|
-
|
|
777
|
-
|
|
635
|
+
})
|
|
636
|
+
}
|
|
778
637
|
|
|
779
|
-
async importHandler(records) {
|
|
780
|
-
const popup = openPopup(
|
|
638
|
+
async importHandler(records) { const popup = openPopup(
|
|
781
639
|
html`
|
|
782
640
|
<kpi-importer
|
|
783
641
|
.kpis=${records}
|
|
784
|
-
@imported=${() => {
|
|
785
|
-
history.back()
|
|
642
|
+
@imported=${() => { history.back()
|
|
786
643
|
this.grist.fetch()
|
|
787
|
-
|
|
644
|
+
}}
|
|
788
645
|
></kpi-importer>
|
|
789
646
|
`,
|
|
790
|
-
{
|
|
791
|
-
backdrop: true,
|
|
647
|
+
{ backdrop: true,
|
|
792
648
|
size: 'large',
|
|
793
649
|
title: i18next.t('title.import kpi')
|
|
794
|
-
|
|
650
|
+
}
|
|
795
651
|
)
|
|
796
652
|
|
|
797
|
-
popup.onclosed = () => {
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
}
|
|
653
|
+
popup.onclosed = () => { this.grist.fetch()
|
|
654
|
+
}
|
|
655
|
+
}
|
|
801
656
|
|
|
802
|
-
async _editGrades(kpi: any) {
|
|
803
|
-
|
|
804
|
-
notify({
|
|
805
|
-
message: 'KPI를 먼저 저장한 후에 등급 설정을 할 수 있습니다.'
|
|
806
|
-
})
|
|
657
|
+
async _editGrades(kpi: any) { if (!kpi.id) { notify({ message: 'KPI를 먼저 저장한 후에 등급 설정을 할 수 있습니다.'
|
|
658
|
+
})
|
|
807
659
|
|
|
808
660
|
return
|
|
809
|
-
|
|
661
|
+
}
|
|
810
662
|
|
|
811
|
-
const popup = await openPopup(html` <kpi-grade-editor .kpi=${kpi}></kpi-grade-editor> `, {
|
|
812
|
-
title: `${kpi.name} - 등급 설정`,
|
|
663
|
+
const popup = await openPopup(html` <kpi-grade-editor .kpi=${kpi}></kpi-grade-editor> `, { title: `${kpi.name} - 등급 설정`,
|
|
813
664
|
size: 'large'
|
|
814
|
-
|
|
665
|
+
})
|
|
815
666
|
|
|
816
|
-
popup.onclosed = () => {
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
}
|
|
667
|
+
popup.onclosed = () => { this.grist.fetch()
|
|
668
|
+
}
|
|
669
|
+
}
|
|
820
670
|
|
|
821
|
-
async _editViz(kpi: any) {
|
|
822
|
-
const popup = await openPopup(
|
|
671
|
+
async _editViz(kpi: any) { const popup = await openPopup(
|
|
823
672
|
html`
|
|
824
673
|
<kpi-viz-editor
|
|
825
674
|
.kpi=${kpi}
|
|
@@ -827,82 +676,58 @@ export class KpiListPage extends connect(store)(p13n(localize(i18next)(ScopedEle
|
|
|
827
676
|
.onCancel=${() => popup.close()}
|
|
828
677
|
></kpi-viz-editor>
|
|
829
678
|
`,
|
|
830
|
-
{
|
|
831
|
-
title: `${kpi.name} - 시각화 설정`,
|
|
679
|
+
{ title: `${kpi.name} - 시각화 설정`,
|
|
832
680
|
size: 'large'
|
|
833
|
-
|
|
681
|
+
}
|
|
834
682
|
)
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
async _onVizUpdated(kpiId: string, vizType: string, vizMeta: any) {
|
|
838
|
-
|
|
839
|
-
const response = await client.mutate({
|
|
840
|
-
mutation: gql`
|
|
841
|
-
mutation ($id: String!, $patch: KpiPatch!) {
|
|
842
|
-
updateKpi(id: $id, patch: $patch) {
|
|
843
|
-
id
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
async _onVizUpdated(kpiId: string, vizType: string, vizMeta: any) { try { const response = await client.mutate({ mutation: gql`
|
|
686
|
+
mutation ($id: String!, $patch: KpiPatch!) { updateKpi(id: $id, patch: $patch) { id
|
|
844
687
|
name
|
|
845
688
|
vizType
|
|
846
689
|
vizMeta
|
|
847
|
-
|
|
848
|
-
|
|
690
|
+
}
|
|
691
|
+
}
|
|
849
692
|
`,
|
|
850
|
-
variables: {
|
|
851
|
-
id: kpiId,
|
|
693
|
+
variables: { id: kpiId,
|
|
852
694
|
patch: { vizType, vizMeta }
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
if (!response.errors) {
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
async _calculateKpiValue(kpi) {
|
|
870
|
-
try {
|
|
871
|
-
const response = await client.mutate({
|
|
872
|
-
mutation: gql`
|
|
873
|
-
mutation ($kpiId: String!) {
|
|
874
|
-
calculateKpiValue(kpiId: $kpiId) {
|
|
875
|
-
id
|
|
695
|
+
}
|
|
696
|
+
})
|
|
697
|
+
|
|
698
|
+
if (!response.errors) { this.grist.fetch()
|
|
699
|
+
notify({ message: '시각화 설정이 성공적으로 업데이트되었습니다.'
|
|
700
|
+
})
|
|
701
|
+
}
|
|
702
|
+
} catch (error) { notify({ message: '시각화 설정 업데이트 중 오류가 발생했습니다.'
|
|
703
|
+
})
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
async _calculateKpiValue(kpi) { try { const response = await client.mutate({ mutation: gql`
|
|
708
|
+
mutation ($kpiId: String!) { calculateKpiValue(kpiId: $kpiId) { id
|
|
876
709
|
value
|
|
877
710
|
valueDate
|
|
878
711
|
org
|
|
879
|
-
|
|
880
|
-
|
|
712
|
+
}
|
|
713
|
+
}
|
|
881
714
|
`,
|
|
882
|
-
variables: {
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
})
|
|
886
|
-
if (!response.errors) {
|
|
887
|
-
notify({ message: 'KPI 실적값이 성공적으로 계산되었습니다.' })
|
|
715
|
+
variables: { kpiId: kpi.id
|
|
716
|
+
}
|
|
717
|
+
})
|
|
718
|
+
if (!response.errors) { notify({ message: 'KPI 실적값이 성공적으로 계산되었습니다.' })
|
|
888
719
|
this.grist.fetch()
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
_toggleHierarchicalView() {
|
|
896
|
-
this.hierarchicalView = !this.hierarchicalView
|
|
720
|
+
}
|
|
721
|
+
} catch (error) { notify({ message: 'KPI 실적값 계산 중 오류가 발생했습니다.' })
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
_toggleHierarchicalView() { this.hierarchicalView = !this.hierarchicalView
|
|
897
726
|
this.grist.fetch()
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
async fetchHierarchicalData() {
|
|
901
|
-
|
|
902
|
-
query: gql`
|
|
903
|
-
query {
|
|
904
|
-
kpiTree {
|
|
905
|
-
id
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
async fetchHierarchicalData() { const response = await client.query({ query: gql`
|
|
730
|
+
query { kpiTree { id
|
|
906
731
|
name
|
|
907
732
|
description
|
|
908
733
|
active
|
|
@@ -917,79 +742,68 @@ export class KpiListPage extends connect(store)(p13n(localize(i18next)(ScopedEle
|
|
|
917
742
|
scheduleId
|
|
918
743
|
timezone
|
|
919
744
|
version
|
|
920
|
-
parent {
|
|
921
|
-
id
|
|
745
|
+
parent { id
|
|
922
746
|
name
|
|
923
|
-
|
|
924
|
-
children {
|
|
925
|
-
id
|
|
747
|
+
}
|
|
748
|
+
children { id
|
|
926
749
|
name
|
|
927
750
|
description
|
|
928
751
|
active
|
|
929
752
|
isLeaf
|
|
930
753
|
weight
|
|
931
|
-
children {
|
|
932
|
-
id
|
|
754
|
+
children { id
|
|
933
755
|
name
|
|
934
756
|
description
|
|
935
757
|
active
|
|
936
758
|
isLeaf
|
|
937
759
|
weight
|
|
938
|
-
children {
|
|
939
|
-
id
|
|
760
|
+
children { id
|
|
940
761
|
name
|
|
941
762
|
description
|
|
942
763
|
active
|
|
943
764
|
isLeaf
|
|
944
765
|
weight
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
948
769
|
isLeaf
|
|
949
|
-
updater {
|
|
950
|
-
id
|
|
770
|
+
updater { id
|
|
951
771
|
name
|
|
952
|
-
|
|
772
|
+
}
|
|
953
773
|
updatedAt
|
|
954
|
-
creator {
|
|
955
|
-
id
|
|
774
|
+
creator { id
|
|
956
775
|
name
|
|
957
|
-
|
|
776
|
+
}
|
|
958
777
|
createdAt
|
|
959
|
-
|
|
960
|
-
|
|
778
|
+
}
|
|
779
|
+
}
|
|
961
780
|
`
|
|
962
|
-
|
|
781
|
+
})
|
|
963
782
|
|
|
964
783
|
const flattenedRecords = this.flattenTreeData(response.data.kpiTree)
|
|
965
784
|
|
|
966
|
-
return {
|
|
967
|
-
total: flattenedRecords.length,
|
|
785
|
+
return { total: flattenedRecords.length,
|
|
968
786
|
records: flattenedRecords
|
|
969
|
-
|
|
970
|
-
|
|
787
|
+
}
|
|
788
|
+
}
|
|
971
789
|
|
|
972
|
-
flattenTreeData(treeData: any[], level = 0): any[] {
|
|
973
|
-
const flattened: any[] = []
|
|
790
|
+
flattenTreeData(treeData: any[], level = 0): any[] { const flattened: any[] = []
|
|
974
791
|
|
|
975
|
-
for (const item of treeData) {
|
|
976
|
-
const flattenedItem = {
|
|
977
|
-
...item,
|
|
792
|
+
for (const item of treeData) { const flattenedItem = { ...item,
|
|
978
793
|
__level: level,
|
|
979
794
|
__hasChildren: item.children && item.children.length > 0,
|
|
980
795
|
__expanded: true
|
|
981
|
-
|
|
796
|
+
}
|
|
982
797
|
|
|
983
798
|
// Add indentation to name for visual hierarchy
|
|
984
799
|
flattenedItem.name = ' '.repeat(level) + (level > 0 ? '└ ' : '') + item.name
|
|
985
800
|
|
|
986
801
|
flattened.push(flattenedItem)
|
|
987
802
|
|
|
988
|
-
if (item.children && item.children.length > 0) {
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
}
|
|
803
|
+
if (item.children && item.children.length > 0) { flattened.push(...this.flattenTreeData(item.children, level + 1))
|
|
804
|
+
}
|
|
805
|
+
}
|
|
992
806
|
|
|
993
807
|
return flattened
|
|
994
|
-
|
|
808
|
+
}
|
|
995
809
|
}
|