@dssp/dkpi 1.0.0-alpha.87 → 1.0.0-alpha.89
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/_index.html +4 -4
- package/assets/helps/index.md +1 -1
- package/assets/manifest.json +2 -2
- package/dist-client/bootstrap.js +1 -1
- package/dist-client/bootstrap.js.map +1 -1
- package/dist-client/components/kpi-boxplot-chart.d.ts +7 -0
- package/dist-client/components/kpi-boxplot-chart.js +20 -5
- package/dist-client/components/kpi-boxplot-chart.js.map +1 -1
- package/dist-client/components/kpi-lookup-chart.js +1 -17
- package/dist-client/components/kpi-lookup-chart.js.map +1 -1
- package/dist-client/components/kpi-mini-trend-chart.d.ts +1 -1
- package/dist-client/components/kpi-mini-trend-chart.js +45 -13
- package/dist-client/components/kpi-mini-trend-chart.js.map +1 -1
- package/dist-client/components/kpi-radar-chart.js +2 -2
- package/dist-client/components/kpi-radar-chart.js.map +1 -1
- package/dist-client/components/kpi-single-boxplot-chart.d.ts +11 -0
- package/dist-client/components/kpi-single-boxplot-chart.js +45 -26
- package/dist-client/components/kpi-single-boxplot-chart.js.map +1 -1
- package/dist-client/components/kpi-step-lookup-chart.d.ts +33 -0
- package/dist-client/components/kpi-step-lookup-chart.js +181 -0
- package/dist-client/components/kpi-step-lookup-chart.js.map +1 -0
- package/dist-client/components/kpi-trend-chart.js +41 -20
- package/dist-client/components/kpi-trend-chart.js.map +1 -1
- package/dist-client/google-map/common-google-map.js +5 -1
- package/dist-client/google-map/common-google-map.js.map +1 -1
- package/dist-client/pages/kpi-admin/dssp-kpi-overview.d.ts +2 -1
- package/dist-client/pages/kpi-admin/dssp-kpi-overview.js +24 -9
- package/dist-client/pages/kpi-admin/dssp-kpi-overview.js.map +1 -1
- package/dist-client/pages/kpi-admin/kpi-system-guide.js +311 -158
- package/dist-client/pages/kpi-admin/kpi-system-guide.js.map +1 -1
- package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.d.ts +8 -0
- package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.js +142 -56
- 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 +0 -9
- package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js +6 -91
- package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js.map +1 -1
- package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.d.ts +2 -0
- package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.js +162 -69
- package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.js.map +1 -1
- package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js +85 -41
- package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js.map +1 -1
- package/dist-client/pages/kpi-dashboard/kpi-dashboard.js +15 -7
- package/dist-client/pages/kpi-dashboard/kpi-dashboard.js.map +1 -1
- package/dist-client/pages/project-complete-tabs/pc-tab1-plan.js +16 -25
- package/dist-client/pages/project-complete-tabs/pc-tab1-plan.js.map +1 -1
- package/dist-client/pages/project-complete-tabs/pc-tab2-rating.js +9 -13
- package/dist-client/pages/project-complete-tabs/pc-tab2-rating.js.map +1 -1
- package/dist-client/pages/project-complete-tabs/pc-tab4-monthly.js +9 -15
- package/dist-client/pages/project-complete-tabs/pc-tab4-monthly.js.map +1 -1
- package/dist-client/pages/sv-project-complete.js +7 -11
- package/dist-client/pages/sv-project-complete.js.map +1 -1
- package/dist-client/pages/sv-project-completed-list.js +4 -4
- package/dist-client/pages/sv-project-completed-list.js.map +1 -1
- package/dist-client/pages/sv-project-detail.d.ts +1 -0
- package/dist-client/pages/sv-project-detail.js +73 -55
- package/dist-client/pages/sv-project-detail.js.map +1 -1
- package/dist-client/pages/sv-project-list.js +15 -12
- package/dist-client/pages/sv-project-list.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/viewparts/menu-tools.js +17 -3
- package/dist-client/viewparts/menu-tools.js.map +1 -1
- package/dist-server/service/kpi-stat/kpi-stat-query.js +20 -19
- package/dist-server/service/kpi-stat/kpi-stat-query.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/openapi/unstable.yaml +2 -2
- package/package.json +3 -3
- package/schema.graphql +20 -0
- package/translations/ko.json +2 -2
- package/views/auth-page.html +4 -4
- package/views/public/home.html +5 -5
|
@@ -13,6 +13,7 @@ import '../components/kpi-boxplot-chart';
|
|
|
13
13
|
import '../components/kpi-single-boxplot-chart';
|
|
14
14
|
import '../components/kpi-radar-chart';
|
|
15
15
|
import '../components/kpi-lookup-chart';
|
|
16
|
+
import '../components/kpi-step-lookup-chart';
|
|
16
17
|
import '../components/kpi-2d-lookup-chart';
|
|
17
18
|
let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(PageView) {
|
|
18
19
|
constructor() {
|
|
@@ -35,7 +36,7 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
|
|
|
35
36
|
};
|
|
36
37
|
}
|
|
37
38
|
render() {
|
|
38
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
39
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
39
40
|
return html `
|
|
40
41
|
<div content>
|
|
41
42
|
<div left>
|
|
@@ -57,7 +58,7 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
|
|
|
57
58
|
<div class="value">${this.project.startDate} ~ ${this.project.endDate}</div>
|
|
58
59
|
</div>
|
|
59
60
|
<div class="row">
|
|
60
|
-
<div class="label">•
|
|
61
|
+
<div class="label">• 프로젝트 상태</div>
|
|
61
62
|
<div class="value status-value">${PROJECT_STATE[this.project.state]}</div>
|
|
62
63
|
</div>
|
|
63
64
|
<div class="row">
|
|
@@ -97,7 +98,7 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
|
|
|
97
98
|
<div class="value">${((_h = (_g = this.project.buildingComplex) === null || _g === void 0 ? void 0 : _g.floorAreaRatio) === null || _h === void 0 ? void 0 : _h.toLocaleString()) || '-'} %</div>
|
|
98
99
|
</div>
|
|
99
100
|
<div class="grid-item row">
|
|
100
|
-
<div class="label">•
|
|
101
|
+
<div class="label">• 총 투입인력(M/M)</div>
|
|
101
102
|
<div class="value">${((_k = (_j = this.project.buildingComplex) === null || _j === void 0 ? void 0 : _j.workerCount) === null || _k === void 0 ? void 0 : _k.toLocaleString()) || '-'} 명</div>
|
|
102
103
|
</div>
|
|
103
104
|
</div>
|
|
@@ -208,14 +209,13 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
|
|
|
208
209
|
<div class="card group-box">
|
|
209
210
|
<div class="kpi-header">
|
|
210
211
|
<div>
|
|
211
|
-
<div
|
|
212
|
+
<div>성과영역별 KPI</div>
|
|
212
213
|
<div class="triangle"></div>
|
|
213
214
|
</div>
|
|
214
215
|
</div>
|
|
215
216
|
<div class="desc">
|
|
216
|
-
Boxplot(박스플롯)은
|
|
217
|
-
|
|
218
|
-
이 프로젝트의 값은 진한 오렌지색 원으로 별도 강조되어 표시되며, 중앙값/평균과 다를 수 있습니다.
|
|
217
|
+
Boxplot(박스플롯)은 박스는 중앙 50% 구간, 수염은 전체 범위, 굵은 파란색 가로선은 중앙값(median), 초록색 원은
|
|
218
|
+
평균값(Mean)을 의미합니다. 당해 프로젝트의 값은 붉은색 원으로 표시됩니다.
|
|
219
219
|
</div>
|
|
220
220
|
<div class="group-chart">
|
|
221
221
|
<sv-kpi-boxplot-chart .data=${this.getYKpiBoxplotData()}></sv-kpi-boxplot-chart>
|
|
@@ -225,7 +225,7 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
|
|
|
225
225
|
<div class="metrics-card">
|
|
226
226
|
<div class="metrics-header">
|
|
227
227
|
<div class="title">
|
|
228
|
-
<span
|
|
228
|
+
<span>성과영역별 KPI 측정값</span>
|
|
229
229
|
<div class="triangle"></div>
|
|
230
230
|
</div>
|
|
231
231
|
</div>
|
|
@@ -270,8 +270,7 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
|
|
|
270
270
|
${this.selectedKpi.score !== undefined && this.selectedKpi.score !== null
|
|
271
271
|
? html `
|
|
272
272
|
<div class="popup-score">
|
|
273
|
-
<span class="score-value">${parseFloat(Number(this.selectedKpi.score).toFixed(
|
|
274
|
-
<span class="score-label">점</span>
|
|
273
|
+
<span class="score-value">${parseFloat(Number(this.selectedKpi.score).toFixed(2))}</span>
|
|
275
274
|
</div>
|
|
276
275
|
`
|
|
277
276
|
: ''}
|
|
@@ -290,18 +289,29 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
|
|
|
290
289
|
* ASSESSMENT: 5단계 게이지 (kpi-lookup-chart 자동 감지)
|
|
291
290
|
*/ ''}
|
|
292
291
|
${
|
|
293
|
-
//
|
|
294
|
-
//
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
292
|
+
// SL-PA 결과(X34 품질, X43 안전) 만 계단형 등급 분포 차트로 표시.
|
|
293
|
+
// (다른 KPI 차트 경로에는 영향 없음)
|
|
294
|
+
this.selectedKpi.pattern === 'X34' || this.selectedKpi.pattern === 'X43'
|
|
295
|
+
? html `
|
|
296
|
+
<kpi-step-lookup-chart
|
|
297
|
+
.grades=${this.selectedKpi.grades || []}
|
|
298
|
+
.value=${this.selectedKpi.value}
|
|
299
|
+
.score=${(_l = this.selectedKpi.score) !== null && _l !== void 0 ? _l : null}
|
|
300
|
+
unit=${this.selectedKpi.unit || ''}
|
|
301
|
+
></kpi-step-lookup-chart>
|
|
302
|
+
`
|
|
303
|
+
: // 2D lookup KPI (X13 등) 는 항상 등급 기준 + 히트맵 함께 표시 (value 가
|
|
304
|
+
// 정수든 소수든 일관). _renderAssessmentGrades 안의 is2D 분기가 히트맵
|
|
305
|
+
// 같이 그림. 그 외 ASSESSMENT 도 등급 기준, LOOKUP 은 분포 커브.
|
|
306
|
+
this.selectedKpi.scoreType === 'CUSTOM' || ((_m = this.selectedKpi.grades) === null || _m === void 0 ? void 0 : _m.type) === 'PROGRESS_DEVIATION_LOOKUP'
|
|
307
|
+
? this._renderAssessmentGrades()
|
|
308
|
+
: this._isAssessmentOrIntegerScore()
|
|
309
|
+
? this._renderAssessmentGrades()
|
|
310
|
+
: html `
|
|
301
311
|
<kpi-lookup-chart
|
|
302
312
|
.grades=${this.selectedKpi.grades || []}
|
|
303
313
|
.value=${this.selectedKpi.value}
|
|
304
|
-
.score=${(
|
|
314
|
+
.score=${(_o = this.selectedKpi.score) !== null && _o !== void 0 ? _o : null}
|
|
305
315
|
.scoreType=${this.selectedKpi.scoreType || ''}
|
|
306
316
|
.valueType=${this.selectedKpi.valueType || ''}
|
|
307
317
|
unit=${this.selectedKpi.unit || ''}
|
|
@@ -653,6 +663,7 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
|
|
|
653
663
|
}
|
|
654
664
|
this.selectedKpi = {
|
|
655
665
|
kpiName: displayName,
|
|
666
|
+
pattern: kpiNamePattern, // X34/X43 등 — 계단형 차트 라우팅용
|
|
656
667
|
grades: kpi.grades || [],
|
|
657
668
|
scoreType: kpi.scoreType || '',
|
|
658
669
|
valueType: kpi.valueType || '',
|
|
@@ -798,30 +809,30 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
|
|
|
798
809
|
return {
|
|
799
810
|
Y1: {
|
|
800
811
|
name: '일정성과 (Y1)',
|
|
801
|
-
score: this.getYKpiScoreFormatted('Y1
|
|
812
|
+
score: this.getYKpiScoreFormatted('일정성과(Y1)'),
|
|
802
813
|
metrics: [
|
|
803
814
|
{ label: '연면적 대비 공사기간', pattern: 'X11', value: this.getMetricValue('X11') },
|
|
804
815
|
{ label: '설계변경 공기 증감률', pattern: 'X12', value: this.getMetricValue('X12') },
|
|
805
816
|
{ label: '일정 이탈 수준', pattern: 'X13', value: this.getMetricValue('X13') },
|
|
806
|
-
{ label: '일정성과
|
|
817
|
+
{ label: '일정성과 정성 평가', pattern: 'X14', value: this.getMetricValue('X14') }
|
|
807
818
|
]
|
|
808
819
|
},
|
|
809
820
|
Y2: {
|
|
810
821
|
name: '비용성과 (Y2)',
|
|
811
|
-
score: this.getYKpiScoreFormatted('Y2
|
|
822
|
+
score: this.getYKpiScoreFormatted('비용성과(Y2)'),
|
|
812
823
|
metrics: [
|
|
813
824
|
{ label: '연면적 대비 공사비', pattern: 'X21', value: this.getMetricValue('X21') },
|
|
814
|
-
{ label: '설계변경 공사비
|
|
815
|
-
{ label: '비용성과
|
|
825
|
+
{ label: '설계변경 공사비 증감률', pattern: 'X22', value: this.getMetricValue('X22') },
|
|
826
|
+
{ label: '비용성과 정성 평가', pattern: 'X23', value: this.getMetricValue('X23') }
|
|
816
827
|
]
|
|
817
828
|
},
|
|
818
829
|
Y3: {
|
|
819
830
|
name: '품질성과 (Y3)',
|
|
820
|
-
score: this.getYKpiScoreFormatted('Y3
|
|
831
|
+
score: this.getYKpiScoreFormatted('품질성과(Y3)'),
|
|
821
832
|
metrics: [
|
|
822
833
|
{ label: '검측 불합격률', pattern: 'X33', value: this.getMetricValue('X33') },
|
|
823
834
|
{ label: '품질 SL-PA 결과', pattern: 'X34', value: this.getMetricValue('X34') },
|
|
824
|
-
{ label: '품질성과
|
|
835
|
+
{ label: '품질성과 정성 평가', pattern: 'X35', value: this.getMetricValue('X35') }
|
|
825
836
|
]
|
|
826
837
|
},
|
|
827
838
|
Y4: {
|
|
@@ -831,41 +842,43 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
|
|
|
831
842
|
{ label: '재해율', pattern: 'X41', value: this.getMetricValue('X41') },
|
|
832
843
|
{ label: '재해강도율', pattern: 'X42', value: this.getMetricValue('X42') },
|
|
833
844
|
{ label: '안전 SL-PA 결과', pattern: 'X43', value: this.getMetricValue('X43') },
|
|
834
|
-
{ label: '안전성과
|
|
845
|
+
{ label: '안전성과 정성 평가', pattern: 'X44', value: this.getMetricValue('X44') }
|
|
835
846
|
]
|
|
836
847
|
},
|
|
837
848
|
Y5: {
|
|
838
849
|
name: '환경성과 (Y5)',
|
|
839
|
-
score: this.getYKpiScoreFormatted('Y5
|
|
850
|
+
score: this.getYKpiScoreFormatted('환경성과(Y5)'),
|
|
840
851
|
metrics: [
|
|
841
852
|
{ label: '건설폐기물 발생량', pattern: 'X51', value: this.getMetricValue('X51') },
|
|
842
|
-
{ label: '환경성과
|
|
853
|
+
{ label: '환경성과 정성 평가', pattern: 'X52', value: this.getMetricValue('X52') }
|
|
843
854
|
]
|
|
844
855
|
},
|
|
845
856
|
Y6: {
|
|
846
857
|
name: '생산성 성과 (Y6)',
|
|
847
|
-
score: this.getYKpiScoreFormatted('Y6
|
|
858
|
+
score: this.getYKpiScoreFormatted('생산성성과(Y6)'),
|
|
848
859
|
metrics: [
|
|
849
|
-
{ label: '투입인력 생산성', pattern: 'X61', value: this.getMetricValue('X61') },
|
|
850
|
-
{ label: '생산성성과
|
|
860
|
+
{ label: '총 투입인력(M/M) 생산성', pattern: 'X61', value: this.getMetricValue('X61') },
|
|
861
|
+
{ label: '생산성성과 정성 평가', pattern: 'X62', value: this.getMetricValue('X62') }
|
|
851
862
|
]
|
|
852
863
|
}
|
|
853
864
|
};
|
|
854
865
|
}
|
|
855
866
|
getYKpiBoxplotData() {
|
|
856
|
-
//
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
867
|
+
// kpiName 표기가 환경마다 다양('Y1. 일정성과' / 'Y1. 일정' / '일정성과(Y1)' 등)하므로
|
|
868
|
+
// Y1~Y6 코드만 추출해 짧은 X축 라벨로 매핑 — 전체 문자열에 의존하지 않아 견고함.
|
|
869
|
+
const yLabelByCode = {
|
|
870
|
+
Y1: '일정',
|
|
871
|
+
Y2: '비용',
|
|
872
|
+
Y3: '품질',
|
|
873
|
+
Y4: '안전',
|
|
874
|
+
Y5: '환경',
|
|
875
|
+
Y6: '생산성'
|
|
864
876
|
};
|
|
865
877
|
const data = [];
|
|
866
878
|
// Y-KPI 카테고리별로 통합된 통계 생성
|
|
867
879
|
this.kpiYComprehensiveStats.forEach(stat => {
|
|
868
|
-
|
|
880
|
+
var _a, _b;
|
|
881
|
+
const category = yLabelByCode[(_b = (_a = (stat.kpiName || '').match(/Y[1-6]/)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : ''] || stat.kpiName;
|
|
869
882
|
data.push({
|
|
870
883
|
org: category, // org 필드 사용 (boxplot 차트가 기대하는 필드명)
|
|
871
884
|
min: stat.minVal * 100,
|
|
@@ -877,7 +890,9 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
|
|
|
877
890
|
value: this.getProjectYKpiValue(stat.kpiName) * 100 // 현재 프로젝트의 실제 Y-KPI 값 (0~1 → 0~20)
|
|
878
891
|
});
|
|
879
892
|
});
|
|
880
|
-
|
|
893
|
+
// 가나다순(localeCompare)이 아니라 Y1~Y6 고정 순서로 정렬 (일정·비용·품질·안전·환경·생산성)
|
|
894
|
+
const ORDER = ['일정', '비용', '품질', '안전', '환경', '생산성'];
|
|
895
|
+
return data.sort((a, b) => ORDER.indexOf(a.org) - ORDER.indexOf(b.org));
|
|
881
896
|
}
|
|
882
897
|
/**
|
|
883
898
|
* KpiMetric.name 이 주어진 이름인 KpiMetricValue 중 가장 최근 valueDate 의 value.
|
|
@@ -906,26 +921,29 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
|
|
|
906
921
|
return (_b = (_a = this.selectedKpi) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : null;
|
|
907
922
|
}
|
|
908
923
|
getProjectYKpiValue(kpiName) {
|
|
909
|
-
var _a, _b;
|
|
910
|
-
//
|
|
911
|
-
|
|
924
|
+
var _a, _b, _c;
|
|
925
|
+
// kpiName 표기가 'Y1. 일정성과' / '일정성과(Y1)' 등으로 달라 정확 매칭은 자주 실패함.
|
|
926
|
+
// Y1~Y6 코드만 추출해 매칭 → 형식 차이와 무관하게 값 조회.
|
|
927
|
+
const code = (_a = (kpiName || '').match(/Y[1-6]/)) === null || _a === void 0 ? void 0 : _a[0];
|
|
928
|
+
const kpiValue = (_c = (_b = this.project) === null || _b === void 0 ? void 0 : _b.kpiValues) === null || _c === void 0 ? void 0 : _c.find(kv => { var _a; return code ? ((_a = (kv.kpiName || '').match(/Y[1-6]/)) === null || _a === void 0 ? void 0 : _a[0]) === code : kv.kpiName === kpiName; });
|
|
912
929
|
return (kpiValue === null || kpiValue === void 0 ? void 0 : kpiValue.value) || 0;
|
|
913
930
|
}
|
|
914
931
|
getRadarChartData() {
|
|
915
|
-
//
|
|
916
|
-
const
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
932
|
+
// kpiName 표기가 다양하므로 Y1~Y6 코드만 추출해 짧은 라벨로 매핑 (박스플롯과 동일 방식).
|
|
933
|
+
const yLabelByCode = {
|
|
934
|
+
Y1: '일정',
|
|
935
|
+
Y2: '비용',
|
|
936
|
+
Y3: '품질',
|
|
937
|
+
Y4: '안전',
|
|
938
|
+
Y5: '환경',
|
|
939
|
+
Y6: '생산성'
|
|
923
940
|
};
|
|
924
941
|
const data = [];
|
|
925
942
|
const categories = [];
|
|
926
943
|
// Create baseline data from comprehensive stats (using avgVal as baseline)
|
|
927
944
|
this.kpiYComprehensiveStats.forEach(stat => {
|
|
928
|
-
|
|
945
|
+
var _a, _b;
|
|
946
|
+
const category = yLabelByCode[(_b = (_a = (stat.kpiName || '').match(/Y[1-6]/)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : ''] || stat.kpiName;
|
|
929
947
|
if (!categories.includes(category)) {
|
|
930
948
|
categories.push(category);
|
|
931
949
|
}
|
|
@@ -946,7 +964,7 @@ let SvProjectDetailPage = class SvProjectDetailPage extends ScopedElementsMixin(
|
|
|
946
964
|
data,
|
|
947
965
|
categories: categories.length > 0
|
|
948
966
|
? categories
|
|
949
|
-
: ['
|
|
967
|
+
: ['일정', '비용', '품질', '안전', '환경', '생산성']
|
|
950
968
|
};
|
|
951
969
|
}
|
|
952
970
|
getBoxPlotDataForProject(project) {
|