@dssp/supervision 1.0.12 → 1.0.14

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.
@@ -6,6 +6,8 @@ import { PageView } from '@operato/shell';
6
6
  import { PageLifecycle } from '@operato/shell/dist/src/app/pages/page-view';
7
7
  import { Shape } from '@operato/image-marker';
8
8
  import { DrawingImageProvider } from '@dssp/drawing/dist-client/drawing-management/drawing-image-provider.js';
9
+ import '@dssp/drawing/dist-client/drawing-bundle/drawing-bundle-viewer.js';
10
+ import { DrawingBundleModel } from '@dssp/drawing/dist-client/drawing-bundle/drawing-bundle-model.js';
9
11
  import './component/building-inspection-detail-header';
10
12
  declare const BuildingInspectionDetailDrawing_base: typeof PageView & import("@open-wc/dedupe-mixin").Constructor<import("@open-wc/scoped-elements/types/src/types").ScopedElementsHost>;
11
13
  export declare class BuildingInspectionDetailDrawing extends BuildingInspectionDetailDrawing_base {
@@ -18,6 +20,14 @@ export declare class BuildingInspectionDetailDrawing extends BuildingInspectionD
18
20
  linkUrl?: string;
19
21
  linkShapes: Shape[];
20
22
  drawingImageProvider: DrawingImageProvider;
23
+ /** 도면 번들 (있으면 하이퍼링크 뷰어로, 없으면 기존 외부 도면 방식으로 그린다) */
24
+ bundleModel?: DrawingBundleModel;
25
+ /** 번들 뷰어가 열 첫 도면 — 검측에 할당된 패키지 루트 */
26
+ bundleRootId: string;
27
+ /** 도면별 사용자 그림 — { [도면 id]: Shape[] } */
28
+ bundleMarkers: {
29
+ [drawingId: string]: Shape[];
30
+ };
21
31
  imageMarker: any;
22
32
  linkViewer: any;
23
33
  dialog: HTMLDialogElement;
@@ -26,10 +36,31 @@ export declare class BuildingInspectionDetailDrawing extends BuildingInspectionD
26
36
  };
27
37
  connectedCallback(): void;
28
38
  render(): import("lit-html").TemplateResult<1>;
39
+ /** 번들이 없는 검측(기존 데이터·DSSP 경로)은 예전 방식 그대로 그린다 */
40
+ private renderLegacyDrawing;
29
41
  protected updated(changes: PropertyValues): Promise<void>;
30
42
  pageUpdated(changes: any, lifecycle: PageLifecycle): Promise<void>;
31
43
  initBuildingInspection(buildingInspectionId?: string): Promise<void>;
32
44
  private _getProjectByBuildingComplexId;
45
+ /**
46
+ * 검측에 할당된 도면 패키지를 찾아 번들 뷰어를 준비한다.
47
+ *
48
+ * checklist.inspectionDrawingType 에는 패키지 루트 도면 id 가 들어 있다.
49
+ * 예전 데이터는 검측 도면 '이름' 이 들어 있으므로, 그 경우엔 동·층으로 패키지를 찾아본다.
50
+ * 둘 다 실패하면 false 를 돌려 기존 방식으로 그리게 한다.
51
+ */
52
+ private initBundle;
53
+ /**
54
+ * 저장된 도면 마커를 읽는다.
55
+ * 예전 형식은 Shape 배열 하나였고, 지금은 { root, markers: { 도면 id: Shape[] } } 다.
56
+ * 예전 값은 루트 도면의 그림으로 옮겨 읽는다.
57
+ */
58
+ private parseDrawingMarker;
59
+ /**
60
+ * 번들 뷰어의 저장.
61
+ * 전체 패키지가 아니라 루트 한 장 + 그림이 그려진 하위 도면만 묶어 저장한다(하이퍼링크는 죽은 상태).
62
+ */
63
+ private onBundleMarkersSave;
33
64
  private onClickMarkerSave;
34
65
  private parseBoxCoordinates;
35
66
  }
@@ -11,6 +11,9 @@ import { CommonGristStyles, ScrollbarStyles } from '@operato/styles';
11
11
  import { client } from '@operato/graphql';
12
12
  import { notify } from '@operato/layout';
13
13
  import { DrawingImageProvider } from '@dssp/drawing/dist-client/drawing-management/drawing-image-provider.js';
14
+ import '@dssp/drawing/dist-client/drawing-bundle/drawing-bundle-viewer.js';
15
+ import { DrawingBundleModel } from '@dssp/drawing/dist-client/drawing-bundle/drawing-bundle-model.js';
16
+ import { loadDrawingBundle } from '@dssp/drawing/dist-client/drawing-bundle/drawing-bundle-loader.js';
14
17
  import './component/building-inspection-detail-header';
15
18
  import { BuildingInspectionStatus } from './building-inspection-list';
16
19
  let BuildingInspectionDetailDrawing = class BuildingInspectionDetailDrawing extends ScopedElementsMixin(PageView) {
@@ -22,6 +25,10 @@ let BuildingInspectionDetailDrawing = class BuildingInspectionDetailDrawing exte
22
25
  this.shapes = [];
23
26
  this.linkShapes = [];
24
27
  this.drawingImageProvider = new DrawingImageProvider();
28
+ /** 번들 뷰어가 열 첫 도면 — 검측에 할당된 패키지 루트 */
29
+ this.bundleRootId = '';
30
+ /** 도면별 사용자 그림 — { [도면 id]: Shape[] } */
31
+ this.bundleMarkers = {};
25
32
  }
26
33
  get context() {
27
34
  return {
@@ -53,6 +60,35 @@ let BuildingInspectionDetailDrawing = class BuildingInspectionDetailDrawing exte
53
60
  .projectId=${this.project.id}
54
61
  ></building-inspection-detail-header>
55
62
 
63
+ ${this.bundleModel
64
+ ? html `
65
+ <div body bundle>
66
+ <drawing-bundle-viewer
67
+ .model=${this.bundleModel}
68
+ .rootId=${this.bundleRootId}
69
+ .markers=${this.bundleMarkers}
70
+ ?readonly=${((_j = this.buildingInspection) === null || _j === void 0 ? void 0 : _j.status) == BuildingInspectionStatus.PASS}
71
+ @markers-changed=${this.onBundleMarkersSave}
72
+ @switch-unavailable=${(e) => notify({ message: e.detail.message, level: 'warn' })}
73
+ ></drawing-bundle-viewer>
74
+ </div>
75
+ `
76
+ : this.renderLegacyDrawing()}
77
+
78
+ <dialog>
79
+ <ox-image-marker-view
80
+ id="link-viewer"
81
+ .imageUrl=${this.linkUrl}
82
+ .shapes=${this.linkShapes}
83
+ .imageProvider=${this.drawingImageProvider}
84
+ ></ox-image-marker-view>
85
+ </dialog>
86
+ `;
87
+ }
88
+ /** 번들이 없는 검측(기존 데이터·DSSP 경로)은 예전 방식 그대로 그린다 */
89
+ renderLegacyDrawing() {
90
+ var _a;
91
+ return html `
56
92
  <div
57
93
  body
58
94
  @link-clicked=${async (e) => {
@@ -96,7 +132,7 @@ let BuildingInspectionDetailDrawing = class BuildingInspectionDetailDrawing exte
96
132
  }
97
133
  }}
98
134
  >
99
- ${((_j = this.buildingInspection) === null || _j === void 0 ? void 0 : _j.status) == BuildingInspectionStatus.PASS
135
+ ${((_a = this.buildingInspection) === null || _a === void 0 ? void 0 : _a.status) == BuildingInspectionStatus.PASS
100
136
  ? html `<ox-image-marker-view
101
137
  id="image-marker"
102
138
  .imageUrl=${this.imageUrl}
@@ -112,20 +148,14 @@ let BuildingInspectionDetailDrawing = class BuildingInspectionDetailDrawing exte
112
148
  .currentMode=${'view'}
113
149
  ></ox-image-marker>`}
114
150
  </div>
115
-
116
- <dialog>
117
- <ox-image-marker-view
118
- id="link-viewer"
119
- .imageUrl=${this.linkUrl}
120
- .shapes=${this.linkShapes}
121
- .imageProvider=${this.drawingImageProvider}
122
- ></ox-image-marker-view>
123
- </dialog>
124
151
  `;
125
152
  }
126
153
  async updated(changes) {
127
154
  var _a, _b, _c;
128
155
  if (changes.has('buildingInspection') && ((_a = this.buildingInspection) === null || _a === void 0 ? void 0 : _a.checklist)) {
156
+ // 도면 번들이 있으면 하이퍼링크 뷰어로 그린다. 없으면 아래 기존 방식으로 떨어진다.
157
+ if (await this.initBundle())
158
+ return;
129
159
  // 1-1. 위치 정보 - 체크리스트에 들어가는 위치정보 텍스트
130
160
  const location_1 = (_b = this.buildingInspection.checklist) === null || _b === void 0 ? void 0 : _b.location;
131
161
  // 1-2. 위치 정보 - 실제 위치정보 텍스트 (동 + 층) - ID 필드를 사용하면 DB ID 필드입니다.
@@ -218,6 +248,72 @@ let BuildingInspectionDetailDrawing = class BuildingInspectionDetailDrawing exte
218
248
  return;
219
249
  this.project = response.data.project;
220
250
  }
251
+ /**
252
+ * 검측에 할당된 도면 패키지를 찾아 번들 뷰어를 준비한다.
253
+ *
254
+ * checklist.inspectionDrawingType 에는 패키지 루트 도면 id 가 들어 있다.
255
+ * 예전 데이터는 검측 도면 '이름' 이 들어 있으므로, 그 경우엔 동·층으로 패키지를 찾아본다.
256
+ * 둘 다 실패하면 false 를 돌려 기존 방식으로 그리게 한다.
257
+ */
258
+ async initBundle() {
259
+ var _a, _b, _c, _d, _e, _f;
260
+ const projectId = (_a = this.project) === null || _a === void 0 ? void 0 : _a.id;
261
+ if (!projectId)
262
+ return false;
263
+ const model = await loadDrawingBundle(projectId, { withLinks: true });
264
+ if (!model)
265
+ return false;
266
+ const buildingLevel = (_b = this.buildingInspection) === null || _b === void 0 ? void 0 : _b.buildingLevel;
267
+ const assigned = (_d = (_c = this.buildingInspection) === null || _c === void 0 ? void 0 : _c.checklist) === null || _d === void 0 ? void 0 : _d.inspectionDrawingType;
268
+ const rootId = (assigned && model.drawing(assigned) && assigned) ||
269
+ ((_f = model.packageOfLevel((_e = buildingLevel === null || buildingLevel === void 0 ? void 0 : buildingLevel.building) === null || _e === void 0 ? void 0 : _e.name, buildingLevel === null || buildingLevel === void 0 ? void 0 : buildingLevel.floor)) === null || _f === void 0 ? void 0 : _f.root);
270
+ if (!rootId)
271
+ return false;
272
+ this.bundleModel = model;
273
+ this.bundleRootId = rootId;
274
+ this.bundleMarkers = this.parseDrawingMarker(rootId);
275
+ return true;
276
+ }
277
+ /**
278
+ * 저장된 도면 마커를 읽는다.
279
+ * 예전 형식은 Shape 배열 하나였고, 지금은 { root, markers: { 도면 id: Shape[] } } 다.
280
+ * 예전 값은 루트 도면의 그림으로 옮겨 읽는다.
281
+ */
282
+ parseDrawingMarker(rootId) {
283
+ var _a;
284
+ const stored = JSON.parse(((_a = this.buildingInspection) === null || _a === void 0 ? void 0 : _a.drawingMarker) || null);
285
+ if (!stored)
286
+ return {};
287
+ if (Array.isArray(stored))
288
+ return { [rootId]: stored };
289
+ return stored.markers || {};
290
+ }
291
+ /**
292
+ * 번들 뷰어의 저장.
293
+ * 전체 패키지가 아니라 루트 한 장 + 그림이 그려진 하위 도면만 묶어 저장한다(하이퍼링크는 죽은 상태).
294
+ */
295
+ async onBundleMarkersSave(e) {
296
+ const { root, markers } = e.detail;
297
+ const response = await client.query({
298
+ query: gql `
299
+ mutation UpdateBuildingInspection($patch: UpdateBuildingInspection!) {
300
+ updateBuildingInspection(patch: $patch) {
301
+ id
302
+ drawingMarker
303
+ }
304
+ }
305
+ `,
306
+ variables: {
307
+ patch: {
308
+ id: this.buildingInspectionId,
309
+ drawingMarker: JSON.stringify({ root, markers })
310
+ }
311
+ }
312
+ });
313
+ if (response.errors)
314
+ return;
315
+ notify({ message: '저장되었습니다.' });
316
+ }
221
317
  async onClickMarkerSave(e) {
222
318
  const response = await client.query({
223
319
  query: gql `
@@ -303,6 +399,17 @@ BuildingInspectionDetailDrawing.styles = [
303
399
  --grid-record-emphasized-color: yellow;
304
400
  }
305
401
 
402
+ div[body][bundle] {
403
+ display: block;
404
+ height: calc(100vh - 120px);
405
+ padding: 0 var(--spacing-large, 12px) var(--spacing-large, 12px);
406
+ }
407
+
408
+ drawing-bundle-viewer {
409
+ width: 100%;
410
+ height: 100%;
411
+ }
412
+
306
413
  div[body] {
307
414
  display: flex;
308
415
  justify-content: center;
@@ -350,6 +457,20 @@ __decorate([
350
457
  state(),
351
458
  __metadata("design:type", DrawingImageProvider)
352
459
  ], BuildingInspectionDetailDrawing.prototype, "drawingImageProvider", void 0);
460
+ __decorate([
461
+ state(),
462
+ __metadata("design:type", DrawingBundleModel
463
+ /** 번들 뷰어가 열 첫 도면 — 검측에 할당된 패키지 루트 */
464
+ )
465
+ ], BuildingInspectionDetailDrawing.prototype, "bundleModel", void 0);
466
+ __decorate([
467
+ state(),
468
+ __metadata("design:type", String)
469
+ ], BuildingInspectionDetailDrawing.prototype, "bundleRootId", void 0);
470
+ __decorate([
471
+ state(),
472
+ __metadata("design:type", Object)
473
+ ], BuildingInspectionDetailDrawing.prototype, "bundleMarkers", void 0);
353
474
  __decorate([
354
475
  query('#image-marker'),
355
476
  __metadata("design:type", Object)
@@ -1 +1 @@
1
- {"version":3,"file":"building-inspection-detail-drawing.js","sourceRoot":"","sources":["../../../client/pages/building-inspection/building-inspection-detail-drawing.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@operato/image-marker/ox-image-marker.js'\nimport '@operato/image-marker/ox-image-marker-view.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, PropertyValues } from 'lit'\nimport { customElement, query, state } from 'lit/decorators.js'\nimport { consume } from '@lit/context'\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements'\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'\nimport { Shape } from '@operato/image-marker'\n\nimport { DrawingImageProvider } from '@dssp/drawing/dist-client/drawing-management/drawing-image-provider.js'\n\nimport './component/building-inspection-detail-header'\nimport { BuildingInspectionStatus } from './building-inspection-list'\n\n@customElement('building-inspection-detail-drawing')\nexport class BuildingInspectionDetailDrawing extends ScopedElementsMixin(PageView) {\n static styles = [\n ScrollbarStyles,\n CommonGristStyles,\n css`\n :host {\n display: grid;\n grid-template-rows: 55px auto;\n color: #4e5055;\n\n width: 100%;\n background-color: var(--md-sys-color-background, #f6f6f6);\n overflow-y: auto;\n\n --grid-record-emphasized-background-color: red;\n --grid-record-emphasized-color: yellow;\n }\n\n div[body] {\n display: flex;\n justify-content: center;\n\n ox-image-marker-view {\n width: 100%;\n }\n }\n\n dialog ox-image-marker-view {\n width: 80vw;\n height: 80vh;\n }\n `\n ]\n\n @state() project: any = {}\n @state() buildingInspection: any = {}\n @state() buildingInspectionId: string = ''\n @state() imageUrl?: string\n @state() shapes: Shape[] = []\n @state() linkUrl?: string\n @state() linkShapes: Shape[] = []\n\n @state() drawingImageProvider: DrawingImageProvider = new DrawingImageProvider()\n // @consume({ context: OxUserPreferencesContext, subscribe: true })\n\n @query('#image-marker') imageMarker!: any\n @query('#link-viewer') linkViewer!: any\n @query('dialog') dialog!: HTMLDialogElement\n\n get context() {\n return {\n title: '검측 관리 상세 - 검측 도면'\n }\n }\n\n connectedCallback(): void {\n super.connectedCallback()\n\n requestAnimationFrame(() => {\n this.dialog.addEventListener('click', event => {\n const rect = this.dialog.getBoundingClientRect()\n const isInDialog =\n rect.top <= event.clientY && event.clientY <= rect.bottom && rect.left <= event.clientX && event.clientX <= rect.right\n\n // 다이아로그 내부를 클릭한 것이 아니면 다이아로그 닫기\n if (!isInDialog) {\n this.dialog.close()\n }\n })\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\n body\n @link-clicked=${async (e: CustomEvent) => {\n const { link } = e.detail\n const { id, type, symbol, box, dwgId } = JSON.parse(link) || {}\n\n // 좌표 파싱 및 유효성 검증\n const coordinates = this.parseBoxCoordinates(box, {\n id,\n type,\n symbol,\n dwgId,\n currentPdfId: this.linkUrl || 'unknown',\n buildingInspectionId: this.buildingInspectionId\n })\n\n this.linkUrl = `DWGID:${dwgId}`\n\n // 유효한 좌표가 있으면 마커 표시, 없으면 빈 배열\n if (coordinates) {\n this.linkShapes = [\n {\n id: id || 'unknown',\n type: 'link' as const,\n ...coordinates,\n link: JSON.stringify({ id, type, symbol, dwgId })\n }\n ]\n } else {\n // 좌표가 유효하지 않아도 팝업은 열고 마커만 숨김\n this.linkShapes = []\n console.warn('Invalid link coordinates, popup will open without marker:', {\n box,\n id,\n type,\n symbol,\n dwgId,\n currentPdfId: this.linkUrl || 'unknown',\n buildingInspectionId: this.buildingInspectionId,\n fullLink: link\n })\n }\n\n if (this.dialog) {\n this.dialog.showModal()\n\n requestAnimationFrame(() => {\n this.linkViewer.reset()\n })\n }\n }}\n >\n ${this.buildingInspection?.status == BuildingInspectionStatus.PASS\n ? html`<ox-image-marker-view\n id=\"image-marker\"\n .imageUrl=${this.imageUrl}\n .shapes=${this.shapes}\n .imageProvider=${this.drawingImageProvider}\n ></ox-image-marker-view>`\n : html` <ox-image-marker\n id=\"image-marker\"\n .imageUrl=${this.imageUrl}\n .shapes=${this.shapes}\n .imageProvider=${this.drawingImageProvider}\n @shapes-changed=${this.onClickMarkerSave}\n .currentMode=${'view'}\n ></ox-image-marker>`}\n </div>\n\n <dialog>\n <ox-image-marker-view\n id=\"link-viewer\"\n .imageUrl=${this.linkUrl}\n .shapes=${this.linkShapes}\n .imageProvider=${this.drawingImageProvider}\n ></ox-image-marker-view>\n </dialog>\n `\n }\n\n protected async updated(changes: PropertyValues): Promise<void> {\n if (changes.has('buildingInspection') && this.buildingInspection?.checklist) {\n // 1-1. 위치 정보 - 체크리스트에 들어가는 위치정보 텍스트\n const location_1 = this.buildingInspection.checklist?.location\n\n // 1-2. 위치 정보 - 실제 위치정보 텍스트 (동 + 층) - ID 필드를 사용하면 DB ID 필드입니다.\n const location_building = this.buildingInspection.buildingLevel.building.name\n const location_floor = this.buildingInspection.buildingLevel.floor\n\n // 2. 평면도 pdf 파일\n // mainDrawing {\n // id\n // name\n // fullpath\n // }\n const mainDrawing = this.buildingInspection.buildingLevel.mainDrawing\n\n // 3. 선택 도면\n const inspectionDrawingType = this.buildingInspection.checklist.inspectionDrawingType\n\n const shapes = JSON.parse(this.buildingInspection?.drawingMarker || null) || []\n const markers = await this.drawingImageProvider.getMarkers(inspectionDrawingType)\n\n this.imageUrl = String(inspectionDrawingType).normalize('NFC')\n this.shapes = [...shapes, ...markers]\n }\n }\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 this.imageMarker?.reset()\n } else {\n this.dialog?.close()\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 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 private async onClickMarkerSave(e) {\n const response = await client.query({\n query: gql`\n mutation UpdateBuildingInspection($patch: UpdateBuildingInspection!) {\n updateBuildingInspection(patch: $patch) {\n id\n drawingMarker\n }\n }\n `,\n variables: {\n patch: {\n id: this.buildingInspectionId,\n drawingMarker: JSON.stringify(e.detail)\n }\n }\n })\n\n if (response.errors) return\n\n notify({ message: '저장되었습니다.' })\n }\n\n private parseBoxCoordinates(\n box: string | undefined,\n context: {\n id?: string\n type?: string\n symbol?: string\n dwgId?: string\n currentPdfId?: string\n buildingInspectionId?: string\n } = {}\n ): {\n x: number\n y: number\n width: number\n height: number\n } | null {\n if (!box || typeof box !== 'string') {\n console.warn('Invalid box coordinate for link:', {\n box,\n context,\n reason: 'Box is undefined, null, or not a string'\n })\n return null\n }\n\n try {\n const coords = box.split(',').map(str => {\n const num = Number(str.trim())\n return Number.isFinite(num) ? num : NaN\n })\n\n if (coords.length !== 4 || coords.some(coord => isNaN(coord))) {\n console.warn('Box coordinate should have 4 valid numbers:', {\n box,\n parsedCoords: coords,\n context,\n reason: `Expected 4 numbers, got ${coords.length} values with NaN: ${coords.some(coord => isNaN(coord))}`\n })\n return null\n }\n\n const [x, y, width, height] = coords\n\n // width, height가 0 이하면 유효하지 않음\n if (width <= 0 || height <= 0) {\n console.warn('Invalid width or height for link:', {\n box,\n coords: { x, y, width, height },\n context,\n reason: `Width (${width}) or height (${height}) is <= 0`\n })\n return null\n }\n\n return { x, y, width, height }\n } catch (error) {\n console.warn('Error parsing box coordinates:', {\n box,\n context,\n error: error instanceof Error ? error.message : String(error),\n reason: 'Exception thrown during parsing'\n })\n return null\n }\n }\n}\n"]}
1
+ {"version":3,"file":"building-inspection-detail-drawing.js","sourceRoot":"","sources":["../../../client/pages/building-inspection/building-inspection-detail-drawing.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@operato/image-marker/ox-image-marker.js'\nimport '@operato/image-marker/ox-image-marker-view.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, PropertyValues } from 'lit'\nimport { customElement, query, state } from 'lit/decorators.js'\nimport { consume } from '@lit/context'\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements'\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'\nimport { Shape } from '@operato/image-marker'\n\nimport { DrawingImageProvider } from '@dssp/drawing/dist-client/drawing-management/drawing-image-provider.js'\nimport '@dssp/drawing/dist-client/drawing-bundle/drawing-bundle-viewer.js'\nimport { DrawingBundleModel } from '@dssp/drawing/dist-client/drawing-bundle/drawing-bundle-model.js'\nimport { loadDrawingBundle } from '@dssp/drawing/dist-client/drawing-bundle/drawing-bundle-loader.js'\n\nimport './component/building-inspection-detail-header'\nimport { BuildingInspectionStatus } from './building-inspection-list'\n\n@customElement('building-inspection-detail-drawing')\nexport class BuildingInspectionDetailDrawing extends ScopedElementsMixin(PageView) {\n static styles = [\n ScrollbarStyles,\n CommonGristStyles,\n css`\n :host {\n display: grid;\n grid-template-rows: 55px auto;\n color: #4e5055;\n\n width: 100%;\n background-color: var(--md-sys-color-background, #f6f6f6);\n overflow-y: auto;\n\n --grid-record-emphasized-background-color: red;\n --grid-record-emphasized-color: yellow;\n }\n\n div[body][bundle] {\n display: block;\n height: calc(100vh - 120px);\n padding: 0 var(--spacing-large, 12px) var(--spacing-large, 12px);\n }\n\n drawing-bundle-viewer {\n width: 100%;\n height: 100%;\n }\n\n div[body] {\n display: flex;\n justify-content: center;\n\n ox-image-marker-view {\n width: 100%;\n }\n }\n\n dialog ox-image-marker-view {\n width: 80vw;\n height: 80vh;\n }\n `\n ]\n\n @state() project: any = {}\n @state() buildingInspection: any = {}\n @state() buildingInspectionId: string = ''\n @state() imageUrl?: string\n @state() shapes: Shape[] = []\n @state() linkUrl?: string\n @state() linkShapes: Shape[] = []\n\n @state() drawingImageProvider: DrawingImageProvider = new DrawingImageProvider()\n\n /** 도면 번들 (있으면 하이퍼링크 뷰어로, 없으면 기존 외부 도면 방식으로 그린다) */\n @state() bundleModel?: DrawingBundleModel\n /** 번들 뷰어가 열 첫 도면 — 검측에 할당된 패키지 루트 */\n @state() bundleRootId: string = ''\n /** 도면별 사용자 그림 — { [도면 id]: Shape[] } */\n @state() bundleMarkers: { [drawingId: string]: Shape[] } = {}\n // @consume({ context: OxUserPreferencesContext, subscribe: true })\n\n @query('#image-marker') imageMarker!: any\n @query('#link-viewer') linkViewer!: any\n @query('dialog') dialog!: HTMLDialogElement\n\n get context() {\n return {\n title: '검측 관리 상세 - 검측 도면'\n }\n }\n\n connectedCallback(): void {\n super.connectedCallback()\n\n requestAnimationFrame(() => {\n this.dialog.addEventListener('click', event => {\n const rect = this.dialog.getBoundingClientRect()\n const isInDialog =\n rect.top <= event.clientY && event.clientY <= rect.bottom && rect.left <= event.clientX && event.clientX <= rect.right\n\n // 다이아로그 내부를 클릭한 것이 아니면 다이아로그 닫기\n if (!isInDialog) {\n this.dialog.close()\n }\n })\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 ${this.bundleModel\n ? html`\n <div body bundle>\n <drawing-bundle-viewer\n .model=${this.bundleModel}\n .rootId=${this.bundleRootId}\n .markers=${this.bundleMarkers}\n ?readonly=${this.buildingInspection?.status == BuildingInspectionStatus.PASS}\n @markers-changed=${this.onBundleMarkersSave}\n @switch-unavailable=${(e: CustomEvent) => notify({ message: e.detail.message, level: 'warn' })}\n ></drawing-bundle-viewer>\n </div>\n `\n : this.renderLegacyDrawing()}\n\n <dialog>\n <ox-image-marker-view\n id=\"link-viewer\"\n .imageUrl=${this.linkUrl}\n .shapes=${this.linkShapes}\n .imageProvider=${this.drawingImageProvider}\n ></ox-image-marker-view>\n </dialog>\n `\n }\n\n /** 번들이 없는 검측(기존 데이터·DSSP 경로)은 예전 방식 그대로 그린다 */\n private renderLegacyDrawing() {\n return html`\n <div\n body\n @link-clicked=${async (e: CustomEvent) => {\n const { link } = e.detail\n const { id, type, symbol, box, dwgId } = JSON.parse(link) || {}\n\n // 좌표 파싱 및 유효성 검증\n const coordinates = this.parseBoxCoordinates(box, {\n id,\n type,\n symbol,\n dwgId,\n currentPdfId: this.linkUrl || 'unknown',\n buildingInspectionId: this.buildingInspectionId\n })\n\n this.linkUrl = `DWGID:${dwgId}`\n\n // 유효한 좌표가 있으면 마커 표시, 없으면 빈 배열\n if (coordinates) {\n this.linkShapes = [\n {\n id: id || 'unknown',\n type: 'link' as const,\n ...coordinates,\n link: JSON.stringify({ id, type, symbol, dwgId })\n }\n ]\n } else {\n // 좌표가 유효하지 않아도 팝업은 열고 마커만 숨김\n this.linkShapes = []\n console.warn('Invalid link coordinates, popup will open without marker:', {\n box,\n id,\n type,\n symbol,\n dwgId,\n currentPdfId: this.linkUrl || 'unknown',\n buildingInspectionId: this.buildingInspectionId,\n fullLink: link\n })\n }\n\n if (this.dialog) {\n this.dialog.showModal()\n\n requestAnimationFrame(() => {\n this.linkViewer.reset()\n })\n }\n }}\n >\n ${this.buildingInspection?.status == BuildingInspectionStatus.PASS\n ? html`<ox-image-marker-view\n id=\"image-marker\"\n .imageUrl=${this.imageUrl}\n .shapes=${this.shapes}\n .imageProvider=${this.drawingImageProvider}\n ></ox-image-marker-view>`\n : html` <ox-image-marker\n id=\"image-marker\"\n .imageUrl=${this.imageUrl}\n .shapes=${this.shapes}\n .imageProvider=${this.drawingImageProvider}\n @shapes-changed=${this.onClickMarkerSave}\n .currentMode=${'view'}\n ></ox-image-marker>`}\n </div>\n `\n }\n\n protected async updated(changes: PropertyValues): Promise<void> {\n if (changes.has('buildingInspection') && this.buildingInspection?.checklist) {\n // 도면 번들이 있으면 하이퍼링크 뷰어로 그린다. 없으면 아래 기존 방식으로 떨어진다.\n if (await this.initBundle()) return\n\n // 1-1. 위치 정보 - 체크리스트에 들어가는 위치정보 텍스트\n const location_1 = this.buildingInspection.checklist?.location\n\n // 1-2. 위치 정보 - 실제 위치정보 텍스트 (동 + 층) - ID 필드를 사용하면 DB ID 필드입니다.\n const location_building = this.buildingInspection.buildingLevel.building.name\n const location_floor = this.buildingInspection.buildingLevel.floor\n\n // 2. 평면도 pdf 파일\n // mainDrawing {\n // id\n // name\n // fullpath\n // }\n const mainDrawing = this.buildingInspection.buildingLevel.mainDrawing\n\n // 3. 선택 도면\n const inspectionDrawingType = this.buildingInspection.checklist.inspectionDrawingType\n\n const shapes = JSON.parse(this.buildingInspection?.drawingMarker || null) || []\n const markers = await this.drawingImageProvider.getMarkers(inspectionDrawingType)\n\n this.imageUrl = String(inspectionDrawingType).normalize('NFC')\n this.shapes = [...shapes, ...markers]\n }\n }\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 this.imageMarker?.reset()\n } else {\n this.dialog?.close()\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 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 /**\n * 검측에 할당된 도면 패키지를 찾아 번들 뷰어를 준비한다.\n *\n * checklist.inspectionDrawingType 에는 패키지 루트 도면 id 가 들어 있다.\n * 예전 데이터는 검측 도면 '이름' 이 들어 있으므로, 그 경우엔 동·층으로 패키지를 찾아본다.\n * 둘 다 실패하면 false 를 돌려 기존 방식으로 그리게 한다.\n */\n private async initBundle(): Promise<boolean> {\n const projectId = this.project?.id\n if (!projectId) return false\n\n const model = await loadDrawingBundle(projectId, { withLinks: true })\n if (!model) return false\n\n const buildingLevel = this.buildingInspection?.buildingLevel\n const assigned = this.buildingInspection?.checklist?.inspectionDrawingType\n\n const rootId =\n (assigned && model.drawing(assigned) && assigned) ||\n model.packageOfLevel(buildingLevel?.building?.name, buildingLevel?.floor)?.root\n\n if (!rootId) return false\n\n this.bundleModel = model\n this.bundleRootId = rootId\n this.bundleMarkers = this.parseDrawingMarker(rootId)\n\n return true\n }\n\n /**\n * 저장된 도면 마커를 읽는다.\n * 예전 형식은 Shape 배열 하나였고, 지금은 { root, markers: { 도면 id: Shape[] } } 다.\n * 예전 값은 루트 도면의 그림으로 옮겨 읽는다.\n */\n private parseDrawingMarker(rootId: string): { [drawingId: string]: Shape[] } {\n const stored = JSON.parse(this.buildingInspection?.drawingMarker || null)\n\n if (!stored) return {}\n if (Array.isArray(stored)) return { [rootId]: stored }\n\n return stored.markers || {}\n }\n\n /**\n * 번들 뷰어의 저장.\n * 전체 패키지가 아니라 루트 한 장 + 그림이 그려진 하위 도면만 묶어 저장한다(하이퍼링크는 죽은 상태).\n */\n private async onBundleMarkersSave(e: CustomEvent) {\n const { root, markers } = e.detail\n\n const response = await client.query({\n query: gql`\n mutation UpdateBuildingInspection($patch: UpdateBuildingInspection!) {\n updateBuildingInspection(patch: $patch) {\n id\n drawingMarker\n }\n }\n `,\n variables: {\n patch: {\n id: this.buildingInspectionId,\n drawingMarker: JSON.stringify({ root, markers })\n }\n }\n })\n\n if (response.errors) return\n\n notify({ message: '저장되었습니다.' })\n }\n\n private async onClickMarkerSave(e) {\n const response = await client.query({\n query: gql`\n mutation UpdateBuildingInspection($patch: UpdateBuildingInspection!) {\n updateBuildingInspection(patch: $patch) {\n id\n drawingMarker\n }\n }\n `,\n variables: {\n patch: {\n id: this.buildingInspectionId,\n drawingMarker: JSON.stringify(e.detail)\n }\n }\n })\n\n if (response.errors) return\n\n notify({ message: '저장되었습니다.' })\n }\n\n private parseBoxCoordinates(\n box: string | undefined,\n context: {\n id?: string\n type?: string\n symbol?: string\n dwgId?: string\n currentPdfId?: string\n buildingInspectionId?: string\n } = {}\n ): {\n x: number\n y: number\n width: number\n height: number\n } | null {\n if (!box || typeof box !== 'string') {\n console.warn('Invalid box coordinate for link:', {\n box,\n context,\n reason: 'Box is undefined, null, or not a string'\n })\n return null\n }\n\n try {\n const coords = box.split(',').map(str => {\n const num = Number(str.trim())\n return Number.isFinite(num) ? num : NaN\n })\n\n if (coords.length !== 4 || coords.some(coord => isNaN(coord))) {\n console.warn('Box coordinate should have 4 valid numbers:', {\n box,\n parsedCoords: coords,\n context,\n reason: `Expected 4 numbers, got ${coords.length} values with NaN: ${coords.some(coord => isNaN(coord))}`\n })\n return null\n }\n\n const [x, y, width, height] = coords\n\n // width, height가 0 이하면 유효하지 않음\n if (width <= 0 || height <= 0) {\n console.warn('Invalid width or height for link:', {\n box,\n coords: { x, y, width, height },\n context,\n reason: `Width (${width}) or height (${height}) is <= 0`\n })\n return null\n }\n\n return { x, y, width, height }\n } catch (error) {\n console.warn('Error parsing box coordinates:', {\n box,\n context,\n error: error instanceof Error ? error.message : String(error),\n reason: 'Exception thrown during parsing'\n })\n return null\n }\n }\n}\n"]}