@dssp/supervision 1.0.0-alpha.47 → 1.0.0-alpha.48
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/dist-client/pages/building-inspection/building-inspection-detail-ai-measurement.d.ts +56 -0
- package/dist-client/pages/building-inspection/building-inspection-detail-ai-measurement.js +789 -0
- package/dist-client/pages/building-inspection/building-inspection-detail-ai-measurement.js.map +1 -0
- package/dist-client/pages/building-inspection/building-inspection-detail-camera.d.ts +6 -33
- package/dist-client/pages/building-inspection/building-inspection-detail-camera.js +57 -427
- package/dist-client/pages/building-inspection/building-inspection-detail-camera.js.map +1 -1
- package/dist-client/pages/building-inspection/component/building-inspection-detail-header.d.ts +3 -0
- package/dist-client/pages/building-inspection/component/building-inspection-detail-header.js +77 -8
- package/dist-client/pages/building-inspection/component/building-inspection-detail-header.js.map +1 -1
- package/dist-client/pages/building-inspection/component/inspection-document/photo-album-popup.js +21 -6
- package/dist-client/pages/building-inspection/component/inspection-document/photo-album-popup.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/route.js +3 -0
- package/dist-client/route.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/service/checklist/checklist-query.d.ts +1 -0
- package/dist-server/service/checklist/checklist-query.js +20 -0
- package/dist-server/service/checklist/checklist-query.js.map +1 -1
- package/dist-server/service/checklist-template-item/index.d.ts +1 -1
- package/dist-server/service/index.d.ts +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -2
- package/things-factory.config.js +1 -0
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { __decorate, __metadata } from "tslib";
|
|
2
2
|
import '@material/web/icon/icon.js';
|
|
3
|
-
import '@operato/input/ox-input-switch.js';
|
|
4
|
-
import '@operato/mini-map/ox-zoomable-image.js';
|
|
5
3
|
import '@material/web/progress/circular-progress.js';
|
|
6
4
|
import gql from 'graphql-tag';
|
|
7
5
|
import { css, html } from 'lit';
|
|
@@ -9,77 +7,17 @@ import { customElement, state, query } from 'lit/decorators.js';
|
|
|
9
7
|
import { PageView } from '@operato/shell';
|
|
10
8
|
import { CommonGristStyles, ScrollbarStyles } from '@operato/styles';
|
|
11
9
|
import { client } from '@operato/graphql';
|
|
10
|
+
import { notify } from '@operato/layout';
|
|
12
11
|
import './component/building-inspection-detail-header';
|
|
13
12
|
let BuildingInspectionCamera = class BuildingInspectionCamera extends PageView {
|
|
14
13
|
constructor() {
|
|
15
14
|
super(...arguments);
|
|
16
|
-
this.KEYPOINT_RULER_API_BASE_URL = 'https://hatiolab-korea-uni.ettisoft.com';
|
|
17
15
|
this.project = {};
|
|
18
16
|
this.buildingInspection = {};
|
|
19
17
|
this.buildingInspectionId = '';
|
|
20
|
-
this.
|
|
21
|
-
this.
|
|
22
|
-
this.
|
|
23
|
-
this.analyzing = false;
|
|
24
|
-
this.selectedPoints = {
|
|
25
|
-
x1: null,
|
|
26
|
-
y1: null,
|
|
27
|
-
x2: null,
|
|
28
|
-
y2: null
|
|
29
|
-
};
|
|
30
|
-
this.frameNaturalWidth = 0;
|
|
31
|
-
this.frameNaturalHeight = 0;
|
|
32
|
-
this.displayedImageRect = null;
|
|
33
|
-
this.distance = null;
|
|
34
|
-
this.unit = null;
|
|
35
|
-
this._onImageLoad = () => {
|
|
36
|
-
if (!this.frameImageEl || !this.imageWrapperEl)
|
|
37
|
-
return;
|
|
38
|
-
const img = this.frameImageEl;
|
|
39
|
-
const wrapperRect = this.imageWrapperEl.getBoundingClientRect();
|
|
40
|
-
const imgRect = img.getBoundingClientRect();
|
|
41
|
-
this.frameNaturalWidth = img.naturalWidth;
|
|
42
|
-
this.frameNaturalHeight = img.naturalHeight;
|
|
43
|
-
this.displayedImageRect = {
|
|
44
|
-
width: imgRect.width,
|
|
45
|
-
height: imgRect.height,
|
|
46
|
-
left: imgRect.left - wrapperRect.left,
|
|
47
|
-
top: imgRect.top - wrapperRect.top
|
|
48
|
-
};
|
|
49
|
-
};
|
|
50
|
-
this._onImageClick = (event) => {
|
|
51
|
-
if (!this.frameImageEl || !this.imageWrapperEl)
|
|
52
|
-
return;
|
|
53
|
-
const imgRect = this.frameImageEl.getBoundingClientRect();
|
|
54
|
-
const wrapperRect = this.imageWrapperEl.getBoundingClientRect();
|
|
55
|
-
const clientX = event.clientX;
|
|
56
|
-
const clientY = event.clientY;
|
|
57
|
-
// Ignore clicks outside the displayed image area
|
|
58
|
-
if (clientX < imgRect.left || clientX > imgRect.right || clientY < imgRect.top || clientY > imgRect.bottom) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
const relativeX = clientX - imgRect.left;
|
|
62
|
-
const relativeY = clientY - imgRect.top;
|
|
63
|
-
const xOnNatural = Math.round((relativeX * this.frameNaturalWidth) / imgRect.width);
|
|
64
|
-
const yOnNatural = Math.round((relativeY * this.frameNaturalHeight) / imgRect.height);
|
|
65
|
-
if (this.selectedPoints.x1 === null || this.selectedPoints.y1 === null) {
|
|
66
|
-
this.selectedPoints = Object.assign(Object.assign({}, this.selectedPoints), { x1: xOnNatural, y1: yOnNatural });
|
|
67
|
-
}
|
|
68
|
-
else if (this.selectedPoints.x2 === null || this.selectedPoints.y2 === null) {
|
|
69
|
-
this.selectedPoints = Object.assign(Object.assign({}, this.selectedPoints), { x2: xOnNatural, y2: yOnNatural });
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
// 세 번째 클릭부터는 초기화 후 첫 점으로 설정
|
|
73
|
-
this.selectedPoints = { x1: xOnNatural, y1: yOnNatural, x2: null, y2: null };
|
|
74
|
-
}
|
|
75
|
-
// Update displayed rect cache (in case layout changed)
|
|
76
|
-
this.displayedImageRect = {
|
|
77
|
-
width: imgRect.width,
|
|
78
|
-
height: imgRect.height,
|
|
79
|
-
left: imgRect.left - wrapperRect.left,
|
|
80
|
-
top: imgRect.top - wrapperRect.top
|
|
81
|
-
};
|
|
82
|
-
};
|
|
18
|
+
this.capturedImageUrl = null;
|
|
19
|
+
this.imageFile = null;
|
|
20
|
+
this.isSaved = false;
|
|
83
21
|
}
|
|
84
22
|
get context() {
|
|
85
23
|
return {
|
|
@@ -87,7 +25,7 @@ let BuildingInspectionCamera = class BuildingInspectionCamera extends PageView {
|
|
|
87
25
|
};
|
|
88
26
|
}
|
|
89
27
|
render() {
|
|
90
|
-
var _a, _b, _c, _d, _e, _f, _g, _h
|
|
28
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
91
29
|
return html `
|
|
92
30
|
<building-inspection-detail-header
|
|
93
31
|
.buildingInspectionId=${(_a = this.buildingInspection) === null || _a === void 0 ? void 0 : _a.id}
|
|
@@ -98,57 +36,25 @@ let BuildingInspectionCamera = class BuildingInspectionCamera extends PageView {
|
|
|
98
36
|
></building-inspection-detail-header>
|
|
99
37
|
|
|
100
38
|
<div body>
|
|
101
|
-
<!-- Preview selected or recorded video -->
|
|
102
39
|
<div preview>
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
? html `<
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
</div>`
|
|
109
|
-
: // 동영상 분석 완료 단일 프레임 표시
|
|
110
|
-
this.frame
|
|
111
|
-
? html `
|
|
112
|
-
<div class="image-wrapper" @click=${this._onImageClick}>
|
|
113
|
-
<img
|
|
114
|
-
id="frameImage"
|
|
115
|
-
src="${this.KEYPOINT_RULER_API_BASE_URL + ((_j = this.frame) === null || _j === void 0 ? void 0 : _j.download_url)}"
|
|
116
|
-
alt="frame"
|
|
117
|
-
loading="eager"
|
|
118
|
-
@load=${this._onImageLoad}
|
|
119
|
-
/>
|
|
120
|
-
${this._renderMarkers()}
|
|
121
|
-
</div>
|
|
122
|
-
`
|
|
123
|
-
: // 동영상 선택 후 동영상 프리뷰
|
|
124
|
-
this.capturedVideoUrl
|
|
125
|
-
? html `<video src=${this.capturedVideoUrl} controls playsinline></video>`
|
|
126
|
-
: // 초기 상태, 동영상 선택 전
|
|
127
|
-
html `<md-icon>videocam</md-icon>`}
|
|
40
|
+
<div class="image-wrapper">
|
|
41
|
+
${this.capturedImageUrl
|
|
42
|
+
? html `<img id="imageImage" src="${this.capturedImageUrl}" alt="image" />`
|
|
43
|
+
: html `<md-icon>add_a_photo</md-icon>`}
|
|
44
|
+
</div>
|
|
128
45
|
</div>
|
|
129
46
|
|
|
130
47
|
<div controls>
|
|
131
|
-
<span class="controls-title"
|
|
48
|
+
<span class="controls-title">사진 촬영</span>
|
|
132
49
|
|
|
133
|
-
<!-- Camera shutter button (record video) -->
|
|
134
50
|
<div class="camera-shutter">
|
|
135
51
|
<md-icon>camera</md-icon>
|
|
136
|
-
<input id="
|
|
52
|
+
<input id="imageInput" type="file" accept="image/*" @change="${this._onImageSelected}" />
|
|
137
53
|
</div>
|
|
138
54
|
|
|
139
55
|
<!-- Action buttons -->
|
|
140
56
|
<div action-buttons>
|
|
141
|
-
|
|
142
|
-
? html `
|
|
143
|
-
<button class="photo" ?disabled=${this.analyzing || !this._hasTwoPoints()} @click=${this._onAnalyzePhoto}>
|
|
144
|
-
사진 분석
|
|
145
|
-
</button>
|
|
146
|
-
`
|
|
147
|
-
: html `
|
|
148
|
-
<button class="save" ?disabled=${this.analyzing || !this.capturedVideoUrl} @click=${this._onAnalyzeVideo}>
|
|
149
|
-
동영상 분석
|
|
150
|
-
</button>
|
|
151
|
-
`}
|
|
57
|
+
<button class="save" ?disabled=${!this.imageFile || this.isSaved} @click=${this._savePhoto}>사진 저장</button>
|
|
152
58
|
<button class="retry" @click=${this._onRetry}>초기화</button>
|
|
153
59
|
</div>
|
|
154
60
|
</div>
|
|
@@ -171,20 +77,12 @@ let BuildingInspectionCamera = class BuildingInspectionCamera extends PageView {
|
|
|
171
77
|
id
|
|
172
78
|
status
|
|
173
79
|
requestDate
|
|
174
|
-
drawingMarker
|
|
175
80
|
checklist {
|
|
176
|
-
|
|
177
|
-
inspectionDrawingType
|
|
81
|
+
id
|
|
178
82
|
}
|
|
179
83
|
buildingLevel {
|
|
180
84
|
id
|
|
181
85
|
floor
|
|
182
|
-
mainDrawing {
|
|
183
|
-
id
|
|
184
|
-
name
|
|
185
|
-
fullpath
|
|
186
|
-
}
|
|
187
|
-
mainDrawingImage
|
|
188
86
|
building {
|
|
189
87
|
id
|
|
190
88
|
name
|
|
@@ -223,163 +121,62 @@ let BuildingInspectionCamera = class BuildingInspectionCamera extends PageView {
|
|
|
223
121
|
return;
|
|
224
122
|
this.project = response.data.project;
|
|
225
123
|
}
|
|
226
|
-
|
|
124
|
+
_onImageSelected(event) {
|
|
227
125
|
var _a;
|
|
228
126
|
const input = event.target;
|
|
229
127
|
const file = (_a = input === null || input === void 0 ? void 0 : input.files) === null || _a === void 0 ? void 0 : _a[0];
|
|
230
128
|
if (!file)
|
|
231
129
|
return;
|
|
232
130
|
// Only allow video files
|
|
233
|
-
if (!file.type.startsWith('
|
|
234
|
-
console.warn('선택된 파일이
|
|
131
|
+
if (!file.type.startsWith('image/')) {
|
|
132
|
+
console.warn('선택된 파일이 이미지가 아닙니다.');
|
|
235
133
|
return;
|
|
236
134
|
}
|
|
237
135
|
// Revoke old object URL if exists
|
|
238
|
-
if (this.
|
|
239
|
-
URL.revokeObjectURL(this.
|
|
240
|
-
}
|
|
241
|
-
this.videoFile = file;
|
|
242
|
-
this.capturedVideoUrl = URL.createObjectURL(file);
|
|
243
|
-
}
|
|
244
|
-
async _onAnalyzeVideo() {
|
|
245
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
246
|
-
if (!this.videoFile) {
|
|
247
|
-
console.warn('선택된 동영상이 없습니다.');
|
|
248
|
-
return;
|
|
249
|
-
}
|
|
250
|
-
try {
|
|
251
|
-
this.analyzing = true;
|
|
252
|
-
const form = new FormData();
|
|
253
|
-
form.append('files', this.videoFile, this.videoFile.name);
|
|
254
|
-
const response = await fetch(`${this.KEYPOINT_RULER_API_BASE_URL}/api/run/keypoint-ruler`, {
|
|
255
|
-
method: 'POST',
|
|
256
|
-
headers: { Authorization: `Basic ${btoa('admin:admin1234')}` },
|
|
257
|
-
body: form
|
|
258
|
-
});
|
|
259
|
-
const data = await response.json();
|
|
260
|
-
this.frame = {
|
|
261
|
-
file_id: (_b = (_a = data === null || data === void 0 ? void 0 : data.result) === null || _a === void 0 ? void 0 : _a.output_files[0]) === null || _b === void 0 ? void 0 : _b.file_id,
|
|
262
|
-
download_url: (_d = (_c = data === null || data === void 0 ? void 0 : data.result) === null || _c === void 0 ? void 0 : _c.output_files[0]) === null || _d === void 0 ? void 0 : _d.download_url,
|
|
263
|
-
file_path: (_f = (_e = data === null || data === void 0 ? void 0 : data.result) === null || _e === void 0 ? void 0 : _e.frames[0]) === null || _f === void 0 ? void 0 : _f.file_path,
|
|
264
|
-
calibration: (_g = data === null || data === void 0 ? void 0 : data.result) === null || _g === void 0 ? void 0 : _g.calibration
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
catch (error) {
|
|
268
|
-
console.error('동영상 업로드 실패:', error);
|
|
269
|
-
}
|
|
270
|
-
finally {
|
|
271
|
-
this.analyzing = false;
|
|
136
|
+
if (this.capturedImageUrl) {
|
|
137
|
+
URL.revokeObjectURL(this.capturedImageUrl);
|
|
272
138
|
}
|
|
139
|
+
this.imageFile = file;
|
|
140
|
+
this.capturedImageUrl = URL.createObjectURL(file);
|
|
141
|
+
this.isSaved = false; // 새 이미지 선택 시 저장 상태 초기화
|
|
273
142
|
}
|
|
274
143
|
_onRetry() {
|
|
275
144
|
// Clear current selection and reopen camera
|
|
276
|
-
if (this.
|
|
277
|
-
URL.revokeObjectURL(this.
|
|
145
|
+
if (this.capturedImageUrl) {
|
|
146
|
+
URL.revokeObjectURL(this.capturedImageUrl);
|
|
278
147
|
}
|
|
279
|
-
this.
|
|
280
|
-
this.
|
|
281
|
-
this.
|
|
282
|
-
this.
|
|
283
|
-
this.displayedImageRect = null;
|
|
284
|
-
this.frameNaturalWidth = 0;
|
|
285
|
-
this.frameNaturalHeight = 0;
|
|
286
|
-
this.cameraInputEl.value = '';
|
|
287
|
-
this.distance = null;
|
|
288
|
-
this.unit = null;
|
|
289
|
-
}
|
|
290
|
-
_hasTwoPoints() {
|
|
291
|
-
const { x1, y1, x2, y2 } = this.selectedPoints;
|
|
292
|
-
return x1 !== null && y1 !== null && x2 !== null && y2 !== null;
|
|
293
|
-
}
|
|
294
|
-
_renderMarkers() {
|
|
295
|
-
if (!this.displayedImageRect)
|
|
296
|
-
return html ``;
|
|
297
|
-
const { left, top, width, height } = this.displayedImageRect;
|
|
298
|
-
const { x1, y1, x2, y2 } = this.selectedPoints;
|
|
299
|
-
const toDisplay = (x, y) => {
|
|
300
|
-
const dx = left + (x * width) / (this.frameNaturalWidth || 1);
|
|
301
|
-
const dy = top + (y * height) / (this.frameNaturalHeight || 1);
|
|
302
|
-
return { dx, dy };
|
|
303
|
-
};
|
|
304
|
-
return html `
|
|
305
|
-
${x1 !== null && y1 !== null
|
|
306
|
-
? (() => {
|
|
307
|
-
const p = toDisplay(x1, y1);
|
|
308
|
-
return html `<div class="point-marker point-1" style="left:${p.dx}px; top:${p.dy}px;"></div>`;
|
|
309
|
-
})()
|
|
310
|
-
: ''}
|
|
311
|
-
${x2 !== null && y2 !== null
|
|
312
|
-
? (() => {
|
|
313
|
-
const p = toDisplay(x2, y2);
|
|
314
|
-
return html `<div class="point-marker point-2" style="left:${p.dx}px; top:${p.dy}px;"></div>`;
|
|
315
|
-
})()
|
|
316
|
-
: ''}
|
|
317
|
-
${this._hasTwoPoints()
|
|
318
|
-
? (() => {
|
|
319
|
-
const p1 = toDisplay(x1, y1);
|
|
320
|
-
const p2 = toDisplay(x2, y2);
|
|
321
|
-
const x = Math.min(p1.dx, p2.dx);
|
|
322
|
-
const y = Math.min(p1.dy, p2.dy);
|
|
323
|
-
const w = Math.abs(p1.dx - p2.dx);
|
|
324
|
-
const h = Math.abs(p1.dy - p2.dy);
|
|
325
|
-
const cx = (p1.dx + p2.dx) / 2;
|
|
326
|
-
const cy = (p1.dy + p2.dy) / 2;
|
|
327
|
-
return html `
|
|
328
|
-
<svg class="line-overlay" style="left:${x}px; top:${y}px; width:${w}px; height:${h}px;">
|
|
329
|
-
<line
|
|
330
|
-
x1=${p1.dx < p2.dx ? 0 : w}
|
|
331
|
-
y1=${p1.dy < p2.dy ? 0 : h}
|
|
332
|
-
x2=${p1.dx < p2.dx ? w : 0}
|
|
333
|
-
y2=${p1.dy < p2.dy ? h : 0}
|
|
334
|
-
stroke="#ff9800"
|
|
335
|
-
stroke-width="3"
|
|
336
|
-
/>
|
|
337
|
-
</svg>
|
|
338
|
-
${this.distance !== null && this.unit
|
|
339
|
-
? html `<div class="distance-label" style="left:${cx}px; top:${cy}px;">${this.distance} ${this.unit}</div>`
|
|
340
|
-
: ''}
|
|
341
|
-
`;
|
|
342
|
-
})()
|
|
343
|
-
: ''}
|
|
344
|
-
`;
|
|
148
|
+
this.capturedImageUrl = null;
|
|
149
|
+
this.imageFile = null;
|
|
150
|
+
this.isSaved = false; // 초기화 시 저장 상태도 리셋
|
|
151
|
+
this.imageInputEl.value = '';
|
|
345
152
|
}
|
|
346
|
-
async
|
|
347
|
-
|
|
348
|
-
|
|
153
|
+
async _savePhoto() {
|
|
154
|
+
var _a, _b, _c;
|
|
155
|
+
if (!this.imageFile) {
|
|
156
|
+
notify({ message: '사진을 선택한 후 저장할 수 있습니다.', level: 'warn' });
|
|
349
157
|
return;
|
|
350
158
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
y1: this.selectedPoints.y1,
|
|
360
|
-
x2: this.selectedPoints.x2,
|
|
361
|
-
y2: this.selectedPoints.y2,
|
|
362
|
-
file_path: this.frame.file_path,
|
|
363
|
-
calibration: this.frame.calibration
|
|
364
|
-
};
|
|
365
|
-
const form = new FormData();
|
|
366
|
-
form.append('input', JSON.stringify(payload));
|
|
367
|
-
const response = await fetch(`${this.KEYPOINT_RULER_API_BASE_URL}/api/run/keypoint-ruler`, {
|
|
368
|
-
method: 'POST',
|
|
369
|
-
headers: { Authorization: `Basic ${btoa('admin:admin1234')}` },
|
|
370
|
-
body: form
|
|
371
|
-
});
|
|
372
|
-
const result = await response.json();
|
|
373
|
-
const { distance, unit } = result.result || {};
|
|
374
|
-
this.distance = distance;
|
|
375
|
-
this.unit = unit;
|
|
376
|
-
}
|
|
377
|
-
catch (error) {
|
|
378
|
-
console.error('사진 분석 실패:', error);
|
|
159
|
+
const checklistId = (_b = (_a = this.buildingInspection) === null || _a === void 0 ? void 0 : _a.checklist) === null || _b === void 0 ? void 0 : _b.id;
|
|
160
|
+
const file = this.imageFile;
|
|
161
|
+
const response = await client.mutate({
|
|
162
|
+
mutation: gql `
|
|
163
|
+
mutation ($attachments: [NewAttachment!]!) {
|
|
164
|
+
createAttachments(attachments: $attachments) {
|
|
165
|
+
id
|
|
166
|
+
}
|
|
379
167
|
}
|
|
380
|
-
|
|
381
|
-
|
|
168
|
+
`,
|
|
169
|
+
variables: {
|
|
170
|
+
attachments: [{ file, refBy: checklistId, refType: 'Checklist', description: (_c = this.buildingInspection) === null || _c === void 0 ? void 0 : _c.status }]
|
|
171
|
+
},
|
|
172
|
+
context: { hasUpload: true }
|
|
173
|
+
});
|
|
174
|
+
if (!response.errors) {
|
|
175
|
+
notify({ message: '사진 대지를 저장하였습니다.', level: 'info' });
|
|
176
|
+
this.isSaved = true; // 저장 성공 시 상태 업데이트
|
|
177
|
+
return;
|
|
382
178
|
}
|
|
179
|
+
return response.data.createAttachments;
|
|
383
180
|
}
|
|
384
181
|
};
|
|
385
182
|
BuildingInspectionCamera.styles = [
|
|
@@ -431,119 +228,12 @@ BuildingInspectionCamera.styles = [
|
|
|
431
228
|
--md-icon-size: 160px;
|
|
432
229
|
}
|
|
433
230
|
|
|
434
|
-
.loading-container {
|
|
435
|
-
display: flex;
|
|
436
|
-
flex-direction: column;
|
|
437
|
-
align-items: center;
|
|
438
|
-
justify-content: center;
|
|
439
|
-
gap: 12px;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
.loading-text {
|
|
443
|
-
font-size: 14px;
|
|
444
|
-
color: #666;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
.frame-container {
|
|
448
|
-
width: 100%;
|
|
449
|
-
height: 100%;
|
|
450
|
-
max-height: 100%;
|
|
451
|
-
min-height: 0;
|
|
452
|
-
overflow-y: auto;
|
|
453
|
-
display: flex;
|
|
454
|
-
flex-direction: column;
|
|
455
|
-
gap: 12px;
|
|
456
|
-
padding: 12px;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
.frames-header {
|
|
460
|
-
display: flex;
|
|
461
|
-
align-items: center;
|
|
462
|
-
justify-content: center;
|
|
463
|
-
gap: 12px;
|
|
464
|
-
font-size: 20px;
|
|
465
|
-
font-weight: 700;
|
|
466
|
-
color: #333;
|
|
467
|
-
text-align: center;
|
|
468
|
-
padding-block: 8px;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
.frames-count {
|
|
472
|
-
font-size: 16px;
|
|
473
|
-
color: #777;
|
|
474
|
-
font-weight: 600;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
.frames-grid {
|
|
478
|
-
display: grid;
|
|
479
|
-
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
|
|
480
|
-
gap: 12px;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
.frame-item {
|
|
484
|
-
border: 1px solid #ddd;
|
|
485
|
-
border-radius: 8px;
|
|
486
|
-
overflow: hidden;
|
|
487
|
-
background: #fff;
|
|
488
|
-
cursor: pointer;
|
|
489
|
-
transition:
|
|
490
|
-
box-shadow 0.2s,
|
|
491
|
-
transform 0.1s;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
.frame-item:hover {
|
|
495
|
-
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
496
|
-
transform: translateY(-1px);
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
.frame-item img {
|
|
500
|
-
display: block;
|
|
501
|
-
width: 100%;
|
|
502
|
-
height: 120px;
|
|
503
|
-
object-fit: cover;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
231
|
.image-wrapper {
|
|
507
232
|
position: relative;
|
|
508
233
|
width: 100%;
|
|
509
234
|
height: 100%;
|
|
510
235
|
align-content: center;
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
.point-marker {
|
|
514
|
-
position: absolute;
|
|
515
|
-
width: 14px;
|
|
516
|
-
height: 14px;
|
|
517
|
-
border-radius: 50%;
|
|
518
|
-
border: 2px solid #fff;
|
|
519
|
-
transform: translate(-50%, -50%);
|
|
520
|
-
pointer-events: none;
|
|
521
|
-
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.25);
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
.point-1 {
|
|
525
|
-
background-color: #e53935;
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
.point-2 {
|
|
529
|
-
background-color: #1e88e5;
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
.line-overlay {
|
|
533
|
-
position: absolute;
|
|
534
|
-
pointer-events: none;
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
.distance-label {
|
|
538
|
-
position: absolute;
|
|
539
|
-
background: rgba(0, 0, 0, 0.7);
|
|
540
|
-
color: #fff;
|
|
541
|
-
font-size: 14px;
|
|
542
|
-
padding: 2px 6px;
|
|
543
|
-
border-radius: 4px;
|
|
544
|
-
transform: translate(-50%, -120%);
|
|
545
|
-
pointer-events: none;
|
|
546
|
-
white-space: nowrap;
|
|
236
|
+
text-align: center;
|
|
547
237
|
}
|
|
548
238
|
|
|
549
239
|
div[controls] {
|
|
@@ -561,20 +251,6 @@ BuildingInspectionCamera.styles = [
|
|
|
561
251
|
gap: 15px;
|
|
562
252
|
}
|
|
563
253
|
|
|
564
|
-
.switch-container {
|
|
565
|
-
display: flex;
|
|
566
|
-
align-items: center;
|
|
567
|
-
gap: 10px;
|
|
568
|
-
font-size: 24px;
|
|
569
|
-
font-weight: bold;
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
ox-input-switch {
|
|
573
|
-
--ox-simple-switch-fullwidth: 68px;
|
|
574
|
-
--ox-simple-switch-fullheight: 34px;
|
|
575
|
-
--ox-simple-switch-thumbnail-size: 34px;
|
|
576
|
-
}
|
|
577
|
-
|
|
578
254
|
.camera-shutter {
|
|
579
255
|
display: flex;
|
|
580
256
|
justify-content: center;
|
|
@@ -627,16 +303,6 @@ BuildingInspectionCamera.styles = [
|
|
|
627
303
|
background-color: #f0ad4e;
|
|
628
304
|
color: white;
|
|
629
305
|
}
|
|
630
|
-
|
|
631
|
-
button.photo {
|
|
632
|
-
background-color: #1e88e5;
|
|
633
|
-
color: white;
|
|
634
|
-
|
|
635
|
-
&:disabled {
|
|
636
|
-
background-color: #ccc;
|
|
637
|
-
cursor: default;
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
306
|
`
|
|
641
307
|
];
|
|
642
308
|
__decorate([
|
|
@@ -654,55 +320,19 @@ __decorate([
|
|
|
654
320
|
__decorate([
|
|
655
321
|
state(),
|
|
656
322
|
__metadata("design:type", Object)
|
|
657
|
-
], BuildingInspectionCamera.prototype, "
|
|
658
|
-
__decorate([
|
|
659
|
-
state(),
|
|
660
|
-
__metadata("design:type", Object)
|
|
661
|
-
], BuildingInspectionCamera.prototype, "videoFile", void 0);
|
|
323
|
+
], BuildingInspectionCamera.prototype, "capturedImageUrl", void 0);
|
|
662
324
|
__decorate([
|
|
663
325
|
state(),
|
|
664
326
|
__metadata("design:type", Object)
|
|
665
|
-
], BuildingInspectionCamera.prototype, "
|
|
327
|
+
], BuildingInspectionCamera.prototype, "imageFile", void 0);
|
|
666
328
|
__decorate([
|
|
667
329
|
state(),
|
|
668
330
|
__metadata("design:type", Boolean)
|
|
669
|
-
], BuildingInspectionCamera.prototype, "
|
|
670
|
-
__decorate([
|
|
671
|
-
state(),
|
|
672
|
-
__metadata("design:type", Object)
|
|
673
|
-
], BuildingInspectionCamera.prototype, "selectedPoints", void 0);
|
|
674
|
-
__decorate([
|
|
675
|
-
state(),
|
|
676
|
-
__metadata("design:type", Number)
|
|
677
|
-
], BuildingInspectionCamera.prototype, "frameNaturalWidth", void 0);
|
|
678
|
-
__decorate([
|
|
679
|
-
state(),
|
|
680
|
-
__metadata("design:type", Number)
|
|
681
|
-
], BuildingInspectionCamera.prototype, "frameNaturalHeight", void 0);
|
|
682
|
-
__decorate([
|
|
683
|
-
state(),
|
|
684
|
-
__metadata("design:type", Object)
|
|
685
|
-
], BuildingInspectionCamera.prototype, "displayedImageRect", void 0);
|
|
686
|
-
__decorate([
|
|
687
|
-
state(),
|
|
688
|
-
__metadata("design:type", Object)
|
|
689
|
-
], BuildingInspectionCamera.prototype, "distance", void 0);
|
|
690
|
-
__decorate([
|
|
691
|
-
state(),
|
|
692
|
-
__metadata("design:type", Object)
|
|
693
|
-
], BuildingInspectionCamera.prototype, "unit", void 0);
|
|
694
|
-
__decorate([
|
|
695
|
-
query('img#frameImage'),
|
|
696
|
-
__metadata("design:type", HTMLImageElement)
|
|
697
|
-
], BuildingInspectionCamera.prototype, "frameImageEl", void 0);
|
|
698
|
-
__decorate([
|
|
699
|
-
query('div.image-wrapper'),
|
|
700
|
-
__metadata("design:type", HTMLDivElement)
|
|
701
|
-
], BuildingInspectionCamera.prototype, "imageWrapperEl", void 0);
|
|
331
|
+
], BuildingInspectionCamera.prototype, "isSaved", void 0);
|
|
702
332
|
__decorate([
|
|
703
|
-
query('#
|
|
333
|
+
query('#imageInput'),
|
|
704
334
|
__metadata("design:type", HTMLInputElement)
|
|
705
|
-
], BuildingInspectionCamera.prototype, "
|
|
335
|
+
], BuildingInspectionCamera.prototype, "imageInputEl", void 0);
|
|
706
336
|
BuildingInspectionCamera = __decorate([
|
|
707
337
|
customElement('building-inspection-detail-camera')
|
|
708
338
|
], BuildingInspectionCamera);
|