@things-factory/kpi 9.0.17 → 9.0.19
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/bootstrap.ts +8 -0
- package/client/pages/kpi/kpi-list-page.ts +99 -11
- package/client/pages/kpi/kpi-viz-editor.ts +214 -14
- package/client/pages/kpi-category/kpi-category-list-page.ts +80 -8
- package/client/pages/kpi-history/kpi-history-list-page.ts +1 -1
- package/client/pages/kpi-metric/kpi-metric-list-page.ts +31 -7
- package/client/pages/kpi-metric-value/kpi-metric-value-importer.ts +65 -0
- package/client/pages/kpi-metric-value/kpi-metric-value-list-page.ts +299 -0
- package/client/pages/{kpi-value/kpi-value-manual-entry-form.ts → kpi-metric-value/kpi-metric-value-manual-entry-form.ts} +18 -44
- package/client/pages/{kpi-value/kpi-value-manual-entry-page.ts → kpi-metric-value/kpi-metric-value-manual-entry-page.ts} +21 -21
- package/client/pages/kpi-value/kpi-value-list-page.ts +4 -6
- package/client/route.ts +6 -2
- package/dist-client/bootstrap.d.ts +2 -0
- package/dist-client/bootstrap.js +7 -0
- package/dist-client/bootstrap.js.map +1 -0
- package/dist-client/pages/kpi/kpi-list-page.d.ts +6 -0
- package/dist-client/pages/kpi/kpi-list-page.js +100 -11
- package/dist-client/pages/kpi/kpi-list-page.js.map +1 -1
- package/dist-client/pages/kpi/kpi-viz-editor.js +208 -14
- package/dist-client/pages/kpi/kpi-viz-editor.js.map +1 -1
- package/dist-client/pages/kpi-category/kpi-category-list-page.d.ts +5 -0
- package/dist-client/pages/kpi-category/kpi-category-list-page.js +83 -8
- package/dist-client/pages/kpi-category/kpi-category-list-page.js.map +1 -1
- package/dist-client/pages/kpi-history/kpi-history-list-page.js +1 -1
- package/dist-client/pages/kpi-history/kpi-history-list-page.js.map +1 -1
- package/dist-client/pages/kpi-metric/kpi-metric-list-page.js +29 -5
- package/dist-client/pages/kpi-metric/kpi-metric-list-page.js.map +1 -1
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.d.ts +23 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.js +75 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.js.map +1 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.d.ts +61 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js +301 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js.map +1 -0
- package/dist-client/pages/{kpi-value/kpi-value-manual-entry-form.d.ts → kpi-metric-value/kpi-metric-value-manual-entry-form.d.ts} +3 -5
- package/dist-client/pages/{kpi-value/kpi-value-manual-entry-form.js → kpi-metric-value/kpi-metric-value-manual-entry-form.js} +27 -56
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.js.map +1 -0
- package/dist-client/pages/{kpi-value/kpi-value-manual-entry-page.d.ts → kpi-metric-value/kpi-metric-value-manual-entry-page.d.ts} +5 -5
- package/dist-client/pages/{kpi-value/kpi-value-manual-entry-page.js → kpi-metric-value/kpi-metric-value-manual-entry-page.js} +28 -28
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.js.map +1 -0
- package/dist-client/pages/kpi-value/kpi-value-list-page.js +4 -6
- 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 +5 -2
- package/dist-client/route.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/service/index.d.ts +4 -2
- package/dist-server/service/index.js +6 -1
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/kpi/aggregate-kpi.js +5 -7
- package/dist-server/service/kpi/aggregate-kpi.js.map +1 -1
- package/dist-server/service/kpi/kpi-history.d.ts +3 -1
- package/dist-server/service/kpi/kpi-history.js +10 -0
- package/dist-server/service/kpi/kpi-history.js.map +1 -1
- package/dist-server/service/kpi/kpi-mutation.js +1 -1
- package/dist-server/service/kpi/kpi-mutation.js.map +1 -1
- package/dist-server/service/kpi/kpi-type.d.ts +2 -0
- package/dist-server/service/kpi/kpi-type.js +8 -0
- package/dist-server/service/kpi/kpi-type.js.map +1 -1
- package/dist-server/service/kpi/kpi.d.ts +9 -0
- package/dist-server/service/kpi/kpi.js +23 -1
- package/dist-server/service/kpi/kpi.js.map +1 -1
- package/dist-server/service/kpi-category/kpi-category-mutation.js +0 -8
- package/dist-server/service/kpi-category/kpi-category-mutation.js.map +1 -1
- package/dist-server/service/kpi-category/kpi-category-type.d.ts +4 -2
- package/dist-server/service/kpi-category/kpi-category-type.js +16 -8
- package/dist-server/service/kpi-category/kpi-category-type.js.map +1 -1
- package/dist-server/service/kpi-category/kpi-category.d.ts +2 -2
- package/dist-server/service/kpi-category/kpi-category.js +8 -8
- package/dist-server/service/kpi-category/kpi-category.js.map +1 -1
- package/dist-server/service/kpi-metric/aggregate-kpi-metric.js +31 -74
- package/dist-server/service/kpi-metric/aggregate-kpi-metric.js.map +1 -1
- package/dist-server/service/kpi-metric/kpi-metric-mutation.d.ts +1 -1
- package/dist-server/service/kpi-metric/kpi-metric-mutation.js +15 -28
- package/dist-server/service/kpi-metric/kpi-metric-mutation.js.map +1 -1
- package/dist-server/service/kpi-metric/kpi-metric-type.d.ts +6 -4
- package/dist-server/service/kpi-metric/kpi-metric-type.js +20 -12
- package/dist-server/service/kpi-metric/kpi-metric-type.js.map +1 -1
- package/dist-server/service/kpi-metric/kpi-metric.d.ts +15 -2
- package/dist-server/service/kpi-metric/kpi-metric.js +34 -14
- package/dist-server/service/kpi-metric/kpi-metric.js.map +1 -1
- package/dist-server/service/kpi-metric-value/index.d.ts +6 -0
- package/dist-server/service/kpi-metric-value/index.js +10 -0
- package/dist-server/service/kpi-metric-value/index.js.map +1 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.d.ts +11 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js +229 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js.map +1 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-query.d.ts +13 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-query.js +95 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-query.js.map +1 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-type.d.ts +26 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-type.js +112 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-type.js.map +1 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value.d.ts +23 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value.js +106 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value.js.map +1 -0
- package/dist-server/service/kpi-value/kpi-value-mutation.js +1 -2
- package/dist-server/service/kpi-value/kpi-value-mutation.js.map +1 -1
- package/dist-server/service/kpi-value/kpi-value-query.js +1 -1
- package/dist-server/service/kpi-value/kpi-value-query.js.map +1 -1
- package/dist-server/service/kpi-value/kpi-value-type.d.ts +2 -4
- package/dist-server/service/kpi-value/kpi-value-type.js +4 -18
- package/dist-server/service/kpi-value/kpi-value-type.js.map +1 -1
- package/dist-server/service/kpi-value/kpi-value.d.ts +3 -3
- package/dist-server/service/kpi-value/kpi-value.js +13 -14
- package/dist-server/service/kpi-value/kpi-value.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/server/service/index.ts +6 -1
- package/server/service/kpi/aggregate-kpi.ts +5 -8
- package/server/service/kpi/kpi-history.ts +9 -1
- package/server/service/kpi/kpi-mutation.ts +1 -1
- package/server/service/kpi/kpi-type.ts +6 -0
- package/server/service/kpi/kpi.ts +21 -0
- package/server/service/kpi-category/kpi-category-mutation.ts +0 -10
- package/server/service/kpi-category/kpi-category-type.ts +12 -6
- package/server/service/kpi-category/kpi-category.ts +6 -6
- package/server/service/kpi-metric/aggregate-kpi-metric.ts +29 -69
- package/server/service/kpi-metric/kpi-metric-mutation.ts +15 -26
- package/server/service/kpi-metric/kpi-metric-type.ts +17 -12
- package/server/service/kpi-metric/kpi-metric.ts +32 -11
- package/server/service/kpi-metric-value/index.ts +7 -0
- package/server/service/kpi-metric-value/kpi-metric-value-mutation.ts +215 -0
- package/server/service/kpi-metric-value/kpi-metric-value-query.ts +60 -0
- package/server/service/kpi-metric-value/kpi-metric-value-type.ts +82 -0
- package/server/service/kpi-metric-value/kpi-metric-value.ts +91 -0
- package/server/service/kpi-value/kpi-value-mutation.ts +1 -2
- package/server/service/kpi-value/kpi-value-query.ts +1 -1
- package/server/service/kpi-value/kpi-value-type.ts +4 -16
- package/server/service/kpi-value/kpi-value.ts +14 -14
- package/things-factory.config.js +5 -3
- package/translations/en.json +8 -1
- package/translations/ja.json +8 -1
- package/translations/ko.json +9 -2
- package/translations/ms.json +9 -2
- package/translations/zh.json +8 -1
- package/dist-client/pages/kpi-value/kpi-value-manual-entry-form.js.map +0 -1
- package/dist-client/pages/kpi-value/kpi-value-manual-entry-page.js.map +0 -1
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import '@material/web/icon/icon.js'
|
|
2
|
+
import '@operato/data-grist'
|
|
3
|
+
import gql from 'graphql-tag'
|
|
4
|
+
import { css, html, LitElement } from 'lit'
|
|
5
|
+
import { property } from 'lit/decorators.js'
|
|
6
|
+
import { client } from '@operato/graphql'
|
|
7
|
+
import { i18next } from '@operato/i18n'
|
|
8
|
+
import { isMobileDevice } from '@operato/utils'
|
|
9
|
+
import { ButtonContainerStyles } from '@operato/styles'
|
|
10
|
+
|
|
11
|
+
export class KpiMetricValueImporter extends LitElement {
|
|
12
|
+
static styles = [
|
|
13
|
+
ButtonContainerStyles,
|
|
14
|
+
css`
|
|
15
|
+
:host {
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
background-color: #fff;
|
|
19
|
+
}
|
|
20
|
+
ox-grist {
|
|
21
|
+
flex: 1;
|
|
22
|
+
}
|
|
23
|
+
`
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
@property({ type: Array }) metricValues: any[] = []
|
|
27
|
+
@property({ type: Object }) columns = {
|
|
28
|
+
list: { fields: ['metric', 'value', 'valueDate', 'group', 'meta'] },
|
|
29
|
+
pagination: { infinite: true },
|
|
30
|
+
columns: [
|
|
31
|
+
{ type: 'string', name: 'metric', header: 'Metric', width: 150 },
|
|
32
|
+
{ type: 'number', name: 'value', header: '값', width: 120 },
|
|
33
|
+
{ type: 'date', name: 'valueDate', header: '날짜', width: 120 },
|
|
34
|
+
{ type: 'string', name: 'group', header: '그룹', width: 120 },
|
|
35
|
+
{ type: 'object', name: 'meta', header: '메타', width: 120 }
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
render() {
|
|
40
|
+
return html`
|
|
41
|
+
<ox-grist
|
|
42
|
+
.mode=${isMobileDevice() ? 'LIST' : 'GRID'}
|
|
43
|
+
.config=${this.columns}
|
|
44
|
+
.data=${{ records: this.metricValues }}
|
|
45
|
+
></ox-grist>
|
|
46
|
+
<div class="button-container">
|
|
47
|
+
<button @click="${this.save.bind(this)}"><md-icon>save</md-icon>${i18next.t('button.save')}</button>
|
|
48
|
+
</div>
|
|
49
|
+
`
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async save() {
|
|
53
|
+
const response = await client.mutate({
|
|
54
|
+
mutation: gql`
|
|
55
|
+
mutation importKpiMetricValues($metricValues: [KpiMetricValuePatch!]!) {
|
|
56
|
+
importKpiMetricValues(metricValues: $metricValues)
|
|
57
|
+
}
|
|
58
|
+
`,
|
|
59
|
+
variables: { metricValues: this.metricValues }
|
|
60
|
+
})
|
|
61
|
+
if (response.errors?.length) return
|
|
62
|
+
this.dispatchEvent(new CustomEvent('imported'))
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
customElements.define('kpi-metric-value-importer', KpiMetricValueImporter)
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import '@material/web/icon/icon.js'
|
|
2
|
+
import '@material/web/button/elevated-button.js'
|
|
3
|
+
import '@operato/data-grist/ox-grist.js'
|
|
4
|
+
import '@operato/data-grist/ox-filters-form.js'
|
|
5
|
+
import '@operato/data-grist/ox-record-creator.js'
|
|
6
|
+
|
|
7
|
+
import { CommonButtonStyles, CommonHeaderStyles, CommonGristStyles, ScrollbarStyles } from '@operato/styles'
|
|
8
|
+
import { PageView, store } from '@operato/shell'
|
|
9
|
+
import { css, html } from 'lit'
|
|
10
|
+
import { customElement, property, query } from 'lit/decorators.js'
|
|
11
|
+
import { ScopedElementsMixin } from '@open-wc/scoped-elements'
|
|
12
|
+
import { ColumnConfig, DataGrist, FetchOption } from '@operato/data-grist'
|
|
13
|
+
import { client } from '@operato/graphql'
|
|
14
|
+
import { i18next, localize } from '@operato/i18n'
|
|
15
|
+
import { notify, openPopup } from '@operato/layout'
|
|
16
|
+
import { OxPopup, OxPrompt } from '@operato/popup'
|
|
17
|
+
import { isMobileDevice } from '@operato/utils'
|
|
18
|
+
|
|
19
|
+
import { connect } from 'pwa-helpers/connect-mixin'
|
|
20
|
+
import gql from 'graphql-tag'
|
|
21
|
+
|
|
22
|
+
@customElement('kpi-metric-value-list-page')
|
|
23
|
+
export class KpiMetricValueListPage extends connect(store)(localize(i18next)(ScopedElementsMixin(PageView))) {
|
|
24
|
+
static styles = [
|
|
25
|
+
ScrollbarStyles,
|
|
26
|
+
CommonGristStyles,
|
|
27
|
+
CommonHeaderStyles,
|
|
28
|
+
css`
|
|
29
|
+
:host {
|
|
30
|
+
display: flex;
|
|
31
|
+
width: 100%;
|
|
32
|
+
}
|
|
33
|
+
ox-grist {
|
|
34
|
+
overflow-y: auto;
|
|
35
|
+
flex: 1;
|
|
36
|
+
}
|
|
37
|
+
ox-filters-form {
|
|
38
|
+
flex: 1;
|
|
39
|
+
}
|
|
40
|
+
`
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
@property({ type: Object }) gristConfig: any
|
|
44
|
+
@property({ type: String }) mode: 'CARD' | 'GRID' | 'LIST' = isMobileDevice() ? 'CARD' : 'GRID'
|
|
45
|
+
@query('ox-grist') private grist!: DataGrist
|
|
46
|
+
|
|
47
|
+
get context() {
|
|
48
|
+
return {
|
|
49
|
+
title: i18next.t('title.kpi metric value list'),
|
|
50
|
+
search: {
|
|
51
|
+
handler: (search: string) => {
|
|
52
|
+
this.grist.searchText = search
|
|
53
|
+
},
|
|
54
|
+
value: this.grist.searchText
|
|
55
|
+
},
|
|
56
|
+
filter: {
|
|
57
|
+
handler: () => {
|
|
58
|
+
this.grist.toggleHeadroom()
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
help: 'kpi/kpi-metric-value',
|
|
62
|
+
actions: [
|
|
63
|
+
{
|
|
64
|
+
title: i18next.t('button.save'),
|
|
65
|
+
action: this._updateKpiMetricValue.bind(this),
|
|
66
|
+
...CommonButtonStyles.save
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
title: i18next.t('button.delete'),
|
|
70
|
+
action: this._deleteKpiMetricValue.bind(this),
|
|
71
|
+
...CommonButtonStyles.delete
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
exportable: {
|
|
75
|
+
name: i18next.t('title.kpi metric value list'),
|
|
76
|
+
data: this.exportHandler.bind(this)
|
|
77
|
+
},
|
|
78
|
+
importable: {
|
|
79
|
+
handler: this.importHandler.bind(this)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
render() {
|
|
85
|
+
const mode = this.mode || (isMobileDevice() ? 'CARD' : 'GRID')
|
|
86
|
+
return html`
|
|
87
|
+
<ox-grist .mode=${mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>
|
|
88
|
+
<div slot="headroom" class="header">
|
|
89
|
+
<div class="filters">
|
|
90
|
+
<ox-filters-form autofocus without-search></ox-filters-form>
|
|
91
|
+
<div id="modes">
|
|
92
|
+
<md-icon @click=${() => (this.mode = 'GRID')} ?active=${mode == 'GRID'}>grid_on</md-icon>
|
|
93
|
+
<md-icon @click=${() => (this.mode = 'LIST')} ?active=${mode == 'LIST'}>format_list_bulleted</md-icon>
|
|
94
|
+
<md-icon @click=${() => (this.mode = 'CARD')} ?active=${mode == 'CARD'}>apps</md-icon>
|
|
95
|
+
</div>
|
|
96
|
+
<ox-record-creator id="add" .callback=${this.creationCallback.bind(this)}>
|
|
97
|
+
<button>
|
|
98
|
+
<md-icon>add</md-icon>
|
|
99
|
+
</button>
|
|
100
|
+
</ox-record-creator>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
</ox-grist>
|
|
104
|
+
`
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async pageInitialized() {
|
|
108
|
+
this.gristConfig = {
|
|
109
|
+
list: {
|
|
110
|
+
fields: ['metric', 'valueDate', 'value', 'group', 'meta', 'createdAt', 'updatedAt', 'creator', 'updater'],
|
|
111
|
+
details: ['metric', 'valueDate', 'value', 'group', 'meta', 'createdAt', 'updatedAt', 'creator', 'updater']
|
|
112
|
+
},
|
|
113
|
+
columns: [
|
|
114
|
+
{ type: 'gutter', gutterName: 'sequence' },
|
|
115
|
+
{ type: 'gutter', gutterName: 'row-selector', multiple: true },
|
|
116
|
+
{
|
|
117
|
+
type: 'string',
|
|
118
|
+
name: 'metric',
|
|
119
|
+
header: 'Metric',
|
|
120
|
+
record: { editable: false, renderer: (v, c, r) => r.metric?.name },
|
|
121
|
+
width: 150
|
|
122
|
+
},
|
|
123
|
+
{ type: 'date', name: 'valueDate', header: '날짜', record: { editable: true }, width: 120 },
|
|
124
|
+
{ type: 'number', name: 'value', header: '값', record: { editable: true }, width: 120 },
|
|
125
|
+
{ type: 'string', name: 'group', header: '그룹', record: { editable: false }, width: 120 },
|
|
126
|
+
{ type: 'object', name: 'meta', header: '메타', record: { editable: false }, width: 120 },
|
|
127
|
+
{ type: 'datetime', name: 'createdAt', header: '생성일', record: { editable: false }, width: 180 },
|
|
128
|
+
{ type: 'datetime', name: 'updatedAt', header: '수정일', record: { editable: false }, width: 180 },
|
|
129
|
+
{
|
|
130
|
+
type: 'resource-object',
|
|
131
|
+
name: 'creator',
|
|
132
|
+
header: '생성자',
|
|
133
|
+
record: { editable: false, renderer: (v, c, r) => r.creator?.name },
|
|
134
|
+
width: 120
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
type: 'resource-object',
|
|
138
|
+
name: 'updater',
|
|
139
|
+
header: '수정자',
|
|
140
|
+
record: { editable: false, renderer: (v, c, r) => r.updater?.name },
|
|
141
|
+
width: 120
|
|
142
|
+
}
|
|
143
|
+
],
|
|
144
|
+
rows: {
|
|
145
|
+
appendable: false,
|
|
146
|
+
selectable: {
|
|
147
|
+
multiple: true
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
sorters: [{ name: 'valueDate' }]
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async fetchHandler({ page = 1, limit = 100, sortings = [], filters = [] }: FetchOption) {
|
|
155
|
+
const response = await client.query({
|
|
156
|
+
query: gql`
|
|
157
|
+
query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
|
|
158
|
+
responses: kpiMetricValues(filters: $filters, pagination: $pagination, sortings: $sortings) {
|
|
159
|
+
items {
|
|
160
|
+
id
|
|
161
|
+
metric {
|
|
162
|
+
id
|
|
163
|
+
name
|
|
164
|
+
}
|
|
165
|
+
valueDate
|
|
166
|
+
value
|
|
167
|
+
meta
|
|
168
|
+
group
|
|
169
|
+
updater {
|
|
170
|
+
id
|
|
171
|
+
name
|
|
172
|
+
}
|
|
173
|
+
updatedAt
|
|
174
|
+
creator {
|
|
175
|
+
id
|
|
176
|
+
name
|
|
177
|
+
}
|
|
178
|
+
createdAt
|
|
179
|
+
}
|
|
180
|
+
total
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
`,
|
|
184
|
+
variables: {
|
|
185
|
+
filters,
|
|
186
|
+
pagination: { page, limit },
|
|
187
|
+
sortings
|
|
188
|
+
}
|
|
189
|
+
})
|
|
190
|
+
return {
|
|
191
|
+
total: response.data.responses.total || 0,
|
|
192
|
+
records: response.data.responses.items || []
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
async _deleteKpiMetricValue() {
|
|
197
|
+
if (
|
|
198
|
+
await OxPrompt.open({
|
|
199
|
+
title: i18next.t('text.are_you_sure'),
|
|
200
|
+
text: i18next.t('text.sure_to_x', { x: i18next.t('text.delete') }),
|
|
201
|
+
confirmButton: { text: i18next.t('button.confirm') },
|
|
202
|
+
cancelButton: { text: i18next.t('button.cancel') }
|
|
203
|
+
})
|
|
204
|
+
) {
|
|
205
|
+
const ids = this.grist.selected.map(record => record.id)
|
|
206
|
+
if (ids && ids.length > 0) {
|
|
207
|
+
const response = await client.mutate({
|
|
208
|
+
mutation: gql`
|
|
209
|
+
mutation ($ids: [String!]!) {
|
|
210
|
+
deleteKpiMetricValues(ids: $ids)
|
|
211
|
+
}
|
|
212
|
+
`,
|
|
213
|
+
variables: { ids }
|
|
214
|
+
})
|
|
215
|
+
if (!response.errors) {
|
|
216
|
+
this.grist.fetch()
|
|
217
|
+
notify({ message: i18next.t('text.info_x_successfully', { x: i18next.t('text.delete') }) })
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async _updateKpiMetricValue() {
|
|
224
|
+
let patches = this.grist.dirtyRecords
|
|
225
|
+
if (patches && patches.length) {
|
|
226
|
+
patches = patches.map(patch => {
|
|
227
|
+
let patchField: any = patch.id ? { id: patch.id } : {}
|
|
228
|
+
const dirtyFields = patch.__dirtyfields__
|
|
229
|
+
for (let key in dirtyFields) {
|
|
230
|
+
patchField[key] = dirtyFields[key].after
|
|
231
|
+
}
|
|
232
|
+
patchField.cuFlag = patch.__dirty__
|
|
233
|
+
return patchField
|
|
234
|
+
})
|
|
235
|
+
const response = await client.mutate({
|
|
236
|
+
mutation: gql`
|
|
237
|
+
mutation ($patches: [KpiMetricValuePatch!]!) {
|
|
238
|
+
updateMultipleKpiMetricValue(patches: $patches) {
|
|
239
|
+
id
|
|
240
|
+
metric {
|
|
241
|
+
id
|
|
242
|
+
name
|
|
243
|
+
}
|
|
244
|
+
valueDate
|
|
245
|
+
value
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
`,
|
|
249
|
+
variables: { patches }
|
|
250
|
+
})
|
|
251
|
+
if (!response.errors) {
|
|
252
|
+
this.grist.fetch()
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
async creationCallback(metricValue) {
|
|
258
|
+
try {
|
|
259
|
+
const response = await client.mutate({
|
|
260
|
+
mutation: gql`
|
|
261
|
+
mutation ($metricValue: NewKpiMetricValue!) {
|
|
262
|
+
createKpiMetricValue(metricValue: $metricValue) {
|
|
263
|
+
id
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
`,
|
|
267
|
+
variables: { metricValue },
|
|
268
|
+
context: { hasUpload: true }
|
|
269
|
+
})
|
|
270
|
+
if (!response.errors) {
|
|
271
|
+
this.grist.fetch()
|
|
272
|
+
document.dispatchEvent(
|
|
273
|
+
new CustomEvent('notify', { detail: { message: i18next.t('text.data_created_successfully') } })
|
|
274
|
+
)
|
|
275
|
+
}
|
|
276
|
+
return true
|
|
277
|
+
} catch (ex) {
|
|
278
|
+
console.error(ex)
|
|
279
|
+
document.dispatchEvent(new CustomEvent('notify', { detail: { type: 'error', message: i18next.t('text.error') } }))
|
|
280
|
+
return false
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
async exportHandler() {
|
|
285
|
+
const exportTargets = this.grist.selected.length ? this.grist.selected : this.grist.dirtyData.records
|
|
286
|
+
const targetFieldSet = new Set(['id', 'metric', 'valueDate', 'value', 'group', 'meta'])
|
|
287
|
+
return exportTargets.map(metricValue => {
|
|
288
|
+
let tempObj = {}
|
|
289
|
+
for (const field of targetFieldSet) {
|
|
290
|
+
tempObj[field] = metricValue[field]
|
|
291
|
+
}
|
|
292
|
+
return tempObj
|
|
293
|
+
})
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
async importHandler(records) {
|
|
297
|
+
// 임포트 팝업 등은 추후 구현
|
|
298
|
+
}
|
|
299
|
+
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import '@material/web/icon/icon.js'
|
|
2
|
-
|
|
3
1
|
import { html, LitElement, css } from 'lit'
|
|
4
2
|
import { customElement, property, state } from 'lit/decorators.js'
|
|
5
3
|
import { client } from '@operato/graphql'
|
|
@@ -7,8 +5,8 @@ import { notify } from '@operato/layout'
|
|
|
7
5
|
import gql from 'graphql-tag'
|
|
8
6
|
import { CommonHeaderStyles, ScrollbarStyles } from '@operato/styles'
|
|
9
7
|
|
|
10
|
-
@customElement('kpi-value-manual-entry-form')
|
|
11
|
-
export class
|
|
8
|
+
@customElement('kpi-metric-value-manual-entry-form')
|
|
9
|
+
export class KpiMetricValueManualEntryForm extends LitElement {
|
|
12
10
|
static styles = [
|
|
13
11
|
CommonHeaderStyles,
|
|
14
12
|
ScrollbarStyles,
|
|
@@ -18,14 +16,12 @@ export class KpiValueManualEntryForm extends LitElement {
|
|
|
18
16
|
flex-direction: column;
|
|
19
17
|
background-color: var(--md-sys-color-surface, #f4f6fa);
|
|
20
18
|
}
|
|
21
|
-
|
|
22
19
|
form {
|
|
23
20
|
flex: 1;
|
|
24
21
|
display: flex;
|
|
25
22
|
flex-direction: column;
|
|
26
23
|
overflow-y: auto;
|
|
27
24
|
}
|
|
28
|
-
|
|
29
25
|
.form-card {
|
|
30
26
|
flex: 1;
|
|
31
27
|
display: flex;
|
|
@@ -33,7 +29,6 @@ export class KpiValueManualEntryForm extends LitElement {
|
|
|
33
29
|
padding: 32px 32px 0 32px;
|
|
34
30
|
background: #fff;
|
|
35
31
|
}
|
|
36
|
-
|
|
37
32
|
label {
|
|
38
33
|
font-weight: 500;
|
|
39
34
|
margin-bottom: 4px;
|
|
@@ -41,7 +36,6 @@ export class KpiValueManualEntryForm extends LitElement {
|
|
|
41
36
|
flex-direction: column;
|
|
42
37
|
gap: 2px;
|
|
43
38
|
}
|
|
44
|
-
|
|
45
39
|
input,
|
|
46
40
|
textarea {
|
|
47
41
|
font-size: 1em;
|
|
@@ -50,13 +44,11 @@ export class KpiValueManualEntryForm extends LitElement {
|
|
|
50
44
|
margin-top: 2px;
|
|
51
45
|
resize: none;
|
|
52
46
|
}
|
|
53
|
-
|
|
54
47
|
.desc {
|
|
55
48
|
font-size: 0.95em;
|
|
56
49
|
color: #888;
|
|
57
50
|
margin-top: 8px;
|
|
58
51
|
}
|
|
59
|
-
|
|
60
52
|
.footer span {
|
|
61
53
|
font-size: 0.8em;
|
|
62
54
|
color: var(--md-sys-color-on-surface);
|
|
@@ -66,11 +58,10 @@ export class KpiValueManualEntryForm extends LitElement {
|
|
|
66
58
|
`
|
|
67
59
|
]
|
|
68
60
|
|
|
69
|
-
@property({ type: Object })
|
|
61
|
+
@property({ type: Object }) metric: any
|
|
70
62
|
@state() valueDate = new Date().toISOString().slice(0, 10)
|
|
71
63
|
@state() value = ''
|
|
72
|
-
@state()
|
|
73
|
-
@state() groupType = ''
|
|
64
|
+
@state() group = ''
|
|
74
65
|
@state() meta = ''
|
|
75
66
|
@state() loading = false
|
|
76
67
|
|
|
@@ -78,22 +69,18 @@ export class KpiValueManualEntryForm extends LitElement {
|
|
|
78
69
|
return html`
|
|
79
70
|
<form style="display:flex;flex-direction:column;height:100%;">
|
|
80
71
|
<div class="form-card">
|
|
81
|
-
<div style="font-size:1.1em;font-weight:bold;margin-bottom:16px;"><b>
|
|
72
|
+
<div style="font-size:1.1em;font-weight:bold;margin-bottom:16px;"><b>Metric:</b> ${this.metric?.name}</div>
|
|
82
73
|
<label>
|
|
83
|
-
|
|
74
|
+
날짜
|
|
84
75
|
<input type="date" .value=${this.valueDate} @input=${e => (this.valueDate = e.target.value)} required />
|
|
85
76
|
</label>
|
|
86
77
|
<label>
|
|
87
|
-
|
|
78
|
+
값
|
|
88
79
|
<input type="number" .value=${this.value} @input=${e => (this.value = e.target.value)} required />
|
|
89
80
|
</label>
|
|
90
81
|
<label>
|
|
91
|
-
그룹
|
|
92
|
-
<input type="text" .value=${this.
|
|
93
|
-
</label>
|
|
94
|
-
<label>
|
|
95
|
-
그룹유형 (선택)
|
|
96
|
-
<input type="text" .value=${this.groupType} @input=${e => (this.groupType = e.target.value)} />
|
|
82
|
+
그룹 (선택)
|
|
83
|
+
<input type="text" .value=${this.group} @input=${e => (this.group = e.target.value)} />
|
|
97
84
|
</label>
|
|
98
85
|
<label>
|
|
99
86
|
메타정보 (선택, JSON)
|
|
@@ -102,7 +89,6 @@ export class KpiValueManualEntryForm extends LitElement {
|
|
|
102
89
|
<div class="desc">입력방식: MANUAL, Source: MANUAL (자동 지정)</div>
|
|
103
90
|
</div>
|
|
104
91
|
</form>
|
|
105
|
-
|
|
106
92
|
<div class="footer">
|
|
107
93
|
<div filler></div>
|
|
108
94
|
<button type="button" ?disabled=${this.loading} done @click=${this.save}><md-icon>save</md-icon>저장</button>
|
|
@@ -125,25 +111,15 @@ export class KpiValueManualEntryForm extends LitElement {
|
|
|
125
111
|
try {
|
|
126
112
|
await client.mutate({
|
|
127
113
|
mutation: gql`
|
|
128
|
-
mutation (
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
$groupId: String
|
|
133
|
-
$groupType: String
|
|
134
|
-
$meta: Object
|
|
135
|
-
) {
|
|
136
|
-
createKpiValue(
|
|
137
|
-
kpiValue: {
|
|
138
|
-
kpiId: $kpiId
|
|
114
|
+
mutation ($metricId: ID!, $valueDate: String!, $value: Float!, $group: String, $meta: Object) {
|
|
115
|
+
createKpiMetricValue(
|
|
116
|
+
metricValue: {
|
|
117
|
+
metricId: $metricId
|
|
139
118
|
valueDate: $valueDate
|
|
140
119
|
value: $value
|
|
141
|
-
|
|
142
|
-
groupId: $groupId
|
|
143
|
-
groupType: $groupType
|
|
144
|
-
inputType: MANUAL
|
|
145
|
-
source: "MANUAL"
|
|
120
|
+
group: $group
|
|
146
121
|
meta: $meta
|
|
122
|
+
periodType: DAY
|
|
147
123
|
}
|
|
148
124
|
) {
|
|
149
125
|
id
|
|
@@ -151,17 +127,15 @@ export class KpiValueManualEntryForm extends LitElement {
|
|
|
151
127
|
}
|
|
152
128
|
`,
|
|
153
129
|
variables: {
|
|
154
|
-
|
|
130
|
+
metricId: this.metric.id,
|
|
155
131
|
valueDate: this.valueDate,
|
|
156
132
|
value: parseFloat(this.value),
|
|
157
|
-
|
|
158
|
-
groupType: this.groupType || undefined,
|
|
133
|
+
group: this.group || undefined,
|
|
159
134
|
meta: parsedMeta
|
|
160
135
|
}
|
|
161
136
|
})
|
|
162
|
-
notify({ message: '
|
|
137
|
+
notify({ message: 'Metric 값이 저장되었습니다.' })
|
|
163
138
|
this.dispatchEvent(new CustomEvent('saved', { bubbles: true, composed: true }))
|
|
164
|
-
// 팝업 닫기 로직
|
|
165
139
|
let el: any = this.parentElement
|
|
166
140
|
while (el) {
|
|
167
141
|
if (typeof el.close === 'function') {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import '@material/web/icon/icon.js'
|
|
2
2
|
import '@operato/data-grist'
|
|
3
|
-
import './kpi-value-manual-entry-form.js'
|
|
3
|
+
import './kpi-metric-value-manual-entry-form.js'
|
|
4
4
|
|
|
5
5
|
import { css, html } from 'lit'
|
|
6
6
|
import { customElement, property, query, state } from 'lit/decorators.js'
|
|
@@ -13,8 +13,8 @@ import { PageView, store } from '@operato/shell'
|
|
|
13
13
|
import { CommonHeaderStyles, ScrollbarStyles } from '@operato/styles'
|
|
14
14
|
import gql from 'graphql-tag'
|
|
15
15
|
|
|
16
|
-
@customElement('kpi-value-manual-entry-page')
|
|
17
|
-
export class
|
|
16
|
+
@customElement('kpi-metric-value-manual-entry-page')
|
|
17
|
+
export class KpiMetricValueManualEntryPage extends connect(store)(localize(i18next)(PageView)) {
|
|
18
18
|
static styles = [
|
|
19
19
|
ScrollbarStyles,
|
|
20
20
|
CommonHeaderStyles,
|
|
@@ -32,7 +32,7 @@ export class KpiValueManualEntryPage extends connect(store)(localize(i18next)(Pa
|
|
|
32
32
|
|
|
33
33
|
get context() {
|
|
34
34
|
return {
|
|
35
|
-
title: i18next.t('title.kpi value manual entry'),
|
|
35
|
+
title: i18next.t('title.kpi metric value manual entry'),
|
|
36
36
|
search: {
|
|
37
37
|
handler: (search: string) => {
|
|
38
38
|
this.grist.searchText = search
|
|
@@ -44,12 +44,12 @@ export class KpiValueManualEntryPage extends connect(store)(localize(i18next)(Pa
|
|
|
44
44
|
this.grist.toggleHeadroom()
|
|
45
45
|
}
|
|
46
46
|
},
|
|
47
|
-
help: 'kpi/kpi-value'
|
|
47
|
+
help: 'kpi/kpi-metric-value'
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
@state() private gristConfig: any
|
|
52
|
-
@state() private
|
|
52
|
+
@state() private metrics: any[] = []
|
|
53
53
|
@query('ox-grist') private grist!: DataGrist
|
|
54
54
|
|
|
55
55
|
render() {
|
|
@@ -62,7 +62,7 @@ export class KpiValueManualEntryPage extends connect(store)(localize(i18next)(Pa
|
|
|
62
62
|
this.gristConfig = {
|
|
63
63
|
list: {
|
|
64
64
|
fields: ['name', 'description'],
|
|
65
|
-
details: ['
|
|
65
|
+
details: ['periodType', 'active']
|
|
66
66
|
},
|
|
67
67
|
columns: [
|
|
68
68
|
{
|
|
@@ -72,7 +72,7 @@ export class KpiValueManualEntryPage extends connect(store)(localize(i18next)(Pa
|
|
|
72
72
|
iconOnly: false,
|
|
73
73
|
width: 96,
|
|
74
74
|
fixed: true,
|
|
75
|
-
title: () => i18next.t('button.enter-kpi-value'),
|
|
75
|
+
title: () => i18next.t('button.enter-kpi-metric-value'),
|
|
76
76
|
handlers: {
|
|
77
77
|
click: (columns, data, column, record, rowIndex) => {
|
|
78
78
|
this.openManualEntryForm(record)
|
|
@@ -96,11 +96,11 @@ export class KpiValueManualEntryPage extends connect(store)(localize(i18next)(Pa
|
|
|
96
96
|
width: 200
|
|
97
97
|
},
|
|
98
98
|
{
|
|
99
|
-
type: '
|
|
100
|
-
name: '
|
|
101
|
-
header:
|
|
102
|
-
record: { editable:
|
|
103
|
-
width:
|
|
99
|
+
type: 'select',
|
|
100
|
+
name: 'periodType',
|
|
101
|
+
header: '주기',
|
|
102
|
+
record: { editable: true, options: ['', 'DAY', 'WEEK', 'MONTH', 'QUARTER', 'YEAR', 'RANGE'] },
|
|
103
|
+
width: 80
|
|
104
104
|
},
|
|
105
105
|
{
|
|
106
106
|
type: 'checkbox',
|
|
@@ -131,16 +131,13 @@ export class KpiValueManualEntryPage extends connect(store)(localize(i18next)(Pa
|
|
|
131
131
|
const response = await client.query({
|
|
132
132
|
query: gql`
|
|
133
133
|
query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
|
|
134
|
-
responses:
|
|
134
|
+
responses: kpiMetrics(filters: $filters, pagination: $pagination, sortings: $sortings) {
|
|
135
135
|
items {
|
|
136
136
|
id
|
|
137
137
|
name
|
|
138
138
|
description
|
|
139
|
+
periodType
|
|
139
140
|
active
|
|
140
|
-
category {
|
|
141
|
-
id
|
|
142
|
-
name
|
|
143
|
-
}
|
|
144
141
|
}
|
|
145
142
|
total
|
|
146
143
|
}
|
|
@@ -158,15 +155,18 @@ export class KpiValueManualEntryPage extends connect(store)(localize(i18next)(Pa
|
|
|
158
155
|
}
|
|
159
156
|
}
|
|
160
157
|
|
|
161
|
-
openManualEntryForm(
|
|
158
|
+
openManualEntryForm(metric) {
|
|
162
159
|
openPopup(
|
|
163
160
|
html`
|
|
164
|
-
<kpi-
|
|
161
|
+
<kpi-metric-value-manual-entry-form
|
|
162
|
+
.metric=${metric}
|
|
163
|
+
@saved=${() => this.grist.fetch()}
|
|
164
|
+
></kpi-metric-value-manual-entry-form>
|
|
165
165
|
`,
|
|
166
166
|
{
|
|
167
167
|
backdrop: true,
|
|
168
168
|
size: 'medium',
|
|
169
|
-
title: `${
|
|
169
|
+
title: `${metric.name} - Metric 값 수동 입력`
|
|
170
170
|
}
|
|
171
171
|
)
|
|
172
172
|
}
|
|
@@ -130,8 +130,7 @@ export class KpiValueListPage extends connect(store)(localize(i18next)(ScopedEle
|
|
|
130
130
|
'version',
|
|
131
131
|
'valueDate',
|
|
132
132
|
'value',
|
|
133
|
-
'
|
|
134
|
-
'groupType',
|
|
133
|
+
'group',
|
|
135
134
|
'inputType',
|
|
136
135
|
'source',
|
|
137
136
|
'meta',
|
|
@@ -145,8 +144,7 @@ export class KpiValueListPage extends connect(store)(localize(i18next)(ScopedEle
|
|
|
145
144
|
'version',
|
|
146
145
|
'valueDate',
|
|
147
146
|
'value',
|
|
148
|
-
'
|
|
149
|
-
'groupType',
|
|
147
|
+
'group',
|
|
150
148
|
'inputType',
|
|
151
149
|
'source',
|
|
152
150
|
'meta',
|
|
@@ -169,8 +167,7 @@ export class KpiValueListPage extends connect(store)(localize(i18next)(ScopedEle
|
|
|
169
167
|
{ type: 'number', name: 'version', header: '버전', record: { editable: false }, width: 80 },
|
|
170
168
|
{ type: 'date', name: 'valueDate', header: '실적일', record: { editable: true }, width: 120 },
|
|
171
169
|
{ type: 'number', name: 'value', header: '실적값', record: { editable: true }, width: 120 },
|
|
172
|
-
{ type: 'string', name: '
|
|
173
|
-
{ type: 'string', name: 'groupType', header: '그룹유형', record: { editable: false }, width: 100 },
|
|
170
|
+
{ type: 'string', name: 'group', header: '그룹', record: { editable: false }, width: 120 },
|
|
174
171
|
{ type: 'string', name: 'inputType', header: '입력방식', record: { editable: false }, width: 100 },
|
|
175
172
|
{ type: 'string', name: 'source', header: '수집출처', record: { editable: false }, width: 120 },
|
|
176
173
|
{ type: 'object', name: 'meta', header: '메타', record: { editable: false }, width: 120 },
|
|
@@ -224,6 +221,7 @@ export class KpiValueListPage extends connect(store)(localize(i18next)(ScopedEle
|
|
|
224
221
|
inputType
|
|
225
222
|
source
|
|
226
223
|
meta
|
|
224
|
+
group
|
|
227
225
|
updater {
|
|
228
226
|
id
|
|
229
227
|
name
|