@dssp/dkpi 1.0.0-y.0 → 1.0.0

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.
Files changed (139) hide show
  1. package/KPI-STATISTICS-SERVICE.md +233 -0
  2. package/_index.html +4 -9
  3. package/assets/helps/index.md +1 -1
  4. package/assets/images/project-image.png +0 -0
  5. package/assets/manifest.json +2 -2
  6. package/config/config.development.js +2 -1
  7. package/config/config.production.js +2 -1
  8. package/kpi-module-service-tests.md +1286 -0
  9. package/kpi-module-test-report.md +676 -0
  10. package/kpi-module-unit-test-detailed-report.md +925 -0
  11. package/kpi-module-unit-tests-detailed.md +1452 -0
  12. package/openapi/unstable.yaml +2 -2
  13. package/package.json +58 -54
  14. package/recalculate-batch.sh +64 -0
  15. package/recalculate-projects-range.sh +98 -0
  16. package/schema.graphql +1159 -55
  17. package/things-factory.config.js +6 -1
  18. package/translations/en.json +5 -1
  19. package/translations/ko.json +5 -1
  20. package/views/auth-page.html +4 -5
  21. package/views/public/home.html +5 -6
  22. package/dist-client/bootstrap.d.ts +0 -8
  23. package/dist-client/bootstrap.js +0 -257
  24. package/dist-client/bootstrap.js.map +0 -1
  25. package/dist-client/components/kpi-single-boxplot-chart.d.ts +0 -24
  26. package/dist-client/components/kpi-single-boxplot-chart.js +0 -317
  27. package/dist-client/components/kpi-single-boxplot-chart.js.map +0 -1
  28. package/dist-client/components/sv-pagenation-control.d.ts +0 -18
  29. package/dist-client/components/sv-pagenation-control.js +0 -142
  30. package/dist-client/components/sv-pagenation-control.js.map +0 -1
  31. package/dist-client/entries/public/home.d.ts +0 -8
  32. package/dist-client/entries/public/home.js +0 -97
  33. package/dist-client/entries/public/home.js.map +0 -1
  34. package/dist-client/icons/menu-icons.d.ts +0 -11
  35. package/dist-client/icons/menu-icons.js +0 -126
  36. package/dist-client/icons/menu-icons.js.map +0 -1
  37. package/dist-client/index.d.ts +0 -0
  38. package/dist-client/index.js +0 -2
  39. package/dist-client/index.js.map +0 -1
  40. package/dist-client/menu.d.ts +0 -23
  41. package/dist-client/menu.js +0 -59
  42. package/dist-client/menu.js.map +0 -1
  43. package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.d.ts +0 -58
  44. package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.js +0 -731
  45. package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.js.map +0 -1
  46. package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.d.ts +0 -23
  47. package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.js +0 -76
  48. package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.js.map +0 -1
  49. package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.d.ts +0 -69
  50. package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js +0 -385
  51. package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js.map +0 -1
  52. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.d.ts +0 -12
  53. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.js +0 -174
  54. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.js.map +0 -1
  55. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.d.ts +0 -41
  56. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.js +0 -191
  57. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.js.map +0 -1
  58. package/dist-client/pages/kpi-value/kpi-value-importer.d.ts +0 -23
  59. package/dist-client/pages/kpi-value/kpi-value-importer.js +0 -93
  60. package/dist-client/pages/kpi-value/kpi-value-importer.js.map +0 -1
  61. package/dist-client/pages/kpi-value/kpi-value-list-page.d.ts +0 -72
  62. package/dist-client/pages/kpi-value/kpi-value-list-page.js +0 -465
  63. package/dist-client/pages/kpi-value/kpi-value-list-page.js.map +0 -1
  64. package/dist-client/pages/project-complete-tabs/pc-tab1-plan.d.ts +0 -13
  65. package/dist-client/pages/project-complete-tabs/pc-tab1-plan.js +0 -248
  66. package/dist-client/pages/project-complete-tabs/pc-tab1-plan.js.map +0 -1
  67. package/dist-client/pages/project-complete-tabs/pc-tab2-rating.d.ts +0 -10
  68. package/dist-client/pages/project-complete-tabs/pc-tab2-rating.js +0 -229
  69. package/dist-client/pages/project-complete-tabs/pc-tab2-rating.js.map +0 -1
  70. package/dist-client/pages/project-complete-tabs/pc-tab3-upload.d.ts +0 -12
  71. package/dist-client/pages/project-complete-tabs/pc-tab3-upload.js +0 -213
  72. package/dist-client/pages/project-complete-tabs/pc-tab3-upload.js.map +0 -1
  73. package/dist-client/pages/sv-project-complete.d.ts +0 -22
  74. package/dist-client/pages/sv-project-complete.js +0 -213
  75. package/dist-client/pages/sv-project-complete.js.map +0 -1
  76. package/dist-client/pages/sv-project-completed-list.d.ts +0 -24
  77. package/dist-client/pages/sv-project-completed-list.js +0 -357
  78. package/dist-client/pages/sv-project-completed-list.js.map +0 -1
  79. package/dist-client/pages/sv-project-detail.d.ts +0 -13
  80. package/dist-client/pages/sv-project-detail.js +0 -494
  81. package/dist-client/pages/sv-project-detail.js.map +0 -1
  82. package/dist-client/pages/sv-project-list.d.ts +0 -157
  83. package/dist-client/pages/sv-project-list.js +0 -431
  84. package/dist-client/pages/sv-project-list.js.map +0 -1
  85. package/dist-client/pages/sv-user-management.d.ts +0 -5
  86. package/dist-client/pages/sv-user-management.js +0 -219
  87. package/dist-client/pages/sv-user-management.js.map +0 -1
  88. package/dist-client/route.d.ts +0 -1
  89. package/dist-client/route.js +0 -31
  90. package/dist-client/route.js.map +0 -1
  91. package/dist-client/shared/complete-api.d.ts +0 -5
  92. package/dist-client/shared/complete-api.js +0 -125
  93. package/dist-client/shared/complete-api.js.map +0 -1
  94. package/dist-client/shared/func.d.ts +0 -2
  95. package/dist-client/shared/func.js +0 -22
  96. package/dist-client/shared/func.js.map +0 -1
  97. package/dist-client/themes/dark.css +0 -51
  98. package/dist-client/themes/light.css +0 -51
  99. package/dist-client/tsconfig.tsbuildinfo +0 -1
  100. package/dist-client/viewparts/menu-tools.d.ts +0 -54
  101. package/dist-client/viewparts/menu-tools.js +0 -503
  102. package/dist-client/viewparts/menu-tools.js.map +0 -1
  103. package/dist-client/viewparts/user-circle.d.ts +0 -5
  104. package/dist-client/viewparts/user-circle.js +0 -26
  105. package/dist-client/viewparts/user-circle.js.map +0 -1
  106. package/dist-server/index.d.ts +0 -2
  107. package/dist-server/index.js +0 -6
  108. package/dist-server/index.js.map +0 -1
  109. package/dist-server/migrations/index.d.ts +0 -1
  110. package/dist-server/migrations/index.js +0 -12
  111. package/dist-server/migrations/index.js.map +0 -1
  112. package/dist-server/scripts/calculate-kpi-scores.d.ts +0 -10
  113. package/dist-server/scripts/calculate-kpi-scores.js +0 -271
  114. package/dist-server/scripts/calculate-kpi-scores.js.map +0 -1
  115. package/dist-server/scripts/load-grade-data-migration.d.ts +0 -10
  116. package/dist-server/scripts/load-grade-data-migration.js +0 -194
  117. package/dist-server/scripts/load-grade-data-migration.js.map +0 -1
  118. package/dist-server/scripts/propagate-parent-kpi-values.d.ts +0 -10
  119. package/dist-server/scripts/propagate-parent-kpi-values.js +0 -440
  120. package/dist-server/scripts/propagate-parent-kpi-values.js.map +0 -1
  121. package/dist-server/service/index.d.ts +0 -6
  122. package/dist-server/service/index.js +0 -21
  123. package/dist-server/service/index.js.map +0 -1
  124. package/dist-server/service/kpi-metric-value/index.d.ts +0 -4
  125. package/dist-server/service/kpi-metric-value/index.js +0 -8
  126. package/dist-server/service/kpi-metric-value/index.js.map +0 -1
  127. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.d.ts +0 -7
  128. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js +0 -112
  129. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js.map +0 -1
  130. package/dist-server/service/kpi-metric-value/kpi-metric-value-query.d.ts +0 -7
  131. package/dist-server/service/kpi-metric-value/kpi-metric-value-query.js +0 -47
  132. package/dist-server/service/kpi-metric-value/kpi-metric-value-query.js.map +0 -1
  133. package/dist-server/service/kpi-value/index.d.ts +0 -3
  134. package/dist-server/service/kpi-value/index.js +0 -7
  135. package/dist-server/service/kpi-value/index.js.map +0 -1
  136. package/dist-server/service/kpi-value/kpi-value-query.d.ts +0 -7
  137. package/dist-server/service/kpi-value/kpi-value-query.js +0 -47
  138. package/dist-server/service/kpi-value/kpi-value-query.js.map +0 -1
  139. package/dist-server/tsconfig.tsbuildinfo +0 -1
@@ -1,317 +0,0 @@
1
- import { __decorate, __metadata } from "tslib";
2
- import { LitElement, html, css } from 'lit';
3
- import { customElement, property } from 'lit/decorators.js';
4
- import * as d3 from 'd3';
5
- let KpiSingleBoxplotChart = class KpiSingleBoxplotChart extends LitElement {
6
- constructor() {
7
- super(...arguments);
8
- this.data = {};
9
- this.minKey = 'min';
10
- this.maxKey = 'max';
11
- this.meanKey = 'mean';
12
- this.medianKey = 'median';
13
- this.q1Key = 'q1';
14
- this.q3Key = 'q3';
15
- this.valueKey = 'value';
16
- this.color = '#2196f3';
17
- this.vertical = true; // true: 세로형, false: 가로형
18
- this.chartWidth = 0;
19
- this.chartHeight = 0;
20
- }
21
- render() {
22
- return html `
23
- <svg
24
- id="single-boxplot"
25
- width=${this.chartWidth}
26
- height=${this.chartHeight}
27
- viewBox="0 0 ${this.chartWidth} ${this.chartHeight}"
28
- preserveAspectRatio="xMidYMid meet"
29
- ></svg>
30
- `;
31
- }
32
- connectedCallback() {
33
- super.connectedCallback();
34
- this.resizeObserver = new ResizeObserver(entries => {
35
- for (const entry of entries) {
36
- const rect = entry.contentRect;
37
- this.chartWidth = rect.width;
38
- this.chartHeight = rect.height;
39
- this.requestUpdate();
40
- }
41
- });
42
- this.resizeObserver.observe(this);
43
- }
44
- disconnectedCallback() {
45
- var _a;
46
- (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
47
- super.disconnectedCallback();
48
- }
49
- updated() {
50
- this.drawSingleBoxplot();
51
- }
52
- drawSingleBoxplot() {
53
- const svg = d3.select(this.renderRoot.querySelector('#single-boxplot'));
54
- svg.selectAll('*').remove();
55
- // 데이터 검증
56
- if (!this.data || Object.keys(this.data).length === 0) {
57
- return;
58
- }
59
- const w = this.chartWidth || 200;
60
- const h = this.chartHeight || 200;
61
- const margin = 20;
62
- const plotW = w - margin * 2;
63
- const plotH = h - margin * 2;
64
- // 필수 필드 검증
65
- const requiredFields = [this.minKey, this.maxKey, this.q1Key, this.q3Key, this.medianKey, this.meanKey];
66
- const missingFields = requiredFields.filter(field => this.data[field] == null);
67
- if (missingFields.length > 0) {
68
- console.warn('Missing required fields:', missingFields);
69
- return;
70
- }
71
- const values = [
72
- this.data[this.minKey],
73
- this.data[this.maxKey],
74
- this.data[this.q1Key],
75
- this.data[this.q3Key],
76
- this.data[this.medianKey],
77
- this.data[this.meanKey]
78
- ];
79
- if (this.data[this.valueKey] != null) {
80
- values.push(this.data[this.valueKey]);
81
- }
82
- const g = svg
83
- .attr('width', w)
84
- .attr('height', h)
85
- .append('g')
86
- .attr('transform', `translate(${margin}, ${margin})`);
87
- if (this.vertical) {
88
- // 세로형 boxplot (기본)
89
- this.drawVerticalBoxplot(g, plotW, plotH, values);
90
- }
91
- else {
92
- // 가로형 boxplot
93
- this.drawHorizontalBoxplot(g, plotW, plotH, values);
94
- }
95
- }
96
- drawVerticalBoxplot(g, plotW, plotH, values) {
97
- var _a, _b;
98
- const y = d3
99
- .scaleLinear()
100
- .domain([(_a = d3.min(values)) !== null && _a !== void 0 ? _a : 0, (_b = d3.max(values)) !== null && _b !== void 0 ? _b : 1])
101
- .nice()
102
- .range([plotH, 0]);
103
- const boxWidth = Math.min(plotW * 0.6, 60); // 박스 너비 제한
104
- const boxX = (plotW - boxWidth) / 2; // 중앙 정렬
105
- // Outlier 계산
106
- const iqr = this.data[this.q3Key] - this.data[this.q1Key];
107
- const lowerFence = this.data[this.q1Key] - 1.5 * iqr;
108
- const upperFence = this.data[this.q3Key] + 1.5 * iqr;
109
- const actualMin = Math.max(this.data[this.minKey], lowerFence);
110
- const actualMax = Math.min(this.data[this.maxKey], upperFence);
111
- // 박스
112
- g.append('rect')
113
- .attr('x', boxX)
114
- .attr('y', y(Math.max(this.data[this.q1Key], this.data[this.q3Key])))
115
- .attr('width', boxWidth)
116
- .attr('height', Math.abs(y(this.data[this.q1Key]) - y(this.data[this.q3Key])))
117
- .attr('fill', this.color)
118
- .attr('opacity', 0.6)
119
- .attr('stroke', '#333')
120
- .attr('stroke-width', 1);
121
- // 중앙선(중앙값)
122
- g.append('line')
123
- .attr('x1', boxX)
124
- .attr('x2', boxX + boxWidth)
125
- .attr('y1', y(this.data[this.medianKey]))
126
- .attr('y2', y(this.data[this.medianKey]))
127
- .attr('stroke', '#333')
128
- .attr('stroke-width', 2);
129
- // 수염
130
- const centerX = boxX + boxWidth / 2;
131
- g.append('line')
132
- .attr('x1', centerX)
133
- .attr('x2', centerX)
134
- .attr('y1', y(actualMin))
135
- .attr('y2', y(actualMax))
136
- .attr('stroke', '#333')
137
- .attr('stroke-width', 1);
138
- // min/max 선
139
- const capWidth = boxWidth / 3;
140
- g.append('line')
141
- .attr('x1', centerX - capWidth / 2)
142
- .attr('x2', centerX + capWidth / 2)
143
- .attr('y1', y(actualMin))
144
- .attr('y2', y(actualMin))
145
- .attr('stroke', '#333')
146
- .attr('stroke-width', 1);
147
- g.append('line')
148
- .attr('x1', centerX - capWidth / 2)
149
- .attr('x2', centerX + capWidth / 2)
150
- .attr('y1', y(actualMax))
151
- .attr('y2', y(actualMax))
152
- .attr('stroke', '#333')
153
- .attr('stroke-width', 1);
154
- // Outliers
155
- if (this.data[this.minKey] < lowerFence) {
156
- g.append('circle')
157
- .attr('cx', centerX)
158
- .attr('cy', y(this.data[this.minKey]))
159
- .attr('r', 4.5)
160
- .attr('fill', '#ff4444');
161
- }
162
- if (this.data[this.maxKey] > upperFence) {
163
- g.append('circle')
164
- .attr('cx', centerX)
165
- .attr('cy', y(this.data[this.maxKey]))
166
- .attr('r', 4.5)
167
- .attr('fill', '#ff4444');
168
- }
169
- // 현재값 (있는 경우)
170
- if (this.data[this.valueKey] != null) {
171
- g.append('circle')
172
- .attr('cx', centerX)
173
- .attr('cy', y(this.data[this.valueKey]))
174
- .attr('r', 3)
175
- .attr('fill', '#ff4444');
176
- }
177
- }
178
- drawHorizontalBoxplot(g, plotW, plotH, values) {
179
- var _a, _b;
180
- const x = d3
181
- .scaleLinear()
182
- .domain([(_a = d3.min(values)) !== null && _a !== void 0 ? _a : 0, (_b = d3.max(values)) !== null && _b !== void 0 ? _b : 1])
183
- .nice()
184
- .range([0, plotW]);
185
- const boxHeight = Math.min(plotH * 0.6, 60);
186
- const boxY = (plotH - boxHeight) / 2;
187
- // Outlier 계산
188
- const iqr = this.data[this.q3Key] - this.data[this.q1Key];
189
- const lowerFence = this.data[this.q1Key] - 1.5 * iqr;
190
- const upperFence = this.data[this.q3Key] + 1.5 * iqr;
191
- const actualMin = Math.max(this.data[this.minKey], lowerFence);
192
- const actualMax = Math.min(this.data[this.maxKey], upperFence);
193
- // 박스 (가로)
194
- g.append('rect')
195
- .attr('x', x(Math.min(this.data[this.q1Key], this.data[this.q3Key])))
196
- .attr('y', boxY)
197
- .attr('width', Math.abs(x(this.data[this.q3Key]) - x(this.data[this.q1Key])))
198
- .attr('height', boxHeight)
199
- .attr('fill', this.color)
200
- .attr('opacity', 0.6)
201
- .attr('stroke', '#333')
202
- .attr('stroke-width', 1);
203
- // 중앙선 (가로)
204
- g.append('line')
205
- .attr('x1', x(this.data[this.medianKey]))
206
- .attr('x2', x(this.data[this.medianKey]))
207
- .attr('y1', boxY)
208
- .attr('y2', boxY + boxHeight)
209
- .attr('stroke', '#333')
210
- .attr('stroke-width', 2);
211
- // 수염 (가로)
212
- const centerY = boxY + boxHeight / 2;
213
- g.append('line')
214
- .attr('x1', x(actualMin))
215
- .attr('x2', x(actualMax))
216
- .attr('y1', centerY)
217
- .attr('y2', centerY)
218
- .attr('stroke', '#333')
219
- .attr('stroke-width', 1);
220
- // min/max 선 (가로)
221
- const capHeight = boxHeight / 3;
222
- g.append('line')
223
- .attr('x1', x(actualMin))
224
- .attr('x2', x(actualMin))
225
- .attr('y1', centerY - capHeight / 2)
226
- .attr('y2', centerY + capHeight / 2)
227
- .attr('stroke', '#333')
228
- .attr('stroke-width', 1);
229
- g.append('line')
230
- .attr('x1', x(actualMax))
231
- .attr('x2', x(actualMax))
232
- .attr('y1', centerY - capHeight / 2)
233
- .attr('y2', centerY + capHeight / 2)
234
- .attr('stroke', '#333')
235
- .attr('stroke-width', 1);
236
- // Outliers (가로)
237
- if (this.data[this.minKey] < lowerFence) {
238
- g.append('circle')
239
- .attr('cx', x(this.data[this.minKey]))
240
- .attr('cy', centerY)
241
- .attr('r', 4.5)
242
- .attr('fill', '#ff4444');
243
- }
244
- if (this.data[this.maxKey] > upperFence) {
245
- g.append('circle')
246
- .attr('cx', x(this.data[this.maxKey]))
247
- .attr('cy', centerY)
248
- .attr('r', 4.5)
249
- .attr('fill', '#ff4444');
250
- }
251
- // 현재값 (가로)
252
- if (this.data[this.valueKey] != null) {
253
- g.append('circle')
254
- .attr('cx', x(this.data[this.valueKey]))
255
- .attr('cy', centerY)
256
- .attr('r', 3)
257
- .attr('fill', '#ff4444');
258
- }
259
- }
260
- };
261
- KpiSingleBoxplotChart.styles = css `
262
- :host {
263
- display: block;
264
- width: 100%;
265
- height: 100%;
266
- }
267
- svg {
268
- width: 100%;
269
- height: 100%;
270
- display: block;
271
- }
272
- `;
273
- __decorate([
274
- property({ type: Object }),
275
- __metadata("design:type", Object)
276
- ], KpiSingleBoxplotChart.prototype, "data", void 0);
277
- __decorate([
278
- property({ type: String }),
279
- __metadata("design:type", String)
280
- ], KpiSingleBoxplotChart.prototype, "minKey", void 0);
281
- __decorate([
282
- property({ type: String }),
283
- __metadata("design:type", String)
284
- ], KpiSingleBoxplotChart.prototype, "maxKey", void 0);
285
- __decorate([
286
- property({ type: String }),
287
- __metadata("design:type", String)
288
- ], KpiSingleBoxplotChart.prototype, "meanKey", void 0);
289
- __decorate([
290
- property({ type: String }),
291
- __metadata("design:type", String)
292
- ], KpiSingleBoxplotChart.prototype, "medianKey", void 0);
293
- __decorate([
294
- property({ type: String }),
295
- __metadata("design:type", String)
296
- ], KpiSingleBoxplotChart.prototype, "q1Key", void 0);
297
- __decorate([
298
- property({ type: String }),
299
- __metadata("design:type", String)
300
- ], KpiSingleBoxplotChart.prototype, "q3Key", void 0);
301
- __decorate([
302
- property({ type: String }),
303
- __metadata("design:type", String)
304
- ], KpiSingleBoxplotChart.prototype, "valueKey", void 0);
305
- __decorate([
306
- property({ type: String }),
307
- __metadata("design:type", String)
308
- ], KpiSingleBoxplotChart.prototype, "color", void 0);
309
- __decorate([
310
- property({ type: Boolean }),
311
- __metadata("design:type", Boolean)
312
- ], KpiSingleBoxplotChart.prototype, "vertical", void 0);
313
- KpiSingleBoxplotChart = __decorate([
314
- customElement('kpi-single-boxplot-chart')
315
- ], KpiSingleBoxplotChart);
316
- export { KpiSingleBoxplotChart };
317
- //# sourceMappingURL=kpi-single-boxplot-chart.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"kpi-single-boxplot-chart.js","sourceRoot":"","sources":["../../client/components/kpi-single-boxplot-chart.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, css } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport * as d3 from 'd3'\n\n@customElement('kpi-single-boxplot-chart')\nexport class KpiSingleBoxplotChart extends LitElement {\n @property({ type: Object }) data: any = {}\n @property({ type: String }) minKey: string = 'min'\n @property({ type: String }) maxKey: string = 'max'\n @property({ type: String }) meanKey: string = 'mean'\n @property({ type: String }) medianKey: string = 'median'\n @property({ type: String }) q1Key: string = 'q1'\n @property({ type: String }) q3Key: string = 'q3'\n @property({ type: String }) valueKey: string = 'value'\n @property({ type: String }) color: string = '#2196f3'\n @property({ type: Boolean }) vertical: boolean = true // true: 세로형, false: 가로형\n\n static styles = css`\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n svg {\n width: 100%;\n height: 100%;\n display: block;\n }\n `\n\n private chartWidth = 0\n private chartHeight = 0\n private resizeObserver?: ResizeObserver\n\n render() {\n return html`\n <svg\n id=\"single-boxplot\"\n width=${this.chartWidth}\n height=${this.chartHeight}\n viewBox=\"0 0 ${this.chartWidth} ${this.chartHeight}\"\n preserveAspectRatio=\"xMidYMid meet\"\n ></svg>\n `\n }\n\n connectedCallback() {\n super.connectedCallback()\n this.resizeObserver = new ResizeObserver(entries => {\n for (const entry of entries) {\n const rect = entry.contentRect\n this.chartWidth = rect.width\n this.chartHeight = rect.height\n this.requestUpdate()\n }\n })\n this.resizeObserver.observe(this)\n }\n\n disconnectedCallback() {\n this.resizeObserver?.disconnect()\n super.disconnectedCallback()\n }\n\n updated() {\n this.drawSingleBoxplot()\n }\n\n private drawSingleBoxplot() {\n const svg = d3.select(this.renderRoot.querySelector('#single-boxplot'))\n svg.selectAll('*').remove()\n\n // 데이터 검증\n if (!this.data || Object.keys(this.data).length === 0) {\n return\n }\n\n const w = this.chartWidth || 200\n const h = this.chartHeight || 200\n const margin = 20\n const plotW = w - margin * 2\n const plotH = h - margin * 2\n\n // 필수 필드 검증\n const requiredFields = [this.minKey, this.maxKey, this.q1Key, this.q3Key, this.medianKey, this.meanKey]\n const missingFields = requiredFields.filter(field => this.data[field] == null)\n if (missingFields.length > 0) {\n console.warn('Missing required fields:', missingFields)\n return\n }\n\n const values = [\n this.data[this.minKey],\n this.data[this.maxKey],\n this.data[this.q1Key],\n this.data[this.q3Key],\n this.data[this.medianKey],\n this.data[this.meanKey]\n ]\n\n if (this.data[this.valueKey] != null) {\n values.push(this.data[this.valueKey])\n }\n\n const g = svg\n .attr('width', w)\n .attr('height', h)\n .append('g')\n .attr('transform', `translate(${margin}, ${margin})`)\n\n if (this.vertical) {\n // 세로형 boxplot (기본)\n this.drawVerticalBoxplot(g, plotW, plotH, values)\n } else {\n // 가로형 boxplot\n this.drawHorizontalBoxplot(g, plotW, plotH, values)\n }\n }\n\n private drawVerticalBoxplot(g: any, plotW: number, plotH: number, values: number[]) {\n const y = d3\n .scaleLinear()\n .domain([d3.min(values) ?? 0, d3.max(values) ?? 1])\n .nice()\n .range([plotH, 0])\n\n const boxWidth = Math.min(plotW * 0.6, 60) // 박스 너비 제한\n const boxX = (plotW - boxWidth) / 2 // 중앙 정렬\n\n // Outlier 계산\n const iqr = this.data[this.q3Key] - this.data[this.q1Key]\n const lowerFence = this.data[this.q1Key] - 1.5 * iqr\n const upperFence = this.data[this.q3Key] + 1.5 * iqr\n\n const actualMin = Math.max(this.data[this.minKey], lowerFence)\n const actualMax = Math.min(this.data[this.maxKey], upperFence)\n\n // 박스\n g.append('rect')\n .attr('x', boxX)\n .attr('y', y(Math.max(this.data[this.q1Key], this.data[this.q3Key])))\n .attr('width', boxWidth)\n .attr('height', Math.abs(y(this.data[this.q1Key]) - y(this.data[this.q3Key])))\n .attr('fill', this.color)\n .attr('opacity', 0.6)\n .attr('stroke', '#333')\n .attr('stroke-width', 1)\n\n // 중앙선(중앙값)\n g.append('line')\n .attr('x1', boxX)\n .attr('x2', boxX + boxWidth)\n .attr('y1', y(this.data[this.medianKey]))\n .attr('y2', y(this.data[this.medianKey]))\n .attr('stroke', '#333')\n .attr('stroke-width', 2)\n\n // 수염\n const centerX = boxX + boxWidth / 2\n g.append('line')\n .attr('x1', centerX)\n .attr('x2', centerX)\n .attr('y1', y(actualMin))\n .attr('y2', y(actualMax))\n .attr('stroke', '#333')\n .attr('stroke-width', 1)\n\n // min/max 선\n const capWidth = boxWidth / 3\n g.append('line')\n .attr('x1', centerX - capWidth / 2)\n .attr('x2', centerX + capWidth / 2)\n .attr('y1', y(actualMin))\n .attr('y2', y(actualMin))\n .attr('stroke', '#333')\n .attr('stroke-width', 1)\n\n g.append('line')\n .attr('x1', centerX - capWidth / 2)\n .attr('x2', centerX + capWidth / 2)\n .attr('y1', y(actualMax))\n .attr('y2', y(actualMax))\n .attr('stroke', '#333')\n .attr('stroke-width', 1)\n\n // Outliers\n if (this.data[this.minKey] < lowerFence) {\n g.append('circle')\n .attr('cx', centerX)\n .attr('cy', y(this.data[this.minKey]))\n .attr('r', 4.5)\n .attr('fill', '#ff4444')\n }\n\n if (this.data[this.maxKey] > upperFence) {\n g.append('circle')\n .attr('cx', centerX)\n .attr('cy', y(this.data[this.maxKey]))\n .attr('r', 4.5)\n .attr('fill', '#ff4444')\n }\n\n\n // 현재값 (있는 경우)\n if (this.data[this.valueKey] != null) {\n g.append('circle')\n .attr('cx', centerX)\n .attr('cy', y(this.data[this.valueKey]))\n .attr('r', 3)\n .attr('fill', '#ff4444')\n }\n }\n\n private drawHorizontalBoxplot(g: any, plotW: number, plotH: number, values: number[]) {\n const x = d3\n .scaleLinear()\n .domain([d3.min(values) ?? 0, d3.max(values) ?? 1])\n .nice()\n .range([0, plotW])\n\n const boxHeight = Math.min(plotH * 0.6, 60)\n const boxY = (plotH - boxHeight) / 2\n\n // Outlier 계산\n const iqr = this.data[this.q3Key] - this.data[this.q1Key]\n const lowerFence = this.data[this.q1Key] - 1.5 * iqr\n const upperFence = this.data[this.q3Key] + 1.5 * iqr\n\n const actualMin = Math.max(this.data[this.minKey], lowerFence)\n const actualMax = Math.min(this.data[this.maxKey], upperFence)\n\n // 박스 (가로)\n g.append('rect')\n .attr('x', x(Math.min(this.data[this.q1Key], this.data[this.q3Key])))\n .attr('y', boxY)\n .attr('width', Math.abs(x(this.data[this.q3Key]) - x(this.data[this.q1Key])))\n .attr('height', boxHeight)\n .attr('fill', this.color)\n .attr('opacity', 0.6)\n .attr('stroke', '#333')\n .attr('stroke-width', 1)\n\n // 중앙선 (가로)\n g.append('line')\n .attr('x1', x(this.data[this.medianKey]))\n .attr('x2', x(this.data[this.medianKey]))\n .attr('y1', boxY)\n .attr('y2', boxY + boxHeight)\n .attr('stroke', '#333')\n .attr('stroke-width', 2)\n\n // 수염 (가로)\n const centerY = boxY + boxHeight / 2\n g.append('line')\n .attr('x1', x(actualMin))\n .attr('x2', x(actualMax))\n .attr('y1', centerY)\n .attr('y2', centerY)\n .attr('stroke', '#333')\n .attr('stroke-width', 1)\n\n // min/max 선 (가로)\n const capHeight = boxHeight / 3\n g.append('line')\n .attr('x1', x(actualMin))\n .attr('x2', x(actualMin))\n .attr('y1', centerY - capHeight / 2)\n .attr('y2', centerY + capHeight / 2)\n .attr('stroke', '#333')\n .attr('stroke-width', 1)\n\n g.append('line')\n .attr('x1', x(actualMax))\n .attr('x2', x(actualMax))\n .attr('y1', centerY - capHeight / 2)\n .attr('y2', centerY + capHeight / 2)\n .attr('stroke', '#333')\n .attr('stroke-width', 1)\n\n // Outliers (가로)\n if (this.data[this.minKey] < lowerFence) {\n g.append('circle')\n .attr('cx', x(this.data[this.minKey]))\n .attr('cy', centerY)\n .attr('r', 4.5)\n .attr('fill', '#ff4444')\n }\n\n if (this.data[this.maxKey] > upperFence) {\n g.append('circle')\n .attr('cx', x(this.data[this.maxKey]))\n .attr('cy', centerY)\n .attr('r', 4.5)\n .attr('fill', '#ff4444')\n }\n\n\n // 현재값 (가로)\n if (this.data[this.valueKey] != null) {\n g.append('circle')\n .attr('cx', x(this.data[this.valueKey]))\n .attr('cy', centerY)\n .attr('r', 3)\n .attr('fill', '#ff4444')\n }\n }\n}"]}
@@ -1,18 +0,0 @@
1
- import '@material/web/button/outlined-button.js';
2
- import '@material/web/icon/icon.js';
3
- import { LitElement } from 'lit';
4
- export declare class SvPagenationControl extends LitElement {
5
- static styles: import("lit").CSSResult[];
6
- currentPage: number;
7
- totalItems: number;
8
- pageLimit: number;
9
- private get totalPages();
10
- private get pageBlock();
11
- render(): import("lit-html").TemplateResult<1>;
12
- private _emitPageChange;
13
- private _numberButtons;
14
- private _onFirst;
15
- private _onPrev;
16
- private _onNext;
17
- private _onLast;
18
- }
@@ -1,142 +0,0 @@
1
- import { __decorate, __metadata } from "tslib";
2
- import '@material/web/button/outlined-button.js';
3
- import '@material/web/icon/icon.js';
4
- import { css, html, LitElement } from 'lit';
5
- import { customElement, property } from 'lit/decorators.js';
6
- let SvPagenationControl = class SvPagenationControl extends LitElement {
7
- constructor() {
8
- super(...arguments);
9
- this.currentPage = 1;
10
- this.totalItems = 0;
11
- this.pageLimit = 20;
12
- }
13
- get totalPages() {
14
- const totalPages = Math.ceil((this.totalItems || 0) / (this.pageLimit || 1));
15
- return Math.max(1, totalPages);
16
- }
17
- get pageBlock() {
18
- const blockSize = 10;
19
- const blockIndex = Math.floor((this.currentPage - 1) / blockSize);
20
- const start = blockIndex * blockSize + 1;
21
- const end = Math.min(start + blockSize - 1, this.totalPages);
22
- return { start, end };
23
- }
24
- render() {
25
- return html `
26
- <div pagination>
27
- <md-outlined-button icon ?disabled=${this.currentPage <= 1} @click=${this._onFirst}>
28
- <md-icon>first_page</md-icon>
29
- </md-outlined-button>
30
- <md-outlined-button icon ?disabled=${this.currentPage <= 1} @click=${this._onPrev}>
31
- <md-icon>chevron_left</md-icon>
32
- </md-outlined-button>
33
-
34
- <div numbers>${this._numberButtons()}</div>
35
-
36
- <md-outlined-button icon ?disabled=${this.currentPage >= this.totalPages} @click=${this._onNext}>
37
- <md-icon>chevron_right</md-icon>
38
- </md-outlined-button>
39
- <md-outlined-button icon ?disabled=${this.currentPage >= this.totalPages} @click=${this._onLast}>
40
- <md-icon>last_page</md-icon>
41
- </md-outlined-button>
42
- </div>
43
- `;
44
- }
45
- _emitPageChange(nextPage) {
46
- const bounded = Math.min(Math.max(1, nextPage), this.totalPages);
47
- if (bounded !== this.currentPage) {
48
- this.dispatchEvent(new CustomEvent('page-change', {
49
- detail: { page: bounded },
50
- bubbles: true,
51
- composed: true
52
- }));
53
- }
54
- }
55
- _numberButtons() {
56
- const { start, end } = this.pageBlock;
57
- const buttons = [];
58
- for (let page = start; page <= end; page++) {
59
- const selected = page === this.currentPage;
60
- buttons.push(html `<md-outlined-button data-page ?selected=${selected} @click=${() => this._emitPageChange(page)}
61
- >${page}</md-outlined-button
62
- >`);
63
- }
64
- return buttons;
65
- }
66
- _onFirst() {
67
- this._emitPageChange(1);
68
- }
69
- _onPrev() {
70
- this._emitPageChange(this.currentPage - 1);
71
- }
72
- _onNext() {
73
- this._emitPageChange(this.currentPage + 1);
74
- }
75
- _onLast() {
76
- this._emitPageChange(this.totalPages);
77
- }
78
- };
79
- SvPagenationControl.styles = [
80
- css `
81
- div[pagination] {
82
- display: flex;
83
- align-items: center;
84
- justify-content: center;
85
- gap: var(--spacing-medium, 8px);
86
- margin: var(--spacing-large, 12px);
87
-
88
- div[numbers] {
89
- display: inline-flex;
90
- gap: var(--spacing-tiny, 2px);
91
- }
92
-
93
- md-icon {
94
- --md-icon-size: 18px;
95
- }
96
-
97
- md-outlined-button {
98
- --md-outlined-button-container-height: 30px;
99
- --md-outlined-button-label-text-size: 13px;
100
- padding: 0 10px;
101
- }
102
-
103
- md-outlined-button[selected] {
104
- --md-outlined-button-label-text-color: #ffffff;
105
- --md-sys-color-outline: #0595e5;
106
- background-color: #0595e5;
107
- }
108
-
109
- md-outlined-button[icon] {
110
- min-width: 30px;
111
- width: 30px;
112
- padding: 0;
113
- }
114
-
115
- md-outlined-button[icon] md-icon {
116
- margin-top: 5px;
117
- }
118
-
119
- md-outlined-button[data-page] {
120
- min-width: 34px;
121
- padding: 0 8px;
122
- }
123
- }
124
- `
125
- ];
126
- __decorate([
127
- property({ type: Number }),
128
- __metadata("design:type", Number)
129
- ], SvPagenationControl.prototype, "currentPage", void 0);
130
- __decorate([
131
- property({ type: Number }),
132
- __metadata("design:type", Number)
133
- ], SvPagenationControl.prototype, "totalItems", void 0);
134
- __decorate([
135
- property({ type: Number }),
136
- __metadata("design:type", Number)
137
- ], SvPagenationControl.prototype, "pageLimit", void 0);
138
- SvPagenationControl = __decorate([
139
- customElement('sv-pagenation-control')
140
- ], SvPagenationControl);
141
- export { SvPagenationControl };
142
- //# sourceMappingURL=sv-pagenation-control.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sv-pagenation-control.js","sourceRoot":"","sources":["../../client/components/sv-pagenation-control.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/outlined-button.js'\nimport '@material/web/icon/icon.js'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\n@customElement('sv-pagenation-control')\nexport class SvPagenationControl extends LitElement {\n static styles = [\n css`\n div[pagination] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--spacing-medium, 8px);\n margin: var(--spacing-large, 12px);\n\n div[numbers] {\n display: inline-flex;\n gap: var(--spacing-tiny, 2px);\n }\n\n md-icon {\n --md-icon-size: 18px;\n }\n\n md-outlined-button {\n --md-outlined-button-container-height: 30px;\n --md-outlined-button-label-text-size: 13px;\n padding: 0 10px;\n }\n\n md-outlined-button[selected] {\n --md-outlined-button-label-text-color: #ffffff;\n --md-sys-color-outline: #0595e5;\n background-color: #0595e5;\n }\n\n md-outlined-button[icon] {\n min-width: 30px;\n width: 30px;\n padding: 0;\n }\n\n md-outlined-button[icon] md-icon {\n margin-top: 5px;\n }\n\n md-outlined-button[data-page] {\n min-width: 34px;\n padding: 0 8px;\n }\n }\n `\n ]\n\n @property({ type: Number }) currentPage: number = 1\n @property({ type: Number }) totalItems: number = 0\n @property({ type: Number }) pageLimit: number = 20\n\n private get totalPages(): number {\n const totalPages = Math.ceil((this.totalItems || 0) / (this.pageLimit || 1))\n return Math.max(1, totalPages)\n }\n\n private get pageBlock(): { start: number; end: number } {\n const blockSize = 10\n const blockIndex = Math.floor((this.currentPage - 1) / blockSize)\n const start = blockIndex * blockSize + 1\n const end = Math.min(start + blockSize - 1, this.totalPages)\n return { start, end }\n }\n\n render() {\n return html`\n <div pagination>\n <md-outlined-button icon ?disabled=${this.currentPage <= 1} @click=${this._onFirst}>\n <md-icon>first_page</md-icon>\n </md-outlined-button>\n <md-outlined-button icon ?disabled=${this.currentPage <= 1} @click=${this._onPrev}>\n <md-icon>chevron_left</md-icon>\n </md-outlined-button>\n\n <div numbers>${this._numberButtons()}</div>\n\n <md-outlined-button icon ?disabled=${this.currentPage >= this.totalPages} @click=${this._onNext}>\n <md-icon>chevron_right</md-icon>\n </md-outlined-button>\n <md-outlined-button icon ?disabled=${this.currentPage >= this.totalPages} @click=${this._onLast}>\n <md-icon>last_page</md-icon>\n </md-outlined-button>\n </div>\n `\n }\n\n private _emitPageChange(nextPage: number) {\n const bounded = Math.min(Math.max(1, nextPage), this.totalPages)\n if (bounded !== this.currentPage) {\n this.dispatchEvent(\n new CustomEvent('page-change', {\n detail: { page: bounded },\n bubbles: true,\n composed: true\n })\n )\n }\n }\n\n private _numberButtons() {\n const { start, end } = this.pageBlock\n const buttons = [] as any[]\n for (let page = start; page <= end; page++) {\n const selected = page === this.currentPage\n buttons.push(\n html`<md-outlined-button data-page ?selected=${selected} @click=${() => this._emitPageChange(page)}\n >${page}</md-outlined-button\n >`\n )\n }\n return buttons\n }\n\n private _onFirst() {\n this._emitPageChange(1)\n }\n\n private _onPrev() {\n this._emitPageChange(this.currentPage - 1)\n }\n\n private _onNext() {\n this._emitPageChange(this.currentPage + 1)\n }\n\n private _onLast() {\n this._emitPageChange(this.totalPages)\n }\n}\n"]}
@@ -1,8 +0,0 @@
1
- import '@material/web/icon/icon.js';
2
- import { LitElement } from 'lit';
3
- export declare class HomePage extends LitElement {
4
- static styles: import("lit").CSSResult[];
5
- private _applicationMeta;
6
- render(): import("lit-html").TemplateResult<1>;
7
- get applicationMeta(): any;
8
- }
@@ -1,97 +0,0 @@
1
- import { __decorate } from "tslib";
2
- import '@material/web/icon/icon.js';
3
- import { css, html, LitElement } from 'lit';
4
- import { customElement } from 'lit/decorators.js';
5
- let HomePage = class HomePage extends LitElement {
6
- render() {
7
- var { title, description } = this.applicationMeta;
8
- return html `
9
- <div message>
10
- <strong>${title}</strong>
11
- ${description}
12
- <video autoplay muted playsinline loop>
13
- <source src="/assets/videos/intro.mp4" type="video/mp4" />
14
- </video>
15
- </div>
16
-
17
- <md-icon signin @click=${e => (window.location.href = '/auth/signin')}>login</md-icon>
18
- `;
19
- }
20
- get applicationMeta() {
21
- if (!this._applicationMeta) {
22
- var iconLink = document.querySelector('link[rel="application-icon"]');
23
- var titleMeta = document.querySelector('meta[name="application-name"]');
24
- var descriptionMeta = document.querySelector('meta[name="application-description"]');
25
- this._applicationMeta = {
26
- icon: iconLink === null || iconLink === void 0 ? void 0 : iconLink.href,
27
- title: (titleMeta === null || titleMeta === void 0 ? void 0 : titleMeta.content) || 'Things Factory',
28
- description: (descriptionMeta === null || descriptionMeta === void 0 ? void 0 : descriptionMeta.content) || 'Reimagining Software'
29
- };
30
- }
31
- return this._applicationMeta;
32
- }
33
- };
34
- HomePage.styles = [
35
- css `
36
- :host {
37
- background-color: var(--md-sys-color-background);
38
-
39
- display: block;
40
- position: relative;
41
-
42
- max-width: 100vw;
43
- width: 100vw;
44
- height: 100vh;
45
- height: 100dvh;
46
- }
47
-
48
- [signin] {
49
- position: absolute;
50
- right: 20px;
51
- top: 20px;
52
- font-size: 2em;
53
- color: white;
54
- }
55
-
56
- [message] {
57
- background-color: rgba(50, 66, 97, 0.8);
58
- padding: 60px 50px 0 50px;
59
- color: #fff;
60
- text-align: center;
61
- font-size: 20px;
62
- }
63
-
64
- [message] strong {
65
- display: block;
66
- font-size: 2.5rem;
67
- }
68
-
69
- video {
70
- position: absolute;
71
- top: 50%;
72
- left: 50%;
73
- width: 100vw;
74
- height: 100vh;
75
- object-fit: cover;
76
- transform: translate(-50%, -50%);
77
- }
78
-
79
- @media screen and (max-width: 480px) {
80
- [message] {
81
- padding: 60px 30px 0 30px;
82
- color: #fff;
83
- text-align: center;
84
- font-size: 15px;
85
- }
86
-
87
- [message] strong {
88
- font-size: 1.6rem;
89
- }
90
- }
91
- `
92
- ];
93
- HomePage = __decorate([
94
- customElement('home-page')
95
- ], HomePage);
96
- export { HomePage };
97
- //# sourceMappingURL=home.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"home.js","sourceRoot":"","sources":["../../../client/entries/public/home.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AAEnC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAG1C,IAAM,QAAQ,GAAd,MAAM,QAAS,SAAQ,UAAU;IA+DtC,MAAM;QACJ,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,eAAe,CAAA;QAEjD,OAAO,IAAI,CAAA;;kBAEG,KAAK;UACb,WAAW;;;;;;+BAMU,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,cAAc,CAAC;KACtE,CAAA;IACH,CAAC;IAED,IAAI,eAAe;QACjB,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,IAAI,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,8BAA8B,CAAoB,CAAA;YACxF,IAAI,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,+BAA+B,CAAoB,CAAA;YAC1F,IAAI,eAAe,GAAG,QAAQ,CAAC,aAAa,CAAC,sCAAsC,CAAoB,CAAA;YAEvG,IAAI,CAAC,gBAAgB,GAAG;gBACtB,IAAI,EAAE,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,IAAI;gBACpB,KAAK,EAAE,CAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,OAAO,KAAI,gBAAgB;gBAC7C,WAAW,EAAE,CAAA,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,OAAO,KAAI,sBAAsB;aAChE,CAAA;QACH,CAAC;QAED,OAAO,IAAI,CAAC,gBAAgB,CAAA;IAC9B,CAAC;;AA5FM,eAAM,GAAG;IACd,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAwDF;CACF,AA1DY,CA0DZ;AA3DU,QAAQ;IADpB,aAAa,CAAC,WAAW,CAAC;GACd,QAAQ,CA8FpB","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { css, html, LitElement } from 'lit'\nimport { customElement } from 'lit/decorators.js'\n\n@customElement('home-page')\nexport class HomePage extends LitElement {\n static styles = [\n css`\n :host {\n background-color: var(--md-sys-color-background);\n\n display: block;\n position: relative;\n\n max-width: 100vw;\n width: 100vw;\n height: 100vh;\n height: 100dvh;\n }\n\n [signin] {\n position: absolute;\n right: 20px;\n top: 20px;\n font-size: 2em;\n color: white;\n }\n\n [message] {\n background-color: rgba(50, 66, 97, 0.8);\n padding: 60px 50px 0 50px;\n color: #fff;\n text-align: center;\n font-size: 20px;\n }\n\n [message] strong {\n display: block;\n font-size: 2.5rem;\n }\n\n video {\n position: absolute;\n top: 50%;\n left: 50%;\n width: 100vw;\n height: 100vh;\n object-fit: cover;\n transform: translate(-50%, -50%);\n }\n\n @media screen and (max-width: 480px) {\n [message] {\n padding: 60px 30px 0 30px;\n color: #fff;\n text-align: center;\n font-size: 15px;\n }\n\n [message] strong {\n font-size: 1.6rem;\n }\n }\n `\n ]\n\n private _applicationMeta\n\n render() {\n var { title, description } = this.applicationMeta\n\n return html`\n <div message>\n <strong>${title}</strong>\n ${description}\n <video autoplay muted playsinline loop>\n <source src=\"/assets/videos/intro.mp4\" type=\"video/mp4\" />\n </video>\n </div>\n\n <md-icon signin @click=${e => (window.location.href = '/auth/signin')}>login</md-icon>\n `\n }\n\n get applicationMeta() {\n if (!this._applicationMeta) {\n var iconLink = document.querySelector('link[rel=\"application-icon\"]') as HTMLLinkElement\n var titleMeta = document.querySelector('meta[name=\"application-name\"]') as HTMLMetaElement\n var descriptionMeta = document.querySelector('meta[name=\"application-description\"]') as HTMLMetaElement\n\n this._applicationMeta = {\n icon: iconLink?.href,\n title: titleMeta?.content || 'Things Factory',\n description: descriptionMeta?.content || 'Reimagining Software'\n }\n }\n\n return this._applicationMeta\n }\n}\n"]}