@things-factory/worklist 10.1.4 → 10.1.6

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 (71) hide show
  1. package/dist-client/components/activity-approval-ribon.js +17 -2
  2. package/dist-client/components/activity-approval-ribon.js.map +1 -1
  3. package/dist-client/components/decision-slots.d.ts +89 -0
  4. package/dist-client/components/decision-slots.js +111 -0
  5. package/dist-client/components/decision-slots.js.map +1 -0
  6. package/dist-client/pages/activity-approval/activity-approval-page.d.ts +72 -0
  7. package/dist-client/pages/activity-approval/activity-approval-page.js +425 -43
  8. package/dist-client/pages/activity-approval/activity-approval-page.js.map +1 -1
  9. package/dist-client/pages/activity-catalog/activity-catalog-page.d.ts +24 -0
  10. package/dist-client/pages/activity-catalog/activity-catalog-page.js +101 -6
  11. package/dist-client/pages/activity-catalog/activity-catalog-page.js.map +1 -1
  12. package/dist-client/pages/installable-activity/installable-activity-list-page.d.ts +27 -0
  13. package/dist-client/pages/installable-activity/installable-activity-list-page.js +70 -11
  14. package/dist-client/pages/installable-activity/installable-activity-list-page.js.map +1 -1
  15. package/dist-client/route.d.ts +1 -1
  16. package/dist-client/tsconfig.tsbuildinfo +1 -1
  17. package/dist-server/controllers/activity-approval/approval-line.d.ts +32 -0
  18. package/dist-server/controllers/activity-approval/approval-line.js +35 -0
  19. package/dist-server/controllers/activity-approval/approval-line.js.map +1 -1
  20. package/dist-server/controllers/activity-approval/approve.js +17 -0
  21. package/dist-server/controllers/activity-approval/approve.js.map +1 -1
  22. package/dist-server/controllers/activity-approval/reject.js +21 -1
  23. package/dist-server/controllers/activity-approval/reject.js.map +1 -1
  24. package/dist-server/controllers/activity-installation/activity-installation-controller.js +5 -9
  25. package/dist-server/controllers/activity-installation/activity-installation-controller.js.map +1 -1
  26. package/dist-server/controllers/activity-installation/installable-to-activity.d.ts +49 -0
  27. package/dist-server/controllers/activity-installation/installable-to-activity.js +40 -0
  28. package/dist-server/controllers/activity-installation/installable-to-activity.js.map +1 -0
  29. package/dist-server/controllers/activity-installation/registry-conflict.d.ts +32 -0
  30. package/dist-server/controllers/activity-installation/registry-conflict.js +21 -0
  31. package/dist-server/controllers/activity-installation/registry-conflict.js.map +1 -0
  32. package/dist-server/service/activity/activity-decision-key-item-type.d.ts +160 -0
  33. package/dist-server/service/activity/activity-decision-key-item-type.js +176 -0
  34. package/dist-server/service/activity/activity-decision-key-item-type.js.map +1 -0
  35. package/dist-server/service/activity/activity-type.d.ts +3 -0
  36. package/dist-server/service/activity/activity-type.js +8 -0
  37. package/dist-server/service/activity/activity-type.js.map +1 -1
  38. package/dist-server/service/activity/activity.d.ts +30 -0
  39. package/dist-server/service/activity/activity.js +14 -0
  40. package/dist-server/service/activity/activity.js.map +1 -1
  41. package/dist-server/service/activity/decision-key-declaration.d.ts +33 -0
  42. package/dist-server/service/activity/decision-key-declaration.js +67 -0
  43. package/dist-server/service/activity/decision-key-declaration.js.map +1 -0
  44. package/dist-server/service/activity/{credential-guard-subscriber.d.ts → declaration-guard-subscriber.d.ts} +6 -1
  45. package/dist-server/service/activity/declaration-guard-subscriber.js +46 -0
  46. package/dist-server/service/activity/declaration-guard-subscriber.js.map +1 -0
  47. package/dist-server/service/activity/index.d.ts +3 -3
  48. package/dist-server/service/activity/index.js +2 -2
  49. package/dist-server/service/activity/index.js.map +1 -1
  50. package/dist-server/service/activity/search-key-declaration.d.ts +38 -0
  51. package/dist-server/service/activity/search-key-declaration.js +49 -0
  52. package/dist-server/service/activity/search-key-declaration.js.map +1 -0
  53. package/dist-server/service/activity-instance/activity-instance-type.js.map +1 -1
  54. package/dist-server/service/activity-instance/index.d.ts +1 -1
  55. package/dist-server/service/activity-template/index.d.ts +1 -1
  56. package/dist-server/service/activity-thread/index.d.ts +1 -1
  57. package/dist-server/service/index.d.ts +3 -3
  58. package/dist-server/service/installable-activity/installable-activity-mutation.js +24 -0
  59. package/dist-server/service/installable-activity/installable-activity-mutation.js.map +1 -1
  60. package/dist-server/service/installable-activity/installable-activity.d.ts +9 -0
  61. package/dist-server/service/installable-activity/installable-activity.js +5 -0
  62. package/dist-server/service/installable-activity/installable-activity.js.map +1 -1
  63. package/dist-server/tsconfig.tsbuildinfo +1 -1
  64. package/package.json +9 -9
  65. package/translations/en.json +28 -6
  66. package/translations/ja.json +22 -0
  67. package/translations/ko.json +28 -6
  68. package/translations/ms.json +22 -0
  69. package/translations/zh.json +22 -0
  70. package/dist-server/service/activity/credential-guard-subscriber.js +0 -35
  71. package/dist-server/service/activity/credential-guard-subscriber.js.map +0 -1
@@ -12,7 +12,22 @@ let ActivityApprovalRibon = class ActivityApprovalRibon extends localize(i18next
12
12
  render() {
13
13
  const { activityInstance, state } = this.activityApproval?.activityThread || {};
14
14
  const { description, assignee, approvalLine, activity } = activityInstance || {};
15
- const { startingType } = activity || {};
15
+ const { startingType, label } = activity || {};
16
+ /*
17
+ * What kind of decision this is — the activity's own name, not this instance's.
18
+ *
19
+ * Those are different facts and both belong here: 「부적합 처분 승인」 says what kind, and the
20
+ * headline the activity declares says what this one asks for. The activity's name reached only
21
+ * the catalog until it became a column on the row, so this screen showed the instance
22
+ * description alone.
23
+ *
24
+ * ── The fallback puts English on a Korean screen ──────────────────────
25
+ * Activity.description is what a developer wrote for other developers ("The disposition waiting
26
+ * for approval"), so an activity with no label shows that to the person approving. That is worse
27
+ * than the instance description and it is the reason to fill label in — it is not a fallback
28
+ * anybody should be content with.
29
+ */
30
+ const kind = label || description || '';
16
31
  return html `
17
32
  <span class="state">
18
33
  <i class="dot"></i>
@@ -34,7 +49,7 @@ let ActivityApprovalRibon = class ActivityApprovalRibon extends localize(i18next
34
49
  >info</md-icon
35
50
  >
36
51
 
37
- <span class="desc" title=${description || ''}>${description || ''}</span>
52
+ <span class="desc" title=${kind}>${kind}</span>
38
53
 
39
54
 
40
55
  ${startingType == 'issue' && assignee
@@ -1 +1 @@
1
- {"version":3,"file":"activity-approval-ribon.js","sourceRoot":"","sources":["../../client/components/activity-approval-ribon.ts"],"names":[],"mappings":";AAAA,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;aAC/D,WAAM,GAAG,CAAC,gBAAgB,CAAC,AAArB,CAAqB;IAIlC,MAAM;QACJ,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,gBAAgB,EAAE,cAAc,IAAI,EAAE,CAAA;QAC/E,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,gBAAgB,IAAI,EAAE,CAAA;QAChF,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,qBAAqB,CAAC,CAAC;iBACvC,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;QACJ,YAAY;YACZ,CAAC,CAAC,IAAI,CAAA;qBACO,YAAY;uBACV,IAAI,CAAC,gBAAgB,CAAC,KAAK;kCAChB;YAC1B,CAAC,CAAC,EAAE;KACP,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,qBAAqB,CAAC,EAAE,CAC5C,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,CAAC,cAAc,CAAA;YAEtD,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QACnC,CAAC;IACH,CAAC;;AA1E2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;+DAAsB;AAHtC,qBAAqB;IADjC,aAAa,CAAC,yBAAyB,CAAC;GAC5B,qBAAqB,CA8EjC","sourcesContent":["import '@operato/property-editor/ox-properties-dynamic-view.js'\nimport '@things-factory/organization/dist-client/component/approval-line-brief.js'\nimport '../templates/activity-approval-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-approval-ribon')\nexport class ActivityApprovalRibon extends localize(i18next)(LitElement) {\n static styles = [StateRibonStyles]\n\n @property({ type: Object }) activityApproval: any\n\n render() {\n const { activityInstance, state } = this.activityApproval?.activityThread || {}\n const { description, assignee, approvalLine, activity } = 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.approval-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 ${approvalLine\n ? html`<approval-line-brief\n .model=${approvalLine}\n .current=${this.activityApproval.order}\n ></approval-line-brief>`\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-approval-context-template .activityApproval=${this.activityApproval} state=${state}></activity-approval-context-template>`,\n { title: i18next.t('label.approval-info') }\n )\n }\n\n updated(changes) {\n if (changes.has('activityApproval') && this.activityApproval) {\n const { state } = this.activityApproval.activityThread\n\n this.setAttribute('state', state)\n }\n }\n}\n"]}
1
+ {"version":3,"file":"activity-approval-ribon.js","sourceRoot":"","sources":["../../client/components/activity-approval-ribon.ts"],"names":[],"mappings":";AAAA,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;aAC/D,WAAM,GAAG,CAAC,gBAAgB,CAAC,AAArB,CAAqB;IAIlC,MAAM;QACJ,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,gBAAgB,EAAE,cAAc,IAAI,EAAE,CAAA;QAC/E,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,gBAAgB,IAAI,EAAE,CAAA;QAChF,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,QAAQ,IAAI,EAAE,CAAA;QAE9C;;;;;;;;;;;;;WAaG;QACH,MAAM,IAAI,GAAG,KAAK,IAAI,WAAW,IAAI,EAAE,CAAA;QAEvC,OAAO,IAAI,CAAA;;;UAGL,OAAO,CAAC,CAAC,CAAC,uBAAuB,GAAG,KAAK,CAAC;;;;;;;gBAOpC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC;iBACvC,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,IAAI,IAAI,IAAI;;;QAGrC,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;QACJ,YAAY;YACZ,CAAC,CAAC,IAAI,CAAA;qBACO,YAAY;uBACV,IAAI,CAAC,gBAAgB,CAAC,KAAK;kCAChB;YAC1B,CAAC,CAAC,EAAE;KACP,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,qBAAqB,CAAC,EAAE,CAC5C,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,CAAC,cAAc,CAAA;YAEtD,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QACnC,CAAC;IACH,CAAC;;AA1F2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;+DAAsB;AAHtC,qBAAqB;IADjC,aAAa,CAAC,yBAAyB,CAAC;GAC5B,qBAAqB,CA8FjC","sourcesContent":["import '@operato/property-editor/ox-properties-dynamic-view.js'\nimport '@things-factory/organization/dist-client/component/approval-line-brief.js'\nimport '../templates/activity-approval-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-approval-ribon')\nexport class ActivityApprovalRibon extends localize(i18next)(LitElement) {\n static styles = [StateRibonStyles]\n\n @property({ type: Object }) activityApproval: any\n\n render() {\n const { activityInstance, state } = this.activityApproval?.activityThread || {}\n const { description, assignee, approvalLine, activity } = activityInstance || {}\n const { startingType, label } = activity || {}\n\n /*\n * What kind of decision this is — the activity's own name, not this instance's.\n *\n * Those are different facts and both belong here: 「부적합 처분 승인」 says what kind, and the\n * headline the activity declares says what this one asks for. The activity's name reached only\n * the catalog until it became a column on the row, so this screen showed the instance\n * description alone.\n *\n * ── The fallback puts English on a Korean screen ──────────────────────\n * Activity.description is what a developer wrote for other developers (\"The disposition waiting\n * for approval\"), so an activity with no label shows that to the person approving. That is worse\n * than the instance description and it is the reason to fill label in — it is not a fallback\n * anybody should be content with.\n */\n const kind = label || description || ''\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.approval-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=${kind}>${kind}</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 ${approvalLine\n ? html`<approval-line-brief\n .model=${approvalLine}\n .current=${this.activityApproval.order}\n ></approval-line-brief>`\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-approval-context-template .activityApproval=${this.activityApproval} state=${state}></activity-approval-context-template>`,\n { title: i18next.t('label.approval-info') }\n )\n }\n\n updated(changes) {\n if (changes.has('activityApproval') && this.activityApproval) {\n const { state } = this.activityApproval.activityThread\n\n this.setAttribute('state', state)\n }\n }\n}\n"]}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Turns an activity's decisionKeys declaration plus an instance's input into the slots a decision
3
+ * screen draws.
4
+ *
5
+ * ── Nothing is imported ───────────────────────────────────────────────────
6
+ * No lit, no i18next. The rule is a mapping from a declaration and a payload to an ordered list,
7
+ * and keeping it free of imports is what lets the test runner hold it: that runner parses
8
+ * TypeScript by stripping types and reads neither decorators nor enums, so one heavy import takes
9
+ * a whole test file down with it. Labels and markup are the caller's half.
10
+ */
11
+ /** The roles that may appear more than once. Every other role names one value. */
12
+ export declare const REPEATABLE_ROLES: readonly ["consequence", "evidence"];
13
+ /** Listed in the order the screen reads them: what is asked, then past, present, future. */
14
+ export declare const DECISION_ROLES: readonly ["headline", "subject", "reversibility", "reason", "evidence", "currentState", "consequence", "policy"];
15
+ export type DecisionKeyDeclaration = {
16
+ role?: string;
17
+ inputPath?: string;
18
+ name?: string;
19
+ tKey?: string;
20
+ unit?: string;
21
+ };
22
+ export type DecisionSlot = {
23
+ role: string;
24
+ inputPath: string;
25
+ tKey?: string;
26
+ unit?: string;
27
+ /** What the path led to. Undefined both when the path leads nowhere and when the value is unset. */
28
+ value: unknown;
29
+ /**
30
+ * Whether the path led anywhere at all.
31
+ *
32
+ * A reason nobody wrote and a reason whose path is wrong look identical in `value`, and the screen
33
+ * owes different answers: the first is 「사유 없음」 in grey, the second is a declaration that does
34
+ * not match the payload and must not be drawn as if the person left it blank. Folding them into
35
+ * one value is the fallback that shifts meaning.
36
+ */
37
+ found: boolean;
38
+ };
39
+ /**
40
+ * Reads a dotted path out of the input.
41
+ *
42
+ * Dots only. An array index or a wildcard is not part of the path language — drawing a list is the
43
+ * slot's job — so 'shift.passes[0]' looks for a key spelled "passes[0]", finds nothing, and reports
44
+ * found: false. The declaration guard refuses such a path when it arrives, so this is the second
45
+ * line rather than the first.
46
+ *
47
+ * A path that runs into a non-object partway reports found: false rather than throwing. The screen
48
+ * has to draw something either way, and a thrown error here would take the whole approval down over
49
+ * one slot.
50
+ */
51
+ export declare function valueAtPath(input: any, path: string): {
52
+ value: unknown;
53
+ found: boolean;
54
+ };
55
+ /**
56
+ * The slots to draw, in the order they were declared.
57
+ *
58
+ * Declaration order is the screen's hierarchy: plant wrote four of these screens by hand and all
59
+ * four put the headline first, then the subject, the reason, what changes, and why it came up. That
60
+ * agreement is what makes the order part of the contract rather than a preference, so this function
61
+ * neither sorts nor groups.
62
+ *
63
+ * Every declared key produces a slot, including one whose path leads nowhere. Dropping those would
64
+ * leave the screen unable to say that a declaration and a payload disagree, and a reader would see
65
+ * a screen that looks complete.
66
+ */
67
+ export declare function decisionSlots(decisionKeys: DecisionKeyDeclaration[] | null | undefined, input: any): DecisionSlot[];
68
+ /** The slots for one role, in declared order. Empty when the activity declared none. */
69
+ export declare function slotsOfRole(slots: DecisionSlot[], role: string): DecisionSlot[];
70
+ /**
71
+ * The single slot for a role that names one value, or undefined.
72
+ *
73
+ * Reaching for a second one would be reading a declaration the guard refuses, so this answers the
74
+ * first and does not quietly merge.
75
+ */
76
+ export declare function slotOfRole(slots: DecisionSlot[], role: string): DecisionSlot | undefined;
77
+ /**
78
+ * Whether approving can be undone: true, false, or undefined for "the screen does not know".
79
+ *
80
+ * Three answers, not two. A path that led nowhere and a value that is not a boolean both mean the
81
+ * payload did not say, and the screen must draw nothing then — telling an approver that an action
82
+ * can be taken back when nobody said so is the one mistake this line cannot make. Reading a
83
+ * truthy value as reversible would do exactly that, since a non-empty string is truthy.
84
+ *
85
+ * This is not rejectionIsFinal. That says whether **rejecting** ends the case for good; this says
86
+ * whether **approving** can be taken back. The twin actuation carries both, which is why they must
87
+ * never share a sentence.
88
+ */
89
+ export declare function reversibilityOf(slot?: DecisionSlot): boolean | undefined;
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Turns an activity's decisionKeys declaration plus an instance's input into the slots a decision
3
+ * screen draws.
4
+ *
5
+ * ── Nothing is imported ───────────────────────────────────────────────────
6
+ * No lit, no i18next. The rule is a mapping from a declaration and a payload to an ordered list,
7
+ * and keeping it free of imports is what lets the test runner hold it: that runner parses
8
+ * TypeScript by stripping types and reads neither decorators nor enums, so one heavy import takes
9
+ * a whole test file down with it. Labels and markup are the caller's half.
10
+ */
11
+ /** The roles that may appear more than once. Every other role names one value. */
12
+ export const REPEATABLE_ROLES = ['consequence', 'evidence'];
13
+ /** Listed in the order the screen reads them: what is asked, then past, present, future. */
14
+ export const DECISION_ROLES = [
15
+ 'headline',
16
+ 'subject',
17
+ 'reversibility',
18
+ 'reason',
19
+ 'evidence',
20
+ 'currentState',
21
+ 'consequence',
22
+ 'policy'
23
+ ];
24
+ /**
25
+ * Reads a dotted path out of the input.
26
+ *
27
+ * Dots only. An array index or a wildcard is not part of the path language — drawing a list is the
28
+ * slot's job — so 'shift.passes[0]' looks for a key spelled "passes[0]", finds nothing, and reports
29
+ * found: false. The declaration guard refuses such a path when it arrives, so this is the second
30
+ * line rather than the first.
31
+ *
32
+ * A path that runs into a non-object partway reports found: false rather than throwing. The screen
33
+ * has to draw something either way, and a thrown error here would take the whole approval down over
34
+ * one slot.
35
+ */
36
+ export function valueAtPath(input, path) {
37
+ const steps = String(path ?? '')
38
+ .split('.')
39
+ .filter(step => step.length > 0);
40
+ if (!steps.length) {
41
+ return { value: undefined, found: false };
42
+ }
43
+ let at = input;
44
+ for (const step of steps) {
45
+ if (at === null || at === undefined || typeof at !== 'object') {
46
+ return { value: undefined, found: false };
47
+ }
48
+ if (!Object.prototype.hasOwnProperty.call(at, step)) {
49
+ return { value: undefined, found: false };
50
+ }
51
+ at = at[step];
52
+ }
53
+ return { value: at, found: true };
54
+ }
55
+ /**
56
+ * The slots to draw, in the order they were declared.
57
+ *
58
+ * Declaration order is the screen's hierarchy: plant wrote four of these screens by hand and all
59
+ * four put the headline first, then the subject, the reason, what changes, and why it came up. That
60
+ * agreement is what makes the order part of the contract rather than a preference, so this function
61
+ * neither sorts nor groups.
62
+ *
63
+ * Every declared key produces a slot, including one whose path leads nowhere. Dropping those would
64
+ * leave the screen unable to say that a declaration and a payload disagree, and a reader would see
65
+ * a screen that looks complete.
66
+ */
67
+ export function decisionSlots(decisionKeys, input) {
68
+ if (!decisionKeys?.length) {
69
+ return [];
70
+ }
71
+ return decisionKeys.map(key => {
72
+ const { value, found } = valueAtPath(input, String(key?.inputPath ?? ''));
73
+ return {
74
+ role: String(key?.role ?? ''),
75
+ inputPath: String(key?.inputPath ?? ''),
76
+ tKey: key?.tKey,
77
+ unit: key?.unit,
78
+ value,
79
+ found
80
+ };
81
+ });
82
+ }
83
+ /** The slots for one role, in declared order. Empty when the activity declared none. */
84
+ export function slotsOfRole(slots, role) {
85
+ return slots.filter(slot => slot.role === role);
86
+ }
87
+ /**
88
+ * The single slot for a role that names one value, or undefined.
89
+ *
90
+ * Reaching for a second one would be reading a declaration the guard refuses, so this answers the
91
+ * first and does not quietly merge.
92
+ */
93
+ export function slotOfRole(slots, role) {
94
+ return slots.find(slot => slot.role === role);
95
+ }
96
+ /**
97
+ * Whether approving can be undone: true, false, or undefined for "the screen does not know".
98
+ *
99
+ * Three answers, not two. A path that led nowhere and a value that is not a boolean both mean the
100
+ * payload did not say, and the screen must draw nothing then — telling an approver that an action
101
+ * can be taken back when nobody said so is the one mistake this line cannot make. Reading a
102
+ * truthy value as reversible would do exactly that, since a non-empty string is truthy.
103
+ *
104
+ * This is not rejectionIsFinal. That says whether **rejecting** ends the case for good; this says
105
+ * whether **approving** can be taken back. The twin actuation carries both, which is why they must
106
+ * never share a sentence.
107
+ */
108
+ export function reversibilityOf(slot) {
109
+ return typeof slot?.value === 'boolean' ? slot.value : undefined;
110
+ }
111
+ //# sourceMappingURL=decision-slots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-slots.js","sourceRoot":"","sources":["../../client/components/decision-slots.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Turns an activity's decisionKeys declaration plus an instance's input into the slots a decision\n * screen draws.\n *\n * ── Nothing is imported ───────────────────────────────────────────────────\n * No lit, no i18next. The rule is a mapping from a declaration and a payload to an ordered list,\n * and keeping it free of imports is what lets the test runner hold it: that runner parses\n * TypeScript by stripping types and reads neither decorators nor enums, so one heavy import takes\n * a whole test file down with it. Labels and markup are the caller's half.\n */\n\n/** The roles that may appear more than once. Every other role names one value. */\nexport const REPEATABLE_ROLES = ['consequence', 'evidence'] as const\n\n/** Listed in the order the screen reads them: what is asked, then past, present, future. */\nexport const DECISION_ROLES = [\n 'headline',\n 'subject',\n 'reversibility',\n 'reason',\n 'evidence',\n 'currentState',\n 'consequence',\n 'policy'\n] as const\n\nexport type DecisionKeyDeclaration = {\n role?: string\n inputPath?: string\n name?: string\n tKey?: string\n unit?: string\n}\n\nexport type DecisionSlot = {\n role: string\n inputPath: string\n tKey?: string\n unit?: string\n /** What the path led to. Undefined both when the path leads nowhere and when the value is unset. */\n value: unknown\n /**\n * Whether the path led anywhere at all.\n *\n * A reason nobody wrote and a reason whose path is wrong look identical in `value`, and the screen\n * owes different answers: the first is 「사유 없음」 in grey, the second is a declaration that does\n * not match the payload and must not be drawn as if the person left it blank. Folding them into\n * one value is the fallback that shifts meaning.\n */\n found: boolean\n}\n\n/**\n * Reads a dotted path out of the input.\n *\n * Dots only. An array index or a wildcard is not part of the path language — drawing a list is the\n * slot's job — so 'shift.passes[0]' looks for a key spelled \"passes[0]\", finds nothing, and reports\n * found: false. The declaration guard refuses such a path when it arrives, so this is the second\n * line rather than the first.\n *\n * A path that runs into a non-object partway reports found: false rather than throwing. The screen\n * has to draw something either way, and a thrown error here would take the whole approval down over\n * one slot.\n */\nexport function valueAtPath(input: any, path: string): { value: unknown; found: boolean } {\n const steps = String(path ?? '')\n .split('.')\n .filter(step => step.length > 0)\n\n if (!steps.length) {\n return { value: undefined, found: false }\n }\n\n let at: any = input\n\n for (const step of steps) {\n if (at === null || at === undefined || typeof at !== 'object') {\n return { value: undefined, found: false }\n }\n\n if (!Object.prototype.hasOwnProperty.call(at, step)) {\n return { value: undefined, found: false }\n }\n\n at = at[step]\n }\n\n return { value: at, found: true }\n}\n\n/**\n * The slots to draw, in the order they were declared.\n *\n * Declaration order is the screen's hierarchy: plant wrote four of these screens by hand and all\n * four put the headline first, then the subject, the reason, what changes, and why it came up. That\n * agreement is what makes the order part of the contract rather than a preference, so this function\n * neither sorts nor groups.\n *\n * Every declared key produces a slot, including one whose path leads nowhere. Dropping those would\n * leave the screen unable to say that a declaration and a payload disagree, and a reader would see\n * a screen that looks complete.\n */\nexport function decisionSlots(\n decisionKeys: DecisionKeyDeclaration[] | null | undefined,\n input: any\n): DecisionSlot[] {\n if (!decisionKeys?.length) {\n return []\n }\n\n return decisionKeys.map(key => {\n const { value, found } = valueAtPath(input, String(key?.inputPath ?? ''))\n\n return {\n role: String(key?.role ?? ''),\n inputPath: String(key?.inputPath ?? ''),\n tKey: key?.tKey,\n unit: key?.unit,\n value,\n found\n }\n })\n}\n\n/** The slots for one role, in declared order. Empty when the activity declared none. */\nexport function slotsOfRole(slots: DecisionSlot[], role: string): DecisionSlot[] {\n return slots.filter(slot => slot.role === role)\n}\n\n/**\n * The single slot for a role that names one value, or undefined.\n *\n * Reaching for a second one would be reading a declaration the guard refuses, so this answers the\n * first and does not quietly merge.\n */\nexport function slotOfRole(slots: DecisionSlot[], role: string): DecisionSlot | undefined {\n return slots.find(slot => slot.role === role)\n}\n\n/**\n * Whether approving can be undone: true, false, or undefined for \"the screen does not know\".\n *\n * Three answers, not two. A path that led nowhere and a value that is not a boolean both mean the\n * payload did not say, and the screen must draw nothing then — telling an approver that an action\n * can be taken back when nobody said so is the one mistake this line cannot make. Reading a\n * truthy value as reversible would do exactly that, since a non-empty string is truthy.\n *\n * This is not rejectionIsFinal. That says whether **rejecting** ends the case for good; this says\n * whether **approving** can be taken back. The twin actuation carries both, which is why they must\n * never share a sentence.\n */\nexport function reversibilityOf(slot?: DecisionSlot): boolean | undefined {\n return typeof slot?.value === 'boolean' ? slot.value : undefined\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import '@material/web/icon/icon.js';
1
2
  import '@operato/property-editor/ox-properties-dynamic-view.js';
2
3
  import '@operato/board/ox-board-viewer.js';
3
4
  import '../../components/activity-approval-ribon.js';
@@ -30,6 +31,20 @@ export declare class ActivityApprovalPage extends ActivityApprovalPage_base {
30
31
  activityThread: any;
31
32
  board: any;
32
33
  commentInput: HTMLTextAreaElement;
34
+ /**
35
+ * Is the reader seated here as a reference — someone who comments and does not decide?
36
+ *
37
+ * The rule comes from organization's client types, the same function its own approval-line editor
38
+ * and list use, so the two wire spellings of the enum are handled in one place. The approval line
39
+ * answers rather than ActivityApproval.participation, matching what the server refuses on
40
+ * (isReferenceOrder in approval-line.ts): the line decides who comes next, so letting the row
41
+ * decide who may judge would leave two authorities with nothing to settle a disagreement.
42
+ *
43
+ * The value comes back false while the query is still out. That is the same answer as for an
44
+ * approver, so the buttons show for a moment on a reference's screen — pressing one is refused by
45
+ * the server, which is why the server closed first.
46
+ */
47
+ get isReference(): boolean;
33
48
  get context(): {
34
49
  title: any;
35
50
  help: string;
@@ -72,8 +87,65 @@ export declare class ActivityApprovalPage extends ActivityApprovalPage_base {
72
87
  * approveActivityApproval / rejectActivityApproval 은 id 와 comment 만 보낸다 — 그 값은 어디에도
73
88
  * 가지 않는다. 결재자가 적을 수 있는 것은 의견 하나이고, 그것은 화면 아래 칸이 받는다.
74
89
  */
90
+ /**
91
+ * The decision the activity declared, or nothing when it declared none.
92
+ *
93
+ * Returning nothing is how generatedContent knows to fall back to the model. An activity with no
94
+ * decisionKeys draws exactly what it drew before.
95
+ *
96
+ * A slot whose path led nowhere is skipped rather than drawn empty. Older instances of an activity
97
+ * predate a field the declaration names — plant hit that with its `policy` value — and an empty
98
+ * bar on the screen would read as "there is no reason" when the truth is that this record has no
99
+ * such value. What cannot be shown is left out; what is shown is only what the payload actually
100
+ * carries.
101
+ *
102
+ * `reason` is the exception. Missing and blank mean the same thing to whoever is reading — nobody
103
+ * wrote one — so both draw the grey line rather than disappearing. A reason that silently vanishes
104
+ * would let an approver assume it was never asked for.
105
+ */
106
+ decisionContent(): DirectiveResult<{
107
+ new (_partInfo: import("lit-html/directive.js").PartInfo): import("lit-html/directives/keyed.js").Keyed<TemplateResult<1>>;
108
+ }>;
109
+ /**
110
+ * Whether approving can be undone, drawn as the frame around the decision.
111
+ *
112
+ * Only an explicit true or false draws. Anything else — the path led nowhere, or the value is not
113
+ * a boolean — draws nothing, because saying "this can be undone" on a screen that does not know is
114
+ * the one mistake this line must never make.
115
+ *
116
+ * This is not rejectionIsFinal. That one says whether **rejecting** ends the case for good; this
117
+ * says whether **approving** can be taken back. The twin actuation carries both, which is exactly
118
+ * why they must not share a sentence.
119
+ */
120
+ private renderReversibility;
121
+ /**
122
+ * One slot's value as something to read.
123
+ *
124
+ * A scalar prints with its unit when one was declared. Anything shaped — an object, a list — goes
125
+ * through fieldValue, the same laying-out the model sections use, so a payload reads the same way
126
+ * wherever it appears and a four-level object does not become one long line.
127
+ */
128
+ private slotText;
129
+ /** Did a person actually write something here. Whitespace is not words. */
130
+ private hasWords;
75
131
  generatedContent(): DirectiveResult;
76
132
  boardContent(): DirectiveResult;
133
+ /**
134
+ * The element the activity names, or a plain statement that it could not be loaded.
135
+ *
136
+ * document.createElement answers something for any name, so an activity pointing at an element
137
+ * nobody registered used to produce an empty card. The approver got a screen with nothing on it
138
+ * and the approve button still worked — plant shipped two such forms in one day and found them by
139
+ * reading the file list, not by opening the screen.
140
+ *
141
+ * The reader is told what to judge by instead. Same shape as the empty generated screen: what is
142
+ * missing, and where to look — the submission reason and the history in the timeline below.
143
+ *
144
+ * ── Waiting for a late definition ─────────────────────────────────────────
145
+ * An element can be registered after this page renders, and answering "not loaded" forever in
146
+ * that case would be a screen inventing a defect. whenDefined resolves whenever it arrives and
147
+ * the page redraws; a name nobody ever registers simply never resolves, and the statement stands.
148
+ */
77
149
  customElementContent(): any;
78
150
  oxBoardViewer: any;
79
151
  getOutputFromBoard(): any;