@dssp/supervision 1.0.0-alpha.92 → 1.0.0-alpha.97

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 (30) hide show
  1. package/dist-client/pages/building-inspection/building-inspection-management.d.ts +1 -0
  2. package/dist-client/pages/building-inspection/building-inspection-management.js +19 -4
  3. package/dist-client/pages/building-inspection/building-inspection-management.js.map +1 -1
  4. package/dist-client/pages/building-inspection/component/field-document/field-document-list-panel.js +9 -8
  5. package/dist-client/pages/building-inspection/component/field-document/field-document-list-panel.js.map +1 -1
  6. package/dist-client/pages/building-inspection/component/field-document/field-document-popup.d.ts +3 -0
  7. package/dist-client/pages/building-inspection/component/field-document/field-document-popup.js +86 -23
  8. package/dist-client/pages/building-inspection/component/field-document/field-document-popup.js.map +1 -1
  9. package/dist-client/pages/checklist/checklist-view.d.ts +1 -0
  10. package/dist-client/pages/checklist/checklist-view.js +98 -106
  11. package/dist-client/pages/checklist/checklist-view.js.map +1 -1
  12. package/dist-client/pages/checklist/kcs-criteria-popup.d.ts +16 -0
  13. package/dist-client/pages/checklist/kcs-criteria-popup.js +179 -0
  14. package/dist-client/pages/checklist/kcs-criteria-popup.js.map +1 -0
  15. package/dist-client/pages/project-checklist/project-checklist-management.d.ts +4 -0
  16. package/dist-client/pages/project-checklist/project-checklist-management.js +81 -12
  17. package/dist-client/pages/project-checklist/project-checklist-management.js.map +1 -1
  18. package/dist-client/tsconfig.tsbuildinfo +1 -1
  19. package/dist-server/service/field-document/field-document-mutation.js +8 -5
  20. package/dist-server/service/field-document/field-document-mutation.js.map +1 -1
  21. package/dist-server/service/field-document/field-document-summary-service.d.ts +8 -0
  22. package/dist-server/service/field-document/field-document-summary-service.js +44 -20
  23. package/dist-server/service/field-document/field-document-summary-service.js.map +1 -1
  24. package/dist-server/service/field-document/field-document-type.d.ts +1 -0
  25. package/dist-server/service/field-document/field-document-type.js +4 -0
  26. package/dist-server/service/field-document/field-document-type.js.map +1 -1
  27. package/dist-server/service/project-checklist/spec-matching-service.js +60 -5
  28. package/dist-server/service/project-checklist/spec-matching-service.js.map +1 -1
  29. package/dist-server/tsconfig.tsbuildinfo +1 -1
  30. package/package.json +3 -2
@@ -2,6 +2,7 @@ import { __decorate, __metadata } from "tslib";
2
2
  import '@material/web/icon/icon.js';
3
3
  import '@material/web/button/filled-button.js';
4
4
  import '@material/web/button/outlined-button.js';
5
+ import '@material/web/progress/circular-progress.js';
5
6
  import './field-document-list-panel';
6
7
  import { ScrollbarStyles } from '@operato/styles';
7
8
  import { css, html, LitElement } from 'lit';
@@ -21,6 +22,8 @@ let FieldDocumentPopup = class FieldDocumentPopup extends LitElement {
21
22
  this.selectedDocIds = new Set();
22
23
  this.codeCounts = new Map();
23
24
  this.dragOverItem = '';
25
+ this.uploading = false;
26
+ this.uploadingFile = '';
24
27
  this._tooltipText = '';
25
28
  this._tooltipX = 0;
26
29
  this._tooltipY = 0;
@@ -34,6 +37,15 @@ let FieldDocumentPopup = class FieldDocumentPopup extends LitElement {
34
37
  ${this._tooltipText
35
38
  ? html `<div tooltip style="left:${this._tooltipX + 12}px;top:${this._tooltipY + 12}px">${this._tooltipText}</div>`
36
39
  : ''}
40
+ ${this.uploading
41
+ ? html `
42
+ <div uploading-overlay>
43
+ <md-circular-progress indeterminate></md-circular-progress>
44
+ <span>업로드 및 AI 브리핑 생성 중...</span>
45
+ <span file>${this.uploadingFile}</span>
46
+ </div>
47
+ `
48
+ : ''}
37
49
 
38
50
  <div header>
39
51
  <h2>
@@ -315,29 +327,47 @@ let FieldDocumentPopup = class FieldDocumentPopup extends LitElement {
315
327
  await this._uploadFiles(files, this.selectedMinor.code);
316
328
  }
317
329
  async _uploadFiles(files, code) {
318
- for (const file of files) {
319
- await client.mutate({
320
- mutation: gql `
321
- mutation CreateFieldDocument($patch: NewFieldDocument!) {
322
- createFieldDocument(patch: $patch) {
323
- id
330
+ var _a, _b, _c, _d;
331
+ // AI 브리핑 힌트용 분류 문자열 (대 · 중 · 소분류)
332
+ const path = findClassificationPath(code);
333
+ const category = [(_a = path.major) === null || _a === void 0 ? void 0 : _a.name, (_b = path.middle) === null || _b === void 0 ? void 0 : _b.name, (_c = path.minor) === null || _c === void 0 ? void 0 : _c.name].filter(Boolean).join(' · ');
334
+ this.uploading = true;
335
+ let done = 0;
336
+ try {
337
+ for (const file of files) {
338
+ this.uploadingFile = files.length > 1 ? `${file.name} (${++done}/${files.length})` : file.name;
339
+ console.log('[field-document] upload request:', file.name, 'code:', code, 'category:', category);
340
+ const response = await client.mutate({
341
+ mutation: gql `
342
+ mutation CreateFieldDocument($patch: NewFieldDocument!) {
343
+ createFieldDocument(patch: $patch) {
344
+ id
345
+ aiSummary
346
+ aiSummaryStatus
347
+ }
324
348
  }
325
- }
326
- `,
327
- variables: {
328
- patch: {
329
- projectId: this.projectId,
330
- code,
331
- name: file.name,
332
- file
333
- }
334
- },
335
- context: { hasUpload: true }
336
- });
349
+ `,
350
+ variables: {
351
+ patch: {
352
+ projectId: this.projectId,
353
+ code,
354
+ name: file.name,
355
+ category,
356
+ file
357
+ }
358
+ },
359
+ context: { hasUpload: true }
360
+ });
361
+ console.log('[field-document] upload response:', JSON.stringify((_d = response.data) === null || _d === void 0 ? void 0 : _d.createFieldDocument));
362
+ }
363
+ await this._loadDocuments();
364
+ await this._loadCounts();
365
+ notify({ message: `${files.length}개 파일이 업로드되었습니다.` });
366
+ }
367
+ finally {
368
+ this.uploading = false;
369
+ this.uploadingFile = '';
337
370
  }
338
- await this._loadDocuments();
339
- await this._loadCounts();
340
- notify({ message: `${files.length}개 파일이 업로드되었습니다.` });
341
371
  }
342
372
  async _deleteDocuments() {
343
373
  if (!this.selectedDocIds.size) {
@@ -419,9 +449,10 @@ let FieldDocumentPopup = class FieldDocumentPopup extends LitElement {
419
449
  }
420
450
  }
421
451
  async _onDocumentsChanged(e) {
422
- var _a, _b;
452
+ var _a, _b, _c;
423
453
  const files = (_a = e.detail) === null || _a === void 0 ? void 0 : _a.files;
424
- if ((files === null || files === void 0 ? void 0 : files.length) && ((_b = this.selectedMinor) === null || _b === void 0 ? void 0 : _b.code)) {
454
+ console.log('[field-document] drop received:', files === null || files === void 0 ? void 0 : files.map(f => f.name), 'code:', (_b = this.selectedMinor) === null || _b === void 0 ? void 0 : _b.code);
455
+ if ((files === null || files === void 0 ? void 0 : files.length) && ((_c = this.selectedMinor) === null || _c === void 0 ? void 0 : _c.code)) {
425
456
  await this._uploadFiles(files, this.selectedMinor.code);
426
457
  }
427
458
  else {
@@ -622,6 +653,30 @@ FieldDocumentPopup.styles = [
622
653
  ox-input-file {
623
654
  display: none;
624
655
  }
656
+
657
+ div[uploading-overlay] {
658
+ position: absolute;
659
+ inset: 0;
660
+ z-index: 100;
661
+ display: flex;
662
+ flex-direction: column;
663
+ align-items: center;
664
+ justify-content: center;
665
+ gap: 12px;
666
+ background: rgba(255, 255, 255, 0.75);
667
+
668
+ span {
669
+ font-size: 13px;
670
+ font-weight: bold;
671
+ color: #3f71a0;
672
+ }
673
+
674
+ span[file] {
675
+ font-weight: normal;
676
+ color: #888;
677
+ font-size: 12px;
678
+ }
679
+ }
625
680
  `
626
681
  ];
627
682
  __decorate([
@@ -656,6 +711,14 @@ __decorate([
656
711
  state(),
657
712
  __metadata("design:type", String)
658
713
  ], FieldDocumentPopup.prototype, "dragOverItem", void 0);
714
+ __decorate([
715
+ state(),
716
+ __metadata("design:type", Boolean)
717
+ ], FieldDocumentPopup.prototype, "uploading", void 0);
718
+ __decorate([
719
+ state(),
720
+ __metadata("design:type", String)
721
+ ], FieldDocumentPopup.prototype, "uploadingFile", void 0);
659
722
  __decorate([
660
723
  state(),
661
724
  __metadata("design:type", String)
@@ -1 +1 @@
1
- {"version":3,"file":"field-document-popup.js","sourceRoot":"","sources":["../../../../../client/pages/building-inspection/component/field-document/field-document-popup.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@material/web/button/filled-button.js'\nimport '@material/web/button/outlined-button.js'\nimport './field-document-list-panel'\n\nimport { ScrollbarStyles } from '@operato/styles'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { client } from '@operato/graphql'\nimport { notify } from '@operato/layout'\nimport gql from 'graphql-tag'\n\nimport { Classification, FIELD_DOCUMENT_CLASSIFICATIONS, findClassificationPath } from './field-document-constants'\n\n@customElement('field-document-popup')\nexport class FieldDocumentPopup extends LitElement {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: grid;\n grid-template-rows: auto 1fr auto;\n background-color: #fff;\n width: 100%;\n height: 80vh;\n overflow: hidden;\n position: relative;\n }\n\n div[header] {\n display: flex;\n align-items: center;\n padding: 12px 20px;\n border-bottom: 1px solid #e0e0e0;\n background: linear-gradient(135deg, #f8f9fa, #e8eef5);\n\n h2 {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0;\n font-size: 16px;\n color: #3f71a0;\n\n md-icon {\n --md-icon-size: 22px;\n }\n }\n\n span[breadcrumb] {\n margin-left: auto;\n font-size: 12px;\n color: #888;\n }\n }\n\n div[content] {\n display: grid;\n grid-template-columns: 3.5fr 6.5fr;\n overflow: hidden;\n }\n\n div[classification-panel] {\n display: grid;\n grid-template-columns: 0.8fr 1fr 2fr;\n border-right: 1px solid #e0e0e0;\n overflow: hidden;\n }\n\n div[tooltip] {\n position: absolute;\n background: rgba(0, 0, 0, 0.85);\n color: #fff;\n font-size: 12px;\n padding: 4px 10px;\n border-radius: 4px;\n white-space: nowrap;\n z-index: 9999;\n pointer-events: none;\n }\n\n div[column] {\n display: flex;\n flex-direction: column;\n border-right: 1px solid #eee;\n overflow-y: auto;\n overflow-x: hidden;\n\n &:last-child {\n border-right: none;\n }\n\n div[column-header] {\n position: sticky;\n top: 0;\n background: #f5f5f5;\n padding: 8px 12px;\n font-size: 12px;\n font-weight: bold;\n color: #666;\n border-bottom: 1px solid #e0e0e0;\n z-index: 1;\n }\n\n div[item] {\n display: flex;\n align-items: center;\n padding: 8px 12px;\n cursor: pointer;\n font-size: 13px;\n color: #333;\n border-bottom: 1px solid #f0f0f0;\n transition: background-color 0.15s;\n position: relative;\n\n &:hover {\n background-color: #e3f2fd;\n }\n\n span[code] {\n font-size: 11px;\n color: #999;\n margin-right: 6px;\n min-width: 32px;\n }\n\n span[name] {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n span[count] {\n position: absolute;\n right: 3px;\n top: 50%;\n transform: translateY(-50%);\n font-size: 8px;\n color: #fff;\n background: #0595e5;\n border-radius: 7px;\n padding: 0 3px;\n min-width: 10px;\n text-align: center;\n line-height: 14px;\n }\n }\n\n div[item][selected] {\n background-color: #0595e5;\n color: #fff;\n\n span[code] {\n color: rgba(255, 255, 255, 0.7);\n }\n\n span[count] {\n background: rgba(255, 255, 255, 0.3);\n }\n }\n\n div[item][drag-over] {\n background-color: #bbdefb;\n outline: 2px dashed #1976d2;\n }\n }\n\n div[footer] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 12px 20px;\n border-top: 1px solid #e0e0e0;\n background: #f8f8f8;\n\n md-filled-button {\n cursor: pointer;\n --md-filled-button-container-height: 36px;\n --md-filled-button-trailing-space: 16px;\n --md-filled-button-leading-space: 16px;\n --md-filled-button-container-color: #0595e5;\n --md-filled-button-label-text-color: var(--md-sys-color-on-primary);\n --md-filled-button-hover-label-text-color: var(--md-sys-color-on-primary);\n --md-filled-button-icon-color: var(--md-sys-color-on-primary);\n --md-filled-button-hover-icon-color: var(--md-sys-color-on-primary);\n }\n\n md-filled-button[share] {\n --md-filled-button-container-color: #3f71a0;\n }\n md-filled-button[upload] {\n --md-filled-button-container-color: #008000;\n }\n md-filled-button[delete] {\n --md-filled-button-container-color: #e15757;\n }\n }\n\n ox-input-file {\n display: none;\n }\n `\n ]\n\n @property({ type: String }) projectId: string = ''\n\n @state() private selectedMajor: Classification | null = null\n @state() private selectedMiddle: Classification | null = null\n @state() private selectedMinor: Classification | null = null\n @state() private documents: any[] = []\n @state() private selectedDocIds: Set<string> = new Set()\n @state() private codeCounts: Map<string, number> = new Map()\n @state() private dragOverItem: string = ''\n @state() private _tooltipText: string = ''\n @state() private _tooltipX: number = 0\n @state() private _tooltipY: number = 0\n\n render() {\n const majors = FIELD_DOCUMENT_CLASSIFICATIONS\n const middles = this.selectedMajor?.children || []\n const minors = this.selectedMiddle?.children || []\n\n return html`\n ${this._tooltipText\n ? html`<div tooltip style=\"left:${this._tooltipX + 12}px;top:${this._tooltipY + 12}px\">${this._tooltipText}</div>`\n : ''}\n\n <div header>\n <h2>\n <md-icon>folder_open</md-icon>\n 현장 문서 확인\n </h2>\n <span breadcrumb>\n ${this.selectedMajor ? this.selectedMajor.name : ''} ${this.selectedMiddle ? ` > ${this.selectedMiddle.name}` : ''}\n ${this.selectedMinor ? ` > ${this.selectedMinor.name}` : ''}\n </span>\n </div>\n\n <div content>\n <div classification-panel>\n <div column>\n <div column-header>대분류</div>\n ${majors.map(\n item => html`\n <div\n item\n ?selected=${this.selectedMajor?.code === item.code}\n @click=${() => this._selectMajor(item)}\n @mousemove=${(e: MouseEvent) => this._showTooltip(e, item.name)}\n @mouseleave=${() => (this._tooltipText = '')}\n @dragover=${(e: DragEvent) => this._onFolderDragOver(e, item.code)}\n @dragleave=${() => (this.dragOverItem = '')}\n @drop=${(e: DragEvent) => this._onFolderDrop(e, item.code)}\n ?drag-over=${this.dragOverItem === item.code}\n >\n <span name>${item.name}</span>\n ${this._getMajorCount(item.code) > 0 ? html`<span count>${this._getMajorCount(item.code)}</span>` : ''}\n </div>\n `\n )}\n </div>\n\n <div column>\n <div column-header>중분류</div>\n ${middles.map(\n item => html`\n <div\n item\n ?selected=${this.selectedMiddle?.code === item.code}\n @click=${() => this._selectMiddle(item)}\n @mousemove=${(e: MouseEvent) => this._showTooltip(e, item.name)}\n @mouseleave=${() => (this._tooltipText = '')}\n @dragover=${(e: DragEvent) => this._onFolderDragOver(e, item.code)}\n @dragleave=${() => (this.dragOverItem = '')}\n @drop=${(e: DragEvent) => this._onFolderDrop(e, item.code)}\n ?drag-over=${this.dragOverItem === item.code}\n >\n <span name>${item.name}</span>\n ${this._getMiddleCount(item.code) > 0 ? html`<span count>${this._getMiddleCount(item.code)}</span>` : ''}\n </div>\n `\n )}\n </div>\n\n <div column>\n <div column-header>소분류</div>\n ${minors.map(\n item => html`\n <div\n item\n ?selected=${this.selectedMinor?.code === item.code}\n @click=${() => this._selectMinor(item)}\n @mousemove=${(e: MouseEvent) => this._showTooltip(e, item.name)}\n @mouseleave=${() => (this._tooltipText = '')}\n @dragover=${(e: DragEvent) => this._onFolderDragOver(e, item.code)}\n @dragleave=${() => (this.dragOverItem = '')}\n @drop=${(e: DragEvent) => this._onFolderDrop(e, item.code)}\n ?drag-over=${this.dragOverItem === item.code}\n >\n <span code>${item.code}</span>\n <span name>${item.name}</span>\n ${(this.codeCounts.get(item.code) || 0) > 0 ? html`<span count>${this.codeCounts.get(item.code)}</span>` : ''}\n </div>\n `\n )}\n </div>\n </div>\n\n <field-document-list-panel\n .projectId=${this.projectId}\n .code=${this.selectedMinor?.code || ''}\n .folderName=${this.selectedMinor?.name || ''}\n .documents=${this.documents}\n @document-selected=${(e: CustomEvent) => (this.selectedDocIds = e.detail)}\n @documents-changed=${(e: CustomEvent) => this._onDocumentsChanged(e)}\n ></field-document-list-panel>\n </div>\n\n <div footer>\n <md-filled-button share @click=${this._shareDocuments}> <md-icon slot=\"icon\">share</md-icon>공유 </md-filled-button>\n <md-filled-button favorite @click=${this._toggleFavorites}>\n <md-icon slot=\"icon\">star</md-icon>즐겨찾기\n </md-filled-button>\n <md-filled-button upload @click=${this._triggerUpload}> <md-icon slot=\"icon\">upload</md-icon>업로드 </md-filled-button>\n <md-filled-button delete @click=${this._deleteDocuments}> <md-icon slot=\"icon\">delete</md-icon>삭제 </md-filled-button>\n\n <input\n type=\"file\"\n id=\"native-file-input\"\n multiple\n accept=\"*/*\"\n style=\"display:none\"\n @change=${this._onNativeFileSelected}\n />\n </div>\n `\n }\n\n async firstUpdated() {\n await this._loadCounts()\n // 첫 번째 대분류 자동 선택\n if (FIELD_DOCUMENT_CLASSIFICATIONS.length > 0) {\n this._selectMajor(FIELD_DOCUMENT_CLASSIFICATIONS[0])\n }\n }\n\n private _selectMajor(item: Classification) {\n this.selectedMajor = item\n this.selectedMiddle = null\n this.selectedMinor = null\n this.documents = []\n this.selectedDocIds = new Set()\n\n if (item.children?.length) {\n this._selectMiddle(item.children[0])\n }\n }\n\n private _selectMiddle(item: Classification) {\n this.selectedMiddle = item\n this.selectedMinor = null\n this.documents = []\n this.selectedDocIds = new Set()\n\n if (item.children?.length) {\n this._selectMinor(item.children[0])\n }\n }\n\n private async _selectMinor(item: Classification) {\n this.selectedMinor = item\n this.selectedDocIds = new Set()\n await this._loadDocuments()\n }\n\n private async _loadDocuments() {\n if (!this.selectedMinor?.code || !this.projectId) {\n this.documents = []\n return\n }\n\n const response = await client.query({\n query: gql`\n query FieldDocumentsByCode($projectId: String!, $code: String!) {\n fieldDocumentsByCode(projectId: $projectId, code: $code) {\n items {\n id\n name\n code\n isFavorite\n aiSummary\n aiSummaryStatus\n sourceType\n fullpath\n fileSize\n createdAt\n creator {\n id\n name\n }\n }\n total\n }\n }\n `,\n variables: { projectId: this.projectId, code: this.selectedMinor.code }\n })\n\n this.documents = response.data?.fieldDocumentsByCode?.items || []\n }\n\n private async _loadCounts() {\n if (!this.projectId) return\n\n const response = await client.query({\n query: gql`\n query FieldDocumentCountsByProject($projectId: String!) {\n fieldDocumentCountsByProject(projectId: $projectId) {\n code\n count\n }\n }\n `,\n variables: { projectId: this.projectId }\n })\n\n const counts = response.data?.fieldDocumentCountsByProject || []\n this.codeCounts = new Map(counts.map((c: any) => [c.code, c.count]))\n }\n\n private _getMajorCount(majorCode: string): number {\n let total = 0\n for (const [code, count] of this.codeCounts) {\n if (code.startsWith(majorCode)) total += count\n }\n return total\n }\n\n private _getMiddleCount(middleCode: string): number {\n let total = 0\n for (const [code, count] of this.codeCounts) {\n if (code.startsWith(middleCode)) total += count\n }\n return total\n }\n\n private async _shareDocuments() {\n const selected = this.documents.filter(d => this.selectedDocIds.has(d.id))\n if (!selected.length) {\n notify({ message: '공유할 문서를 선택해주세요.', level: 'info' })\n return\n }\n\n if (navigator.share) {\n try {\n await navigator.share({\n title: '현장 문서',\n text: selected.map(d => d.name).join(', '),\n url: window.location.href\n })\n } catch {\n // 사용자 취소\n }\n } else {\n const links = selected.map(d => d.fullpath || d.name).join('\\n')\n await navigator.clipboard.writeText(links)\n notify({ message: '링크가 복사되었습니다.' })\n }\n }\n\n private async _toggleFavorites() {\n if (!this.selectedDocIds.size) {\n notify({ message: '즐겨찾기할 문서를 선택해주세요.', level: 'info' })\n return\n }\n\n for (const id of this.selectedDocIds) {\n await client.mutate({\n mutation: gql`\n mutation ToggleFieldDocumentFavorite($id: String!) {\n toggleFieldDocumentFavorite(id: $id) {\n id\n isFavorite\n }\n }\n `,\n variables: { id }\n })\n }\n\n await this._loadDocuments()\n notify({ message: '즐겨찾기가 변경되었습니다.' })\n }\n\n private _triggerUpload() {\n if (!this.selectedMinor?.code) {\n notify({ message: '파일을 업로드할 소분류 폴더를 먼저 선택해주세요.', level: 'info' })\n return\n }\n\n const fileInput = this.renderRoot.querySelector('#native-file-input') as HTMLInputElement\n if (fileInput) {\n fileInput.value = ''\n fileInput.click()\n }\n }\n\n private async _onNativeFileSelected(e: Event) {\n const input = e.target as HTMLInputElement\n const files = Array.from(input.files || [])\n if (!files.length || !this.selectedMinor?.code) return\n\n await this._uploadFiles(files, this.selectedMinor.code)\n }\n\n private async _uploadFiles(files: File[], code: string) {\n for (const file of files) {\n await client.mutate({\n mutation: gql`\n mutation CreateFieldDocument($patch: NewFieldDocument!) {\n createFieldDocument(patch: $patch) {\n id\n }\n }\n `,\n variables: {\n patch: {\n projectId: this.projectId,\n code,\n name: file.name,\n file\n }\n },\n context: { hasUpload: true }\n })\n }\n\n await this._loadDocuments()\n await this._loadCounts()\n notify({ message: `${files.length}개 파일이 업로드되었습니다.` })\n }\n\n private async _deleteDocuments() {\n if (!this.selectedDocIds.size) {\n notify({ message: '삭제할 문서를 선택해주세요.', level: 'info' })\n return\n }\n\n if (!confirm('선택한 문서를 삭제하시겠습니까?')) return\n\n const ids = Array.from(this.selectedDocIds)\n\n const response = await client.mutate({\n mutation: gql`\n mutation DeleteFieldDocuments($ids: [String!]!) {\n deleteFieldDocuments(ids: $ids)\n }\n `,\n variables: { ids }\n })\n\n if (!response.errors) {\n this.selectedDocIds = new Set()\n await this._loadDocuments()\n await this._loadCounts()\n notify({ message: '삭제되었습니다.' })\n }\n }\n\n private _onFolderDragOver(e: DragEvent, code: string) {\n const types = e.dataTransfer?.types || []\n if (types.includes('application/x-field-document-ids')) {\n e.preventDefault()\n this.dragOverItem = code\n\n // 대분류/중분류 위에 hover 시 자동 확장\n if (code.length === 2) {\n const major = FIELD_DOCUMENT_CLASSIFICATIONS.find(m => m.code === code)\n if (major && this.selectedMajor?.code !== code) {\n clearTimeout(this._expandTimeout)\n this._expandTimeout = setTimeout(() => this._selectMajor(major), 500)\n }\n } else if (code.length === 4) {\n const middles = this.selectedMajor?.children || []\n const middle = middles.find(m => m.code === code)\n if (middle && this.selectedMiddle?.code !== code) {\n clearTimeout(this._expandTimeout)\n this._expandTimeout = setTimeout(() => {\n this.selectedMiddle = middle\n this.selectedMinor = null\n }, 500)\n }\n }\n }\n }\n\n private _expandTimeout: any\n\n private async _onFolderDrop(e: DragEvent, code: string) {\n e.preventDefault()\n this.dragOverItem = ''\n clearTimeout(this._expandTimeout)\n\n const idsJson = e.dataTransfer?.getData('application/x-field-document-ids')\n if (!idsJson) return\n\n const ids: string[] = JSON.parse(idsJson)\n\n // 소분류 코드에만 이동 가능\n if (code.length !== 6) {\n notify({ message: '소분류 폴더에만 이동할 수 있습니다.', level: 'info' })\n return\n }\n\n const response = await client.mutate({\n mutation: gql`\n mutation MoveFieldDocuments($ids: [String!]!, $targetCode: String!) {\n moveFieldDocuments(ids: $ids, targetCode: $targetCode)\n }\n `,\n variables: { ids, targetCode: code }\n })\n\n if (!response.errors) {\n const path = findClassificationPath(code)\n notify({ message: `${ids.length}개 문서가 \"${path.minor?.name || code}\" 폴더로 이동되었습니다.` })\n await this._loadDocuments()\n await this._loadCounts()\n }\n }\n\n private async _onDocumentsChanged(e: CustomEvent) {\n const files = e.detail?.files as File[]\n if (files?.length && this.selectedMinor?.code) {\n await this._uploadFiles(files, this.selectedMinor.code)\n } else {\n await this._loadDocuments()\n }\n }\n\n private _showTooltip(e: MouseEvent, text: string) {\n this._tooltipText = text\n const rect = this.getBoundingClientRect()\n this._tooltipX = e.clientX - rect.left\n this._tooltipY = e.clientY - rect.top\n }\n}\n"]}
1
+ {"version":3,"file":"field-document-popup.js","sourceRoot":"","sources":["../../../../../client/pages/building-inspection/component/field-document/field-document-popup.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@material/web/button/filled-button.js'\nimport '@material/web/button/outlined-button.js'\nimport '@material/web/progress/circular-progress.js'\nimport './field-document-list-panel'\n\nimport { ScrollbarStyles } from '@operato/styles'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { client } from '@operato/graphql'\nimport { notify } from '@operato/layout'\nimport gql from 'graphql-tag'\n\nimport { Classification, FIELD_DOCUMENT_CLASSIFICATIONS, findClassificationPath } from './field-document-constants'\n\n@customElement('field-document-popup')\nexport class FieldDocumentPopup extends LitElement {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: grid;\n grid-template-rows: auto 1fr auto;\n background-color: #fff;\n width: 100%;\n height: 80vh;\n overflow: hidden;\n position: relative;\n }\n\n div[header] {\n display: flex;\n align-items: center;\n padding: 12px 20px;\n border-bottom: 1px solid #e0e0e0;\n background: linear-gradient(135deg, #f8f9fa, #e8eef5);\n\n h2 {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0;\n font-size: 16px;\n color: #3f71a0;\n\n md-icon {\n --md-icon-size: 22px;\n }\n }\n\n span[breadcrumb] {\n margin-left: auto;\n font-size: 12px;\n color: #888;\n }\n }\n\n div[content] {\n display: grid;\n grid-template-columns: 3.5fr 6.5fr;\n overflow: hidden;\n }\n\n div[classification-panel] {\n display: grid;\n grid-template-columns: 0.8fr 1fr 2fr;\n border-right: 1px solid #e0e0e0;\n overflow: hidden;\n }\n\n div[tooltip] {\n position: absolute;\n background: rgba(0, 0, 0, 0.85);\n color: #fff;\n font-size: 12px;\n padding: 4px 10px;\n border-radius: 4px;\n white-space: nowrap;\n z-index: 9999;\n pointer-events: none;\n }\n\n div[column] {\n display: flex;\n flex-direction: column;\n border-right: 1px solid #eee;\n overflow-y: auto;\n overflow-x: hidden;\n\n &:last-child {\n border-right: none;\n }\n\n div[column-header] {\n position: sticky;\n top: 0;\n background: #f5f5f5;\n padding: 8px 12px;\n font-size: 12px;\n font-weight: bold;\n color: #666;\n border-bottom: 1px solid #e0e0e0;\n z-index: 1;\n }\n\n div[item] {\n display: flex;\n align-items: center;\n padding: 8px 12px;\n cursor: pointer;\n font-size: 13px;\n color: #333;\n border-bottom: 1px solid #f0f0f0;\n transition: background-color 0.15s;\n position: relative;\n\n &:hover {\n background-color: #e3f2fd;\n }\n\n span[code] {\n font-size: 11px;\n color: #999;\n margin-right: 6px;\n min-width: 32px;\n }\n\n span[name] {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n span[count] {\n position: absolute;\n right: 3px;\n top: 50%;\n transform: translateY(-50%);\n font-size: 8px;\n color: #fff;\n background: #0595e5;\n border-radius: 7px;\n padding: 0 3px;\n min-width: 10px;\n text-align: center;\n line-height: 14px;\n }\n }\n\n div[item][selected] {\n background-color: #0595e5;\n color: #fff;\n\n span[code] {\n color: rgba(255, 255, 255, 0.7);\n }\n\n span[count] {\n background: rgba(255, 255, 255, 0.3);\n }\n }\n\n div[item][drag-over] {\n background-color: #bbdefb;\n outline: 2px dashed #1976d2;\n }\n }\n\n div[footer] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 12px 20px;\n border-top: 1px solid #e0e0e0;\n background: #f8f8f8;\n\n md-filled-button {\n cursor: pointer;\n --md-filled-button-container-height: 36px;\n --md-filled-button-trailing-space: 16px;\n --md-filled-button-leading-space: 16px;\n --md-filled-button-container-color: #0595e5;\n --md-filled-button-label-text-color: var(--md-sys-color-on-primary);\n --md-filled-button-hover-label-text-color: var(--md-sys-color-on-primary);\n --md-filled-button-icon-color: var(--md-sys-color-on-primary);\n --md-filled-button-hover-icon-color: var(--md-sys-color-on-primary);\n }\n\n md-filled-button[share] {\n --md-filled-button-container-color: #3f71a0;\n }\n md-filled-button[upload] {\n --md-filled-button-container-color: #008000;\n }\n md-filled-button[delete] {\n --md-filled-button-container-color: #e15757;\n }\n }\n\n ox-input-file {\n display: none;\n }\n\n div[uploading-overlay] {\n position: absolute;\n inset: 0;\n z-index: 100;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n background: rgba(255, 255, 255, 0.75);\n\n span {\n font-size: 13px;\n font-weight: bold;\n color: #3f71a0;\n }\n\n span[file] {\n font-weight: normal;\n color: #888;\n font-size: 12px;\n }\n }\n `\n ]\n\n @property({ type: String }) projectId: string = ''\n\n @state() private selectedMajor: Classification | null = null\n @state() private selectedMiddle: Classification | null = null\n @state() private selectedMinor: Classification | null = null\n @state() private documents: any[] = []\n @state() private selectedDocIds: Set<string> = new Set()\n @state() private codeCounts: Map<string, number> = new Map()\n @state() private dragOverItem: string = ''\n @state() private uploading: boolean = false\n @state() private uploadingFile: string = ''\n @state() private _tooltipText: string = ''\n @state() private _tooltipX: number = 0\n @state() private _tooltipY: number = 0\n\n render() {\n const majors = FIELD_DOCUMENT_CLASSIFICATIONS\n const middles = this.selectedMajor?.children || []\n const minors = this.selectedMiddle?.children || []\n\n return html`\n ${this._tooltipText\n ? html`<div tooltip style=\"left:${this._tooltipX + 12}px;top:${this._tooltipY + 12}px\">${this._tooltipText}</div>`\n : ''}\n ${this.uploading\n ? html`\n <div uploading-overlay>\n <md-circular-progress indeterminate></md-circular-progress>\n <span>업로드 및 AI 브리핑 생성 중...</span>\n <span file>${this.uploadingFile}</span>\n </div>\n `\n : ''}\n\n <div header>\n <h2>\n <md-icon>folder_open</md-icon>\n 현장 문서 확인\n </h2>\n <span breadcrumb>\n ${this.selectedMajor ? this.selectedMajor.name : ''} ${this.selectedMiddle ? ` > ${this.selectedMiddle.name}` : ''}\n ${this.selectedMinor ? ` > ${this.selectedMinor.name}` : ''}\n </span>\n </div>\n\n <div content>\n <div classification-panel>\n <div column>\n <div column-header>대분류</div>\n ${majors.map(\n item => html`\n <div\n item\n ?selected=${this.selectedMajor?.code === item.code}\n @click=${() => this._selectMajor(item)}\n @mousemove=${(e: MouseEvent) => this._showTooltip(e, item.name)}\n @mouseleave=${() => (this._tooltipText = '')}\n @dragover=${(e: DragEvent) => this._onFolderDragOver(e, item.code)}\n @dragleave=${() => (this.dragOverItem = '')}\n @drop=${(e: DragEvent) => this._onFolderDrop(e, item.code)}\n ?drag-over=${this.dragOverItem === item.code}\n >\n <span name>${item.name}</span>\n ${this._getMajorCount(item.code) > 0 ? html`<span count>${this._getMajorCount(item.code)}</span>` : ''}\n </div>\n `\n )}\n </div>\n\n <div column>\n <div column-header>중분류</div>\n ${middles.map(\n item => html`\n <div\n item\n ?selected=${this.selectedMiddle?.code === item.code}\n @click=${() => this._selectMiddle(item)}\n @mousemove=${(e: MouseEvent) => this._showTooltip(e, item.name)}\n @mouseleave=${() => (this._tooltipText = '')}\n @dragover=${(e: DragEvent) => this._onFolderDragOver(e, item.code)}\n @dragleave=${() => (this.dragOverItem = '')}\n @drop=${(e: DragEvent) => this._onFolderDrop(e, item.code)}\n ?drag-over=${this.dragOverItem === item.code}\n >\n <span name>${item.name}</span>\n ${this._getMiddleCount(item.code) > 0 ? html`<span count>${this._getMiddleCount(item.code)}</span>` : ''}\n </div>\n `\n )}\n </div>\n\n <div column>\n <div column-header>소분류</div>\n ${minors.map(\n item => html`\n <div\n item\n ?selected=${this.selectedMinor?.code === item.code}\n @click=${() => this._selectMinor(item)}\n @mousemove=${(e: MouseEvent) => this._showTooltip(e, item.name)}\n @mouseleave=${() => (this._tooltipText = '')}\n @dragover=${(e: DragEvent) => this._onFolderDragOver(e, item.code)}\n @dragleave=${() => (this.dragOverItem = '')}\n @drop=${(e: DragEvent) => this._onFolderDrop(e, item.code)}\n ?drag-over=${this.dragOverItem === item.code}\n >\n <span code>${item.code}</span>\n <span name>${item.name}</span>\n ${(this.codeCounts.get(item.code) || 0) > 0 ? html`<span count>${this.codeCounts.get(item.code)}</span>` : ''}\n </div>\n `\n )}\n </div>\n </div>\n\n <field-document-list-panel\n .projectId=${this.projectId}\n .code=${this.selectedMinor?.code || ''}\n .folderName=${this.selectedMinor?.name || ''}\n .documents=${this.documents}\n @document-selected=${(e: CustomEvent) => (this.selectedDocIds = e.detail)}\n @documents-changed=${(e: CustomEvent) => this._onDocumentsChanged(e)}\n ></field-document-list-panel>\n </div>\n\n <div footer>\n <md-filled-button share @click=${this._shareDocuments}> <md-icon slot=\"icon\">share</md-icon>공유 </md-filled-button>\n <md-filled-button favorite @click=${this._toggleFavorites}>\n <md-icon slot=\"icon\">star</md-icon>즐겨찾기\n </md-filled-button>\n <md-filled-button upload @click=${this._triggerUpload}> <md-icon slot=\"icon\">upload</md-icon>업로드 </md-filled-button>\n <md-filled-button delete @click=${this._deleteDocuments}> <md-icon slot=\"icon\">delete</md-icon>삭제 </md-filled-button>\n\n <input\n type=\"file\"\n id=\"native-file-input\"\n multiple\n accept=\"*/*\"\n style=\"display:none\"\n @change=${this._onNativeFileSelected}\n />\n </div>\n `\n }\n\n async firstUpdated() {\n await this._loadCounts()\n // 첫 번째 대분류 자동 선택\n if (FIELD_DOCUMENT_CLASSIFICATIONS.length > 0) {\n this._selectMajor(FIELD_DOCUMENT_CLASSIFICATIONS[0])\n }\n }\n\n private _selectMajor(item: Classification) {\n this.selectedMajor = item\n this.selectedMiddle = null\n this.selectedMinor = null\n this.documents = []\n this.selectedDocIds = new Set()\n\n if (item.children?.length) {\n this._selectMiddle(item.children[0])\n }\n }\n\n private _selectMiddle(item: Classification) {\n this.selectedMiddle = item\n this.selectedMinor = null\n this.documents = []\n this.selectedDocIds = new Set()\n\n if (item.children?.length) {\n this._selectMinor(item.children[0])\n }\n }\n\n private async _selectMinor(item: Classification) {\n this.selectedMinor = item\n this.selectedDocIds = new Set()\n await this._loadDocuments()\n }\n\n private async _loadDocuments() {\n if (!this.selectedMinor?.code || !this.projectId) {\n this.documents = []\n return\n }\n\n const response = await client.query({\n query: gql`\n query FieldDocumentsByCode($projectId: String!, $code: String!) {\n fieldDocumentsByCode(projectId: $projectId, code: $code) {\n items {\n id\n name\n code\n isFavorite\n aiSummary\n aiSummaryStatus\n sourceType\n fullpath\n fileSize\n createdAt\n creator {\n id\n name\n }\n }\n total\n }\n }\n `,\n variables: { projectId: this.projectId, code: this.selectedMinor.code }\n })\n\n this.documents = response.data?.fieldDocumentsByCode?.items || []\n }\n\n private async _loadCounts() {\n if (!this.projectId) return\n\n const response = await client.query({\n query: gql`\n query FieldDocumentCountsByProject($projectId: String!) {\n fieldDocumentCountsByProject(projectId: $projectId) {\n code\n count\n }\n }\n `,\n variables: { projectId: this.projectId }\n })\n\n const counts = response.data?.fieldDocumentCountsByProject || []\n this.codeCounts = new Map(counts.map((c: any) => [c.code, c.count]))\n }\n\n private _getMajorCount(majorCode: string): number {\n let total = 0\n for (const [code, count] of this.codeCounts) {\n if (code.startsWith(majorCode)) total += count\n }\n return total\n }\n\n private _getMiddleCount(middleCode: string): number {\n let total = 0\n for (const [code, count] of this.codeCounts) {\n if (code.startsWith(middleCode)) total += count\n }\n return total\n }\n\n private async _shareDocuments() {\n const selected = this.documents.filter(d => this.selectedDocIds.has(d.id))\n if (!selected.length) {\n notify({ message: '공유할 문서를 선택해주세요.', level: 'info' })\n return\n }\n\n if (navigator.share) {\n try {\n await navigator.share({\n title: '현장 문서',\n text: selected.map(d => d.name).join(', '),\n url: window.location.href\n })\n } catch {\n // 사용자 취소\n }\n } else {\n const links = selected.map(d => d.fullpath || d.name).join('\\n')\n await navigator.clipboard.writeText(links)\n notify({ message: '링크가 복사되었습니다.' })\n }\n }\n\n private async _toggleFavorites() {\n if (!this.selectedDocIds.size) {\n notify({ message: '즐겨찾기할 문서를 선택해주세요.', level: 'info' })\n return\n }\n\n for (const id of this.selectedDocIds) {\n await client.mutate({\n mutation: gql`\n mutation ToggleFieldDocumentFavorite($id: String!) {\n toggleFieldDocumentFavorite(id: $id) {\n id\n isFavorite\n }\n }\n `,\n variables: { id }\n })\n }\n\n await this._loadDocuments()\n notify({ message: '즐겨찾기가 변경되었습니다.' })\n }\n\n private _triggerUpload() {\n if (!this.selectedMinor?.code) {\n notify({ message: '파일을 업로드할 소분류 폴더를 먼저 선택해주세요.', level: 'info' })\n return\n }\n\n const fileInput = this.renderRoot.querySelector('#native-file-input') as HTMLInputElement\n if (fileInput) {\n fileInput.value = ''\n fileInput.click()\n }\n }\n\n private async _onNativeFileSelected(e: Event) {\n const input = e.target as HTMLInputElement\n const files = Array.from(input.files || [])\n if (!files.length || !this.selectedMinor?.code) return\n\n await this._uploadFiles(files, this.selectedMinor.code)\n }\n\n private async _uploadFiles(files: File[], code: string) {\n // AI 브리핑 힌트용 분류 문자열 (대 · 중 · 소분류)\n const path = findClassificationPath(code)\n const category = [path.major?.name, path.middle?.name, path.minor?.name].filter(Boolean).join(' · ')\n\n this.uploading = true\n let done = 0\n\n try {\n for (const file of files) {\n this.uploadingFile = files.length > 1 ? `${file.name} (${++done}/${files.length})` : file.name\n console.log('[field-document] upload request:', file.name, 'code:', code, 'category:', category)\n const response = await client.mutate({\n mutation: gql`\n mutation CreateFieldDocument($patch: NewFieldDocument!) {\n createFieldDocument(patch: $patch) {\n id\n aiSummary\n aiSummaryStatus\n }\n }\n `,\n variables: {\n patch: {\n projectId: this.projectId,\n code,\n name: file.name,\n category,\n file\n }\n },\n context: { hasUpload: true }\n })\n console.log('[field-document] upload response:', JSON.stringify(response.data?.createFieldDocument))\n }\n\n await this._loadDocuments()\n await this._loadCounts()\n notify({ message: `${files.length}개 파일이 업로드되었습니다.` })\n } finally {\n this.uploading = false\n this.uploadingFile = ''\n }\n }\n\n private async _deleteDocuments() {\n if (!this.selectedDocIds.size) {\n notify({ message: '삭제할 문서를 선택해주세요.', level: 'info' })\n return\n }\n\n if (!confirm('선택한 문서를 삭제하시겠습니까?')) return\n\n const ids = Array.from(this.selectedDocIds)\n\n const response = await client.mutate({\n mutation: gql`\n mutation DeleteFieldDocuments($ids: [String!]!) {\n deleteFieldDocuments(ids: $ids)\n }\n `,\n variables: { ids }\n })\n\n if (!response.errors) {\n this.selectedDocIds = new Set()\n await this._loadDocuments()\n await this._loadCounts()\n notify({ message: '삭제되었습니다.' })\n }\n }\n\n private _onFolderDragOver(e: DragEvent, code: string) {\n const types = e.dataTransfer?.types || []\n if (types.includes('application/x-field-document-ids')) {\n e.preventDefault()\n this.dragOverItem = code\n\n // 대분류/중분류 위에 hover 시 자동 확장\n if (code.length === 2) {\n const major = FIELD_DOCUMENT_CLASSIFICATIONS.find(m => m.code === code)\n if (major && this.selectedMajor?.code !== code) {\n clearTimeout(this._expandTimeout)\n this._expandTimeout = setTimeout(() => this._selectMajor(major), 500)\n }\n } else if (code.length === 4) {\n const middles = this.selectedMajor?.children || []\n const middle = middles.find(m => m.code === code)\n if (middle && this.selectedMiddle?.code !== code) {\n clearTimeout(this._expandTimeout)\n this._expandTimeout = setTimeout(() => {\n this.selectedMiddle = middle\n this.selectedMinor = null\n }, 500)\n }\n }\n }\n }\n\n private _expandTimeout: any\n\n private async _onFolderDrop(e: DragEvent, code: string) {\n e.preventDefault()\n this.dragOverItem = ''\n clearTimeout(this._expandTimeout)\n\n const idsJson = e.dataTransfer?.getData('application/x-field-document-ids')\n if (!idsJson) return\n\n const ids: string[] = JSON.parse(idsJson)\n\n // 소분류 코드에만 이동 가능\n if (code.length !== 6) {\n notify({ message: '소분류 폴더에만 이동할 수 있습니다.', level: 'info' })\n return\n }\n\n const response = await client.mutate({\n mutation: gql`\n mutation MoveFieldDocuments($ids: [String!]!, $targetCode: String!) {\n moveFieldDocuments(ids: $ids, targetCode: $targetCode)\n }\n `,\n variables: { ids, targetCode: code }\n })\n\n if (!response.errors) {\n const path = findClassificationPath(code)\n notify({ message: `${ids.length}개 문서가 \"${path.minor?.name || code}\" 폴더로 이동되었습니다.` })\n await this._loadDocuments()\n await this._loadCounts()\n }\n }\n\n private async _onDocumentsChanged(e: CustomEvent) {\n const files = e.detail?.files as File[]\n console.log(\n '[field-document] drop received:',\n files?.map(f => f.name),\n 'code:',\n this.selectedMinor?.code\n )\n if (files?.length && this.selectedMinor?.code) {\n await this._uploadFiles(files, this.selectedMinor.code)\n } else {\n await this._loadDocuments()\n }\n }\n\n private _showTooltip(e: MouseEvent, text: string) {\n this._tooltipText = text\n const rect = this.getBoundingClientRect()\n this._tooltipX = e.clientX - rect.left\n this._tooltipY = e.clientY - rect.top\n }\n}\n"]}
@@ -3,6 +3,7 @@ import '@material/web/icon/icon.js';
3
3
  import '@operato/input/ox-input-signature.js';
4
4
  import './comment-list-popup';
5
5
  import './attachment-list-popup';
6
+ import './kcs-criteria-popup';
6
7
  import '../../stt/speech-to-text';
7
8
  export declare const enum ProjectType {
8
9
  DSSP = "DSSP",
@@ -12,6 +12,7 @@ import { store, connect } from '@operato/shell';
12
12
  import { openPopup } from '@operato/layout';
13
13
  import './comment-list-popup';
14
14
  import './attachment-list-popup';
15
+ import './kcs-criteria-popup';
15
16
  import '../../stt/speech-to-text';
16
17
  import { parseSpeechCommand } from '../../stt/stt-utils';
17
18
  import { notify } from '@operato/layout';
@@ -34,6 +35,9 @@ let ChecklistView = class ChecklistView extends connect(store)(LitElement) {
34
35
  this.isListening = false;
35
36
  this._tooltip = null;
36
37
  this._kcsDetail = null;
38
+ this._kcsDetailItem = '';
39
+ this._siteSpecDetail = null;
40
+ this._siteSpecDetailItem = '';
37
41
  this._onStartSTT = (e) => {
38
42
  e.preventDefault();
39
43
  const stt = this.renderRoot.querySelector('#stt');
@@ -48,6 +52,10 @@ let ChecklistView = class ChecklistView extends connect(store)(LitElement) {
48
52
  stt === null || stt === void 0 ? void 0 : stt.stopListening();
49
53
  }
50
54
  };
55
+ this._hideSiteSpecDetail = () => {
56
+ this._siteSpecDetail = null;
57
+ this.requestUpdate();
58
+ };
51
59
  this._hideKcsDetail = () => {
52
60
  this._kcsDetail = null;
53
61
  this.requestUpdate();
@@ -163,21 +171,21 @@ let ChecklistView = class ChecklistView extends connect(store)(LitElement) {
163
171
  return html `
164
172
  ${this.mode == "EDITOR" /* ChecklistMode.EDITOR */
165
173
  ? html `
166
- <speech-to-text id="stt"></speech-to-text>
167
- <md-fab
168
- class="stt-fab"
169
- ?active=${this.isListening}
170
- @mousedown=${this._onStartSTT}
171
- @mouseup=${this._onStopSTT}
172
- @mouseleave=${this._onStopSTT}
173
- @touchstart=${this._onStartSTT}
174
- @touchend=${this._onStopSTT}
175
- ?disabled=${false}
176
- .label=${this.isListening ? '말씀하세요...' : '길게 눌러서 음성 인식'}
177
- >
178
- <md-icon slot="icon">mic</md-icon>
179
- </md-fab>
180
- `
174
+ <speech-to-text id="stt"></speech-to-text>
175
+ <md-fab
176
+ class="stt-fab"
177
+ ?active=${this.isListening}
178
+ @mousedown=${this._onStartSTT}
179
+ @mouseup=${this._onStopSTT}
180
+ @mouseleave=${this._onStopSTT}
181
+ @touchstart=${this._onStartSTT}
182
+ @touchend=${this._onStopSTT}
183
+ ?disabled=${false}
184
+ .label=${this.isListening ? '말씀하세요...' : '길게 눌러서 음성 인식'}
185
+ >
186
+ <md-icon slot="icon">mic</md-icon>
187
+ </md-fab>
188
+ `
181
189
  : ''}
182
190
 
183
191
  <div title-row>
@@ -199,16 +207,18 @@ let ChecklistView = class ChecklistView extends connect(store)(LitElement) {
199
207
  <tr>
200
208
  ${this.projectType == "DSSP" /* ProjectType.DSSP */
201
209
  ? html `
202
- <th>담당자</th>
203
- <td>${((_k = this.manager) === null || _k === void 0 ? void 0 : _k.name) || ''}</td>
204
- `
210
+ <th>담당자</th>
211
+ <td>${((_k = this.manager) === null || _k === void 0 ? void 0 : _k.name) || ''}</td>
212
+ `
205
213
  : html `
206
- <th>검측 부위</th>
207
- <td>${((_m = (_l = this.checklist) === null || _l === void 0 ? void 0 : _l.inspectionParts) === null || _m === void 0 ? void 0 : _m.join(', ')) || ''}</td>
208
- `}
214
+ <th>검측 부위</th>
215
+ <td>${((_m = (_l = this.checklist) === null || _l === void 0 ? void 0 : _l.inspectionParts) === null || _m === void 0 ? void 0 : _m.join(', ')) || ''}</td>
216
+ `}
209
217
 
210
218
  <th>검측 상태</th>
211
- <td>${(this.failCount > 0 ? BUILDING_INSPECTION_RE_STATUS_DISPLAY : BUILDING_INSPECTION_STATUS_DISPLAY)[this.status]}</td>
219
+ <td>
220
+ ${(this.failCount > 0 ? BUILDING_INSPECTION_RE_STATUS_DISPLAY : BUILDING_INSPECTION_STATUS_DISPLAY)[this.status]}
221
+ </td>
212
222
  </tr>
213
223
  </table>
214
224
 
@@ -237,16 +247,27 @@ let ChecklistView = class ChecklistView extends connect(store)(LitElement) {
237
247
  <tbody>
238
248
  ${processedItems.map(({ item, showMainTypeCell, mainTypeRowspan, showDetailTypeCell, detailTypeRowspan }, idx) => {
239
249
  var _a;
240
- const recs = ((_a = [item.recommendation1, item.recommendation2, item.recommendation3, item.recommendation4, item.recommendation5]) === null || _a === void 0 ? void 0 : _a.filter(r => r)) || [];
250
+ const recs = ((_a = [
251
+ item.recommendation1,
252
+ item.recommendation2,
253
+ item.recommendation3,
254
+ item.recommendation4,
255
+ item.recommendation5
256
+ ]) === null || _a === void 0 ? void 0 : _a.filter(r => r)) || [];
241
257
  const hasRecs = recs.length > 0;
242
258
  const kcs = this._parseKcs(item.kcsCriteria);
243
259
  const hasKcs = !!kcs;
260
+ const siteSpec = item.siteSpecCriteria || item.inspctionCriteria || '';
244
261
  return html ` <tr>
245
262
  ${showMainTypeCell
246
- ? html `<td main-type bold rowspan="${mainTypeRowspan}">${CHECKLIST_MAIN_TYPE_LIST[item.mainType] || item.mainType}</td>`
263
+ ? html `<td main-type bold rowspan="${mainTypeRowspan}">
264
+ ${CHECKLIST_MAIN_TYPE_LIST[item.mainType] || item.mainType}
265
+ </td>`
247
266
  : ''}
248
267
  ${hasAnyDetailType
249
- ? showDetailTypeCell ? html ` <td bold rowspan="${detailTypeRowspan}">${item.detailType}</td> ` : ''
268
+ ? showDetailTypeCell
269
+ ? html ` <td bold rowspan="${detailTypeRowspan}">${item.detailType}</td> `
270
+ : ''
250
271
  : ''}
251
272
 
252
273
  <td
@@ -254,17 +275,21 @@ let ChecklistView = class ChecklistView extends connect(store)(LitElement) {
254
275
  @mouseenter=${hasRecs ? (e) => this._showRecTooltip(e, item.id || idx, recs) : null}
255
276
  @mouseleave=${hasRecs ? () => this._hideRecTooltip() : null}
256
277
  >
257
- ${idx + 1}. ${item.name} ${hasRecs ? html `<md-icon style="font-size:14px;vertical-align:middle;color:#2e79be;">info</md-icon>` : ''}
278
+ ${idx + 1}. ${item.name}
279
+ ${hasRecs ? html `<md-icon style="font-size:14px;vertical-align:middle;color:#2e79be;">info</md-icon>` : ''}
258
280
  </td>
259
- <td
260
- kcs-criteria
261
- ?has-kcs=${hasKcs}
262
- @click=${hasKcs ? () => this._showKcsDetail(kcs) : null}
263
- >
281
+ <td kcs-criteria ?has-kcs=${hasKcs} @click=${hasKcs ? () => this._showKcsDetail(kcs, item.name) : null}>
264
282
  ${(kcs === null || kcs === void 0 ? void 0 : kcs.file_label) || ''}
265
283
  ${hasKcs ? html `<md-icon style="font-size:14px;vertical-align:middle;color:#2e79be;">search</md-icon>` : ''}
266
284
  </td>
267
- <td site-spec-criteria>${item.siteSpecCriteria || item.inspctionCriteria || ''}</td>
285
+ <td
286
+ site-spec-criteria
287
+ ?has-site-spec=${!!siteSpec}
288
+ @click=${siteSpec ? () => this._showSiteSpecDetail(siteSpec, item.name) : null}
289
+ >
290
+ ${this._summarize(siteSpec)}
291
+ ${siteSpec ? html `<md-icon style="font-size:14px;vertical-align:middle;color:#2e79be;">search</md-icon>` : ''}
292
+ </td>
268
293
  <td radio>
269
294
  <md-radio
270
295
  item-id=${item.id}
@@ -400,31 +425,43 @@ let ChecklistView = class ChecklistView extends connect(store)(LitElement) {
400
425
  <div>- 검사항목 및 검사기준은 각 공종별로 감리원과 협의하여 작성할 것</div>
401
426
  </div>
402
427
 
403
- ${this._tooltip ? html `
404
- <div recommendation-tooltip style="left:${this._tooltip.x}px;top:${this._tooltip.y}px;">
405
- <div tooltip-title>추천 검사 항목</div>
406
- ${this._tooltip.recs.map(r => html `<div tooltip-item>${r}</div>`)}
407
- </div>
408
- ` : ''}
409
-
410
- ${this._kcsDetail ? html `
411
- <div kcs-detail-backdrop @click=${(e) => { if (e.target === e.currentTarget)
412
- this._hideKcsDetail(); }}>
413
- <div kcs-detail-popup>
414
- <div kcs-detail-header>
415
- <span>KCS 시방서 기준</span>
416
- <md-icon @click=${this._hideKcsDetail}>close</md-icon>
417
- </div>
418
- ${this._kcsDetail.file_label ? html `<div kcs-detail-label>${this._kcsDetail.file_label}</div>` : ''}
419
- ${this._kcsDetail.clause_no || this._kcsDetail.clause_title
420
- ? html `<div kcs-detail-clause>${[this._kcsDetail.clause_no, this._kcsDetail.clause_title].filter(Boolean).join(' ')}</div>`
428
+ ${this._tooltip
429
+ ? html `
430
+ <div recommendation-tooltip style="left:${this._tooltip.x}px;top:${this._tooltip.y}px;">
431
+ <div tooltip-title>추천 검사 항목</div>
432
+ ${this._tooltip.recs.map(r => html `<div tooltip-item>${r}</div>`)}
433
+ </div>
434
+ `
435
+ : ''}
436
+ ${this._kcsDetail
437
+ ? html `<kcs-criteria-popup
438
+ .kcs=${this._kcsDetail}
439
+ .itemName=${this._kcsDetailItem}
440
+ @close=${this._hideKcsDetail}
441
+ ></kcs-criteria-popup>`
442
+ : ''}
443
+ ${this._siteSpecDetail
444
+ ? html `<kcs-criteria-popup
445
+ .popupTitle=${'현장 시방서 기준'}
446
+ .kcs=${{ text: this._siteSpecDetail }}
447
+ .itemName=${this._siteSpecDetailItem}
448
+ @close=${this._hideSiteSpecDetail}
449
+ ></kcs-criteria-popup>`
421
450
  : ''}
422
- <div kcs-detail-text>${this._kcsDetail.text || ''}</div>
423
- </div>
424
- </div>
425
- ` : ''}
426
451
  `;
427
452
  }
453
+ // 본문 앞 20글자 요약 (그 뒤는 ... 처리)
454
+ _summarize(text, length = 20) {
455
+ if (!text)
456
+ return '';
457
+ return text.length > length ? `${text.slice(0, length)}...` : text;
458
+ }
459
+ // 현장 시방서 기준 상세(본문 전체)를 팝업으로 표시
460
+ _showSiteSpecDetail(text, itemName = '') {
461
+ this._siteSpecDetail = text;
462
+ this._siteSpecDetailItem = itemName;
463
+ this.requestUpdate();
464
+ }
428
465
  // KCS 기준 JSON 문자열을 오브젝트로 파싱 (file_label/clause/text 포함)
429
466
  _parseKcs(kcsCriteria) {
430
467
  if (!kcsCriteria)
@@ -437,9 +474,10 @@ let ChecklistView = class ChecklistView extends connect(store)(LitElement) {
437
474
  return null;
438
475
  }
439
476
  }
440
- // KCS 기준 상세(text)를 작은 팝업으로 표시
441
- _showKcsDetail(kcs) {
477
+ // KCS 기준 상세(text)를 팝업으로 표시
478
+ _showKcsDetail(kcs, itemName = '') {
442
479
  this._kcsDetail = kcs;
480
+ this._kcsDetailItem = itemName;
443
481
  this.requestUpdate();
444
482
  }
445
483
  _onChangeConfirmStatus(e) {
@@ -833,58 +871,12 @@ ChecklistView.styles = [
833
871
  td[kcs-criteria][has-kcs]:hover {
834
872
  background-color: #f0f7ff !important;
835
873
  }
836
- td[site-spec-criteria] {
837
- white-space: pre-wrap;
838
- }
839
-
840
- /* KCS 시방서 기준 상세 팝업 */
841
- div[kcs-detail-backdrop] {
842
- position: fixed;
843
- inset: 0;
844
- background: rgba(0, 0, 0, 0.4);
845
- z-index: 1100;
846
- display: flex;
847
- align-items: center;
848
- justify-content: center;
849
- }
850
- div[kcs-detail-popup] {
851
- background: #fff;
852
- border-radius: 8px;
853
- box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
854
- width: 480px;
855
- max-width: 90vw;
856
- max-height: 70vh;
857
- overflow-y: auto;
858
- padding: 16px 18px;
859
- color: #333;
860
- }
861
- div[kcs-detail-header] {
862
- display: flex;
863
- align-items: center;
864
- justify-content: space-between;
865
- font-weight: bold;
866
- font-size: 16px;
867
- color: #2e79be;
868
- margin-bottom: 10px;
869
- }
870
- div[kcs-detail-header] md-icon {
874
+ td[site-spec-criteria][has-site-spec] {
871
875
  cursor: pointer;
872
- color: #888;
873
- }
874
- div[kcs-detail-label] {
875
- font-weight: bold;
876
- font-size: 14px;
877
- margin-bottom: 6px;
878
- }
879
- div[kcs-detail-clause] {
880
- font-size: 13px;
881
- color: #666;
882
- margin-bottom: 8px;
876
+ color: #2e79be;
883
877
  }
884
- div[kcs-detail-text] {
885
- font-size: 14px;
886
- line-height: 1.6;
887
- white-space: pre-wrap;
878
+ td[site-spec-criteria][has-site-spec]:hover {
879
+ background-color: #f0f7ff !important;
888
880
  }
889
881
 
890
882
  .stt-fab {