@things-factory/worklist 10.0.18 → 10.1.0

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 (215) hide show
  1. package/dist-client/activity-cells.d.ts +21 -0
  2. package/dist-client/activity-cells.js +117 -0
  3. package/dist-client/activity-cells.js.map +1 -0
  4. package/dist-client/activity-summary-generator.js +57 -11
  5. package/dist-client/activity-summary-generator.js.map +1 -1
  6. package/dist-client/approval-progress.d.ts +18 -0
  7. package/dist-client/approval-progress.js +31 -0
  8. package/dist-client/approval-progress.js.map +1 -0
  9. package/dist-client/bootstrap.js +6 -11
  10. package/dist-client/bootstrap.js.map +1 -1
  11. package/dist-client/chip-filters.d.ts +53 -0
  12. package/dist-client/chip-filters.js +60 -0
  13. package/dist-client/chip-filters.js.map +1 -0
  14. package/dist-client/components/activity-approval-ribon.d.ts +19 -0
  15. package/dist-client/components/activity-approval-ribon.js +50 -126
  16. package/dist-client/components/activity-approval-ribon.js.map +1 -1
  17. package/dist-client/components/activity-fields.d.ts +50 -0
  18. package/dist-client/components/activity-fields.js +393 -0
  19. package/dist-client/components/activity-fields.js.map +1 -0
  20. package/dist-client/components/activity-instance-ribon.d.ts +19 -0
  21. package/dist-client/components/activity-instance-ribon.js +55 -122
  22. package/dist-client/components/activity-instance-ribon.js.map +1 -1
  23. package/dist-client/components/activity-thread-ribon.d.ts +25 -0
  24. package/dist-client/components/activity-thread-ribon.js +64 -121
  25. package/dist-client/components/activity-thread-ribon.js.map +1 -1
  26. package/dist-client/components/activity-thread-timeline.d.ts +14 -2
  27. package/dist-client/components/activity-thread-timeline.js +234 -104
  28. package/dist-client/components/activity-thread-timeline.js.map +1 -1
  29. package/dist-client/components/state-ribon.d.ts +40 -0
  30. package/dist-client/components/state-ribon.js +200 -0
  31. package/dist-client/components/state-ribon.js.map +1 -0
  32. package/dist-client/due.d.ts +16 -0
  33. package/dist-client/due.js +78 -0
  34. package/dist-client/due.js.map +1 -0
  35. package/dist-client/pages/activity/activity-list-page.js +4 -6
  36. package/dist-client/pages/activity/activity-list-page.js.map +1 -1
  37. package/dist-client/pages/activity-approval/activity-approval-list-page.js +2 -1
  38. package/dist-client/pages/activity-approval/activity-approval-list-page.js.map +1 -1
  39. package/dist-client/pages/activity-approval/activity-approval-page.d.ts +52 -5
  40. package/dist-client/pages/activity-approval/activity-approval-page.js +265 -118
  41. package/dist-client/pages/activity-approval/activity-approval-page.js.map +1 -1
  42. package/dist-client/pages/activity-instance/activity-instance-list-page.d.ts +0 -1
  43. package/dist-client/pages/activity-instance/activity-instance-list-page.js +8 -24
  44. package/dist-client/pages/activity-instance/activity-instance-list-page.js.map +1 -1
  45. package/dist-client/pages/activity-instance/activity-instance-start-page.d.ts +1 -0
  46. package/dist-client/pages/activity-instance/activity-instance-start-page.js +7 -0
  47. package/dist-client/pages/activity-instance/activity-instance-start-page.js.map +1 -1
  48. package/dist-client/pages/activity-instance/activity-instance-view.js +1 -1
  49. package/dist-client/pages/activity-instance/activity-instance-view.js.map +1 -1
  50. package/dist-client/pages/activity-stats/activity-stats-list-page.js +2 -1
  51. package/dist-client/pages/activity-stats/activity-stats-list-page.js.map +1 -1
  52. package/dist-client/pages/activity-thread/activity-thread-page.d.ts +30 -4
  53. package/dist-client/pages/activity-thread/activity-thread-page.js +142 -66
  54. package/dist-client/pages/activity-thread/activity-thread-page.js.map +1 -1
  55. package/dist-client/pages/activity-thread/activity-thread-view-page.d.ts +17 -6
  56. package/dist-client/pages/activity-thread/activity-thread-view-page.js +118 -65
  57. package/dist-client/pages/activity-thread/activity-thread-view-page.js.map +1 -1
  58. package/dist-client/pages/activity-thread/activity-thread-view.d.ts +24 -7
  59. package/dist-client/pages/activity-thread/activity-thread-view.js +84 -308
  60. package/dist-client/pages/activity-thread/activity-thread-view.js.map +1 -1
  61. package/dist-client/pages/installable-activity/installable-activity-list-page.d.ts +1 -1
  62. package/dist-client/pages/installable-activity/installable-activity-list-page.js +13 -9
  63. package/dist-client/pages/installable-activity/installable-activity-list-page.js.map +1 -1
  64. package/dist-client/pages/todo/approval-done-list-page.d.ts +1 -0
  65. package/dist-client/pages/todo/approval-done-list-page.js +111 -58
  66. package/dist-client/pages/todo/approval-done-list-page.js.map +1 -1
  67. package/dist-client/pages/todo/approval-pending-list-page.d.ts +32 -1
  68. package/dist-client/pages/todo/approval-pending-list-page.js +485 -130
  69. package/dist-client/pages/todo/approval-pending-list-page.js.map +1 -1
  70. package/dist-client/pages/todo/done-list-calendar-page.d.ts +2 -0
  71. package/dist-client/pages/todo/done-list-calendar-page.js +213 -29
  72. package/dist-client/pages/todo/done-list-calendar-page.js.map +1 -1
  73. package/dist-client/pages/todo/done-list-page.d.ts +1 -0
  74. package/dist-client/pages/todo/done-list-page.js +126 -62
  75. package/dist-client/pages/todo/done-list-page.js.map +1 -1
  76. package/dist-client/pages/todo/draft-list-page.d.ts +1 -0
  77. package/dist-client/pages/todo/draft-list-page.js +82 -34
  78. package/dist-client/pages/todo/draft-list-page.js.map +1 -1
  79. package/dist-client/pages/todo/pickable-list-page.js +6 -10
  80. package/dist-client/pages/todo/pickable-list-page.js.map +1 -1
  81. package/dist-client/pages/todo/todo-list-page.d.ts +1 -1
  82. package/dist-client/pages/todo/todo-list-page.js +102 -78
  83. package/dist-client/pages/todo/todo-list-page.js.map +1 -1
  84. package/dist-client/route.d.ts +1 -1
  85. package/dist-client/route.js +0 -6
  86. package/dist-client/route.js.map +1 -1
  87. package/dist-client/templates/activity-approval-context-template.js +60 -138
  88. package/dist-client/templates/activity-approval-context-template.js.map +1 -1
  89. package/dist-client/templates/activity-instance-context-template.js +13 -172
  90. package/dist-client/templates/activity-instance-context-template.js.map +1 -1
  91. package/dist-client/templates/activity-thread-context-template.js +39 -131
  92. package/dist-client/templates/activity-thread-context-template.js.map +1 -1
  93. package/dist-client/templates/context-panel.d.ts +26 -0
  94. package/dist-client/templates/context-panel.js +182 -0
  95. package/dist-client/templates/context-panel.js.map +1 -0
  96. package/dist-client/tsconfig.tsbuildinfo +1 -1
  97. package/dist-client/when.d.ts +4 -0
  98. package/dist-client/when.js +72 -0
  99. package/dist-client/when.js.map +1 -0
  100. package/dist-server/controllers/activity-approval/_abort.js +2 -1
  101. package/dist-server/controllers/activity-approval/_abort.js.map +1 -1
  102. package/dist-server/controllers/activity-approval/approval-line.d.ts +106 -0
  103. package/dist-server/controllers/activity-approval/approval-line.js +151 -0
  104. package/dist-server/controllers/activity-approval/approval-line.js.map +1 -0
  105. package/dist-server/controllers/activity-approval/approve.js +61 -51
  106. package/dist-server/controllers/activity-approval/approve.js.map +1 -1
  107. package/dist-server/controllers/activity-approval/claim.d.ts +42 -0
  108. package/dist-server/controllers/activity-approval/claim.js +77 -0
  109. package/dist-server/controllers/activity-approval/claim.js.map +1 -0
  110. package/dist-server/controllers/activity-approval/create-approval.d.ts +41 -0
  111. package/dist-server/controllers/activity-approval/create-approval.js +78 -0
  112. package/dist-server/controllers/activity-approval/create-approval.js.map +1 -0
  113. package/dist-server/controllers/activity-approval/delegate.d.ts +16 -0
  114. package/dist-server/controllers/activity-approval/delegate.js +43 -7
  115. package/dist-server/controllers/activity-approval/delegate.js.map +1 -1
  116. package/dist-server/controllers/activity-approval/opinion.d.ts +10 -0
  117. package/dist-server/controllers/activity-approval/opinion.js +43 -0
  118. package/dist-server/controllers/activity-approval/opinion.js.map +1 -0
  119. package/dist-server/controllers/activity-approval/reject.js +21 -1
  120. package/dist-server/controllers/activity-approval/reject.js.map +1 -1
  121. package/dist-server/controllers/activity-approval/save.js +26 -2
  122. package/dist-server/controllers/activity-approval/save.js.map +1 -1
  123. package/dist-server/controllers/activity-installation/activity-installation-controller.d.ts +26 -0
  124. package/dist-server/controllers/activity-installation/activity-installation-controller.js +45 -0
  125. package/dist-server/controllers/activity-installation/activity-installation-controller.js.map +1 -1
  126. package/dist-server/controllers/activity-instance/approval-expectation.d.ts +34 -0
  127. package/dist-server/controllers/activity-instance/approval-expectation.js +18 -0
  128. package/dist-server/controllers/activity-instance/approval-expectation.js.map +1 -0
  129. package/dist-server/controllers/activity-instance/issue.js +32 -0
  130. package/dist-server/controllers/activity-instance/issue.js.map +1 -1
  131. package/dist-server/controllers/activity-thread/restart.js +17 -1
  132. package/dist-server/controllers/activity-thread/restart.js.map +1 -1
  133. package/dist-server/controllers/activity-thread/submit.js +23 -43
  134. package/dist-server/controllers/activity-thread/submit.js.map +1 -1
  135. package/dist-server/controllers/common.js +46 -0
  136. package/dist-server/controllers/common.js.map +1 -1
  137. package/dist-server/controllers/index.d.ts +1 -0
  138. package/dist-server/controllers/index.js +8 -0
  139. package/dist-server/controllers/index.js.map +1 -1
  140. package/dist-server/service/activity/activity-mutation.js +25 -5
  141. package/dist-server/service/activity/activity-mutation.js.map +1 -1
  142. package/dist-server/service/activity/activity-type.d.ts +14 -0
  143. package/dist-server/service/activity/activity-type.js +8 -0
  144. package/dist-server/service/activity/activity-type.js.map +1 -1
  145. package/dist-server/service/activity/activity.d.ts +18 -0
  146. package/dist-server/service/activity/activity.js +5 -0
  147. package/dist-server/service/activity/activity.js.map +1 -1
  148. package/dist-server/service/activity-approval/activity-approval-mutation.js +3 -2
  149. package/dist-server/service/activity-approval/activity-approval-mutation.js.map +1 -1
  150. package/dist-server/service/activity-approval/activity-approval-query.d.ts +19 -1
  151. package/dist-server/service/activity-approval/activity-approval-query.js +186 -56
  152. package/dist-server/service/activity-approval/activity-approval-query.js.map +1 -1
  153. package/dist-server/service/activity-approval/activity-approval.d.ts +29 -1
  154. package/dist-server/service/activity-approval/activity-approval.js +19 -0
  155. package/dist-server/service/activity-approval/activity-approval.js.map +1 -1
  156. package/dist-server/service/activity-approval/my-pending-approvals.d.ts +21 -0
  157. package/dist-server/service/activity-approval/my-pending-approvals.js +40 -0
  158. package/dist-server/service/activity-approval/my-pending-approvals.js.map +1 -0
  159. package/dist-server/service/activity-instance/activity-instance-type.d.ts +20 -0
  160. package/dist-server/service/activity-instance/activity-instance-type.js +11 -0
  161. package/dist-server/service/activity-instance/activity-instance-type.js.map +1 -1
  162. package/dist-server/service/activity-instance/activity-instance.d.ts +6 -0
  163. package/dist-server/service/activity-instance/activity-instance.js +5 -0
  164. package/dist-server/service/activity-instance/activity-instance.js.map +1 -1
  165. package/dist-server/service/activity-stats/activity-stats-query.d.ts +5 -0
  166. package/dist-server/service/activity-stats/activity-stats-query.js +149 -11
  167. package/dist-server/service/activity-stats/activity-stats-query.js.map +1 -1
  168. package/dist-server/service/activity-stats/activity-stats-type.d.ts +19 -6
  169. package/dist-server/service/activity-stats/activity-stats-type.js +37 -10
  170. package/dist-server/service/activity-stats/activity-stats-type.js.map +1 -1
  171. package/dist-server/service/activity-stats/event-placement.d.ts +55 -0
  172. package/dist-server/service/activity-stats/event-placement.js +82 -0
  173. package/dist-server/service/activity-stats/event-placement.js.map +1 -0
  174. package/dist-server/service/activity-thread/activity-thread-query.js +48 -24
  175. package/dist-server/service/activity-thread/activity-thread-query.js.map +1 -1
  176. package/dist-server/service/activity-thread/my-open-threads.d.ts +15 -0
  177. package/dist-server/service/activity-thread/my-open-threads.js +40 -0
  178. package/dist-server/service/activity-thread/my-open-threads.js.map +1 -0
  179. package/dist-server/service/activity-thread/todo-order.d.ts +49 -0
  180. package/dist-server/service/activity-thread/todo-order.js +70 -0
  181. package/dist-server/service/activity-thread/todo-order.js.map +1 -0
  182. package/dist-server/service/installable-activity/installable-activity-mutation.d.ts +6 -0
  183. package/dist-server/service/installable-activity/installable-activity-mutation.js +7 -24
  184. package/dist-server/service/installable-activity/installable-activity-mutation.js.map +1 -1
  185. package/dist-server/service/nulls-last.d.ts +30 -0
  186. package/dist-server/service/nulls-last.js +37 -0
  187. package/dist-server/service/nulls-last.js.map +1 -0
  188. package/dist-server/tsconfig.tsbuildinfo +1 -1
  189. package/helps/dataset/activity-instance-search-page.ko.md +5 -0
  190. package/helps/dataset/activity-instance-search-page.md +13 -0
  191. package/helps/worklist/activity-approval.ko.md +5 -0
  192. package/helps/worklist/activity-approval.md +14 -0
  193. package/helps/worklist/activity-bank-page.ko.md +5 -0
  194. package/helps/worklist/activity-bank-page.md +13 -0
  195. package/helps/worklist/activity-reporter-list.ko.md +5 -0
  196. package/helps/worklist/activity-reporter-list.md +13 -0
  197. package/helps/worklist/activity-store.ko.md +5 -0
  198. package/helps/worklist/activity-store.md +13 -0
  199. package/helps/worklist/activity-template.ko.md +5 -0
  200. package/helps/worklist/activity-template.md +13 -0
  201. package/helps/worklist/installable-activity.ko.md +5 -0
  202. package/helps/worklist/installable-activity.md +13 -0
  203. package/package.json +13 -12
  204. package/things-factory.config.js +0 -5
  205. package/translations/en.json +129 -51
  206. package/translations/ja.json +130 -52
  207. package/translations/ko.json +82 -4
  208. package/translations/ms.json +129 -51
  209. package/translations/zh.json +132 -54
  210. package/dist-client/pages/dashboard/dashboard-home.d.ts +0 -1
  211. package/dist-client/pages/dashboard/dashboard-home.js +0 -22
  212. package/dist-client/pages/dashboard/dashboard-home.js.map +0 -1
  213. package/dist-client/pages/worklist-home.d.ts +0 -1
  214. package/dist-client/pages/worklist-home.js +0 -17
  215. package/dist-client/pages/worklist-home.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity-fields.js","sourceRoot":"","sources":["../../client/components/activity-fields.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { css, html } from 'lit'\n\nimport { i18next } from '@operato/i18n'\n\n/**\n * 업무 항목을 화면에 내는 방식 — **두 화면이 한 벌을 쓴다.**\n *\n * 업무 상세(activity-thread-page)와 결재 상세(activity-approval-page)는 거의 복사본이다. 항목을\n * 고르는 함수, 화면 종류에 따라 그리는 분기, 절을 그리는 부분이 두 파일에 같은 코드로 있었다.\n * 그래서 한쪽만 고치면 나머지가 그대로 남는다 — 실제로 그랬다(2026-09-06, 상세 화면의\n * Input · Output 영문 legend 를 고쳤는데 결재 화면에는 그대로 있었다).\n *\n * 화면마다 다른 것은 남긴다 — 상세는 결과를 적고, 결재는 읽기만 한다.\n */\n\n/** 절과 값 표의 모양. 카드 값은 SurfaceStyles 의 .ui-card 와 같다. */\nexport const ActivityFieldsStyles = css`\n section {\n margin: var(--spacing-large, 16px) var(--spacing-large, 16px) 0;\n padding: 14px;\n background: var(--ui-panel, #ffffff);\n border: 1px solid var(--ui-line, #d5dce0);\n border-radius: var(--ui-r, 10px);\n }\n\n section > h2 {\n margin: 0 0 10px;\n font-size: var(--ui-t-title, 15px);\n font-weight: 600;\n color: var(--ui-ink, #17242c);\n }\n\n /* 읽기만 하는 절 — 값을 바꿀 수 없다는 것이 보여야 한다. */\n section[readonly] > h2 {\n color: var(--ui-muted, #57676f);\n }\n\n /* 받은 값 — 이름과 값을 두 칸으로. 이름은 오른쪽 정렬이라 값의 왼쪽 끝이 한 줄로 선다. */\n dl.given {\n display: grid;\n grid-template-columns: minmax(80px, max-content) 1fr;\n gap: 7px var(--spacing-large, 16px);\n margin: 0;\n }\n\n dl.given dt {\n text-align: right;\n color: var(--ui-muted, #57676f);\n word-break: keep-all;\n }\n\n dl.given dd {\n margin: 0;\n color: var(--ui-ink, #17242c);\n word-break: break-word;\n }\n\n dl.given .none {\n color: var(--ui-faint, #8a959c);\n }\n\n dl.given code {\n font-family: var(--ui-mono, ui-monospace, Menlo, monospace);\n font-size: var(--ui-t-small, 11.5px);\n }\n\n /*\n * 안쪽으로 펼친 오브젝트 · 배열.\n *\n * 바깥과 같은 두 칸 구조를 쓰되 **한 단 들여쓰고 왼쪽에 선을 긋는다.** 선이 없으면 세 단이 겹칠 때\n * 어느 이름이 어느 값에 딸린 것인지 눈으로 못 가른다.\n *\n * 안쪽 이름은 왼쪽 정렬이다. 바깥은 오른쪽 정렬이라 값의 왼쪽 끝이 한 줄로 서는데(dl.given dt),\n * 안쪽까지 그러면 단이 깊어질수록 이름이 값 쪽으로 밀려 붙는다.\n */\n dl.given .nested {\n margin: 2px 0 0;\n padding-left: 10px;\n border-left: 1px solid var(--ui-line, #d5dce0);\n }\n\n dl.given dl.nested {\n display: grid;\n grid-template-columns: minmax(60px, max-content) 1fr;\n gap: 4px var(--spacing-medium, 8px);\n }\n\n dl.given dl.nested dt {\n text-align: left;\n color: var(--ui-faint, #8a959c);\n font-family: var(--ui-mono, ui-monospace, Menlo, monospace);\n font-size: var(--ui-t-small, 11.5px);\n }\n\n /*\n * 페이로드를 그대로 가져가는 자리.\n *\n * 화면은 값을 읽기 좋게 펴 놓지만, 이 값을 **다른 도구에 넣어 볼 일**이 있다 — 트윈 명령 하나가\n * 네 단짜리 오브젝트이고, 그것을 손으로 옮겨 적을 수는 없다. 화면이 편 글자가 아니라 원문 JSON 을\n * 준다. 붙여 넣는 쪽이 기대하는 것은 원문이다.\n *\n * 값 위에 얹지 않고 오른쪽 위 구석에 둔다 — 값이 한 줄일 때도 두 단 깊을 때도 자리가 같다.\n */\n dl.given dd:has(> .payload) {\n position: relative;\n }\n\n .copy {\n position: absolute;\n top: 0;\n right: 0;\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 1px 5px;\n border: 1px solid var(--ui-line, #d5dce0);\n border-radius: 999px;\n background: var(--ui-panel, #ffffff);\n color: var(--ui-muted, #57676f);\n font-size: var(--ui-t-micro, 11px);\n line-height: 16px;\n cursor: pointer;\n }\n\n .copy md-icon {\n font-size: 13px;\n width: 13px;\n height: 13px;\n }\n\n .copy:hover {\n color: var(--ui-ink, #17242c);\n border-color: var(--ui-muted, #57676f);\n }\n\n .copy:focus-visible {\n outline: 2px solid var(--ui-accent, #00727e);\n outline-offset: 1px;\n }\n\n /* 복사한 직후 — 눌린 것이 보여야 한다. 소리도 움직임도 없는 조작이라 이 표시가 유일한 대답이다. */\n .copy[done] {\n border-color: var(--ui-good, #297d39);\n color: var(--ui-good, #297d39);\n }\n\n /*\n * 못 했을 때도 **같은 크기로** 말한다.\n *\n * 처음에는 실패를 title 로만 적었다. 그러면 누른 사람 눈에는 아무 일도 안 일어난 것과 같고,\n * 이유를 알려면 그 자리에 마우스를 올려 두어야 한다 — 손가락으로 쓰는 화면에는 그 길이 없다.\n * 클립보드는 브라우저가 막을 수 있는 자리라(보안 컨텍스트가 아니거나 권한이 없으면) 실제로 나는 일이다.\n */\n .copy[failed] {\n border-color: var(--ui-crit, #d14946);\n color: var(--ui-crit, #d14946);\n }\n\n /* 배열 — 번호로 몇 번째인지 말한다. 순서가 뜻을 갖는 값이 온다(주의 목록 · 권장 조치). */\n dl.given ol.nested {\n list-style: decimal;\n padding-left: 24px;\n }\n\n dl.given ol.nested li {\n margin: 2px 0;\n }\n\n dl.given ol.nested li::marker {\n color: var(--ui-faint, #8a959c);\n font-size: var(--ui-t-small, 11.5px);\n }\n\n /*\n * 빈 화면은 가장 중요한 자리다. 없다고만 하지 않고 왜 비어 있는지 적는다.\n *\n * 두 가지가 있다. 화면 전체가 비는 것(건을 못 읽었다)은 세로로 늘려 가운데에 두고, 절 자리가\n * 비는 것(항목이 정의되지 않았다)은 **다른 절과 같은 카드**로 둔다. 절 하나가 없다고 해서\n * 화면 높이를 다 쓰면 그 아래의 타임라인이 화면 밖으로 밀린다.\n */\n section[empty] {\n display: flex;\n flex: none;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n padding: 28px 14px;\n text-align: center;\n color: var(--ui-muted, #57676f);\n }\n\n div[empty] {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: var(--spacing-large, 16px);\n text-align: center;\n color: var(--ui-muted, #57676f);\n }\n\n [empty] .title {\n font-size: var(--ui-t-title, 15px);\n font-weight: 600;\n color: var(--ui-ink, #17242c);\n }\n\n [empty] .why {\n max-width: 40em;\n font-size: var(--ui-t-body, 13px);\n color: var(--ui-faint, #8a959c);\n word-break: keep-all;\n }\n`\n\n/**\n * 화면에 낼 항목을 고른다.\n *\n * hidden 을 지킨다. 전에는 이 선언을 보지 않았다 — 액티비티가 「이 항목은 보이지 않는다」고 적어\n * 두어도 화면에 나왔다. 편집기가 없는 타입(object 등)이라 조용히 빠졌을 뿐이고, 편집기가 있는\n * 타입이면 그대로 보였다. 값을 표로 그리기 시작하면서 실제로 드러났다 — 처분 승인 화면에\n * disposition 객체의 JSON 원문이 나왔다.\n */\nfunction specsOf(model: any[] | null | undefined, inouts: string[]) {\n return (model || [])\n .filter(item => !item.hidden)\n .filter(item => inouts.includes(item.inout))\n .map(item => ({\n ...item,\n name: item.tag,\n label: item.tKey || item.name,\n property: item.options\n }))\n}\n\n/** 받은 값 — 업무를 시작할 때 함께 온 것. */\nexport function inputSpecOf(model: any[] | null | undefined) {\n return specsOf(model, ['in', 'inout'])\n}\n\n/** 적어 낼 값 — 수행자가 채우는 것. */\nexport function outputSpecOf(model: any[] | null | undefined) {\n return specsOf(model, ['out', 'inout'])\n}\n\n/**\n * 값을 **표로** 보인다. 입력칸으로 그리지 않는다.\n *\n * 전에는 읽기만 하는 절도 ox-properties-dynamic-view 로 그렸다. 그러면 값마다 흰 입력 상자가\n * 생기고 사용자는 고쳐 쓸 수 있는 것으로 읽는다. 그런데 그 절에는 변경을 받는 자리가 없다 —\n * 결재 화면은 아예 output 을 mutation 에 싣지 않는다(approveActivityApproval 은 id 와 comment 만\n * 보낸다). 「적을 수 있게 보이는데 적히지 않는 칸」이라 가장 나쁜 쪽이다.\n */\nexport function renderGiven(specs: any[], values: any) {\n return html`\n <dl class=\"given\">\n ${specs.map(\n spec => html`\n <dt>${fieldLabel(spec)}</dt>\n <dd>${fieldValue(values?.[spec.name])}</dd>\n `\n )}\n </dl>\n `\n}\n\n/**\n * 항목 이름 — ox-property-editor 와 같은 규칙으로 찾는다(그쪽은 label. 접두사를 스스로 붙인다).\n *\n * 번역이 없으면 **키를 그대로 보이지 않는다.** 전에는 label.because 가 없어서 화면에\n * Label.Because 가 나왔다. 사용자에게 뜻이 없는 글자다.\n *\n * description 으로 물러나지도 않는다 — 액티비티의 description 은 개발자가 영어로 적어 둔 설명이다\n * (예: \"The disposition waiting for approval\"). 한국어 화면에 영어 문장이 나오는 것보다 항목\n * 이름이 낫다.\n */\nexport function fieldLabel(spec: any): string {\n const key = String(spec?.label ?? spec?.name ?? '')\n const full = key.indexOf('label.') >= 0 ? key : 'label.' + key\n\n return i18next.t(full, { defaultValue: spec?.name || key })\n}\n\n/**\n * 얼마나 깊이 펼치나.\n *\n * 이 화면들이 받는 값은 액티비티가 정하므로 얼마나 깊을지 알 수 없다. 트윈의 작동 명령은 네 단이다\n * (twinNow → attentions[0] → params → 값). 끝없이 펼치면 어떤 페이로드에서 화면이 통째로 페이로드가\n * 되므로, 이 깊이를 넘으면 원문을 그대로 보인다 — 접는 것이 아니라 **다른 방식으로 보이는 것**이다.\n */\nconst MAX_DEPTH = 4\n\n/**\n * 값 한 칸.\n *\n * ── 오브젝트를 한 줄 JSON 으로 내지 않는다 (2026-09-07) ─────────────────────\n * `JSON.stringify` 한 줄이었다. 트윈의 작동 명령을 열면 그 한 줄이 700자가 넘어서, 「업무 내용」이\n * 읽을 수 없는 글자 덩어리 하나가 됐다. 값은 다 있는데 아무것도 읽히지 않는다.\n *\n * 화면은 이미 이름과 값을 두 칸으로 보이는 말을 갖고 있다(dl.given). 오브젝트도 그 말로 편다 —\n * 새 표현을 만들지 않고, 안쪽이든 바깥쪽이든 같은 모양으로 읽힌다.\n *\n * 값이 없으면 빈 칸으로 두지 않는다 — 빈 칸은 값이 없는 것인지 화면이 못 낸 것인지 모른다.\n */\nexport function fieldValue(value: any, depth = 0): unknown {\n if (value === null || value === undefined || value === '') {\n return html`<span class=\"none\">${i18next.t('text.no-value')}</span>`\n }\n\n if (typeof value === 'boolean') {\n return i18next.t(value ? 'label.yes' : 'label.no', { defaultValue: String(value) })\n }\n\n if (typeof value !== 'object') {\n return String(value)\n }\n\n /* 너무 깊으면 펼치기를 그만두고 원문을 보인다 — 없는 척하지 않는다. */\n if (depth >= MAX_DEPTH) {\n return html`<code>${JSON.stringify(value)}</code>`\n }\n\n const laid = layOut(value, depth)\n\n /*\n * 맨 바깥 값에만 복사를 붙인다.\n *\n * 안쪽 단마다 달면 네 단짜리 페이로드에 단추가 열 개 넘게 붙어, 정작 읽으라고 편 값이 단추에\n * 묻힌다. 사람이 가져가려는 것은 「이 항목」이다.\n */\n return depth === 0 ? html`<span class=\"payload\">${copyButton(value)}${laid}</span>` : laid\n}\n\n/**\n * 이 값을 원문 그대로 가져간다.\n *\n * 화면이 편 글자가 아니라 JSON 을 준다 — 붙여 넣는 쪽(질의 · 로그 검색 · 문의 글)이 기대하는 것은\n * 원문이다. 들여쓰기를 넣어 그대로 읽을 수 있게 한다.\n *\n * 눌러도 화면이 안 바뀌면 눌린 줄을 모른다. 그래서 잠깐 표시를 남긴다 — 이 조작에는 그것 말고\n * 대답이 없다.\n */\nfunction copyButton(value: any) {\n const onCopy = async (e: Event) => {\n const button = e.currentTarget as HTMLElement\n\n const mark = (attr: 'done' | 'failed') => {\n button.toggleAttribute(attr, true)\n setTimeout(() => button.toggleAttribute(attr, false), 1500)\n }\n\n try {\n await navigator.clipboard.writeText(JSON.stringify(value, null, 2))\n } catch {\n /*\n * 클립보드는 브라우저가 막을 수 있다(보안 컨텍스트가 아니거나 권한이 없으면). 안 된 것을 된\n * 것처럼 말하지 않고, 성공과 같은 크기로 보인다 — title 만 바꾸면 누른 사람 눈에는 아무 일도\n * 안 일어난 것과 같다.\n */\n button.setAttribute('title', String(i18next.t('text.copy-failed')))\n mark('failed')\n return\n }\n\n mark('done')\n }\n\n return html`\n <button class=\"copy\" type=\"button\" title=${String(i18next.t('text.copy-payload'))} @click=${onCopy}>\n <md-icon>content_copy</md-icon>${i18next.t('button.copy')}\n </button>\n `\n}\n\n/** 값을 이름·값 두 칸으로 편다. 복사 단추는 여기 끼지 않는다 — 편 결과만 만든다. */\nfunction layOut(value: any, depth: number): unknown {\n if (Array.isArray(value)) {\n /* 빈 배열은 「값 없음」이 아니다 — 「비어 있다」는 그 자체로 사실이다. */\n if (value.length === 0) {\n return html`<span class=\"none\">${i18next.t('text.empty-list')}</span>`\n }\n\n /*\n * 배열은 깊이를 먹지 않는다 — **같은 것이 여러 개**이지 새로운 단이 아니다.\n *\n * 배열도 한 단으로 세었더니 트윈 작동 명령의 마지막 줄이 잘렸다: twinNow → attentions →\n * attentions[0] → recommendedActions → { code } 에서 recommendedActions 의 항목이 다섯 번째가\n * 되어, 정작 가장 단순한 { code: 'advice.raise-priority' } 하나가 JSON 원문으로 남았다.\n * 사람이 세는 단은 넷이다.\n */\n return html`\n <ol class=\"nested\">\n ${value.map(item => html`<li>${fieldValue(item, depth)}</li>`)}\n </ol>\n `\n }\n\n const keys = Object.keys(value)\n\n if (keys.length === 0) {\n return html`<span class=\"none\">${i18next.t('text.empty-object')}</span>`\n }\n\n /*\n * 안쪽 이름은 번역하지 않는다. 액티비티가 정한 키라 번역이 있을 리 없고, 없는 번역을 찾으면\n * 「Label.MaterialDefinitionId」 같은 글자가 나온다 — 사용자에게 뜻이 없는 글자다.\n */\n return html`\n <dl class=\"given nested\">\n ${keys.map(\n key => html`\n <dt>${key}</dt>\n <dd>${fieldValue(value[key], depth + 1)}</dd>\n `\n )}\n </dl>\n `\n}\n"]}
@@ -8,6 +8,25 @@ export declare class ActivityInstanceRibon extends ActivityInstanceRibon_base {
8
8
  static styles: import("lit").CSSResult[];
9
9
  activityInstance: any;
10
10
  render(): import("lit-html").TemplateResult<1>;
11
+ /**
12
+ * 이 건의 기본 정보 — **팝업으로 연다.**
13
+ *
14
+ * ── 왜 aside 가 아닌가 (2026-09-06) ────────────────────────────────────
15
+ * 전에는 화면 오른쪽에서 나오는 aside 판이었다. 두 가지가 걸린다.
16
+ *
17
+ * 자리를 다툰다 화면 오른쪽 세로 판은 operato-twin 의 twin-entity360 이 쓰는 자리다
18
+ * (position: fixed · right: 0 · height: 100vh). 같은 자리에 둘이 선다.
19
+ * 전역 슬롯이다 VIEWPART_POSITION.ASIDEBAR 은 앱이 하나만 갖는다. 열 개가 넘는 패키지가
20
+ * 그 자리를 쓰고 있어(twin 의 AI 협의 도크 · board-ui · help · more-ui …),
21
+ * 이 판을 열면 그중 열려 있던 것이 닫힌다.
22
+ *
23
+ * 그리고 자리의 뜻이 다르다. 오른쪽 드로어는 **보고 있는 대상을 따라다니는 상세**이고(360 이
24
+ * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 판은 **이 화면의 이 건**에
25
+ * 대한 것이라 화면을 벗어나면 뜻이 없다. 페이지에 매인 것을 앱 전역 자리에 두지 않는다.
26
+ *
27
+ * 내용도 팝업 크기다 — 값 여덟 줄과 접힌 타임라인이라 세로 100vh 를 쓸 일이 없었다.
28
+ */
29
+ private openInfo;
11
30
  updated(changes: any): void;
12
31
  }
13
32
  export {};
@@ -3,143 +3,76 @@ import '@material/web/button/elevated-button.js';
3
3
  import '@operato/property-editor/ox-properties-dynamic-view.js';
4
4
  import '@things-factory/organization/dist-client/component/approval-line-brief.js';
5
5
  import '../templates/activity-instance-context-template.js';
6
- import { css, html, LitElement } from 'lit';
6
+ import { html, LitElement } from 'lit';
7
7
  import { customElement, property } from 'lit/decorators.js';
8
8
  import { i18next, localize } from '@operato/i18n';
9
- import { toggleOverlay } from '@operato/layout';
9
+ import { openPopup } from '@operato/layout';
10
+ import { StateRibonStyles } from './state-ribon.js';
10
11
  let ActivityInstanceRibon = class ActivityInstanceRibon extends localize(i18next)(LitElement) {
11
12
  constructor() {
12
13
  super(...arguments);
13
14
  this.activityInstance = {};
14
15
  }
15
- static { this.styles = [
16
- css `
17
- :host {
18
- display: flex;
19
- background-color: var(--worklist-status-color);
20
- color: var(--md-sys-color-on-primary);
21
- align-items: center;
22
- min-height: 44px;
23
- --fontsize-small: 12px;
24
- }
25
-
26
- div {
27
- border-left: var(--border-dim-color);
28
- padding: var(--spacing-small) var(--spacing-medium);
29
- align-self: center;
30
- }
31
-
32
- :host([state='draft']) {
33
- --worklist-status-color: #5f7184;
34
- }
35
-
36
- :host([state='issued']) {
37
- --worklist-status-color: #56af45;
38
- }
39
-
40
- :host([state='assigned']) {
41
- --worklist-status-color: #428df3;
42
- }
43
-
44
- :host([state='started']) {
45
- --worklist-status-color: #595de5;
46
- }
47
-
48
- :host([state='pending']) {
49
- --worklist-status-color: #f27429;
50
- }
51
-
52
- :host([state='ended']) {
53
- --worklist-status-color: #02acae;
54
- }
55
-
56
- :host([state='aborted']) {
57
- --worklist-status-color: #cb3a33;
58
- }
59
-
60
- md-icon {
61
- font-size: 24px;
62
- }
63
-
64
- [desc] {
65
- flex: 2;
66
- font-size: var(--fontsize-small);
67
- }
68
-
69
- [desc] * {
70
- vertical-align: middle;
71
- }
72
-
73
- [assignee] {
74
- text-align: center;
75
- font-size: var(--fontsize-small);
76
- line-height: 1.3;
77
- }
78
-
79
- [assignee] span {
80
- display: block;
81
- font-size: var(--fontsize-large);
82
- font-weight: bold;
83
- }
84
-
85
- approval-line-brief {
86
- background-color: var(--worklist-status-color);
87
- font-size: var(--fontsize-small);
88
- }
89
-
90
- [state] {
91
- text-align: right;
92
- font-size: var(--fontsize-small);
93
- font-weight: bold;
94
- }
95
-
96
- @media only screen and (max-width: 460px) {
97
- div {
98
- border-left: none;
99
- }
100
- [assignee] {
101
- display: none;
102
- }
103
- md-icon {
104
- padding: 0;
105
- }
106
- approval-line-brief {
107
- display: none;
108
- }
109
- }
110
- `
111
- ]; }
16
+ static { this.styles = [StateRibonStyles]; }
112
17
  render() {
113
18
  const { description, state, assignee, approvalLine, activity } = this.activityInstance || {};
114
19
  const { startingType } = activity || {};
115
20
  return html `
116
- <div desc>
117
- <md-icon
118
- @click=${() => {
119
- toggleOverlay('activity-info-overlay', {
120
- template: html `<activity-instance-context-template
121
- .activityInstance=${this.activityInstance}
122
- state=${state}
123
- ></activity-instance-context-template>`
124
- });
21
+ <span class="state">
22
+ <i class="dot"></i>
23
+ ${i18next.t('label.activity-state-' + state)}
24
+ </span>
25
+
26
+ <md-icon
27
+ class="info"
28
+ role="button"
29
+ tabindex="0"
30
+ title=${String(i18next.t('label.thread-info'))}
31
+ @click=${() => this.openInfo(state)}
32
+ @keydown=${(e) => {
33
+ if (e.key === 'Enter' || e.key === ' ') {
34
+ e.preventDefault();
35
+ this.openInfo(state);
36
+ }
125
37
  }}
126
- >description</md-icon
127
- >
128
- ${description}
129
- </div>
130
- ${startingType == 'issue' && assignee
131
- ? html `
132
- <div assignee>
133
- ${i18next.t('field.assignee')}
134
- <span>${assignee?.name}&nbsp;</span>
135
- </div>
136
- `
137
- : html ``}
138
- ${approvalLine ? html `<approval-line-brief .model=${approvalLine}></approval-line-brief>` : html ``}
38
+ >info</md-icon
39
+ >
40
+
41
+ <span class="desc" title=${description || ''}>${description || ''}</span>
139
42
 
140
- <div state>${i18next.t('label.activity-state-' + state)}</div>
43
+
44
+ ${startingType == 'issue' && assignee
45
+ ? html `<span class="who"><span class="who-label">${i18next.t('field.assignee')}</span>${assignee?.name}</span>`
46
+ : ''}
47
+ <!--
48
+ 결재선의 현재 단계를 넘기지 않는다 — 이 ribbon 이 쓰이는 곳은 업무를 시작하는 화면
49
+ 하나뿐이고(activity-instance-start-page), 거기서는 아직 아무도 판단하지 않았다.
50
+ approval-line-brief 는 값이 없으면 기안자를 현재로 표시하는데, 이 화면에서는 그것이 맞다.
51
+ -->
52
+ ${approvalLine ? html `<approval-line-brief .model=${approvalLine}></approval-line-brief>` : ''}
141
53
  `;
142
54
  }
55
+ /**
56
+ * 이 건의 기본 정보 — **팝업으로 연다.**
57
+ *
58
+ * ── 왜 aside 가 아닌가 (2026-09-06) ────────────────────────────────────
59
+ * 전에는 화면 오른쪽에서 나오는 aside 판이었다. 두 가지가 걸린다.
60
+ *
61
+ * 자리를 다툰다 화면 오른쪽 세로 판은 operato-twin 의 twin-entity360 이 쓰는 자리다
62
+ * (position: fixed · right: 0 · height: 100vh). 같은 자리에 둘이 선다.
63
+ * 전역 슬롯이다 VIEWPART_POSITION.ASIDEBAR 은 앱이 하나만 갖는다. 열 개가 넘는 패키지가
64
+ * 그 자리를 쓰고 있어(twin 의 AI 협의 도크 · board-ui · help · more-ui …),
65
+ * 이 판을 열면 그중 열려 있던 것이 닫힌다.
66
+ *
67
+ * 그리고 자리의 뜻이 다르다. 오른쪽 드로어는 **보고 있는 대상을 따라다니는 상세**이고(360 이
68
+ * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 판은 **이 화면의 이 건**에
69
+ * 대한 것이라 화면을 벗어나면 뜻이 없다. 페이지에 매인 것을 앱 전역 자리에 두지 않는다.
70
+ *
71
+ * 내용도 팝업 크기다 — 값 여덟 줄과 접힌 타임라인이라 세로 100vh 를 쓸 일이 없었다.
72
+ */
73
+ openInfo(state) {
74
+ openPopup(html `<activity-instance-context-template .activityInstance=${this.activityInstance} state=${state}></activity-instance-context-template>`, { title: i18next.t('label.thread-info') });
75
+ }
143
76
  updated(changes) {
144
77
  if (changes.has('activityInstance') && this.activityInstance) {
145
78
  const { state } = this.activityInstance;
@@ -1 +1 @@
1
- {"version":3,"file":"activity-instance-ribon.js","sourceRoot":"","sources":["../../client/components/activity-instance-ribon.ts"],"names":[],"mappings":";AAAA,OAAO,yCAAyC,CAAA;AAChD,OAAO,wDAAwD,CAAA;AAC/D,OAAO,2EAA2E,CAAA;AAClF,OAAO,oDAAoD,CAAA;AAE3D,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAS,MAAM,mBAAmB,CAAA;AAElE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAGxC,IAAM,qBAAqB,GAA3B,MAAM,qBAAsB,SAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC;IAAjE;;QAmGuB,qBAAgB,GAAQ,EAAE,CAAA;IA0CxD,CAAC;aA5IQ,WAAM,GAAG;QACd,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA8FF;KACF,AAhGY,CAgGZ;IAID,MAAM;QACJ,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,gBAAgB,IAAI,EAAE,CAAA;QAC5F,MAAM,EAAE,YAAY,EAAE,GAAG,QAAQ,IAAI,EAAE,CAAA;QAEvC,OAAO,IAAI,CAAA;;;mBAGI,GAAG,EAAE;YACZ,aAAa,CAAC,uBAAuB,EAAE;gBACrC,QAAQ,EAAE,IAAI,CAAA;oCACQ,IAAI,CAAC,gBAAgB;wBACjC,KAAK;qDACwB;aACxC,CAAC,CAAA;QACJ,CAAC;;;UAGD,WAAW;;QAEb,YAAY,IAAI,OAAO,IAAI,QAAQ;YACnC,CAAC,CAAC,IAAI,CAAA;;gBAEE,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC;sBACrB,QAAQ,EAAE,IAAI;;WAEzB;YACH,CAAC,CAAC,IAAI,CAAA,EAAE;QACR,YAAY,CAAC,CAAC,CAAC,IAAI,CAAA,+BAA+B,YAAY,yBAAyB,CAAC,CAAC,CAAC,IAAI,CAAA,EAAE;;mBAErF,OAAO,CAAC,CAAC,CAAC,uBAAuB,GAAG,KAAK,CAAC;KACxD,CAAA;IACH,CAAC;IAED,OAAO,CAAC,OAAO;QACb,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC7D,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAA;YAEvC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QACnC,CAAC;IACH,CAAC;;AAzC2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;+DAA2B;AAnG3C,qBAAqB;IADjC,aAAa,CAAC,yBAAyB,CAAC;GAC5B,qBAAqB,CA6IjC","sourcesContent":["import '@material/web/button/elevated-button.js'\nimport '@operato/property-editor/ox-properties-dynamic-view.js'\nimport '@things-factory/organization/dist-client/component/approval-line-brief.js'\nimport '../templates/activity-instance-context-template.js'\n\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { toggleOverlay } from '@operato/layout'\n\n@customElement('activity-instance-ribon')\nexport class ActivityInstanceRibon extends localize(i18next)(LitElement) {\n static styles = [\n css`\n :host {\n display: flex;\n background-color: var(--worklist-status-color);\n color: var(--md-sys-color-on-primary);\n align-items: center;\n min-height: 44px;\n --fontsize-small: 12px;\n }\n\n div {\n border-left: var(--border-dim-color);\n padding: var(--spacing-small) var(--spacing-medium);\n align-self: center;\n }\n\n :host([state='draft']) {\n --worklist-status-color: #5f7184;\n }\n\n :host([state='issued']) {\n --worklist-status-color: #56af45;\n }\n\n :host([state='assigned']) {\n --worklist-status-color: #428df3;\n }\n\n :host([state='started']) {\n --worklist-status-color: #595de5;\n }\n\n :host([state='pending']) {\n --worklist-status-color: #f27429;\n }\n\n :host([state='ended']) {\n --worklist-status-color: #02acae;\n }\n\n :host([state='aborted']) {\n --worklist-status-color: #cb3a33;\n }\n\n md-icon {\n font-size: 24px;\n }\n\n [desc] {\n flex: 2;\n font-size: var(--fontsize-small);\n }\n\n [desc] * {\n vertical-align: middle;\n }\n\n [assignee] {\n text-align: center;\n font-size: var(--fontsize-small);\n line-height: 1.3;\n }\n\n [assignee] span {\n display: block;\n font-size: var(--fontsize-large);\n font-weight: bold;\n }\n\n approval-line-brief {\n background-color: var(--worklist-status-color);\n font-size: var(--fontsize-small);\n }\n\n [state] {\n text-align: right;\n font-size: var(--fontsize-small);\n font-weight: bold;\n }\n\n @media only screen and (max-width: 460px) {\n div {\n border-left: none;\n }\n [assignee] {\n display: none;\n }\n md-icon {\n padding: 0;\n }\n approval-line-brief {\n display: none;\n }\n }\n `\n ]\n\n @property({ type: Object }) activityInstance: any = {}\n\n render() {\n const { description, state, assignee, approvalLine, activity } = this.activityInstance || {}\n const { startingType } = activity || {}\n\n return html`\n <div desc>\n <md-icon\n @click=${() => {\n toggleOverlay('activity-info-overlay', {\n template: html`<activity-instance-context-template\n .activityInstance=${this.activityInstance}\n state=${state}\n ></activity-instance-context-template>`\n })\n }}\n >description</md-icon\n >\n ${description}\n </div>\n ${startingType == 'issue' && assignee\n ? html`\n <div assignee>\n ${i18next.t('field.assignee')}\n <span>${assignee?.name}&nbsp;</span>\n </div>\n `\n : html``}\n ${approvalLine ? html`<approval-line-brief .model=${approvalLine}></approval-line-brief>` : html``}\n\n <div state>${i18next.t('label.activity-state-' + state)}</div>\n `\n }\n\n updated(changes) {\n if (changes.has('activityInstance') && this.activityInstance) {\n const { state } = this.activityInstance\n\n this.setAttribute('state', state)\n }\n }\n}\n"]}
1
+ {"version":3,"file":"activity-instance-ribon.js","sourceRoot":"","sources":["../../client/components/activity-instance-ribon.ts"],"names":[],"mappings":";AAAA,OAAO,yCAAyC,CAAA;AAChD,OAAO,wDAAwD,CAAA;AAC/D,OAAO,2EAA2E,CAAA;AAClF,OAAO,oDAAoD,CAAA;AAE3D,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AACtC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE3D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAG5C,IAAM,qBAAqB,GAA3B,MAAM,qBAAsB,SAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC;IAAjE;;QAGuB,qBAAgB,GAAQ,EAAE,CAAA;IA0ExD,CAAC;aA5EQ,WAAM,GAAG,CAAC,gBAAgB,CAAC,AAArB,CAAqB;IAIlC,MAAM;QACJ,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,gBAAgB,IAAI,EAAE,CAAA;QAC5F,MAAM,EAAE,YAAY,EAAE,GAAG,QAAQ,IAAI,EAAE,CAAA;QAEvC,OAAO,IAAI,CAAA;;;UAGL,OAAO,CAAC,CAAC,CAAC,uBAAuB,GAAG,KAAK,CAAC;;;;;;;gBAOpC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;iBACrC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;mBACxB,CAAC,CAAgB,EAAE,EAAE;YAC9B,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;gBACvC,CAAC,CAAC,cAAc,EAAE,CAAA;gBAClB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;YACtB,CAAC;QACH,CAAC;;;;iCAIwB,WAAW,IAAI,EAAE,IAAI,WAAW,IAAI,EAAE;;;QAG/D,YAAY,IAAI,OAAO,IAAI,QAAQ;YACnC,CAAC,CAAC,IAAI,CAAA,6CAA6C,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,UAAU,QAAQ,EAAE,IAAI,SAAS;YAC/G,CAAC,CAAC,EAAE;;;;;;QAMJ,YAAY,CAAC,CAAC,CAAC,IAAI,CAAA,+BAA+B,YAAY,yBAAyB,CAAC,CAAC,CAAC,EAAE;KAC/F,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACK,QAAQ,CAAC,KAAa;QAC5B,SAAS,CACP,IAAI,CAAA,yDAAyD,IAAI,CAAC,gBAAgB,UAAU,KAAK,wCAAwC,EACzI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,EAAE,CAC1C,CAAA;IACH,CAAC;IAED,OAAO,CAAC,OAAO;QACb,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC7D,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAA;YAEvC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QACnC,CAAC;IACH,CAAC;;AAzE2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;+DAA2B;AAH3C,qBAAqB;IADjC,aAAa,CAAC,yBAAyB,CAAC;GAC5B,qBAAqB,CA6EjC","sourcesContent":["import '@material/web/button/elevated-button.js'\nimport '@operato/property-editor/ox-properties-dynamic-view.js'\nimport '@things-factory/organization/dist-client/component/approval-line-brief.js'\nimport '../templates/activity-instance-context-template.js'\n\nimport { html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { openPopup } from '@operato/layout'\n\nimport { StateRibonStyles } from './state-ribon.js'\n\n@customElement('activity-instance-ribon')\nexport class ActivityInstanceRibon extends localize(i18next)(LitElement) {\n static styles = [StateRibonStyles]\n\n @property({ type: Object }) activityInstance: any = {}\n\n render() {\n const { description, state, assignee, approvalLine, activity } = this.activityInstance || {}\n const { startingType } = activity || {}\n\n return html`\n <span class=\"state\">\n <i class=\"dot\"></i>\n ${i18next.t('label.activity-state-' + state)}\n </span>\n\n <md-icon\n class=\"info\"\n role=\"button\"\n tabindex=\"0\"\n title=${String(i18next.t('label.thread-info'))}\n @click=${() => this.openInfo(state)}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.openInfo(state)\n }\n }}\n >info</md-icon\n >\n\n <span class=\"desc\" title=${description || ''}>${description || ''}</span>\n\n\n ${startingType == 'issue' && assignee\n ? html`<span class=\"who\"><span class=\"who-label\">${i18next.t('field.assignee')}</span>${assignee?.name}</span>`\n : ''}\n <!--\n 결재선의 현재 단계를 넘기지 않는다 — 이 ribbon 이 쓰이는 곳은 업무를 시작하는 화면\n 하나뿐이고(activity-instance-start-page), 거기서는 아직 아무도 판단하지 않았다.\n approval-line-brief 는 값이 없으면 기안자를 현재로 표시하는데, 이 화면에서는 그것이 맞다.\n -->\n ${approvalLine ? html`<approval-line-brief .model=${approvalLine}></approval-line-brief>` : ''}\n `\n }\n\n /**\n * 이 건의 기본 정보 — **팝업으로 연다.**\n *\n * ── 왜 aside 가 아닌가 (2026-09-06) ────────────────────────────────────\n * 전에는 화면 오른쪽에서 나오는 aside 판이었다. 두 가지가 걸린다.\n *\n * 자리를 다툰다 화면 오른쪽 세로 판은 operato-twin twin-entity360 이 쓰는 자리다\n * (position: fixed · right: 0 · height: 100vh). 같은 자리에 둘이 선다.\n * 전역 슬롯이다 VIEWPART_POSITION.ASIDEBAR 은 앱이 하나만 갖는다. 열 개가 넘는 패키지가\n * 그 자리를 쓰고 있어(twin 의 AI 협의 도크 · board-ui · help · more-ui …),\n * 이 판을 열면 그중 열려 있던 것이 닫힌다.\n *\n * 그리고 자리의 뜻이 다르다. 오른쪽 드로어는 **보고 있는 대상을 따라다니는 상세**이고(360 이\n * 그것이다 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 판은 **이 화면의 건**에\n * 대한 것이라 화면을 벗어나면 뜻이 없다. 페이지에 매인 것을 앱 전역 자리에 두지 않는다.\n *\n * 내용도 팝업 크기다 — 값 여덟 줄과 접힌 타임라인이라 세로 100vh 를 쓸 일이 없었다.\n */\n private openInfo(state: string) {\n openPopup(\n html`<activity-instance-context-template .activityInstance=${this.activityInstance} state=${state}></activity-instance-context-template>`,\n { title: i18next.t('label.thread-info') }\n )\n }\n\n updated(changes) {\n if (changes.has('activityInstance') && this.activityInstance) {\n const { state } = this.activityInstance\n\n this.setAttribute('state', state)\n }\n }\n}\n"]}
@@ -4,10 +4,35 @@ import '@things-factory/organization/dist-client/component/approval-line-brief.j
4
4
  import '../templates/activity-thread-context-template.js';
5
5
  import { LitElement } from 'lit';
6
6
  declare const ActivityThreadRibon_base: (new (...args: any[]) => LitElement) & typeof LitElement;
7
+ /**
8
+ * 업무 하나의 머리 — **지금 어떤 상태이고, 누구 손에 있나.**
9
+ *
10
+ * 모양은 `state-ribon.ts` 가 정한다(그 파일의 머리말에 왜 채운 띠를 걷었는지 적어 두었다).
11
+ * 여기서는 이 화면이 무엇을 보일지만 고른다.
12
+ */
7
13
  export declare class ActivityThreadRibon extends ActivityThreadRibon_base {
8
14
  static styles: import("lit").CSSResult[];
9
15
  activityThread: any;
10
16
  render(): import("lit-html").TemplateResult<1>;
17
+ /**
18
+ * 이 건의 기본 정보 — **팝업으로 연다.**
19
+ *
20
+ * ── 왜 aside 가 아닌가 (2026-09-06) ────────────────────────────────────
21
+ * 전에는 화면 오른쪽에서 나오는 aside 판이었다. 두 가지가 걸린다.
22
+ *
23
+ * 자리를 다툰다 화면 오른쪽 세로 판은 operato-twin 의 twin-entity360 이 쓰는 자리다
24
+ * (position: fixed · right: 0 · height: 100vh). 같은 자리에 둘이 선다.
25
+ * 전역 슬롯이다 VIEWPART_POSITION.ASIDEBAR 은 앱이 하나만 갖는다. 열 개가 넘는 패키지가
26
+ * 그 자리를 쓰고 있어(twin 의 AI 협의 도크 · board-ui · help · more-ui …),
27
+ * 이 판을 열면 그중 열려 있던 것이 닫힌다.
28
+ *
29
+ * 그리고 자리의 뜻이 다르다. 오른쪽 드로어는 **보고 있는 대상을 따라다니는 상세**이고(360 이
30
+ * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 판은 **이 화면의 이 건**에
31
+ * 대한 것이라 화면을 벗어나면 뜻이 없다. 페이지에 매인 것을 앱 전역 자리에 두지 않는다.
32
+ *
33
+ * 내용도 팝업 크기다 — 값 여덟 줄과 접힌 타임라인이라 세로 100vh 를 쓸 일이 없었다.
34
+ */
35
+ private openInfo;
11
36
  updated(changes: any): void;
12
37
  }
13
38
  export {};
@@ -3,137 +3,80 @@ import '@material/web/button/elevated-button.js';
3
3
  import '@operato/property-editor/ox-properties-dynamic-view.js';
4
4
  import '@things-factory/organization/dist-client/component/approval-line-brief.js';
5
5
  import '../templates/activity-thread-context-template.js';
6
- import { css, html, LitElement } from 'lit';
6
+ import { html, LitElement } from 'lit';
7
7
  import { customElement, property } from 'lit/decorators.js';
8
8
  import { i18next, localize } from '@operato/i18n';
9
- import { toggleOverlay } from '@operato/layout';
9
+ import { openPopup } from '@operato/layout';
10
+ import { currentApprovalOrder } from '../approval-progress.js';
11
+ import { StateRibonStyles } from './state-ribon.js';
12
+ /**
13
+ * 업무 하나의 머리 — **지금 어떤 상태이고, 누구 손에 있나.**
14
+ *
15
+ * 모양은 `state-ribon.ts` 가 정한다(그 파일의 머리말에 왜 채운 띠를 걷었는지 적어 두었다).
16
+ * 여기서는 이 화면이 무엇을 보일지만 고른다.
17
+ */
10
18
  let ActivityThreadRibon = class ActivityThreadRibon extends localize(i18next)(LitElement) {
11
- static { this.styles = [
12
- css `
13
- :host {
14
- display: flex;
15
- background-color: var(--worklist-status-color);
16
- color: var(--md-sys-color-on-primary);
17
- align-items: center;
18
- min-height: 44px;
19
- --fontsize-small: 12px;
20
- }
21
-
22
- div {
23
- border-left: var(--border-dim-color);
24
- padding: var(--spacing-small) var(--spacing-medium);
25
- align-self: center;
26
- }
27
-
28
- :host([state='unassigned']) {
29
- --worklist-status-color: #5f7184;
30
- }
31
-
32
- :host([state='assigned']) {
33
- --worklist-status-color: #5f7184;
34
- }
35
-
36
- :host([state='started']) {
37
- --worklist-status-color: #56af45;
38
- }
39
-
40
- :host([state='delegated']) {
41
- --worklist-status-color: #8654b0;
42
- }
43
-
44
- :host([state='submitted']) {
45
- --worklist-status-color: #428df3;
46
- }
47
-
48
- :host([state='escalated']) {
49
- --worklist-status-color: #595de5;
50
- }
51
-
52
- :host([state='rejected']) {
53
- --worklist-status-color: #f27429;
54
- }
55
-
56
- :host([state='ended']) {
57
- --worklist-status-color: #02acae;
58
- }
59
-
60
- :host([state='aborted']) {
61
- --worklist-status-color: #cb3a33;
62
- }
63
-
64
- md-icon {
65
- font-size: 24px;
66
- }
67
-
68
- [desc] {
69
- flex: 2;
70
- font-size: var(--fontsize-small);
71
- }
72
-
73
- [desc] * {
74
- vertical-align: middle;
75
- }
76
-
77
- div[assignee] {
78
- display: flex;
79
- align-items: center;
80
- text-align: center;
81
- }
82
-
83
- approval-line-brief {
84
- background-color: var(--worklist-status-color);
85
- font-size: var(--fontsize-small);
86
- }
87
-
88
- [state] {
89
- text-align: right;
90
- font-size: var(--fontsize-small);
91
- }
92
-
93
- @media only screen and (max-width: 460px) {
94
- div {
95
- border-left: none;
96
- }
97
- [assignee] {
98
- display: none;
99
- }
100
- md-icon {
101
- padding: 0;
102
- }
103
- approval-line-brief {
104
- display: none;
105
- }
106
- }
107
- `
108
- ]; }
19
+ static { this.styles = [StateRibonStyles]; }
109
20
  render() {
110
- const { state, assignee, activityInstance } = this.activityThread;
111
- const { description, approvalLine, activity } = activityInstance || {};
112
- const { startingType } = activity || {};
21
+ const { state, assignee, activityInstance, activityApprovals } = this.activityThread;
22
+ const { description, approvalLine } = activityInstance || {};
113
23
  return html `
114
- <div desc>
115
- <md-icon
116
- @click=${() => {
117
- toggleOverlay('activity-info-overlay', {
118
- template: html `<activity-thread-context-template
119
- .activityThread=${this.activityThread}
120
- state=${state}
121
- ></activity-thread-context-template>`
122
- });
24
+ <span class="state">
25
+ <i class="dot"></i>
26
+ ${i18next.t('label.activity-state-' + state)}
27
+ </span>
28
+
29
+ <md-icon
30
+ class="info"
31
+ role="button"
32
+ tabindex="0"
33
+ title=${String(i18next.t('label.thread-info'))}
34
+ @click=${() => this.openInfo(state)}
35
+ @keydown=${(e) => {
36
+ if (e.key === 'Enter' || e.key === ' ') {
37
+ e.preventDefault();
38
+ this.openInfo(state);
39
+ }
123
40
  }}
124
- >description</md-icon
125
- >
126
- ${description}
127
- </div>
41
+ >info</md-icon
42
+ >
43
+
44
+ <span class="desc" title=${description || ''}>${description || ''}</span>
45
+
46
+
128
47
  ${approvalLine
129
- ? html `<approval-line-brief .model=${approvalLine}></approval-line-brief>`
48
+ ? html `<approval-line-brief
49
+ .model=${approvalLine}
50
+ .current=${currentApprovalOrder(activityApprovals)}
51
+ ></approval-line-brief>`
130
52
  : assignee
131
- ? html ` <div assignee title=${String(i18next.t('field.assignee'))}>${assignee?.name}&nbsp;</div> `
132
- : html ``}
133
-
134
- <div state title=${String(i18next.t('field.status'))}>${i18next.t('label.activity-state-' + state)}</div>
53
+ ? html `<span class="who"
54
+ ><span class="who-label">${i18next.t('field.assignee')}</span>${assignee?.name}</span
55
+ >`
56
+ : ''}
135
57
  `;
136
58
  }
59
+ /**
60
+ * 이 건의 기본 정보 — **팝업으로 연다.**
61
+ *
62
+ * ── 왜 aside 가 아닌가 (2026-09-06) ────────────────────────────────────
63
+ * 전에는 화면 오른쪽에서 나오는 aside 판이었다. 두 가지가 걸린다.
64
+ *
65
+ * 자리를 다툰다 화면 오른쪽 세로 판은 operato-twin 의 twin-entity360 이 쓰는 자리다
66
+ * (position: fixed · right: 0 · height: 100vh). 같은 자리에 둘이 선다.
67
+ * 전역 슬롯이다 VIEWPART_POSITION.ASIDEBAR 은 앱이 하나만 갖는다. 열 개가 넘는 패키지가
68
+ * 그 자리를 쓰고 있어(twin 의 AI 협의 도크 · board-ui · help · more-ui …),
69
+ * 이 판을 열면 그중 열려 있던 것이 닫힌다.
70
+ *
71
+ * 그리고 자리의 뜻이 다르다. 오른쪽 드로어는 **보고 있는 대상을 따라다니는 상세**이고(360 이
72
+ * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 판은 **이 화면의 이 건**에
73
+ * 대한 것이라 화면을 벗어나면 뜻이 없다. 페이지에 매인 것을 앱 전역 자리에 두지 않는다.
74
+ *
75
+ * 내용도 팝업 크기다 — 값 여덟 줄과 접힌 타임라인이라 세로 100vh 를 쓸 일이 없었다.
76
+ */
77
+ openInfo(state) {
78
+ openPopup(html `<activity-thread-context-template .activityThread=${this.activityThread} state=${state}></activity-thread-context-template>`, { title: i18next.t('label.thread-info') });
79
+ }
137
80
  updated(changes) {
138
81
  if (changes.has('activityThread') && this.activityThread) {
139
82
  const { state } = this.activityThread;
@@ -1 +1 @@
1
- {"version":3,"file":"activity-thread-ribon.js","sourceRoot":"","sources":["../../client/components/activity-thread-ribon.ts"],"names":[],"mappings":";AAAA,OAAO,yCAAyC,CAAA;AAChD,OAAO,wDAAwD,CAAA;AAC/D,OAAO,2EAA2E,CAAA;AAClF,OAAO,kDAAkD,CAAA;AAEzD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAS,MAAM,mBAAmB,CAAA;AAElE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAGxC,IAAM,mBAAmB,GAAzB,MAAM,mBAAoB,SAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC;aAC7D,WAAM,GAAG;QACd,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA+FF;KACF,AAjGY,CAiGZ;IAID,MAAM;QACJ,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC,cAAc,CAAA;QACjE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,gBAAgB,IAAI,EAAE,CAAA;QACtE,MAAM,EAAE,YAAY,EAAE,GAAG,QAAQ,IAAI,EAAE,CAAA;QAEvC,OAAO,IAAI,CAAA;;;mBAGI,GAAG,EAAE;YACZ,aAAa,CAAC,uBAAuB,EAAE;gBACrC,QAAQ,EAAE,IAAI,CAAA;kCACM,IAAI,CAAC,cAAc;wBAC7B,KAAK;mDACsB;aACtC,CAAC,CAAA;QACJ,CAAC;;;UAGD,WAAW;;QAEb,YAAY;YACZ,CAAC,CAAC,IAAI,CAAA,+BAA+B,YAAY,yBAAyB;YAC1E,CAAC,CAAC,QAAQ;gBACR,CAAC,CAAC,IAAI,CAAA,wBAAwB,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,IAAI,QAAQ,EAAE,IAAI,eAAe;gBAClG,CAAC,CAAC,IAAI,CAAA,EAAE;;yBAEO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,uBAAuB,GAAG,KAAK,CAAC;KACnG,CAAA;IACH,CAAC;IAED,OAAO,CAAC,OAAO;QACb,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACzD,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,cAAc,CAAA;YAErC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QACnC,CAAC;IACH,CAAC;;AAtC2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;2DAAoB;AApGpC,mBAAmB;IAD/B,aAAa,CAAC,uBAAuB,CAAC;GAC1B,mBAAmB,CA2I/B","sourcesContent":["import '@material/web/button/elevated-button.js'\nimport '@operato/property-editor/ox-properties-dynamic-view.js'\nimport '@things-factory/organization/dist-client/component/approval-line-brief.js'\nimport '../templates/activity-thread-context-template.js'\n\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { toggleOverlay } from '@operato/layout'\n\n@customElement('activity-thread-ribon')\nexport class ActivityThreadRibon extends localize(i18next)(LitElement) {\n static styles = [\n css`\n :host {\n display: flex;\n background-color: var(--worklist-status-color);\n color: var(--md-sys-color-on-primary);\n align-items: center;\n min-height: 44px;\n --fontsize-small: 12px;\n }\n\n div {\n border-left: var(--border-dim-color);\n padding: var(--spacing-small) var(--spacing-medium);\n align-self: center;\n }\n\n :host([state='unassigned']) {\n --worklist-status-color: #5f7184;\n }\n\n :host([state='assigned']) {\n --worklist-status-color: #5f7184;\n }\n\n :host([state='started']) {\n --worklist-status-color: #56af45;\n }\n\n :host([state='delegated']) {\n --worklist-status-color: #8654b0;\n }\n\n :host([state='submitted']) {\n --worklist-status-color: #428df3;\n }\n\n :host([state='escalated']) {\n --worklist-status-color: #595de5;\n }\n\n :host([state='rejected']) {\n --worklist-status-color: #f27429;\n }\n\n :host([state='ended']) {\n --worklist-status-color: #02acae;\n }\n\n :host([state='aborted']) {\n --worklist-status-color: #cb3a33;\n }\n\n md-icon {\n font-size: 24px;\n }\n\n [desc] {\n flex: 2;\n font-size: var(--fontsize-small);\n }\n\n [desc] * {\n vertical-align: middle;\n }\n\n div[assignee] {\n display: flex;\n align-items: center;\n text-align: center;\n }\n\n approval-line-brief {\n background-color: var(--worklist-status-color);\n font-size: var(--fontsize-small);\n }\n\n [state] {\n text-align: right;\n font-size: var(--fontsize-small);\n }\n\n @media only screen and (max-width: 460px) {\n div {\n border-left: none;\n }\n [assignee] {\n display: none;\n }\n md-icon {\n padding: 0;\n }\n approval-line-brief {\n display: none;\n }\n }\n `\n ]\n\n @property({ type: Object }) activityThread: any\n\n render() {\n const { state, assignee, activityInstance } = this.activityThread\n const { description, approvalLine, activity } = activityInstance || {}\n const { startingType } = activity || {}\n\n return html`\n <div desc>\n <md-icon\n @click=${() => {\n toggleOverlay('activity-info-overlay', {\n template: html`<activity-thread-context-template\n .activityThread=${this.activityThread}\n state=${state}\n ></activity-thread-context-template>`\n })\n }}\n >description</md-icon\n >\n ${description}\n </div>\n ${approvalLine\n ? html`<approval-line-brief .model=${approvalLine}></approval-line-brief>`\n : assignee\n ? html` <div assignee title=${String(i18next.t('field.assignee'))}>${assignee?.name}&nbsp;</div> `\n : html``}\n\n <div state title=${String(i18next.t('field.status'))}>${i18next.t('label.activity-state-' + state)}</div>\n `\n }\n\n updated(changes) {\n if (changes.has('activityThread') && this.activityThread) {\n const { state } = this.activityThread\n\n this.setAttribute('state', state)\n }\n }\n}\n"]}
1
+ {"version":3,"file":"activity-thread-ribon.js","sourceRoot":"","sources":["../../client/components/activity-thread-ribon.ts"],"names":[],"mappings":";AAAA,OAAO,yCAAyC,CAAA;AAChD,OAAO,wDAAwD,CAAA;AAC/D,OAAO,2EAA2E,CAAA;AAClF,OAAO,kDAAkD,CAAA;AAEzD,OAAO,EAAO,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE3D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAEnD;;;;;GAKG;AAEI,IAAM,mBAAmB,GAAzB,MAAM,mBAAoB,SAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC;aAC7D,WAAM,GAAG,CAAC,gBAAgB,CAAC,AAArB,CAAqB;IAIlC,MAAM;QACJ,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAC,cAAc,CAAA;QACpF,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,gBAAgB,IAAI,EAAE,CAAA;QAE5D,OAAO,IAAI,CAAA;;;UAGL,OAAO,CAAC,CAAC,CAAC,uBAAuB,GAAG,KAAK,CAAC;;;;;;;gBAOpC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;iBACrC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;mBACxB,CAAC,CAAgB,EAAE,EAAE;YAC9B,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;gBACvC,CAAC,CAAC,cAAc,EAAE,CAAA;gBAClB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;YACtB,CAAC;QACH,CAAC;;;;iCAIwB,WAAW,IAAI,EAAE,IAAI,WAAW,IAAI,EAAE;;;QAG/D,YAAY;YACZ,CAAC,CAAC,IAAI,CAAA;qBACO,YAAY;uBACV,oBAAoB,CAAC,iBAAiB,CAAC;kCAC5B;YAC1B,CAAC,CAAC,QAAQ;gBACR,CAAC,CAAC,IAAI,CAAA;yCACyB,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,UAAU,QAAQ,EAAE,IAAI;cAC9E;gBACJ,CAAC,CAAC,EAAE;KACT,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACK,QAAQ,CAAC,KAAa;QAC5B,SAAS,CACP,IAAI,CAAA,qDAAqD,IAAI,CAAC,cAAc,UAAU,KAAK,sCAAsC,EACjI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,EAAE,CAC1C,CAAA;IACH,CAAC;IAED,OAAO,CAAC,OAAO;QACb,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACzD,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,cAAc,CAAA;YAErC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QACnC,CAAC;IACH,CAAC;;AA1E2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;2DAAoB;AAHpC,mBAAmB;IAD/B,aAAa,CAAC,uBAAuB,CAAC;GAC1B,mBAAmB,CA8E/B","sourcesContent":["import '@material/web/button/elevated-button.js'\nimport '@operato/property-editor/ox-properties-dynamic-view.js'\nimport '@things-factory/organization/dist-client/component/approval-line-brief.js'\nimport '../templates/activity-thread-context-template.js'\n\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { openPopup } from '@operato/layout'\n\nimport { currentApprovalOrder } from '../approval-progress.js'\nimport { StateRibonStyles } from './state-ribon.js'\n\n/**\n * 업무 하나의 머리 — **지금 어떤 상태이고, 누구 손에 있나.**\n *\n * 모양은 `state-ribon.ts` 가 정한다(그 파일의 머리말에 왜 채운 띠를 걷었는지 적어 두었다).\n * 여기서는 이 화면이 무엇을 보일지만 고른다.\n */\n@customElement('activity-thread-ribon')\nexport class ActivityThreadRibon extends localize(i18next)(LitElement) {\n static styles = [StateRibonStyles]\n\n @property({ type: Object }) activityThread: any\n\n render() {\n const { state, assignee, activityInstance, activityApprovals } = this.activityThread\n const { description, approvalLine } = activityInstance || {}\n\n return html`\n <span class=\"state\">\n <i class=\"dot\"></i>\n ${i18next.t('label.activity-state-' + state)}\n </span>\n\n <md-icon\n class=\"info\"\n role=\"button\"\n tabindex=\"0\"\n title=${String(i18next.t('label.thread-info'))}\n @click=${() => this.openInfo(state)}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.openInfo(state)\n }\n }}\n >info</md-icon\n >\n\n <span class=\"desc\" title=${description || ''}>${description || ''}</span>\n\n\n ${approvalLine\n ? html`<approval-line-brief\n .model=${approvalLine}\n .current=${currentApprovalOrder(activityApprovals)}\n ></approval-line-brief>`\n : assignee\n ? html`<span class=\"who\"\n ><span class=\"who-label\">${i18next.t('field.assignee')}</span>${assignee?.name}</span\n >`\n : ''}\n `\n }\n\n /**\n * 건의 기본 정보 — **팝업으로 연다.**\n *\n * ── 왜 aside 가 아닌가 (2026-09-06) ────────────────────────────────────\n * 전에는 화면 오른쪽에서 나오는 aside 판이었다. 두 가지가 걸린다.\n *\n * 자리를 다툰다 화면 오른쪽 세로 판은 operato-twin 의 twin-entity360 이 쓰는 자리다\n * (position: fixed · right: 0 · height: 100vh). 같은 자리에 둘이 선다.\n * 전역 슬롯이다 VIEWPART_POSITION.ASIDEBAR 은 앱이 하나만 갖는다. 열 개가 넘는 패키지가\n * 그 자리를 쓰고 있어(twin 의 AI 협의 도크 · board-ui · help · more-ui …),\n * 이 판을 열면 그중 열려 있던 것이 닫힌다.\n *\n * 그리고 자리의 뜻이 다르다. 오른쪽 드로어는 **보고 있는 대상을 따라다니는 상세**이고(360 이\n * 그것이다 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 판은 **이 화면의 건**에\n * 대한 것이라 화면을 벗어나면 뜻이 없다. 페이지에 매인 것을 앱 전역 자리에 두지 않는다.\n *\n * 내용도 팝업 크기다 — 값 여덟 줄과 접힌 타임라인이라 세로 100vh 를 쓸 일이 없었다.\n */\n private openInfo(state: string) {\n openPopup(\n html`<activity-thread-context-template .activityThread=${this.activityThread} state=${state}></activity-thread-context-template>`,\n { title: i18next.t('label.thread-info') }\n )\n }\n\n updated(changes) {\n if (changes.has('activityThread') && this.activityThread) {\n const { state } = this.activityThread\n\n this.setAttribute('state', state)\n }\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import '@material/web/icon/icon.js';
2
2
  import '@things-factory/organization/dist-client/component/approval-line-view.js';
3
- import { LitElement } from 'lit';
3
+ import { LitElement, nothing } from 'lit';
4
4
  import { ActivityThread } from '../types/activity-thread.js';
5
5
  import { ActivityThreadHistory } from '../types/activity-thread-history.js';
6
6
  import { ActivityApproval } from '../types/activity-approval.js';
@@ -9,8 +9,20 @@ export declare class ActivityThreadTimeline extends LitElement {
9
9
  activityThread?: ActivityThread;
10
10
  subtitle?: string;
11
11
  shortForm?: boolean;
12
- render(): import("lit-html").TemplateResult<1>;
12
+ /**
13
+ * 펴 둘 것인가 — **담는 화면이 정한다.**
14
+ *
15
+ * 기본은 접는다. 펴는 곳은 둘이다.
16
+ * 완료 조회 지난 일을 보러 온 화면이라 이력이 곧 본문이다
17
+ * 보일 항목 없음 화면이 「타임라인의 상신 사유를 보고 판단하세요」로 여기를 가리킨다
18
+ */
19
+ open?: boolean;
20
+ render(): import("lit-html").TemplateResult<1> | typeof nothing;
21
+ /** 접혔을 때 보이는 한 줄 — 마지막 기록의 「무엇을 · 누가 · 언제」. */
22
+ lastLine(item: any): string;
13
23
  renderActivityThreadHistory(activityThreadHistory: ActivityThreadHistory): import("lit-html").TemplateResult<1>;
14
24
  renderActivityApproval(activityApproval: ActivityApproval): import("lit-html").TemplateResult<1>;
25
+ /** 적힌 말이 없으면 상자를 그리지 않는다 — 빈 회색 상자는 내용이 있는 줄과 구별되지 않는다. */
26
+ renderSaid(said?: string): import("lit-html").TemplateResult<1> | typeof nothing;
15
27
  renderOutput(output: any): string;
16
28
  }