@dssp/supervision 1.0.18 → 1.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/dist-client/pages/building-inspection/building-inspection-detail-ai-defect.js +7 -0
- package/dist-client/pages/building-inspection/building-inspection-detail-ai-defect.js.map +1 -1
- package/dist-client/pages/building-inspection/building-inspection-detail-ai-measurement.d.ts +1 -0
- package/dist-client/pages/building-inspection/building-inspection-detail-ai-measurement.js +20 -13
- package/dist-client/pages/building-inspection/building-inspection-detail-ai-measurement.js.map +1 -1
- package/dist-client/pages/building-inspection/building-inspection-detail-camera.js +6 -0
- package/dist-client/pages/building-inspection/building-inspection-detail-camera.js.map +1 -1
- package/dist-client/pages/building-inspection/building-inspection-detail-checklist.js +6 -0
- package/dist-client/pages/building-inspection/building-inspection-detail-checklist.js.map +1 -1
- package/dist-client/pages/building-inspection/building-inspection-detail-drawing.js +6 -0
- package/dist-client/pages/building-inspection/building-inspection-detail-drawing.js.map +1 -1
- package/dist-client/pages/building-inspection/component/building-inspection-detail-header.js +6 -6
- package/dist-client/pages/building-inspection/component/building-inspection-detail-header.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -9,6 +9,7 @@ import { customElement, state } from 'lit/decorators.js';
|
|
|
9
9
|
import { PageView } from '@operato/shell';
|
|
10
10
|
import { CommonGristStyles, ScrollbarStyles } from '@operato/styles';
|
|
11
11
|
import { client } from '@operato/graphql';
|
|
12
|
+
import { notify } from '@operato/layout';
|
|
12
13
|
import './component/building-inspection-detail-header';
|
|
13
14
|
let BuildingInspectionAiDefect = class BuildingInspectionAiDefect extends PageView {
|
|
14
15
|
constructor() {
|
|
@@ -90,6 +91,12 @@ let BuildingInspectionAiDefect = class BuildingInspectionAiDefect extends PageVi
|
|
|
90
91
|
if (response.errors)
|
|
91
92
|
return;
|
|
92
93
|
this.buildingInspection = response.data.buildingInspection;
|
|
94
|
+
// 삭제(soft delete)됐거나 다른 projectType의 검측이면 서버가 null을 준다.
|
|
95
|
+
// 그대로 진행하면 뒤 쿼리에 undefined가 실려 GraphQL 에러가 난다.
|
|
96
|
+
if (!this.buildingInspection) {
|
|
97
|
+
notify({ message: '삭제되었거나 접근할 수 없는 검측입니다.', level: 'warn' });
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
93
100
|
await this._getProjectByBuildingComplexId((_d = (_c = (_b = (_a = this.buildingInspection) === null || _a === void 0 ? void 0 : _a.buildingLevel) === null || _b === void 0 ? void 0 : _b.building) === null || _c === void 0 ? void 0 : _c.buildingComplex) === null || _d === void 0 ? void 0 : _d.id);
|
|
94
101
|
}
|
|
95
102
|
async _getProjectByBuildingComplexId(buildingComplexId) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"building-inspection-detail-ai-defect.js","sourceRoot":"","sources":["../../../client/pages/building-inspection/building-inspection-detail-ai-defect.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AACnC,OAAO,mCAAmC,CAAA;AAC1C,OAAO,wCAAwC,CAAA;AAC/C,OAAO,6CAA6C,CAAA;AAEpD,OAAO,GAAG,MAAM,aAAa,CAAA;AAC7B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAkB,MAAM,KAAK,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,KAAK,EAAS,MAAM,mBAAmB,CAAA;AAE/D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEpE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"building-inspection-detail-ai-defect.js","sourceRoot":"","sources":["../../../client/pages/building-inspection/building-inspection-detail-ai-defect.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@operato/input/ox-input-switch.js'\nimport '@operato/mini-map/ox-zoomable-image.js'\nimport '@material/web/progress/circular-progress.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, PropertyValues } from 'lit'\nimport { customElement, state, query } from 'lit/decorators.js'\n\nimport { PageView } from '@operato/shell'\nimport { CommonGristStyles, ScrollbarStyles } from '@operato/styles'\nimport { PageLifecycle } from '@operato/shell/dist/src/app/pages/page-view'\nimport { client } from '@operato/graphql'\nimport { notify } from '@operato/layout'\n\nimport './component/building-inspection-detail-header'\n\n@customElement('building-inspection-detail-ai-defect')\nexport class BuildingInspectionAiDefect extends PageView {\n static styles = [\n ScrollbarStyles,\n CommonGristStyles,\n css`\n :host {\n display: grid;\n grid-template-rows: 75px 1fr;\n color: #4e5055;\n width: 100%;\n height: 100%;\n background-color: #f7f7f7;\n }\n\n div[body] {\n display: flex;\n justify-items: center;\n gap: var(--spacing-medium);\n margin: var(--spacing-medium);\n min-height: 0;\n }\n\n div[preview] {\n flex: 1;\n border: 2px solid #ddd;\n border-radius: 10px;\n\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 0;\n overflow: hidden;\n }\n\n div[preview] video {\n flex: 1;\n max-width: 100%;\n max-height: 100%;\n object-fit: contain;\n }\n `\n ]\n\n @state() project: any = {}\n @state() buildingInspection: any = {}\n @state() buildingInspectionId: string = ''\n\n get context() {\n return {\n title: '검측 관리 상세 - AI 하자 분석'\n }\n }\n\n render() {\n return html`\n <building-inspection-detail-header\n .buildingInspectionId=${this.buildingInspection?.id}\n .buildingLevelId=${this.buildingInspection?.buildingLevel?.id}\n .projectName=${this.project.name}\n .buildingName=${this.buildingInspection?.buildingLevel?.building?.name}\n .buildingLevelFloor=${this.buildingInspection?.buildingLevel?.floor}\n .projectId=${this.project.id}\n ></building-inspection-detail-header>\n\n <div body>\n <div preview>\n <video src=\"/attachment/21e53688-5262-4fae-961a-591db7114b75.mp4\" controls playsinline></video>\n </div>\n </div>\n `\n }\n\n protected async updated(changes: PropertyValues): Promise<void> {}\n\n async pageUpdated(changes: any, lifecycle: PageLifecycle) {\n if (this.active) {\n this.buildingInspectionId = lifecycle.resourceId || ''\n await this.initBuildingInspection(this.buildingInspectionId)\n }\n }\n\n async initBuildingInspection(buildingInspectionId: string = '') {\n const response = await client.query({\n query: gql`\n query BuildingInspection($buildingInspectionId: String!) {\n buildingInspection(id: $buildingInspectionId) {\n id\n status\n requestDate\n drawingMarker\n checklist {\n id\n location\n inspectionDrawingType\n }\n buildingLevel {\n id\n floor\n mainDrawing {\n id\n name\n fullpath\n }\n mainDrawingImage\n building {\n id\n name\n buildingComplex {\n id\n }\n }\n }\n }\n }\n `,\n variables: {\n buildingInspectionId\n }\n })\n\n if (response.errors) return\n\n this.buildingInspection = response.data.buildingInspection\n\n // 삭제(soft delete)됐거나 다른 projectType의 검측이면 서버가 null을 준다.\n // 그대로 진행하면 뒤 쿼리에 undefined가 실려 GraphQL 에러가 난다.\n if (!this.buildingInspection) {\n notify({ message: '삭제되었거나 접근할 수 없는 검측입니다.', level: 'warn' })\n return\n }\n\n await this._getProjectByBuildingComplexId(this.buildingInspection?.buildingLevel?.building?.buildingComplex?.id)\n }\n\n private async _getProjectByBuildingComplexId(buildingComplexId) {\n const response = await client.query({\n query: gql`\n query ProjectByBuildingComplexId($buildingComplexId: String!) {\n project: projectByBuildingComplexId(buildingComplexId: $buildingComplexId) {\n id\n name\n }\n }\n `,\n variables: {\n buildingComplexId\n }\n })\n\n if (response.errors) return\n\n this.project = response.data.project\n }\n}\n"]}
|
package/dist-client/pages/building-inspection/building-inspection-detail-ai-measurement.d.ts
CHANGED
|
@@ -41,6 +41,7 @@ export declare class BuildingInspectionAiMeasurement extends PageView {
|
|
|
41
41
|
setPickerFor: number | null;
|
|
42
42
|
recentSets: any[];
|
|
43
43
|
recentLoading: boolean;
|
|
44
|
+
private autoAttachSince;
|
|
44
45
|
expandedReportId: string | null;
|
|
45
46
|
measureSetIndex: number;
|
|
46
47
|
measureInputs: Record<string, string>;
|
|
@@ -82,6 +82,7 @@ let BuildingInspectionAiMeasurement = class BuildingInspectionAiMeasurement exte
|
|
|
82
82
|
this.setPickerFor = null; // 세트 고르는 중인 촬영 번호 (-1 = 재촬영)
|
|
83
83
|
this.recentSets = []; // 측정 서버에 올라온 최근 세트 (앱이 촬영 직후 자동 전송)
|
|
84
84
|
this.recentLoading = false;
|
|
85
|
+
this.autoAttachSince = 0; // 이 시각(초) 이후 업로드된 세트만 자동 등록
|
|
85
86
|
this.expandedReportId = null; // 종합 리포트에서 펼친 항목(아코디언)
|
|
86
87
|
/* 측정 패널 상태 */
|
|
87
88
|
this.measureSetIndex = 0;
|
|
@@ -184,14 +185,10 @@ let BuildingInspectionAiMeasurement = class BuildingInspectionAiMeasurement exte
|
|
|
184
185
|
${this.result ? this._renderResult() : this._renderGuide()}
|
|
185
186
|
</div>
|
|
186
187
|
|
|
187
|
-
<!-- 세트 파일 선택: video.mov/poses.jsonl/meta.json 3개 멀티선택 또는 zip 1
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
accept=".mov,.jsonl,.json,.zip,video/quicktime"
|
|
192
|
-
multiple
|
|
193
|
-
@change=${this._onSetFilesSelected}
|
|
194
|
-
/>
|
|
188
|
+
<!-- 세트 파일 선택: video.mov/poses.jsonl/meta.json 3개 멀티선택 또는 zip 1개.
|
|
189
|
+
accept을 두지 않는다 — iOS는 확장자를 UTI로 바꿔 거르는데 .jsonl은 매핑이 없어
|
|
190
|
+
파일 앱에서 poses.jsonl이 비활성으로 보인다. 파일명 검증은 아래 핸들러가 한다. -->
|
|
191
|
+
<input id="setInput" type="file" multiple @change=${this._onSetFilesSelected} />
|
|
195
192
|
|
|
196
193
|
${this.loading
|
|
197
194
|
? html `
|
|
@@ -771,6 +768,12 @@ let BuildingInspectionAiMeasurement = class BuildingInspectionAiMeasurement exte
|
|
|
771
768
|
if (response.errors)
|
|
772
769
|
return;
|
|
773
770
|
this.buildingInspection = response.data.buildingInspection;
|
|
771
|
+
// 삭제(soft delete)됐거나 다른 projectType의 검측이면 서버가 null을 준다.
|
|
772
|
+
// 그대로 진행하면 뒤 쿼리에 undefined가 실려 GraphQL 에러가 난다.
|
|
773
|
+
if (!this.buildingInspection) {
|
|
774
|
+
notify({ message: '삭제되었거나 접근할 수 없는 검측입니다.', level: 'warn' });
|
|
775
|
+
return;
|
|
776
|
+
}
|
|
774
777
|
await this._getProjectByBuildingComplexId((_d = (_c = (_b = (_a = this.buildingInspection) === null || _a === void 0 ? void 0 : _a.buildingLevel) === null || _b === void 0 ? void 0 : _b.building) === null || _c === void 0 ? void 0 : _c.buildingComplex) === null || _d === void 0 ? void 0 : _d.id);
|
|
775
778
|
}
|
|
776
779
|
async _getProjectByBuildingComplexId(buildingComplexId) {
|
|
@@ -841,6 +844,9 @@ let BuildingInspectionAiMeasurement = class BuildingInspectionAiMeasurement exte
|
|
|
841
844
|
this.loadingText = 'AI 촬영 가이드 생성 중...';
|
|
842
845
|
this.guide = await this._callEngine({ action: 'plan-shots', checklist });
|
|
843
846
|
this.sets = new Array((((_a = this.guide) === null || _a === void 0 ? void 0 : _a.shots) || []).length).fill(null);
|
|
847
|
+
// 자동 등록 기준 시각 — 이 시점 이후 올라온 세트만 자동으로 붙인다.
|
|
848
|
+
// (예전 테스트 세트가 태그만 같다고 채워지면 "찍지도 않았는데 완료"로 보인다)
|
|
849
|
+
this.autoAttachSince = Date.now() / 1000;
|
|
844
850
|
}
|
|
845
851
|
catch (error) {
|
|
846
852
|
console.error('촬영 가이드 생성 실패:', error);
|
|
@@ -873,22 +879,23 @@ let BuildingInspectionAiMeasurement = class BuildingInspectionAiMeasurement exte
|
|
|
873
879
|
return;
|
|
874
880
|
await this._loadRecentSets();
|
|
875
881
|
const used = new Set(this.uploadedSets.map(s => s.setId));
|
|
876
|
-
|
|
882
|
+
const attached = [];
|
|
877
883
|
const next = [...this.sets];
|
|
878
884
|
this.guide.shots.forEach((shot, i) => {
|
|
879
885
|
if (next[i])
|
|
880
886
|
return;
|
|
881
887
|
const tag = this._shotTag((shot === null || shot === void 0 ? void 0 : shot.shot_no) || i + 1);
|
|
882
|
-
|
|
888
|
+
// 이 화면을 연 뒤에 올라온 것만 — 예전 세트는 목록에서 직접 고르게 둔다
|
|
889
|
+
const hit = this.recentSets.find(s => s.member_id === tag && !used.has(s.set_id) && (s.uploaded_at || 0) >= this.autoAttachSince);
|
|
883
890
|
if (!hit)
|
|
884
891
|
return;
|
|
885
892
|
used.add(hit.set_id);
|
|
886
893
|
next[i] = { setId: hit.set_id, technique: hit.technique, label: `세트 ${hit.set_id}`, warnings: [] };
|
|
887
|
-
|
|
894
|
+
attached.push((shot === null || shot === void 0 ? void 0 : shot.shot_no) || i + 1);
|
|
888
895
|
});
|
|
889
|
-
if (
|
|
896
|
+
if (attached.length) {
|
|
890
897
|
this.sets = next;
|
|
891
|
-
notify({ message: '
|
|
898
|
+
notify({ message: `촬영 ${attached.join('·')} 세트를 자동으로 등록했습니다.` });
|
|
892
899
|
}
|
|
893
900
|
}
|
|
894
901
|
/* 세트 선택 목록 — 앱이 올린 최근 세트 + 파일 직접 선택 폴백 */
|