@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.
@@ -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":"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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'\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 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"]}
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"]}
@@ -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
- <input
189
- id="setInput"
190
- type="file"
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
- let changed = false;
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
- const hit = this.recentSets.find(s => s.member_id === tag && !used.has(s.set_id));
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
- changed = true;
894
+ attached.push((shot === null || shot === void 0 ? void 0 : shot.shot_no) || i + 1);
888
895
  });
889
- if (changed) {
896
+ if (attached.length) {
890
897
  this.sets = next;
891
- notify({ message: '촬영한 세트를 자동으로 등록했습니다.' });
898
+ notify({ message: `촬영 ${attached.join('·')} 세트를 자동으로 등록했습니다.` });
892
899
  }
893
900
  }
894
901
  /* 세트 선택 목록 — 앱이 올린 최근 세트 + 파일 직접 선택 폴백 */