@dssp/project 1.0.0-alpha.8 → 1.0.0-alpha.80

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 (149) hide show
  1. package/dist-client/index.d.ts +1 -0
  2. package/dist-client/index.js +1 -1
  3. package/dist-client/index.js.map +1 -1
  4. package/dist-client/pages/lib/chatbot-widget.d.ts +53 -0
  5. package/dist-client/pages/lib/chatbot-widget.js +631 -0
  6. package/dist-client/pages/lib/chatbot-widget.js.map +1 -0
  7. package/dist-client/pages/lib/select2-component.d.ts +1 -1
  8. package/dist-client/pages/lib/select2-component.js +35 -35
  9. package/dist-client/pages/lib/select2-component.js.map +1 -1
  10. package/dist-client/pages/project/component/pagenation.d.ts +18 -0
  11. package/dist-client/pages/project/component/pagenation.js +142 -0
  12. package/dist-client/pages/project/component/pagenation.js.map +1 -0
  13. package/dist-client/pages/project/component/project-update-header.js +26 -3
  14. package/dist-client/pages/project/component/project-update-header.js.map +1 -1
  15. package/dist-client/pages/project/popup/checklist/task-checklist-attachment-list-popup.d.ts +1 -0
  16. package/dist-client/pages/project/popup/checklist/task-checklist-attachment-list-popup.js +308 -0
  17. package/dist-client/pages/project/popup/checklist/task-checklist-attachment-list-popup.js.map +1 -0
  18. package/dist-client/pages/project/popup/checklist/task-checklist-comment-list-popup.d.ts +1 -0
  19. package/dist-client/pages/project/popup/checklist/task-checklist-comment-list-popup.js +356 -0
  20. package/dist-client/pages/project/popup/checklist/task-checklist-comment-list-popup.js.map +1 -0
  21. package/dist-client/pages/project/popup/checklist/task-checklist-create-popup.d.ts +1 -0
  22. package/dist-client/pages/project/popup/checklist/task-checklist-create-popup.js +681 -0
  23. package/dist-client/pages/project/popup/checklist/task-checklist-create-popup.js.map +1 -0
  24. package/dist-client/pages/project/popup/checklist/task-checklist-view.d.ts +32 -0
  25. package/dist-client/pages/project/popup/checklist/task-checklist-view.js +620 -0
  26. package/dist-client/pages/project/popup/checklist/task-checklist-view.js.map +1 -0
  27. package/dist-client/pages/project/popup/popup-plan-export.js +8 -2
  28. package/dist-client/pages/project/popup/popup-plan-export.js.map +1 -1
  29. package/dist-client/pages/project/popup/{popup-schedule-upload.d.ts → popup-task-upload.d.ts} +1 -1
  30. package/dist-client/pages/project/popup/{popup-schedule-upload.js → popup-task-upload.js} +9 -9
  31. package/dist-client/pages/project/popup/popup-task-upload.js.map +1 -0
  32. package/dist-client/pages/project/project-completed-list.d.ts +5 -0
  33. package/dist-client/pages/project/project-completed-list.js +32 -3
  34. package/dist-client/pages/project/project-completed-list.js.map +1 -1
  35. package/dist-client/pages/project/project-detail.d.ts +6 -0
  36. package/dist-client/pages/project/project-detail.js +222 -89
  37. package/dist-client/pages/project/project-detail.js.map +1 -1
  38. package/dist-client/pages/project/project-list.d.ts +57 -0
  39. package/dist-client/pages/project/project-list.js +80 -9
  40. package/dist-client/pages/project/project-list.js.map +1 -1
  41. package/dist-client/pages/project/project-plan-management.js +3 -1
  42. package/dist-client/pages/project/project-plan-management.js.map +1 -1
  43. package/dist-client/pages/project/project-setting-list.d.ts +7 -0
  44. package/dist-client/pages/project/project-setting-list.js +61 -7
  45. package/dist-client/pages/project/project-setting-list.js.map +1 -1
  46. package/dist-client/pages/project/{project-schedule-list.d.ts → project-task-list.d.ts} +2 -2
  47. package/dist-client/pages/project/{project-schedule-list.js → project-task-list.js} +11 -11
  48. package/dist-client/pages/project/project-task-list.js.map +1 -0
  49. package/dist-client/pages/project/{project-schedule.d.ts → project-task.d.ts} +17 -4
  50. package/dist-client/pages/project/project-task.js +688 -0
  51. package/dist-client/pages/project/project-task.js.map +1 -0
  52. package/dist-client/pages/project/project-update.d.ts +34 -0
  53. package/dist-client/pages/project/project-update.js +505 -35
  54. package/dist-client/pages/project/project-update.js.map +1 -1
  55. package/dist-client/pages/resource/construction-type-management.js +14 -0
  56. package/dist-client/pages/resource/construction-type-management.js.map +1 -1
  57. package/dist-client/pages/resource/resource-list-page.d.ts +1 -2
  58. package/dist-client/pages/resource/resource-list-page.js +1 -2
  59. package/dist-client/pages/resource/resource-list-page.js.map +1 -1
  60. package/dist-client/pages/task/task-list-page.d.ts +1 -2
  61. package/dist-client/pages/task/task-list-page.js +1 -2
  62. package/dist-client/pages/task/task-list-page.js.map +1 -1
  63. package/dist-client/pages/task-resource/task-resource-list-page.d.ts +1 -2
  64. package/dist-client/pages/task-resource/task-resource-list-page.js +1 -2
  65. package/dist-client/pages/task-resource/task-resource-list-page.js.map +1 -1
  66. package/dist-client/route.d.ts +1 -1
  67. package/dist-client/route.js +4 -4
  68. package/dist-client/route.js.map +1 -1
  69. package/dist-client/tsconfig.tsbuildinfo +1 -1
  70. package/dist-server/controllers/parse-excel.js.map +1 -1
  71. package/dist-server/migrations/1723861466414-seed-codes.js +1 -1
  72. package/dist-server/migrations/1723861466414-seed-codes.js.map +1 -1
  73. package/dist-server/service/construction-type/construction-type-query.d.ts +2 -2
  74. package/dist-server/service/construction-type/construction-type-query.js +5 -10
  75. package/dist-server/service/construction-type/construction-type-query.js.map +1 -1
  76. package/dist-server/service/construction-type/construction-type-type.d.ts +1 -0
  77. package/dist-server/service/construction-type/construction-type-type.js +4 -0
  78. package/dist-server/service/construction-type/construction-type-type.js.map +1 -1
  79. package/dist-server/service/construction-type/construction-type.d.ts +1 -0
  80. package/dist-server/service/construction-type/construction-type.js +5 -0
  81. package/dist-server/service/construction-type/construction-type.js.map +1 -1
  82. package/dist-server/service/index.d.ts +2 -2
  83. package/dist-server/service/index.js +5 -2
  84. package/dist-server/service/index.js.map +1 -1
  85. package/dist-server/service/inspection-drawing-type/inspection-drawing-type-query.d.ts +2 -2
  86. package/dist-server/service/inspection-drawing-type/inspection-drawing-type-query.js +5 -10
  87. package/dist-server/service/inspection-drawing-type/inspection-drawing-type-query.js.map +1 -1
  88. package/dist-server/service/manager/manager-query.d.ts +1 -1
  89. package/dist-server/service/manager/manager-query.js +2 -6
  90. package/dist-server/service/manager/manager-query.js.map +1 -1
  91. package/dist-server/service/project/issue-project-code.d.ts +7 -0
  92. package/dist-server/service/project/issue-project-code.js +27 -0
  93. package/dist-server/service/project/issue-project-code.js.map +1 -0
  94. package/dist-server/service/project/project-mutation.d.ts +2 -0
  95. package/dist-server/service/project/project-mutation.js +98 -9
  96. package/dist-server/service/project/project-mutation.js.map +1 -1
  97. package/dist-server/service/project/project-query.d.ts +13 -2
  98. package/dist-server/service/project/project-query.js +138 -13
  99. package/dist-server/service/project/project-query.js.map +1 -1
  100. package/dist-server/service/project/project-type.d.ts +8 -1
  101. package/dist-server/service/project/project-type.js +27 -1
  102. package/dist-server/service/project/project-type.js.map +1 -1
  103. package/dist-server/service/project/project.d.ts +22 -0
  104. package/dist-server/service/project/project.js +80 -2
  105. package/dist-server/service/project/project.js.map +1 -1
  106. package/dist-server/service/resource/resource-mutation.js +5 -6
  107. package/dist-server/service/resource/resource-mutation.js.map +1 -1
  108. package/dist-server/service/resource/resource-query.d.ts +2 -2
  109. package/dist-server/service/resource/resource-query.js +5 -10
  110. package/dist-server/service/resource/resource-query.js.map +1 -1
  111. package/dist-server/service/task/task-query.d.ts +2 -0
  112. package/dist-server/service/task/task-query.js +11 -0
  113. package/dist-server/service/task/task-query.js.map +1 -1
  114. package/dist-server/service/task/task.d.ts +2 -0
  115. package/dist-server/service/task/task.js +6 -0
  116. package/dist-server/service/task/task.js.map +1 -1
  117. package/dist-server/service/task-checklist-binding/index.d.ts +5 -0
  118. package/dist-server/service/task-checklist-binding/index.js +9 -0
  119. package/dist-server/service/task-checklist-binding/index.js.map +1 -0
  120. package/dist-server/service/task-checklist-binding/task-checklist-binding-mutation.d.ts +5 -0
  121. package/dist-server/service/task-checklist-binding/task-checklist-binding-mutation.js +186 -0
  122. package/dist-server/service/task-checklist-binding/task-checklist-binding-mutation.js.map +1 -0
  123. package/dist-server/service/task-checklist-binding/task-checklist-binding-query.d.ts +8 -0
  124. package/dist-server/service/task-checklist-binding/task-checklist-binding-query.js +61 -0
  125. package/dist-server/service/task-checklist-binding/task-checklist-binding-query.js.map +1 -0
  126. package/dist-server/service/task-checklist-binding/task-checklist-binding-type.d.ts +15 -0
  127. package/dist-server/service/task-checklist-binding/task-checklist-binding-type.js +57 -0
  128. package/dist-server/service/task-checklist-binding/task-checklist-binding-type.js.map +1 -0
  129. package/dist-server/service/task-checklist-binding/task-checklist-binding.d.ts +22 -0
  130. package/dist-server/service/task-checklist-binding/task-checklist-binding.js +106 -0
  131. package/dist-server/service/task-checklist-binding/task-checklist-binding.js.map +1 -0
  132. package/dist-server/service/task-resource/task-resource-query.d.ts +2 -2
  133. package/dist-server/service/task-resource/task-resource-query.js +4 -9
  134. package/dist-server/service/task-resource/task-resource-query.js.map +1 -1
  135. package/dist-server/service/worker-type/worker-type-query.d.ts +2 -2
  136. package/dist-server/service/worker-type/worker-type-query.js +5 -10
  137. package/dist-server/service/worker-type/worker-type-query.js.map +1 -1
  138. package/dist-server/tsconfig.tsbuildinfo +1 -1
  139. package/package.json +15 -13
  140. package/things-factory.config.js +3 -3
  141. package/translations/en.json +10 -9
  142. package/translations/ja.json +15 -1
  143. package/translations/ko.json +3 -0
  144. package/translations/ms.json +15 -1
  145. package/translations/zh.json +15 -1
  146. package/dist-client/pages/project/popup/popup-schedule-upload.js.map +0 -1
  147. package/dist-client/pages/project/project-schedule-list.js.map +0 -1
  148. package/dist-client/pages/project/project-schedule.js +0 -407
  149. package/dist-client/pages/project/project-schedule.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chatbot-widget.js","sourceRoot":"","sources":["../../../client/pages/lib/chatbot-widget.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, css } from 'lit'\n\n// API 상수\nconst CHATBOT_API_URL = 'https://korea-uni-chat-ui.ettisoft.com/chat'\n\ninterface SourceItem {\n title: string\n url: string\n}\n\ninterface ChatMessage {\n id: string\n text: string\n isUser: boolean\n timestamp: Date\n sources?: SourceItem[]\n}\n\nexport class ChatbotWidget extends LitElement {\n static styles = css`\n :host {\n position: fixed;\n bottom: 40px;\n right: 20px;\n z-index: 1000;\n }\n\n .chatbot-container {\n position: relative;\n }\n\n .chatbot-icon {\n width: 60px;\n height: 60px;\n background: linear-gradient(135deg, var(--md-sys-color-tertiary, #b85d5a) 0%, var(--md-sys-color-primary) 100%);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n transition: all 0.3s ease;\n border: none;\n outline: none;\n }\n\n .chatbot-icon:hover {\n transform: scale(1.1);\n box-shadow: 0 6px 25px rgba(0, 0, 0, 0.2);\n }\n\n .chatbot-icon svg {\n width: 28px;\n height: 28px;\n fill: white;\n }\n\n .chat-window {\n position: absolute;\n bottom: 80px;\n right: 0;\n width: 350px;\n height: 500px;\n background: white;\n border-radius: 20px;\n box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n transform: translateY(20px) scale(0.95);\n opacity: 0;\n transition: all 0.3s ease;\n border: 1px solid #e1e5e9;\n pointer-events: none; /* 닫혀있을 때 클릭 차단 해제 */\n }\n\n .chat-window.open {\n transform: translateY(0) scale(1);\n opacity: 1;\n pointer-events: auto; /* 열렸을 때 클릭 가능 */\n }\n\n .chat-header {\n background: linear-gradient(135deg, var(--md-sys-color-tertiary, #b85d5a) 0%, var(--md-sys-color-primary) 100%);\n color: white;\n padding: 15px 20px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .chat-header h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n }\n\n .close-btn {\n background: none;\n border: none;\n color: white;\n cursor: pointer;\n font-size: 32px;\n padding: 0;\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n transition: background-color 0.2s ease;\n }\n\n .close-btn:hover {\n background-color: rgba(255, 255, 255, 0.2);\n }\n\n .messages-container {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n display: flex;\n flex-direction: column;\n gap: 15px;\n }\n\n .message {\n display: flex;\n align-items: flex-end;\n gap: 10px;\n max-width: 80%;\n }\n\n .message.user {\n align-self: flex-end;\n flex-direction: row-reverse;\n }\n\n .message.bot {\n align-self: flex-start;\n }\n\n .message-bubble {\n padding: 12px 16px;\n border-radius: 18px;\n font-size: 14px;\n line-height: 1.4;\n word-wrap: break-word;\n position: relative;\n }\n\n .message.user .message-bubble {\n background: linear-gradient(135deg, var(--md-sys-color-tertiary, #b85d5a) 0%, var(--md-sys-color-primary) 100%);\n color: white;\n border-bottom-right-radius: 4px;\n }\n\n .message.bot .message-bubble {\n background: #f1f3f4;\n color: #333;\n border-bottom-left-radius: 4px;\n }\n\n .message-avatar {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: 600;\n flex-shrink: 0;\n }\n\n .message.user .message-avatar {\n background: linear-gradient(135deg, var(--md-sys-color-tertiary, #b85d5a) 0%, var(--md-sys-color-primary) 100%);\n color: white;\n }\n\n .message.bot .message-avatar {\n background: #e8eaf0;\n color: #666;\n }\n\n .input-container {\n padding: 20px;\n border-top: 1px solid #e1e5e9;\n display: flex;\n gap: 10px;\n align-items: center;\n }\n\n .message-input {\n flex: 1;\n border: 1px solid #e1e5e9;\n border-radius: 25px;\n padding: 12px 16px;\n font-size: 14px;\n outline: none;\n transition: border-color 0.2s ease;\n }\n\n .message-input:focus {\n border-color: var(--md-sys-color-primary);\n }\n\n .send-btn {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: linear-gradient(135deg, var(--md-sys-color-tertiary, #b85d5a) 0%, var(--md-sys-color-primary) 100%);\n border: none;\n color: white;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n }\n\n .send-btn:hover:not(:disabled) {\n transform: scale(1.05);\n }\n\n .send-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .loading-indicator {\n display: flex;\n align-items: center;\n gap: 8px;\n color: #666;\n font-size: 12px;\n }\n\n .loading-dots {\n display: flex;\n gap: 4px;\n }\n\n .loading-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--md-sys-color-primary);\n animation: loading 1.4s infinite ease-in-out;\n }\n\n .loading-dot:nth-child(1) {\n animation-delay: -0.32s;\n }\n .loading-dot:nth-child(2) {\n animation-delay: -0.16s;\n }\n\n @keyframes loading {\n 0%,\n 80%,\n 100% {\n transform: scale(0);\n }\n 40% {\n transform: scale(1);\n }\n }\n\n /* 스크롤바 스타일링 */\n .messages-container::-webkit-scrollbar {\n width: 6px;\n }\n\n .messages-container::-webkit-scrollbar-track {\n background: #f1f1f1;\n border-radius: 3px;\n }\n\n .messages-container::-webkit-scrollbar-thumb {\n background: #c1c1c1;\n border-radius: 3px;\n }\n\n .messages-container::-webkit-scrollbar-thumb:hover {\n background: #a8a8a8;\n }\n\n /* 근거 버튼 */\n .evidence-btn {\n margin-top: 8px;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n border: 1px solid #d6daf0;\n background: #ffffff;\n color: #3b4cca;\n border-radius: 14px;\n padding: 6px 10px;\n font-size: 12px;\n cursor: pointer;\n transition:\n background-color 0.2s ease,\n border-color 0.2s ease;\n }\n\n .evidence-btn:hover {\n background-color: #f4f6ff;\n border-color: #c2c8ef;\n }\n\n /* 오버레이 */\n .overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.35);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.2s ease;\n z-index: 1100; /* 챗봇보다 위 */\n }\n\n .overlay.open {\n opacity: 1;\n pointer-events: auto;\n }\n\n .overlay-panel {\n width: min(520px, calc(100vw - 40px));\n max-height: min(70vh, 560px);\n background: #ffffff;\n border-radius: 14px;\n box-shadow: 0 18px 60px rgba(0, 0, 0, 0.18);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n .overlay-header {\n padding: 14px 16px;\n background: linear-gradient(135deg, var(--md-sys-color-tertiary, #b85d5a) 0%, var(--md-sys-color-primary) 100%);\n color: #ffffff;\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .overlay-title {\n font-weight: 600;\n font-size: 16px;\n }\n\n .overlay-close {\n background: none;\n border: none;\n color: #ffffff;\n font-size: 26px;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n cursor: pointer;\n }\n\n .overlay-body {\n padding: 12px 16px 16px 16px;\n overflow-y: auto;\n }\n\n .source-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n .source-item {\n border: 1px solid #e6e9f2;\n border-radius: 10px;\n padding: 10px 12px;\n background: #f9fafc;\n }\n\n .source-link {\n color: #1e3a8a;\n text-decoration: none;\n display: block;\n word-break: break-all;\n }\n\n .source-link:hover {\n text-decoration: underline;\n }\n `\n\n static get properties() {\n return {\n isOpen: { type: Boolean },\n messages: { type: Array },\n inputValue: { type: String },\n isLoading: { type: Boolean },\n isSourcesOpen: { type: Boolean },\n currentSources: { type: Array }\n }\n }\n\n isOpen = false\n messages: ChatMessage[] = []\n inputValue = ''\n isLoading = false\n isSourcesOpen = false\n currentSources: SourceItem[] = []\n\n render() {\n return html`\n <div class=\"chatbot-container\">\n <!-- 챗봇 아이콘 -->\n <button class=\"chatbot-icon\" @click=\"${this.toggleChat}\">\n <svg viewBox=\"0 0 24 24\">\n <path\n d=\"M20 2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h4l4 4 4-4h4c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z\"\n />\n </svg>\n </button>\n\n <!-- 대화창 -->\n <div class=\"chat-window ${this.isOpen ? 'open' : ''}\">\n <!-- 헤더 -->\n <div class=\"chat-header\">\n <h3>챗봇 도우미</h3>\n <button class=\"close-btn\" @click=\"${this.toggleChat}\">×</button>\n </div>\n\n <!-- 메시지 영역 -->\n <div class=\"messages-container\">\n ${this.messages.length === 0\n ? html`\n <div class=\"message bot\">\n <div class=\"message-avatar\">🤖</div>\n <div class=\"message-bubble\">안녕하세요! 무엇을 도와드릴까요?</div>\n </div>\n `\n : ''}\n ${this.messages.map(\n message => html`\n <div class=\"message ${message.isUser ? 'user' : 'bot'}\">\n <div class=\"message-avatar\">${message.isUser ? '👤' : '🤖'}</div>\n <div class=\"message-bubble\">\n ${message.text}\n ${!message.isUser && message.sources && message.sources.length\n ? html`\n <div>\n <button class=\"evidence-btn\" @click=\"${() => this.openSourcesOverlay(message.sources || [])}\">\n 근거 ${message.sources.length}개 보기\n </button>\n </div>\n `\n : ''}\n </div>\n </div>\n `\n )}\n ${this.isLoading\n ? html`\n <div class=\"message bot\">\n <div class=\"message-avatar\">🤖</div>\n <div class=\"message-bubble\">\n <div class=\"loading-indicator\">\n <span>답변 중</span>\n <div class=\"loading-dots\">\n <div class=\"loading-dot\"></div>\n <div class=\"loading-dot\"></div>\n <div class=\"loading-dot\"></div>\n </div>\n </div>\n </div>\n </div>\n `\n : ''}\n </div>\n\n <!-- 입력 영역 -->\n <div class=\"input-container\">\n <input\n class=\"message-input\"\n type=\"text\"\n placeholder=\"메시지를 입력하세요...\"\n .value=\"${this.inputValue}\"\n @input=\"${(e: Event) => (this.inputValue = (e.target as HTMLInputElement).value)}\"\n @keypress=\"${this.handleKeyPress}\"\n ?disabled=\"${this.isLoading}\"\n />\n <button class=\"send-btn\" @click=\"${this.sendMessage}\" ?disabled=\"${this.isLoading || !this.inputValue.trim()}\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M2.01 21L23 12 2.01 3 2 10l15 2-15 2z\" />\n </svg>\n </button>\n </div>\n </div>\n <!-- 근거 오버레이 -->\n <div class=\"overlay ${this.isSourcesOpen ? 'open' : ''}\" @click=\"${this.closeSourcesOverlay}\">\n <div class=\"overlay-panel\" @click=\"${(e: Event) => e.stopPropagation()}\">\n <div class=\"overlay-header\">\n <div class=\"overlay-title\">근거 ${this.currentSources.length}개</div>\n <button class=\"overlay-close\" @click=\"${this.closeSourcesOverlay}\">×</button>\n </div>\n <div class=\"overlay-body\">\n <ul class=\"source-list\">\n ${this.currentSources.map(\n (s, idx) =>\n html` <li class=\"source-item\">\n <a class=\"source-link\" href=\"${s.url}\" target=\"_blank\" rel=\"noopener noreferrer\"\n >[#${idx + 1}] ${s.title}</a\n >\n </li>`\n )}\n </ul>\n </div>\n </div>\n </div>\n </div>\n `\n }\n\n private boundHandleEscapeKey = this.handleEscapeKey.bind(this)\n\n connectedCallback() {\n super.connectedCallback()\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n // 컴포넌트가 제거될 때 이벤트 리스너 정리\n document.removeEventListener('keydown', this.boundHandleEscapeKey)\n }\n\n handleEscapeKey(event: KeyboardEvent) {\n if (event.key === 'Escape') {\n if (this.isSourcesOpen) {\n this.isSourcesOpen = false\n } else if (this.isOpen) {\n this.isOpen = false\n }\n }\n }\n\n toggleChat() {\n this.isOpen = !this.isOpen\n if (this.isOpen) {\n // 챗봇이 열릴 때 ESC 키 이벤트 리스너 추가\n document.addEventListener('keydown', this.boundHandleEscapeKey)\n // 챗봇이 열릴 때 스크롤을 맨 아래로\n this.requestUpdate()\n setTimeout(() => this.scrollToBottom(), 100)\n } else {\n // 챗봇이 닫힐 때 ESC 키 이벤트 리스너 제거\n document.removeEventListener('keydown', this.boundHandleEscapeKey)\n this.isSourcesOpen = false\n this.currentSources = []\n }\n }\n\n scrollToBottom() {\n const messagesContainer = this.shadowRoot?.querySelector('.messages-container') as HTMLElement\n if (messagesContainer) {\n messagesContainer.scrollTop = messagesContainer.scrollHeight\n }\n }\n\n async sendMessage() {\n if (!this.inputValue.trim() || this.isLoading) return\n\n const userMessage: ChatMessage = {\n id: Date.now().toString(),\n text: this.inputValue.trim(),\n isUser: true,\n timestamp: new Date()\n }\n\n this.messages = [...this.messages, userMessage]\n const messageText = this.inputValue.trim()\n this.inputValue = ''\n this.isLoading = true\n\n // 사용자 메시지 추가 후 스크롤을 맨 아래로\n setTimeout(() => this.scrollToBottom(), 50)\n\n // 포커스 유지를 위해 input 요소 참조 저장\n const input = this.shadowRoot?.querySelector('.message-input') as HTMLInputElement\n\n try {\n // API 호출\n const response = await fetch(CHATBOT_API_URL, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({ query: messageText, top_k: 6 })\n })\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`)\n }\n\n const data = await response.json()\n\n const botMessage: ChatMessage = {\n id: (Date.now() + 1).toString(),\n text: data?.answer?.trim() || '죄송합니다. 응답을 처리할 수 없습니다.',\n isUser: false,\n timestamp: new Date(),\n sources: data?.sources || []\n }\n\n this.messages = [...this.messages, botMessage]\n // 봇 메시지 추가 후 스크롤을 맨 아래로\n setTimeout(() => this.scrollToBottom(), 50)\n } catch (error) {\n const errorMessage: ChatMessage = {\n id: (Date.now() + 1).toString(),\n text: '죄송합니다. 일시적인 오류가 발생했습니다. 잠시 후 다시 시도해주세요.',\n isUser: false,\n timestamp: new Date()\n }\n this.messages = [...this.messages, errorMessage]\n // 에러 메시지 추가 후 스크롤을 맨 아래로\n setTimeout(() => this.scrollToBottom(), 50)\n } finally {\n this.isLoading = false\n // 로딩 완료 후 포커스 복원\n setTimeout(() => {\n if (input) {\n input.focus()\n }\n }, 100)\n }\n }\n\n openSourcesOverlay(sources: SourceItem[]) {\n if (!sources || sources.length === 0) return\n this.currentSources = sources\n this.isSourcesOpen = true\n }\n\n closeSourcesOverlay() {\n this.isSourcesOpen = false\n this.currentSources = []\n }\n\n handleKeyPress(event: KeyboardEvent) {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault()\n this.sendMessage()\n }\n }\n}\n\ncustomElements.define('chatbot-widget', ChatbotWidget)\n"]}
@@ -12,6 +12,7 @@ export declare class Select2Component extends LitElement {
12
12
  name: string;
13
13
  value: string;
14
14
  } | undefined)[];
15
+ render(): import("lit-html").TemplateResult<1>;
15
16
  connectedCallback(): void;
16
17
  disconnectedCallback(): void;
17
18
  private _handleOutsideClick;
@@ -19,5 +20,4 @@ export declare class Select2Component extends LitElement {
19
20
  private _handleSelect;
20
21
  private _handleRemove;
21
22
  private _dispatchEvent;
22
- render(): import("lit-html").TemplateResult<1>;
23
23
  }
@@ -18,6 +18,37 @@ let Select2Component = class Select2Component extends LitElement {
18
18
  get selectedItems() {
19
19
  return this.selectedValues.map(id => this.options.find(option => option.value === id)).filter(Boolean);
20
20
  }
21
+ render() {
22
+ return html `
23
+ <div select-container>
24
+ <div tags @click="${this._toggleOptions}">${this.placeholder}</div>
25
+ ${this.showOptions
26
+ ? html `
27
+ <div options>
28
+ ${this.options.map(option => html `
29
+ <div
30
+ option
31
+ ?selected=${this.selectedValues.includes(option.value)}
32
+ @click=${() => this._handleSelect(option.value)}
33
+ >
34
+ ${option.name}
35
+ </div>
36
+ `)}
37
+ </div>
38
+ `
39
+ : ''}
40
+ </div>
41
+
42
+ <div selected-tags>
43
+ ${this.selectedItems.map((tag) => html `
44
+ <div tag @click=${() => this._handleRemove(tag.value)}>
45
+ ${tag.name}
46
+ <span tag-close>&times;</span>
47
+ </div>
48
+ `)}
49
+ </div>
50
+ `;
51
+ }
21
52
  connectedCallback() {
22
53
  super.connectedCallback();
23
54
  document.addEventListener('click', this._handleOutsideClick);
@@ -52,42 +83,11 @@ let Select2Component = class Select2Component extends LitElement {
52
83
  composed: true
53
84
  }));
54
85
  }
55
- render() {
56
- return html `
57
- <div select-container>
58
- <div tags @click="${this._toggleOptions}">${this.placeholder}</div>
59
- ${this.showOptions
60
- ? html `
61
- <div options>
62
- ${this.options.map(option => html `
63
- <div
64
- option
65
- ?selected=${this.selectedValues.includes(option.value)}
66
- @click=${() => this._handleSelect(option.value)}
67
- >
68
- ${option.name}
69
- </div>
70
- `)}
71
- </div>
72
- `
73
- : ''}
74
- </div>
75
-
76
- <div selected-tags>
77
- ${this.selectedItems.map((tag) => html `
78
- <div tag @click=${() => this._handleRemove(tag.value)}>
79
- ${tag.name}
80
- <span tag-close>&times;</span>
81
- </div>
82
- `)}
83
- </div>
84
- `;
85
- }
86
86
  };
87
87
  Select2Component.styles = css `
88
88
  div[select-container] {
89
89
  position: relative;
90
- border: 1px solid rgba(51,51,51,.20);
90
+ border: 1px solid rgba(51, 51, 51, 0.2);
91
91
  border-radius: 5px;
92
92
  padding: var(--spacing-small, 4px) var(--spacing-medium, 8px);
93
93
  font-size: 14px;
@@ -110,7 +110,7 @@ Select2Component.styles = css `
110
110
  min-width: 50%;
111
111
  border: 1px solid #ccc;
112
112
  background-color: var(--md-sys-color-surface-tint);
113
- color:var(--md-sys-color-on-primary);
113
+ color: var(--md-sys-color-on-primary);
114
114
  max-height: 150px;
115
115
  overflow-y: auto;
116
116
  display: block;
@@ -120,7 +120,7 @@ Select2Component.styles = css `
120
120
  div[option] {
121
121
  padding: var(--spacing-small, 4px) var(--spacing-medium, 8px);
122
122
  cursor: pointer;
123
- border-bottom: 1px solid rgba(0,0,0,.4);
123
+ border-bottom: 1px solid rgba(0, 0, 0, 0.4);
124
124
  }
125
125
  div[option]:last-child {
126
126
  border-bottom: none;
@@ -133,7 +133,7 @@ Select2Component.styles = css `
133
133
  div[option][selected] {
134
134
  background-color: var(--md-sys-color-tertiary-container);
135
135
  font-weight: bold;
136
- color:var(--md-sys-color-on-primary);
136
+ color: var(--md-sys-color-on-primary);
137
137
  }
138
138
 
139
139
  div[selected-tags] {
@@ -1 +1 @@
1
- {"version":3,"file":"select2-component.js","sourceRoot":"","sources":["../../../client/pages/lib/select2-component.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, css } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\n@customElement('select2-component')\nexport class Select2Component extends LitElement {\n static styles = css`\n div[select-container] {\n position: relative;\n border: 1px solid rgba(51,51,51,.20);\n border-radius: 5px;\n padding: var(--spacing-small, 4px) var(--spacing-medium, 8px);\n font-size: 14px;\n color: var(--md-sys-color-primary);\n }\n div[select-container]:focus {\n border: 1px solid #1f7fd9;\n }\n\n div[dropdown] {\n border: 1px solid #ccc;\n padding: var(--spacing-small, 4px);\n cursor: pointer;\n }\n\n div[options] {\n position: absolute;\n left: 0;\n top: 30px;\n min-width: 50%;\n border: 1px solid #ccc;\n background-color: var(--md-sys-color-surface-tint);\n color:var(--md-sys-color-on-primary);\n max-height: 150px;\n overflow-y: auto;\n display: block;\n z-index: 1;\n }\n\n div[option] {\n padding: var(--spacing-small, 4px) var(--spacing-medium, 8px);\n cursor: pointer;\n border-bottom: 1px solid rgba(0,0,0,.4);\n }\n div[option]:last-child {\n border-bottom: none;\n }\n\n div[option]:hover {\n background-color: var(--md-sys-color-tertiary-container);\n }\n\n div[option][selected] {\n background-color: var(--md-sys-color-tertiary-container);\n font-weight: bold;\n color:var(--md-sys-color-on-primary);\n }\n\n div[selected-tags] {\n display: flex;\n flex-wrap: wrap;\n gap: var(--spacing-small, 4px);\n margin-top: var(--spacing-small, 4px);\n }\n\n div[tag] {\n background-color: #2e79be;\n color: white;\n padding: var(--spacing-tiny, 2px) var(--spacing-medium, 8px);\n border-radius: 20px;\n font-size: 12px;\n display: inline-flex;\n align-items: center;\n cursor: pointer;\n }\n\n span[tag-close] {\n margin-left: var(--spacing-small, 4px);\n }\n `\n\n @property({ type: String }) placeholder: string = ''\n @property({ type: Array }) options: Array<{ name: string; value: string }> = []\n @property({ type: Array }) selectedValues: string[] = []\n\n @state() showOptions: boolean = false\n\n get selectedItems() {\n return this.selectedValues.map(id => this.options.find(option => option.value === id)).filter(Boolean)\n }\n\n connectedCallback() {\n super.connectedCallback()\n document.addEventListener('click', this._handleOutsideClick)\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n document.removeEventListener('click', this._handleOutsideClick)\n }\n\n private _handleOutsideClick = (event: MouseEvent) => {\n const path = event.composedPath()\n if (!path.includes(this)) {\n this.showOptions = false\n }\n }\n\n private _toggleOptions() {\n this.showOptions = !this.showOptions\n }\n\n private _handleSelect(optionValue: string) {\n if (this.selectedValues.includes(optionValue)) {\n // 이미 선택된 옵션을 선택한 경우 해제\n this.selectedValues = this.selectedValues.filter(value => value !== optionValue)\n } else {\n // 선택되지 않은 옵션 추가\n this.selectedValues = [...this.selectedValues, optionValue]\n }\n\n this.showOptions = false\n this._dispatchEvent(this.selectedValues)\n }\n\n private _handleRemove(tagValue: string) {\n this.selectedValues = this.selectedValues.filter(value => value !== tagValue)\n this._dispatchEvent(this.selectedValues)\n }\n\n private _dispatchEvent(selectedValues: string[]) {\n this.dispatchEvent(\n new CustomEvent('selection-changed', {\n detail: { selectedValues }, // ID 배열을 부모로 전달\n bubbles: true,\n composed: true\n })\n )\n }\n\n render() {\n return html`\n <div select-container>\n <div tags @click=\"${this._toggleOptions}\">${this.placeholder}</div>\n ${this.showOptions\n ? html`\n <div options>\n ${this.options.map(\n option => html`\n <div\n option\n ?selected=${this.selectedValues.includes(option.value)}\n @click=${() => this._handleSelect(option.value)}\n >\n ${option.name}\n </div>\n `\n )}\n </div>\n `\n : ''}\n </div>\n\n <div selected-tags>\n ${this.selectedItems.map(\n (tag: any) => html`\n <div tag @click=${() => this._handleRemove(tag.value)}>\n ${tag!.name}\n <span tag-close>&times;</span>\n </div>\n `\n )}\n </div>\n `\n }\n}\n"]}
1
+ {"version":3,"file":"select2-component.js","sourceRoot":"","sources":["../../../client/pages/lib/select2-component.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, css } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\n@customElement('select2-component')\nexport class Select2Component extends LitElement {\n static styles = css`\n div[select-container] {\n position: relative;\n border: 1px solid rgba(51, 51, 51, 0.2);\n border-radius: 5px;\n padding: var(--spacing-small, 4px) var(--spacing-medium, 8px);\n font-size: 14px;\n color: var(--md-sys-color-primary);\n }\n div[select-container]:focus {\n border: 1px solid #1f7fd9;\n }\n\n div[dropdown] {\n border: 1px solid #ccc;\n padding: var(--spacing-small, 4px);\n cursor: pointer;\n }\n\n div[options] {\n position: absolute;\n left: 0;\n top: 30px;\n min-width: 50%;\n border: 1px solid #ccc;\n background-color: var(--md-sys-color-surface-tint);\n color: var(--md-sys-color-on-primary);\n max-height: 150px;\n overflow-y: auto;\n display: block;\n z-index: 1;\n }\n\n div[option] {\n padding: var(--spacing-small, 4px) var(--spacing-medium, 8px);\n cursor: pointer;\n border-bottom: 1px solid rgba(0, 0, 0, 0.4);\n }\n div[option]:last-child {\n border-bottom: none;\n }\n\n div[option]:hover {\n background-color: var(--md-sys-color-tertiary-container);\n }\n\n div[option][selected] {\n background-color: var(--md-sys-color-tertiary-container);\n font-weight: bold;\n color: var(--md-sys-color-on-primary);\n }\n\n div[selected-tags] {\n display: flex;\n flex-wrap: wrap;\n gap: var(--spacing-small, 4px);\n margin-top: var(--spacing-small, 4px);\n }\n\n div[tag] {\n background-color: #2e79be;\n color: white;\n padding: var(--spacing-tiny, 2px) var(--spacing-medium, 8px);\n border-radius: 20px;\n font-size: 12px;\n display: inline-flex;\n align-items: center;\n cursor: pointer;\n }\n\n span[tag-close] {\n margin-left: var(--spacing-small, 4px);\n }\n `\n\n @property({ type: String }) placeholder: string = ''\n @property({ type: Array }) options: Array<{ name: string; value: string }> = []\n @property({ type: Array }) selectedValues: string[] = []\n\n @state() showOptions: boolean = false\n\n get selectedItems() {\n return this.selectedValues.map(id => this.options.find(option => option.value === id)).filter(Boolean)\n }\n\n render() {\n return html`\n <div select-container>\n <div tags @click=\"${this._toggleOptions}\">${this.placeholder}</div>\n ${this.showOptions\n ? html`\n <div options>\n ${this.options.map(\n option => html`\n <div\n option\n ?selected=${this.selectedValues.includes(option.value)}\n @click=${() => this._handleSelect(option.value)}\n >\n ${option.name}\n </div>\n `\n )}\n </div>\n `\n : ''}\n </div>\n\n <div selected-tags>\n ${this.selectedItems.map(\n (tag: any) => html`\n <div tag @click=${() => this._handleRemove(tag.value)}>\n ${tag!.name}\n <span tag-close>&times;</span>\n </div>\n `\n )}\n </div>\n `\n }\n\n connectedCallback() {\n super.connectedCallback()\n document.addEventListener('click', this._handleOutsideClick)\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n document.removeEventListener('click', this._handleOutsideClick)\n }\n\n private _handleOutsideClick = (event: MouseEvent) => {\n const path = event.composedPath()\n if (!path.includes(this)) {\n this.showOptions = false\n }\n }\n\n private _toggleOptions() {\n this.showOptions = !this.showOptions\n }\n\n private _handleSelect(optionValue: string) {\n if (this.selectedValues.includes(optionValue)) {\n // 이미 선택된 옵션을 선택한 경우 해제\n this.selectedValues = this.selectedValues.filter(value => value !== optionValue)\n } else {\n // 선택되지 않은 옵션 추가\n this.selectedValues = [...this.selectedValues, optionValue]\n }\n\n this.showOptions = false\n this._dispatchEvent(this.selectedValues)\n }\n\n private _handleRemove(tagValue: string) {\n this.selectedValues = this.selectedValues.filter(value => value !== tagValue)\n this._dispatchEvent(this.selectedValues)\n }\n\n private _dispatchEvent(selectedValues: string[]) {\n this.dispatchEvent(\n new CustomEvent('selection-changed', {\n detail: { selectedValues }, // ID 배열을 부모로 전달\n bubbles: true,\n composed: true\n })\n )\n }\n}\n"]}
@@ -0,0 +1,18 @@
1
+ import '@material/web/button/outlined-button.js';
2
+ import '@material/web/icon/icon.js';
3
+ import { LitElement } from 'lit';
4
+ export declare class PagenationControl extends LitElement {
5
+ static styles: import("lit").CSSResult[];
6
+ currentPage: number;
7
+ totalItems: number;
8
+ pageLimit: number;
9
+ private get totalPages();
10
+ private get pageBlock();
11
+ render(): import("lit-html").TemplateResult<1>;
12
+ private _emitPageChange;
13
+ private _numberButtons;
14
+ private _onFirst;
15
+ private _onPrev;
16
+ private _onNext;
17
+ private _onLast;
18
+ }
@@ -0,0 +1,142 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import '@material/web/button/outlined-button.js';
3
+ import '@material/web/icon/icon.js';
4
+ import { css, html, LitElement } from 'lit';
5
+ import { customElement, property } from 'lit/decorators.js';
6
+ let PagenationControl = class PagenationControl extends LitElement {
7
+ constructor() {
8
+ super(...arguments);
9
+ this.currentPage = 1;
10
+ this.totalItems = 0;
11
+ this.pageLimit = 20;
12
+ }
13
+ get totalPages() {
14
+ const totalPages = Math.ceil((this.totalItems || 0) / (this.pageLimit || 1));
15
+ return Math.max(1, totalPages);
16
+ }
17
+ get pageBlock() {
18
+ const blockSize = 10;
19
+ const blockIndex = Math.floor((this.currentPage - 1) / blockSize);
20
+ const start = blockIndex * blockSize + 1;
21
+ const end = Math.min(start + blockSize - 1, this.totalPages);
22
+ return { start, end };
23
+ }
24
+ render() {
25
+ return html `
26
+ <div pagination>
27
+ <md-outlined-button icon ?disabled=${this.currentPage <= 1} @click=${this._onFirst}>
28
+ <md-icon>first_page</md-icon>
29
+ </md-outlined-button>
30
+ <md-outlined-button icon ?disabled=${this.currentPage <= 1} @click=${this._onPrev}>
31
+ <md-icon>chevron_left</md-icon>
32
+ </md-outlined-button>
33
+
34
+ <div numbers>${this._numberButtons()}</div>
35
+
36
+ <md-outlined-button icon ?disabled=${this.currentPage >= this.totalPages} @click=${this._onNext}>
37
+ <md-icon>chevron_right</md-icon>
38
+ </md-outlined-button>
39
+ <md-outlined-button icon ?disabled=${this.currentPage >= this.totalPages} @click=${this._onLast}>
40
+ <md-icon>last_page</md-icon>
41
+ </md-outlined-button>
42
+ </div>
43
+ `;
44
+ }
45
+ _emitPageChange(nextPage) {
46
+ const bounded = Math.min(Math.max(1, nextPage), this.totalPages);
47
+ if (bounded !== this.currentPage) {
48
+ this.dispatchEvent(new CustomEvent('page-change', {
49
+ detail: { page: bounded },
50
+ bubbles: true,
51
+ composed: true
52
+ }));
53
+ }
54
+ }
55
+ _numberButtons() {
56
+ const { start, end } = this.pageBlock;
57
+ const buttons = [];
58
+ for (let page = start; page <= end; page++) {
59
+ const selected = page === this.currentPage;
60
+ buttons.push(html `<md-outlined-button data-page ?selected=${selected} @click=${() => this._emitPageChange(page)}
61
+ >${page}</md-outlined-button
62
+ >`);
63
+ }
64
+ return buttons;
65
+ }
66
+ _onFirst() {
67
+ this._emitPageChange(1);
68
+ }
69
+ _onPrev() {
70
+ this._emitPageChange(this.currentPage - 1);
71
+ }
72
+ _onNext() {
73
+ this._emitPageChange(this.currentPage + 1);
74
+ }
75
+ _onLast() {
76
+ this._emitPageChange(this.totalPages);
77
+ }
78
+ };
79
+ PagenationControl.styles = [
80
+ css `
81
+ div[pagination] {
82
+ display: flex;
83
+ align-items: center;
84
+ justify-content: center;
85
+ gap: var(--spacing-medium, 8px);
86
+ margin: var(--spacing-large, 12px);
87
+
88
+ div[numbers] {
89
+ display: inline-flex;
90
+ gap: var(--spacing-tiny, 2px);
91
+ }
92
+
93
+ md-icon {
94
+ --md-icon-size: 18px;
95
+ }
96
+
97
+ md-outlined-button {
98
+ --md-outlined-button-container-height: 30px;
99
+ --md-outlined-button-label-text-size: 13px;
100
+ padding: 0 10px;
101
+ }
102
+
103
+ md-outlined-button[selected] {
104
+ --md-outlined-button-label-text-color: #ffffff;
105
+ --md-sys-color-outline: #0595e5;
106
+ background-color: #0595e5;
107
+ }
108
+
109
+ md-outlined-button[icon] {
110
+ min-width: 30px;
111
+ width: 30px;
112
+ padding: 0;
113
+ }
114
+
115
+ md-outlined-button[icon] md-icon {
116
+ margin-top: 5px;
117
+ }
118
+
119
+ md-outlined-button[data-page] {
120
+ min-width: 34px;
121
+ padding: 0 8px;
122
+ }
123
+ }
124
+ `
125
+ ];
126
+ __decorate([
127
+ property({ type: Number }),
128
+ __metadata("design:type", Number)
129
+ ], PagenationControl.prototype, "currentPage", void 0);
130
+ __decorate([
131
+ property({ type: Number }),
132
+ __metadata("design:type", Number)
133
+ ], PagenationControl.prototype, "totalItems", void 0);
134
+ __decorate([
135
+ property({ type: Number }),
136
+ __metadata("design:type", Number)
137
+ ], PagenationControl.prototype, "pageLimit", void 0);
138
+ PagenationControl = __decorate([
139
+ customElement('pagenation-control')
140
+ ], PagenationControl);
141
+ export { PagenationControl };
142
+ //# sourceMappingURL=pagenation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagenation.js","sourceRoot":"","sources":["../../../../client/pages/project/component/pagenation.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/outlined-button.js'\nimport '@material/web/icon/icon.js'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\n@customElement('pagenation-control')\nexport class PagenationControl extends LitElement {\n static styles = [\n css`\n div[pagination] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--spacing-medium, 8px);\n margin: var(--spacing-large, 12px);\n\n div[numbers] {\n display: inline-flex;\n gap: var(--spacing-tiny, 2px);\n }\n\n md-icon {\n --md-icon-size: 18px;\n }\n\n md-outlined-button {\n --md-outlined-button-container-height: 30px;\n --md-outlined-button-label-text-size: 13px;\n padding: 0 10px;\n }\n\n md-outlined-button[selected] {\n --md-outlined-button-label-text-color: #ffffff;\n --md-sys-color-outline: #0595e5;\n background-color: #0595e5;\n }\n\n md-outlined-button[icon] {\n min-width: 30px;\n width: 30px;\n padding: 0;\n }\n\n md-outlined-button[icon] md-icon {\n margin-top: 5px;\n }\n\n md-outlined-button[data-page] {\n min-width: 34px;\n padding: 0 8px;\n }\n }\n `\n ]\n\n @property({ type: Number }) currentPage: number = 1\n @property({ type: Number }) totalItems: number = 0\n @property({ type: Number }) pageLimit: number = 20\n\n private get totalPages(): number {\n const totalPages = Math.ceil((this.totalItems || 0) / (this.pageLimit || 1))\n return Math.max(1, totalPages)\n }\n\n private get pageBlock(): { start: number; end: number } {\n const blockSize = 10\n const blockIndex = Math.floor((this.currentPage - 1) / blockSize)\n const start = blockIndex * blockSize + 1\n const end = Math.min(start + blockSize - 1, this.totalPages)\n return { start, end }\n }\n\n render() {\n return html`\n <div pagination>\n <md-outlined-button icon ?disabled=${this.currentPage <= 1} @click=${this._onFirst}>\n <md-icon>first_page</md-icon>\n </md-outlined-button>\n <md-outlined-button icon ?disabled=${this.currentPage <= 1} @click=${this._onPrev}>\n <md-icon>chevron_left</md-icon>\n </md-outlined-button>\n\n <div numbers>${this._numberButtons()}</div>\n\n <md-outlined-button icon ?disabled=${this.currentPage >= this.totalPages} @click=${this._onNext}>\n <md-icon>chevron_right</md-icon>\n </md-outlined-button>\n <md-outlined-button icon ?disabled=${this.currentPage >= this.totalPages} @click=${this._onLast}>\n <md-icon>last_page</md-icon>\n </md-outlined-button>\n </div>\n `\n }\n\n private _emitPageChange(nextPage: number) {\n const bounded = Math.min(Math.max(1, nextPage), this.totalPages)\n if (bounded !== this.currentPage) {\n this.dispatchEvent(\n new CustomEvent('page-change', {\n detail: { page: bounded },\n bubbles: true,\n composed: true\n })\n )\n }\n }\n\n private _numberButtons() {\n const { start, end } = this.pageBlock\n const buttons = [] as any[]\n for (let page = start; page <= end; page++) {\n const selected = page === this.currentPage\n buttons.push(\n html`<md-outlined-button data-page ?selected=${selected} @click=${() => this._emitPageChange(page)}\n >${page}</md-outlined-button\n >`\n )\n }\n return buttons\n }\n\n private _onFirst() {\n this._emitPageChange(1)\n }\n\n private _onPrev() {\n this._emitPageChange(this.currentPage - 1)\n }\n\n private _onNext() {\n this._emitPageChange(this.currentPage + 1)\n }\n\n private _onLast() {\n this._emitPageChange(this.totalPages)\n }\n}\n"]}
@@ -13,7 +13,11 @@ let ProjectUpdateHeader = class ProjectUpdateHeader extends LitElement {
13
13
  const path = window.location.pathname;
14
14
  return html `
15
15
  <div header>
16
- <h2>${this.title}</h2>
16
+ <h2>
17
+ <md-icon slot="icon" back @click=${() => history.back()}>arrow_back</md-icon>
18
+ ${this.title}
19
+ </h2>
20
+
17
21
  <div button-container>
18
22
  <md-elevated-button green @click=${this._dispatchEvent} ?disabled=${!this.projectId}>
19
23
  <md-icon slot="icon">save</md-icon>정보 저장
@@ -47,10 +51,29 @@ ProjectUpdateHeader.styles = [
47
51
  margin: 0px var(--spacing-large, 12px);
48
52
 
49
53
  h2 {
54
+ display: flex;
55
+ gap: 7px;
50
56
  flex: 1;
51
57
  margin-bottom: var(--spacing-medium, 8px);
52
58
  color: #3f71a0;
53
- font-size:18px;
59
+ font-size: 18px;
60
+
61
+ md-icon[back] {
62
+ background: linear-gradient(135deg, #3f71a0 0%, #5a8cc7 100%);
63
+ color: white;
64
+ padding: 8px;
65
+ border-radius: 50%;
66
+ cursor: pointer;
67
+ box-shadow: 0 2px 8px rgba(63, 113, 160, 0.3);
68
+ width: 14px;
69
+ height: 14px;
70
+ --md-icon-size: 20px;
71
+ }
72
+
73
+ md-icon[back]:hover {
74
+ background: linear-gradient(135deg, #2e5c89 0%, #4a7bb0 100%);
75
+ box-shadow: 0 4px 12px rgba(63, 113, 160, 0.4);
76
+ }
54
77
  }
55
78
  }
56
79
 
@@ -59,7 +82,7 @@ ProjectUpdateHeader.styles = [
59
82
  align-items: center;
60
83
  justify-content: end;
61
84
  flex: 1;
62
- padding-top: var(--spacing-medium, 8px);
85
+ padding-top: var(--spacing-medium, 8px);
63
86
 
64
87
  md-elevated-button {
65
88
  margin: 0 var(--spacing-small, 4px);
@@ -1 +1 @@
1
- {"version":3,"file":"project-update-header.js","sourceRoot":"","sources":["../../../../client/pages/project/component/project-update-header.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AACnC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAGxE,IAAM,mBAAmB,GAAzB,MAAM,mBAAoB,SAAQ,UAAU;IAA5C;;QAgD8B,cAAS,GAAW,EAAE,CAAA;QACtB,UAAK,GAAW,EAAE,CAAA;IAgChD,CAAC;IA9BC,MAAM;QACJ,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAA;QAErC,OAAO,IAAI,CAAA;;cAED,IAAI,CAAC,KAAK;;6CAEqB,IAAI,CAAC,cAAc,cAAc,CAAC,IAAI,CAAC,SAAS;;;;mBAI1E,kBAAkB,IAAI,CAAC,SAAS,EAAE;wBAC7B,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC;;;;;mBAKxD,2BAA2B,IAAI,CAAC,SAAS,EAAE;wBACtC,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,0BAA0B,CAAC;;;;;;KAM/E,CAAA;IACH,CAAC;IAEO,cAAc;QACpB,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,cAAc,CAAC,CAAC,CAAA;IACrD,CAAC;;AA/EM,0BAAM,GAAG;IACd,qBAAqB;IACrB,eAAe;IACf,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAyCF;CACF,AA7CY,CA6CZ;AAE2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;sDAAuB;AACtB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;kDAAmB;AAjD1C,mBAAmB;IADxB,aAAa,CAAC,uBAAuB,CAAC;GACjC,mBAAmB,CAiFxB","sourcesContent":["import '@material/web/icon/icon.js'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { ButtonContainerStyles, ScrollbarStyles } from '@operato/styles'\n\n@customElement('project-update-header')\nclass ProjectUpdateHeader extends LitElement {\n static styles = [\n ButtonContainerStyles,\n ScrollbarStyles,\n css`\n div[header] {\n display: flex;\n margin: 0px var(--spacing-large, 12px);\n\n h2 {\n flex: 1;\n margin-bottom: var(--spacing-medium, 8px);\n color: #3f71a0;\n font-size:18px;\n }\n }\n\n div[button-container] {\n display: flex;\n align-items: center;\n justify-content: end;\n flex: 1;\n padding-top: var(--spacing-medium, 8px); \n\n md-elevated-button {\n margin: 0 var(--spacing-small, 4px);\n\n --md-elevated-button-container-height: 32px;\n --md-elevated-button-label-text-size: 16px;\n --md-elevated-button-container-color: #0595e5;\n\n --md-elevated-button-label-text-color: var(--md-sys-color-on-primary);\n --md-elevated-button-hover-label-text-color: var(--md-sys-color-on-primary);\n --md-elevated-button-pressed-label-text-color: var(--md-sys-color-on-primary);\n --md-elevated-button-focus-label-text-color: var(--md-sys-color-on-primary);\n --md-elevated-button-icon-color: var(--md-sys-color-on-primary);\n --md-elevated-button-hover-icon-color: var(--md-sys-color-on-primary);\n --md-elevated-button-pressed-icon-color: var(--md-sys-color-on-primary);\n --md-elevated-button-focus-icon-color: var(--md-sys-color-on-primary);\n\n &[green] {\n --md-elevated-button-container-color: #42b382;\n }\n }\n }\n `\n ]\n\n @property({ type: String }) projectId: string = ''\n @property({ type: String }) title: string = ''\n\n render() {\n const path = window.location.pathname\n\n return html`\n <div header>\n <h2>${this.title}</h2>\n <div button-container>\n <md-elevated-button green @click=${this._dispatchEvent} ?disabled=${!this.projectId}>\n <md-icon slot=\"icon\">save</md-icon>정보 저장\n </md-elevated-button>\n <md-elevated-button\n href=${`project-update/${this.projectId}`}\n ?disabled=${!this.projectId || path.includes('project-update/')}\n >\n <md-icon slot=\"icon\">assignment</md-icon>프로젝트 정보 수정\n </md-elevated-button>\n <md-elevated-button\n href=${`project-plan-management/${this.projectId}`}\n ?disabled=${!this.projectId || path.includes('project-plan-management/')}\n >\n <md-icon slot=\"icon\">description</md-icon>도면 관리\n </md-elevated-button>\n </div>\n </div>\n `\n }\n\n private _dispatchEvent() {\n this.dispatchEvent(new CustomEvent('custom-click'))\n }\n}\n"]}
1
+ {"version":3,"file":"project-update-header.js","sourceRoot":"","sources":["../../../../client/pages/project/component/project-update-header.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AACnC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAGxE,IAAM,mBAAmB,GAAzB,MAAM,mBAAoB,SAAQ,UAAU;IAA5C;;QAmE8B,cAAS,GAAW,EAAE,CAAA;QACtB,UAAK,GAAW,EAAE,CAAA;IAoChD,CAAC;IAlCC,MAAM;QACJ,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAA;QAErC,OAAO,IAAI,CAAA;;;6CAG8B,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE;YACrD,IAAI,CAAC,KAAK;;;;6CAIuB,IAAI,CAAC,cAAc,cAAc,CAAC,IAAI,CAAC,SAAS;;;;mBAI1E,kBAAkB,IAAI,CAAC,SAAS,EAAE;wBAC7B,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC;;;;;mBAKxD,2BAA2B,IAAI,CAAC,SAAS,EAAE;wBACtC,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,0BAA0B,CAAC;;;;;;KAM/E,CAAA;IACH,CAAC;IAEO,cAAc;QACpB,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,cAAc,CAAC,CAAC,CAAA;IACrD,CAAC;;AAtGM,0BAAM,GAAG;IACd,qBAAqB;IACrB,eAAe;IACf,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA4DF;CACF,AAhEY,CAgEZ;AAE2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;sDAAuB;AACtB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;kDAAmB;AApE1C,mBAAmB;IADxB,aAAa,CAAC,uBAAuB,CAAC;GACjC,mBAAmB,CAwGxB","sourcesContent":["import '@material/web/icon/icon.js'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { ButtonContainerStyles, ScrollbarStyles } from '@operato/styles'\n\n@customElement('project-update-header')\nclass ProjectUpdateHeader extends LitElement {\n static styles = [\n ButtonContainerStyles,\n ScrollbarStyles,\n css`\n div[header] {\n display: flex;\n margin: 0px var(--spacing-large, 12px);\n\n h2 {\n display: flex;\n gap: 7px;\n flex: 1;\n margin-bottom: var(--spacing-medium, 8px);\n color: #3f71a0;\n font-size: 18px;\n\n md-icon[back] {\n background: linear-gradient(135deg, #3f71a0 0%, #5a8cc7 100%);\n color: white;\n padding: 8px;\n border-radius: 50%;\n cursor: pointer;\n box-shadow: 0 2px 8px rgba(63, 113, 160, 0.3);\n width: 14px;\n height: 14px;\n --md-icon-size: 20px;\n }\n\n md-icon[back]:hover {\n background: linear-gradient(135deg, #2e5c89 0%, #4a7bb0 100%);\n box-shadow: 0 4px 12px rgba(63, 113, 160, 0.4);\n }\n }\n }\n\n div[button-container] {\n display: flex;\n align-items: center;\n justify-content: end;\n flex: 1;\n padding-top: var(--spacing-medium, 8px);\n\n md-elevated-button {\n margin: 0 var(--spacing-small, 4px);\n\n --md-elevated-button-container-height: 32px;\n --md-elevated-button-label-text-size: 16px;\n --md-elevated-button-container-color: #0595e5;\n\n --md-elevated-button-label-text-color: var(--md-sys-color-on-primary);\n --md-elevated-button-hover-label-text-color: var(--md-sys-color-on-primary);\n --md-elevated-button-pressed-label-text-color: var(--md-sys-color-on-primary);\n --md-elevated-button-focus-label-text-color: var(--md-sys-color-on-primary);\n --md-elevated-button-icon-color: var(--md-sys-color-on-primary);\n --md-elevated-button-hover-icon-color: var(--md-sys-color-on-primary);\n --md-elevated-button-pressed-icon-color: var(--md-sys-color-on-primary);\n --md-elevated-button-focus-icon-color: var(--md-sys-color-on-primary);\n\n &[green] {\n --md-elevated-button-container-color: #42b382;\n }\n }\n }\n `\n ]\n\n @property({ type: String }) projectId: string = ''\n @property({ type: String }) title: string = ''\n\n render() {\n const path = window.location.pathname\n\n return html`\n <div header>\n <h2>\n <md-icon slot=\"icon\" back @click=${() => history.back()}>arrow_back</md-icon>\n ${this.title}\n </h2>\n\n <div button-container>\n <md-elevated-button green @click=${this._dispatchEvent} ?disabled=${!this.projectId}>\n <md-icon slot=\"icon\">save</md-icon>정보 저장\n </md-elevated-button>\n <md-elevated-button\n href=${`project-update/${this.projectId}`}\n ?disabled=${!this.projectId || path.includes('project-update/')}\n >\n <md-icon slot=\"icon\">assignment</md-icon>프로젝트 정보 수정\n </md-elevated-button>\n <md-elevated-button\n href=${`project-plan-management/${this.projectId}`}\n ?disabled=${!this.projectId || path.includes('project-plan-management/')}\n >\n <md-icon slot=\"icon\">description</md-icon>도면 관리\n </md-elevated-button>\n </div>\n </div>\n `\n }\n\n private _dispatchEvent() {\n this.dispatchEvent(new CustomEvent('custom-click'))\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ import '@material/web/icon/icon.js';