@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
@@ -1 +1 @@
1
- {"version":3,"file":"activity-approval-page.js","sourceRoot":"","sources":["../../../client/pages/activity-approval/activity-approval-page.ts"],"names":[],"mappings":";AAAA,OAAO,wDAAwD,CAAA;AAC/D,OAAO,mCAAmC,CAAA;AAC1C,OAAO,6CAA6C,CAAA;AACpD,OAAO,8CAA8C,CAAA;AAErD,OAAO,GAAG,MAAM,aAAa,CAAA;AAC7B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAkB,MAAM,KAAK,CAAA;AAExD,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAC/D,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,wDAAwD,CAAA;AAEjF,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,YAAY,EACZ,WAAW,EACZ,MAAM,qCAAqC,CAAA;AAE5C,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyElC,CAAA;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAI,UAAU,EAAE,YAAY;IAC9D,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,WAAW;IACtB,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;CACnB,CAAA;AAGM,IAAM,oBAAoB,GAA1B,MAAM,oBAAqB,SAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC;IAA9D;;QA6GL;;;;;;;;WAQG;QACM,WAAM,GAAG,KAAK,CAAA;IA8ZzB,CAAC;aAphBgF,WAAM,GAAG;QACtF,eAAe;QACf,oBAAoB;QACpB,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAsGF;KACF,AA1GoF,CA0GpF;IAmBD,IAAI,OAAO;QAAS,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAA;QAElE,OAAO,EAAQ,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC;YAC7F,IAAI,EAAE,4BAA4B;YAClC;;;;;eAKG;YACH,IAAI,EAAE,uBAAuB;YAC7B,OAAO,EAAE,QAAQ;gBACf,CAAC,CAAC;oBACE,EAAgB,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC;wBAC9C,MAAM,EAAE,GAAG,EAAE;4BAAmB,OAAO,CAAC,IAAI,EAAE,CAAA;wBAC3D,CAAC;wBACY,GAAG,kBAAkB,CAAC,IAAI;qBACtC;iBACS;gBACH,CAAC,CAAC;;;;;;;;;;;;qBAYG;oBACH;wBACE,EAAgB,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC;4BAChD,MAAM,EAAE,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC;4BAC/C,IAAI,EAAE,UAAU;4BAChB,QAAQ,EAAE,EAAkB,MAAM,EAAE,IAAI;gCACtC,QAAQ,EAAE,KAAK;gCACf,KAAK,EAAE,KAAK;gCACZ,MAAM,EAAE,KAAK;6BAC3B;yBACA;wBAEU,EAAgB,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;4BAC/C,MAAM,EAAE,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC;4BAC9C,IAAI,EAAE,mBAAmB;4BACzB,QAAQ,EAAE,EAAkB,MAAM,EAAE,KAAK;gCACvC,QAAQ,EAAE,IAAI;gCACd,KAAK,EAAE,KAAK;gCACZ,MAAM,EAAE,KAAK;6BAC3B;yBACA;wBAEU,EAAgB,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,kBAAkB,CAAC;4BAClD,MAAM,EAAE,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC;4BAC5C,IAAI,EAAE,WAAW;4BACjB,QAAQ,EAAE,EAAkB,MAAM,EAAE,KAAK;gCACvC,QAAQ,EAAE,IAAI;gCACd,KAAK,EAAE,KAAK;gCACZ,MAAM,EAAE,KAAK;6BAC3B;yBACA;wBACU,EAAgB,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC;4BAC9C,MAAM,EAAE,GAAG,EAAE;gCAAmB,OAAO,CAAC,IAAI,EAAE,CAAA;4BAC3D,CAAC;4BACY,GAAG,kBAAkB,CAAC,IAAI;4BAC1B,IAAI,EAAE,OAAO;yBACzB;qBACS;YACL,0CAA0C;SAC9C,CAAA;IACD,CAAC;IAEA,MAAM;QAAS,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACtC,OAAO,IAAI,CAAC,MAAM;gBAChB,CAAC,CAAC,IAAI,CAAA;kCACoB,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC;gCAC3C,OAAO,CAAC,CAAC,CAAC,6BAA6B,CAAC;iBACvD;gBACT,CAAC,CAAC,OAAO,CAAA;QACb,CAAC;QAED,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAA;QAC9C,MAAM,QAAQ,GAAG,CAAC,YAAY,CAAA;QAE9B,OAAO,IAAI,CAAA;mDACoC,IAAI,CAAC,gBAAgB;QAChE,IAAI,CAAC,eAAe,EAAE;;;;;;0BAMJ,IAAI,CAAC,cAAc;gBAC7B,CAAC,IAAI,CAAC,SAAS,EAAE;;;QAGzB,QAAQ;YACR,CAAC,CAAC,IAAI,CAAA;;;sBAGQ,OAAO,CAAC,CAAC,CAAC,kBAAkB,CAAC;;gCAEnB,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,gDAAgD,CAAC,CAAC;2BACxE,IAAI,CAAC,gBAAgB,EAAE,OAAO;4BAC7B,CAAC,CAAQ,EAAE,EAAE;gBACrB,IAAI,CAAC,gBAAgB,CAAC,OAAO,GAAI,CAAC,CAAC,MAA8B,CAAC,KAAK,CAAA;YACzE,CAAC;;;;;;kCAMe,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC;;;WAG9D;YACH,CAAC,CAAC,OAAO;KACZ,CAAA;IACJ,CAAC;IAEA,gDAAgD;IAChD,SAAS;QACP,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,gBAAgB,EAAE,QAAQ,EAAE,KAAK,CAAA;QAEpE,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAA;IACxE,CAAC;IAED,eAAe;QAAS,QAAQ,IAAI,CAAC,cAAc,EAAE,gBAAgB,EAAE,QAAQ,EAAE,CAAC;YAAO,KAAK,UAAU;gBAClG,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAA;YACnD,KAAK,WAAW;gBACd,OAAO,IAAI,CAAC,gBAAgB,EAAE,CAAA;YAChC,2DAA2D;YAC3D,KAAK,OAAO;gBACV,OAAO,IAAI,CAAC,YAAY,EAAE,CAAA;YAC5B,KAAK,gBAAgB;gBACnB,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAA;YACxD,KAAK,MAAM,CAAC;YACZ,KAAK,UAAU;gBACb,OAAO,IAAI,CAAA,EAAE,CAAA;YACf;gBACE,OAAO,IAAI,CAAC,gBAAgB,EAAE,CAAA;QACrC,CAAC;IACD,CAAC;IAEA;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,OAAgB;QAC5B,OAAO,IAAI,CAAA,mBAAmB,OAAO,YAAY,CAAA;IACnD,CAAC;IAED,eAAe;QAAS,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAAO,OAAO,IAAI,CAAA,EAAE,CAAA;QAC1E,CAAC;QAEE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE,gBAAgB,CAAA;QACtE,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAA;IAC9B,CAAC;IAEA;;;;;;OAMG;IACH,gBAAgB;QAA0B,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAAO,OAAO,IAAI,CAAA,EAAE,CAAA;QAC5F,CAAC;QAEE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC,cAAc,IAAI,EAAE,CAAA;QAC9D,MAAM,EAAE,KAAK,EAAE,GAAG,gBAAgB,IAAI,EAAE,CAAA;QAExC,MAAM,KAAK,GAAG,gBAAgB,EAAE,QAAQ,EAAE,KAAK,CAAA;QAC/C,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,CAAA;QACpC,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;QAEtC;;;;;;WAMG;QACH,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;YAC5C,OAAO,KAAK,CACV,IAAI,CAAC,gBAAgB,CAAC,EAAE,EACxB,IAAI,CAAA;gCACoB,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC;8BACvC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC;mBACpD,CACZ,CAAA;QACH,CAAC;QAED,OAAO,KAAK,CACV,IAAI,CAAC,gBAAgB,CAAC,EAAE,EACxB,IAAI,CAAA;UACA,SAAS,CAAC,MAAM;YAChB,CAAC,CAAC,IAAI,CAAA;;sBAEM,OAAO,CAAC,CAAC,CAAC,sBAAsB,CAAC;kBACrC,WAAW,CAAC,SAAS,EAAE,KAAK,CAAC;;aAElC;YACH,CAAC,CAAC,EAAE;UACJ,UAAU,CAAC,MAAM;YACjB,CAAC,CAAC,IAAI,CAAA;;sBAEM,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC;kBAC/B,WAAW,CAAC,UAAU,EAAE,MAAM,CAAC;;aAEpC;YACH,CAAC,CAAC,EAAE;OACP,CACF,CAAA;IACJ,CAAC;IAEA,YAAY;QAA0B,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAAO,OAAO,IAAI,CAAA,EAAE,CAAA;QACxF,CAAC;QAEE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC,cAAc,CAAA;QACxD,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,gBAAgB,IAAI,EAAE,CAAA;QAE7D,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,KAAK,OAAO,EAAE,CAAC;YAAO,IAAI,CAAC,KAAK,GAAG,EAAU,EAAE,EAAE,OAAO;aAC1F,CAAA;QACD,CAAC;QAEE,OAAO,KAAK,CACV,IAAI,CAAC,gBAAgB,CAAC,EAAE,EACxB,IAAI,CAAA;;;mBAGS,IAAI,CAAC,KAAK;sBACP,QAAQ;oBACV,EAAE,GAAG,KAAK,EAAE,GAAG,MAAM,EAAE;;;;OAIpC,CACF,CAAA;IACJ,CAAC;IAEA,oBAAoB;QAAS,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAAO,OAAO,IAAI,CAAA,EAAE,CAAA;QAC/E,CAAC;QAEE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC,cAAc,CAAA;QACxD,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,gBAAgB,IAAI,EAAE,CAAA;QAE7D,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;QAC/C,OAAO,CAAC,EAAE,GAAG,gBAAgB,CAAA;QAC7B,OAAO,CAAC,UAAU,GAAG,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAA;QACjD,OAAO,CAAC,KAAK,GAAG,KAAK,CAAA;QACrB,OAAO,CAAC,MAAM,GAAG,MAAM,CAAA;QACvB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,CAAA;QAEhD,OAAO,OAAO,CAAA;IACjB,CAAC;IAIA,kBAAkB;QAAS,MAAM,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC,cAAc,EAAE,gBAAgB,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;QAChH,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,CAAA;QAEhD,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE;YAAS,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACpF,OAAO,MAAM,CAAA;QAClB,CAAC,EAAE,EAAE,CAAC,CAAA;IACN,CAAC;IAiBQ,YAAY;QAClB,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAA;QAEpC,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,gBAAgB,EAAE,YAAY,IAAI,IAAI,CAAC,UAAU,KAAK,EAAE,EAAE,CAAC;YACzF,OAAM;QACR,CAAC;QAED,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAA;QACjD,IAAI,CAAC,UAAU,GAAG,EAAE,CAAA;IACtB,CAAC;IAED,OAAO,CAAC,OAAO;QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,EAAE,CAAC;YAAO,IAAI,CAAC,aAAa,EAAE,CAAA;YACpF,IAAI,CAAC,YAAY,EAAE,CAAA;QACxB,CAAC;IACD,CAAC;IAEA,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,SAAS,EAAE,aAAa;QAAQ,IAAI,IAAI,CAAC,MAAM,IAAI,SAAS,CAAC,UAAU,EAAE,CAAC;YAAO,IAAI,CAAC,qBAAqB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAA;QAC7J,CAAC;IACD,CAAC;IAEA,KAAK,CAAC,qBAAqB,CAAC,EAAE;QAAQ,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,EAAQ,KAAK,EAAE,GAAG,CAAA;qFACT,2BAA2B;;OAEzG;YACD,SAAS,EAAE,EAAU,EAAE;aAC3B;SACA,CAAC,CAAA;QAEC,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAA;QACtD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;QAClB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAAA;QAE1D,IAAI,CAAC,aAAa,EAAE,CAAA;IACvB,CAAC;IAEA,KAAK,CAAC,sBAAsB;QAAS,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAA;QAE9E,IAAI,CAAC,OAAO,EAAE,CAAC;YAAO,QAAQ,CAAC,aAAa,CACxC,IAAI,WAAW,CAAC,QAAQ,EAAE,EAAY,MAAM,EAAE,EAAc,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,sBAAsB,CAAC;iBAC5G;aACA,CAAC,CACI,CAAA;YACD,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAA;YACzB,OAAM;QACX,CAAC;QAEE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,EAAQ,QAAQ,EAAE,GAAG,CAAA;qHACuD,2BAA2B;;OAEzI;YACD,SAAS,EAAE,EAAU,EAAE;gBACrB,OAAO;aACb;SACA,CAAC,CAAA;QAEC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YAAO,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC,IAAI,CAAC,sBAAsB,CAAA;YACxF,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAAA;YAE1D,IAAI,CAAC,aAAa,EAAE,CAAA;YAEpB,QAAQ,CAAC,aAAa,CACpB,IAAI,WAAW,CAAC,QAAQ,EAAE,EAAY,MAAM,EAAE,EAAc,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,oCAAoC,CAAC;iBAC1H;aACA,CAAC,CACI,CAAA;QACN,CAAC;IACD,CAAC;IAEA,KAAK,CAAC,uBAAuB;QAAS,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAA;QAE/E,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,EAAQ,QAAQ,EAAE,GAAG,CAAA;qHACuD,2BAA2B;;OAEzI;YACD,SAAS,EAAE,EAAU,EAAE;gBACrB,OAAO;aACb;SACA,CAAC,CAAA;QAEC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YAAO,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC,IAAI,CAAC,uBAAuB,CAAA;YACzF,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAAA;YAE1D,IAAI,CAAC,aAAa,EAAE,CAAA;YAEpB,QAAQ,CAAC,aAAa,CACpB,IAAI,WAAW,CAAC,QAAQ,EAAE,EAAY,MAAM,EAAE,EAAc,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,oCAAoC,CAAC;iBAC1H;aACA,CAAC,CACI,CAAA;QACN,CAAC;IACD,CAAC;IAEA,KAAK,CAAC,oBAAoB;QAAS,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAA;QAE5E,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,EAAQ,QAAQ,EAAE,GAAG,CAAA;iHACmD,2BAA2B;;OAErI;YACD,SAAS,EAAE,EAAU,EAAE;gBACrB,OAAO;aACb;SACA,CAAC,CAAA;QAEC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YAAO,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC,IAAI,CAAC,oBAAoB,CAAA;YACtF,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAAA;YAE1D,IAAI,CAAC,aAAa,EAAE,CAAA;YAEpB,QAAQ,CAAC,aAAa,CACpB,IAAI,WAAW,CAAC,QAAQ,EAAE,EAAY,MAAM,EAAE,EAAc,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,iCAAiC,CAAC;iBACvH;aACA,CAAC,CACI,CAAA;QACN,CAAC;IACD,CAAC;;AAvaS;IAAR,KAAK,EAAE;;8DAAsB;AAUrB;IAAR,KAAK,EAAE;;oDAAe;AAEd;IAAR,KAAK,EAAE;;4DAAoB;AACnB;IAAR,KAAK,EAAE;;mDAAW;AAEA;IAAlB,KAAK,CAAC,UAAU,CAAC;8BAAgB,mBAAmB;0DAAA;AA6Q3B;IAAzB,KAAK,CAAC,iBAAiB,CAAC;;2DAAmB;AAxYjC,oBAAoB;IADhC,aAAa,CAAC,wBAAwB,CAAC;GAC3B,oBAAoB,CAohBhC","sourcesContent":["import '@operato/property-editor/ox-properties-dynamic-view.js'\nimport '@operato/board/ox-board-viewer.js'\nimport '../../components/activity-approval-ribon.js'\nimport '../../components/activity-thread-timeline.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, nothing, TemplateResult } from 'lit'\nimport { DirectiveResult } from 'lit-html/directive.js'\nimport { unsafeHTML } from 'lit-html/directives/unsafe-html.js'\nimport { customElement, query, state } from 'lit/decorators.js'\nimport { keyed } from 'lit/directives/keyed.js'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { PageView } from '@operato/shell'\nimport { CommonButtonStyles, ScrollbarStyles } from '@operato/styles'\nimport { provider } from '@things-factory/board-ui/dist-client/board-provider.js'\n\nimport {\n ActivityFieldsStyles,\n inputSpecOf,\n outputSpecOf,\n renderGiven\n} from '../../components/activity-fields.js'\n\nconst ActivityApprovalFetchResult = `\\\n{ id\n judgment\n comment\n approver { id\n name\n }\n round\n order\n createdAt\n terminatedAt\n activityThread { state\n dueAt\n assignedAt\n assignee { id\n name\n }\n updatedAt\n terminatedAt\n output\n activityApprovals { round\n order\n approver { name\n }\n judgment\n comment\n createdAt\n updatedAt\n terminatedAt\n }\n activityThreadHistories { transaction\n reason\n updater { name\n }\n updatedAt\n state\n output\n }\n activityInstance { id\n name\n description\n state\n activity { id\n model { name\n description\n active\n tag\n inout\n type\n unit\n options\n quantifier\n spec\n hidden\n }\n }\n approvalLine { type\n value\n approver { id\n name\n description\n controlNo\n }\n }\n thumbnail\n input\n output\n viewType\n viewSource\n dueAt\n createdAt\n } \n }\n}`\n\nexport const ActivityThreadStatus = { Unassigned: 'unassigned',\n Assigned: 'assigned',\n Started: 'started',\n Delegated: 'delegated',\n Ended: 'ended',\n Aborted: 'aborted'\n}\n\n@customElement('activity-approval-page')\nexport class ActivityApprovalPage extends localize(i18next)(PageView) { static styles = [\n ScrollbarStyles,\n ActivityFieldsStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n position: relative;\n\n width: 100%;\n overflow: auto;\n background: var(--ui-bg, #f0f2f4);\n color: var(--ui-ink, #17242c);\n font-size: var(--ui-t-body, 13px);\n }\n\n /* 카드가 담아 주므로 안에 들어오는 화면은 자기 면과 여백을 갖지 않는다. */\n /*\n * 줄어들지 않는다 — 줄어들면 본문이 잘린다.\n *\n * flex 항목인데 크기를 안 정해 두면 기본이 flex: 0 1 auto 다. **1 이 줄어든다는 뜻이다** —\n * 세로가 모자라면 브라우저가 이 칸부터 줄이는데, 여기엔 카드 모서리를 따라 자르려고\n * overflow: hidden 이 걸려 있어서 줄어든 만큼이 **스크롤도 없이 사라진다.**\n *\n * 완료 조회에서 실측했다(1400x620): 칸이 242px 로 줄고 내용은 362px 이라 「업무 내용」 절이\n * 대부분 잘렸고, 잘린 자리 바로 아래에서 타임라인이 시작하니 타임라인이 본문을 덮은 것처럼\n * 보였다. 세로가 넉넉하면 줄일 일이 없어 안 드러난다.\n *\n * 안에 오는 것은 문서다. 높이를 정해 주어야 하는 것은 board 뿐이고 board 는 이 칸을 거치지\n * 않는다(activityContent 참조). 문서는 제 높이로 서고, 모자라면 페이지 전체가 스크롤한다 —\n * :host 의 overflow: auto 가 그 자리다.\n */\n section[hosted] {\n flex: none;\n padding: 0;\n overflow: hidden;\n }\n\n ox-board-viewer {\n width: 100%;\n height: 100%;\n }\n\n activity-thread-timeline {\n margin: var(--spacing-large, 16px);\n }\n\n /*\n * 의견 칸 — 이 화면에서 **결재자가 유일하게 적는 자리**다.\n *\n * 화면 아래에 붙어 있어(sticky) 목록을 내려 읽는 동안에도 보인다. 그 자리를 지키되 모양은\n * 다른 절과 같은 카드로 둔다. 전에는 회색 면(surface-variant)에 다른 테두리라 이 화면에서\n * 혼자 다른 부품처럼 보였다.\n */\n /*\n * 의견 — 이 화면에서 **결재자가 유일하게 적는 자리**다.\n *\n * 화면 아래에 붙어 있어(sticky) 내용을 내려 읽는 동안에도 보인다. 그 자리를 지키되 모양은\n * 다른 절과 같은 카드로 둔다. 전에는 회색 면(surface-variant)에 다른 테두리라 이 화면에서\n * 혼자 다른 부품처럼 보였다.\n */\n div[comment] {\n position: sticky;\n bottom: 0;\n padding-bottom: var(--spacing-large, 16px);\n background: var(--ui-bg, #f0f2f4);\n }\n\n /*\n * 이 화면에서 **사용자가 유일하게 손대는 자리**라는 것을 모양으로 말한다.\n *\n * 나머지 절은 전부 읽는 것이고, 판단은 아래 툴바의 단추가 받는다. 그런데 의견 칸이 읽는\n * 절들과 똑같은 카드라 「내 차례가 어디인지」가 화면에 없었다. 왼쪽에 강조색 띠를 둔다 —\n * sticky 라 툴바 바로 위에 붙으므로 띠와 단추가 한 덩어리로 읽힌다.\n */\n div[comment] section {\n border-left: 3px solid var(--ui-accent, #00727e);\n }\n\n div[comment] textarea {\n display: block;\n box-sizing: border-box;\n width: 100%;\n height: 76px;\n padding: 10px 12px;\n background: var(--ui-panel, #ffffff);\n border: 1px solid var(--ui-line, #d5dce0);\n border-radius: var(--ui-r-small, 6px);\n color: var(--ui-ink, #17242c);\n font: inherit;\n font-size: var(--ui-t-body, 13px);\n resize: none;\n outline: none;\n }\n\n div[comment] textarea:focus {\n border-color: var(--ui-accent, #00727e);\n }\n\n div[comment] .hint {\n margin: 7px 0 0;\n font-size: var(--ui-t-small, 11.5px);\n color: var(--ui-faint, #8a959c);\n word-break: keep-all;\n }\n `\n ]\n\n @state() activityApproval: any\n /**\n * 조회를 마쳤나 — **「아직 안 읽었다」와 「없다」는 다르다.**\n *\n * 전에는 값이 없으면 곧바로 「업무활동 정보가 없습니다」를 그렸다. 그런데 이 화면은 열리자마자\n * 조회를 시작하므로, 응답이 오기 전까지 **없다고 단언하는 화면**이 보인다. 목록에서 줄을 눌러\n * 들어온 사람은 방금 본 건이 없다는 말을 먼저 읽는다.\n *\n * 조회가 끝난 뒤에만 그 말을 한다. 그 전에는 아무 말도 하지 않는다.\n */\n @state() loaded = false\n\n @state() activityThread: any\n @state() board: any\n\n @query('textarea') commentInput!: HTMLTextAreaElement\n\n get context() { const judgment = this.activityApproval?.judgment\n\n return { title: this.lifecycle?.params?.['title'] || i18next.t('title.activity approval'),\n help: 'worklist/activity-approval',\n /*\n * 이 화면은 메뉴에 없다 — 「내 결재함」에서 줄을 눌러 들어온다. 그래서 왼쪽 메뉴가 가리킬\n * 항목이 없고, 표시가 사라져 들어온 사람이 자기가 어디에 있는지 잃는다.\n *\n * 어느 목록에서 열리는지는 이 화면이 안다. 그것을 적어 둔다.\n */\n menu: 'approval-pending-list',\n actions: judgment\n ? [\n { title: i18next.t('button.close'),\n action: () => { history.back()\n },\n ...CommonButtonStyles.back\n }\n ]\n : /*\n * ── 세 단추의 순서와 무게 (2026-09-06) ──────────────────────────\n * 전에는 반려가 첫 자리였고, 승인 · 반려 · 저장이 모두 같은 모양이었다. 되돌리기 어려운\n * 것이 앞에 서고 무엇이 주된 흐름인지 화면이 말하지 않았다.\n *\n * 승인이 주 동작이다 — 채운 단추 하나. 반려는 대등한 선택이지만 예외 경로라 테두리\n * 단추로 그 옆에 둔다.\n *\n * 「저장」은 이름이 뜻을 말하지 않았다. 이 단추가 저장하는 것은 **의견 하나**이고\n * (saveActivityApproval 은 id 와 comment 만 보낸다), 판단은 미뤄 둔다. 그리고 그 결과는\n * 목록에서 「메모 있음」 표식으로 나타난다(activity-cells 의 approvalMarks). 목록이\n * 부르는 이름과 같은 낱말로 맞춘다.\n */\n [\n { title: i18next.t('button.approve'),\n action: this.approveActivityApproval.bind(this),\n icon: 'approval',\n emphasis: { raised: true,\n outlined: false,\n dense: false,\n danger: false\n }\n },\n\n { title: i18next.t('button.reject'),\n action: this.rejectActivityApproval.bind(this),\n icon: 'assignment_return',\n emphasis: { raised: false,\n outlined: true,\n dense: false,\n danger: false\n }\n },\n\n { title: i18next.t('button.save-note'),\n action: this.saveActivityApproval.bind(this),\n icon: 'edit_note',\n emphasis: { raised: false,\n outlined: true,\n dense: false,\n danger: false\n }\n },\n { title: i18next.t('button.close'),\n action: () => { history.back()\n },\n ...CommonButtonStyles.back,\n icon: 'close'\n }\n ]\n // activityApproval: this.activityApproval\n }\n }\n\n render() { if (!this.activityThread) {\n return this.loaded\n ? html`<div empty>\n <span class=\"title\">${i18next.t('text.no activity thread info')}</span>\n <span class=\"why\">${i18next.t('text.no-activity-thread-why')}</span>\n </div>`\n : nothing\n }\n\n const { terminatedAt } = this.activityApproval\n const editable = !terminatedAt\n\n return html`\n <activity-approval-ribon .activityApproval=${this.activityApproval}></activity-approval-ribon>\n ${this.activityContent()}\n <!--\n 보일 항목이 하나도 없으면 타임라인을 편다 — 그때는 화면이 「아래 타임라인의 상신 사유와\n 이력을 보고 판단하세요」로 여기를 가리키므로, 접혀 있으면 그 안내가 거짓말이 된다.\n -->\n <activity-thread-timeline\n .activityThread=${this.activityThread}\n ?open=${!this.hasFields()}\n short-form\n ></activity-thread-timeline>\n ${editable\n ? html`\n <div comment>\n <section>\n <h2>${i18next.t('field.wl-comment')}</h2>\n <textarea\n placeholder=${String(i18next.t('text.explain the reason for approval/rejection'))}\n .value=${this.activityApproval?.comment}\n @change=${(e: Event) => {\n this.activityApproval.comment = (e.target as HTMLTextAreaElement).value\n }}\n ></textarea>\n <!--\n 반려는 의견이 필수다(rejectActivityApproval). 전에는 그 규칙을 **누른 뒤에** 토스트로\n 알렸다. 되돌릴 수 없는 것과 뜻이 다른 동작은 하기 전에 말한다.\n -->\n <p class=\"hint\">${i18next.t('text.approval-comment-hint')}</p>\n </section>\n </div>\n `\n : nothing}\n `\n }\n\n /** 화면에 낼 항목이 하나라도 있나. 타임라인을 펴 둘지 정하는 자리가 쓴다. */\n hasFields(): boolean {\n const model = this.activityThread?.activityInstance?.activity?.model\n\n return inputSpecOf(model).length > 0 || outputSpecOf(model).length > 0\n }\n\n activityContent() { switch (this.activityThread?.activityInstance?.viewType) { case 'template':\n return this.hostedContent(this.templateContent())\n case 'generated':\n return this.generatedContent()\n /* board 는 전체 화면을 쓰는 캔버스라 카드에 담지 않는다(hostedContent 머리말). */\n case 'board':\n return this.boardContent()\n case 'custom-element':\n return this.hostedContent(this.customElementContent())\n case 'page':\n case 'external':\n return html``\n default:\n return this.generatedContent()\n }\n }\n\n /**\n * 화면 종류가 달라도 **같은 자리에 같은 모양으로 놓인다.**\n *\n * worklist 는 네 가지로 내용을 그린다(generated · custom-element · template · board). 그중\n * generated 만 절 카드 안에 있었고 나머지 셋은 면 위에 맨몸으로 놓였다. 그래서 같은 결재 화면이\n * 액티비티에 따라 카드였다가 아니었다가 했다 — 아래의 타임라인 · 의견은 늘 카드라 위계도 어긋났다.\n *\n * board 는 뺀다. 전체 폭 · 전체 높이를 쓰는 캔버스라 카드 안에 넣으면 여백이 두 겹이 되고 크기가\n * 어긋난다.\n *\n * 카드는 여백을 두지 않는다(padding: 0). 안에 들어오는 것이 자기 조판을 갖고 있고, 두 겹으로\n * 주면 안쪽 내용이 카드 가운데로 밀린다.\n */\n hostedContent(content: unknown) {\n return html`<section hosted>${content}</section>`\n }\n\n templateContent() { if (!this.activityApproval) { return html``\n }\n\n const { viewSource: template } = this.activityThread?.activityInstance\n return unsafeHTML(template)\n }\n\n /**\n * 결재자가 보는 내용 — **전부 읽기 전용이다.**\n *\n * 전에는 「Output」 절을 편집기로 그리고 변경을 activityApproval.output 에 적었다. 그런데\n * approveActivityApproval / rejectActivityApproval 은 id 와 comment 만 보낸다 — 그 값은 어디에도\n * 가지 않는다. 결재자가 적을 수 있는 것은 의견 하나이고, 그것은 화면 아래 칸이 받는다.\n */\n generatedContent(): DirectiveResult { if (!this.activityApproval) { return html``\n }\n\n const { output, activityInstance } = this.activityThread || {}\n const { input } = activityInstance || {}\n\n const model = activityInstance?.activity?.model\n const inputSpec = inputSpecOf(model)\n const outputSpec = outputSpecOf(model)\n\n /*\n * **결재 화면에서 내용이 비어 있는 것은 경고다.**\n *\n * 업무 상세라면 「적을 것이 없다」로 끝난다. 여기서는 다르다 — 무엇을 승인하는지 모르는 채로\n * 승인 · 반려 버튼이 그대로 눌린다. 그 사실을 화면이 말하고, 대신 무엇을 보고 판단할지 알려\n * 준다(타임라인의 상신 사유).\n */\n if (!inputSpec.length && !outputSpec.length) {\n return keyed(\n this.activityApproval.id,\n html`<section empty>\n <span class=\"title\">${i18next.t('text.no-approval-content')}</span>\n <span class=\"why\">${i18next.t('text.no-approval-content-why')}</span>\n </section>`\n )\n }\n\n return keyed(\n this.activityApproval.id,\n html`\n ${inputSpec.length\n ? html`\n <section readonly>\n <h2>${i18next.t('label.activity-input')}</h2>\n ${renderGiven(inputSpec, input)}\n </section>\n `\n : ''}\n ${outputSpec.length\n ? html`\n <section readonly>\n <h2>${i18next.t('field.artifact')}</h2>\n ${renderGiven(outputSpec, output)}\n </section>\n `\n : ''}\n `\n )\n }\n\n boardContent(): DirectiveResult { if (!this.activityApproval) { return html``\n }\n\n const { output, activityInstance } = this.activityThread\n const { viewSource: boardId, input } = activityInstance || {}\n\n if (!this.board || this.board.id !== boardId) { this.board = { id: boardId\n }\n }\n\n return keyed(\n this.activityApproval.id,\n html`\n <ox-board-viewer\n style=\"background-color: white;\"\n .board=${this.board}\n .provider=${provider}\n .values=${{ ...input, ...output }}\n hide-fullscreen\n hide-navigation\n ></ox-board-viewer>\n `\n )\n }\n\n customElementContent() { if (!this.activityApproval) { return html``\n }\n\n const { output, activityInstance } = this.activityThread\n const { viewSource: tagName, input } = activityInstance || {}\n\n const element = document.createElement(tagName)\n element.id = 'custom-content'\n element.activityId = activityInstance.activity.id\n element.input = input\n element.output = output\n element.activityApproval = this.activityApproval\n\n return element\n }\n\n @query('ox-board-viewer') oxBoardViewer: any\n\n getOutputFromBoard() { const outputSpec = outputSpecOf(this.activityThread?.activityInstance?.activity?.model)\n const data = this.oxBoardViewer.getSceneValues()\n\n return outputSpec.reduce((output, spec) => { output[spec.name] = data[spec.name]\n return output\n }, {})\n }\n\n /**\n * 화면이 열리면 **의견 칸에 캐럿을 둔다.**\n *\n * 결재자가 이 화면에서 적는 것은 의견 하나다. 나머지는 전부 읽는 것이고, 판단은 아래 버튼이\n * 받는다. 그러면 열자마자 커서가 있어야 하는 자리는 하나뿐이다.\n *\n * 조건 둘을 지킨다.\n *\n * 활성 탭일 때만 MDI 라 뒤에 있는 탭이 응답을 받으면 앞 탭의 입력을 빼앗는다\n * 한 건에 한 번 갱신마다 focus 를 부르면 사용자가 옮긴 커서를 계속 되돌린다\n *\n * preventScroll 을 준다 — 화면을 아래로 끌어내리면 정작 무엇을 승인하는지가 위로 사라진다.\n */\n private focusedFor?: string\n\n private focusComment() {\n const id = this.activityApproval?.id\n\n if (!id || !this.active || this.activityApproval?.terminatedAt || this.focusedFor === id) {\n return\n }\n\n this.commentInput?.focus({ preventScroll: true })\n this.focusedFor = id\n }\n\n updated(changes) { if (changes.has('activityApproval')) { this.updateContext()\n this.focusComment()\n }\n }\n\n async pageUpdated(changes, lifecycle, changedBefore) { if (this.active && lifecycle.resourceId) { this.fetchActivityApproval(lifecycle.resourceId)\n }\n }\n\n async fetchActivityApproval(id) { const response = await client.query({ query: gql`\n query activityApproval($id: String!) { activityApproval(id: $id) ${ActivityApprovalFetchResult}\n }\n `,\n variables: { id\n }\n })\n\n this.activityApproval = response.data.activityApproval\n this.loaded = true\n this.activityThread = this.activityApproval.activityThread\n\n this.updateContext()\n }\n\n async rejectActivityApproval() { var { id, comment } = this.activityApproval\n\n if (!comment) { document.dispatchEvent(\n new CustomEvent('notify', { detail: { message: i18next.t('text.enter a comment')\n }\n })\n )\n this.commentInput.focus()\n return\n }\n\n const response = await client.mutate({ mutation: gql`\n mutation ($id: String!, $comment: String!) { rejectActivityApproval(id: $id, comment: $comment) ${ActivityApprovalFetchResult}\n }\n `,\n variables: { id,\n comment\n }\n })\n\n if (!response.errors) { this.activityApproval = response.data.rejectActivityApproval\n this.activityThread = this.activityApproval.activityThread\n\n this.updateContext()\n\n document.dispatchEvent(\n new CustomEvent('notify', { detail: { message: i18next.t('text.task_is_rejected_successfully')\n }\n })\n )\n }\n }\n\n async approveActivityApproval() { var { id, comment } = this.activityApproval\n\n const response = await client.mutate({ mutation: gql`\n mutation ($id: String!, $comment: String) { approveActivityApproval(id: $id, comment: $comment) ${ActivityApprovalFetchResult}\n }\n `,\n variables: { id,\n comment\n }\n })\n\n if (!response.errors) { this.activityApproval = response.data.approveActivityApproval\n this.activityThread = this.activityApproval.activityThread\n\n this.updateContext()\n\n document.dispatchEvent(\n new CustomEvent('notify', { detail: { message: i18next.t('text.task_is_approved_successfully')\n }\n })\n )\n }\n }\n\n async saveActivityApproval() { var { id, comment } = this.activityApproval\n\n const response = await client.mutate({ mutation: gql`\n mutation ($id: String!, $comment: String) { saveActivityApproval(id: $id, comment: $comment) ${ActivityApprovalFetchResult}\n }\n `,\n variables: { id,\n comment\n }\n })\n\n if (!response.errors) { this.activityApproval = response.data.saveActivityApproval\n this.activityThread = this.activityApproval.activityThread\n\n this.updateContext()\n\n document.dispatchEvent(\n new CustomEvent('notify', { detail: { message: i18next.t('text.task_is_saved_successfully')\n }\n })\n )\n }\n }\n}\n"]}
1
+ {"version":3,"file":"activity-approval-page.js","sourceRoot":"","sources":["../../../client/pages/activity-approval/activity-approval-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@operato/property-editor/ox-properties-dynamic-view.js'\nimport '@operato/board/ox-board-viewer.js'\nimport '../../components/activity-approval-ribon.js'\nimport '../../components/activity-thread-timeline.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, nothing, TemplateResult } from 'lit'\nimport { DirectiveResult } from 'lit-html/directive.js'\nimport { unsafeHTML } from 'lit-html/directives/unsafe-html.js'\nimport { customElement, query, state } from 'lit/decorators.js'\nimport { keyed } from 'lit/directives/keyed.js'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { PageView } from '@operato/shell'\nimport { CommonButtonStyles, ScrollbarStyles } from '@operato/styles'\nimport { provider } from '@things-factory/board-ui/dist-client/board-provider.js'\nimport { isReferenceStep } from '@things-factory/organization/dist-client'\n\nimport {\n ActivityFieldsStyles,\n fieldValue,\n inputSpecOf,\n outputSpecOf,\n renderGiven\n} from '../../components/activity-fields.js'\nimport {\n DecisionSlot,\n decisionSlots,\n reversibilityOf,\n slotOfRole,\n slotsOfRole\n} from '../../components/decision-slots.js'\n\nconst ActivityApprovalFetchResult = `\\\n{ id\n judgment\n comment\n approver { id\n name\n }\n round\n order\n createdAt\n terminatedAt\n activityThread { state\n dueAt\n assignedAt\n assignee { id\n name\n }\n updatedAt\n terminatedAt\n output\n activityApprovals { round\n order\n approver { name\n }\n judgment\n comment\n createdAt\n updatedAt\n terminatedAt\n }\n activityThreadHistories { transaction\n reason\n updater { name\n }\n updatedAt\n state\n output\n }\n activityInstance { id\n name\n description\n state\n activity { id\n label\n decisionKeys { role\n inputPath\n tKey\n unit\n }\n model { name\n description\n active\n tag\n inout\n type\n unit\n options\n quantifier\n spec\n hidden\n }\n }\n approvalLine { type\n value\n participation\n approver { id\n name\n description\n controlNo\n }\n }\n thumbnail\n input\n output\n viewType\n viewSource\n dueAt\n createdAt\n } \n }\n}`\n\nexport const ActivityThreadStatus = { Unassigned: 'unassigned',\n Assigned: 'assigned',\n Started: 'started',\n Delegated: 'delegated',\n Ended: 'ended',\n Aborted: 'aborted'\n}\n\n@customElement('activity-approval-page')\nexport class ActivityApprovalPage extends localize(i18next)(PageView) { static styles = [\n ScrollbarStyles,\n ActivityFieldsStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n position: relative;\n\n width: 100%;\n overflow: auto;\n background: var(--ui-bg, #f0f2f4);\n color: var(--ui-ink, #17242c);\n font-size: var(--ui-t-body, 13px);\n }\n\n /* 카드가 담아 주므로 안에 들어오는 화면은 자기 면과 여백을 갖지 않는다. */\n /*\n * 줄어들지 않는다 — 줄어들면 본문이 잘린다.\n *\n * flex 항목인데 크기를 안 정해 두면 기본이 flex: 0 1 auto 다. **1 이 줄어든다는 뜻이다** —\n * 세로가 모자라면 브라우저가 이 칸부터 줄이는데, 여기엔 카드 모서리를 따라 자르려고\n * overflow: hidden 이 걸려 있어서 줄어든 만큼이 **스크롤도 없이 사라진다.**\n *\n * 완료 조회에서 실측했다(1400x620): 칸이 242px 로 줄고 내용은 362px 이라 「업무 내용」 절이\n * 대부분 잘렸고, 잘린 자리 바로 아래에서 타임라인이 시작하니 타임라인이 본문을 덮은 것처럼\n * 보였다. 세로가 넉넉하면 줄일 일이 없어 안 드러난다.\n *\n * 안에 오는 것은 문서다. 높이를 정해 주어야 하는 것은 board 뿐이고 board 는 이 칸을 거치지\n * 않는다(activityContent 참조). 문서는 제 높이로 서고, 모자라면 페이지 전체가 스크롤한다 —\n * :host 의 overflow: auto 가 그 자리다.\n */\n section[hosted] {\n flex: none;\n padding: 0;\n overflow: hidden;\n }\n\n ox-board-viewer {\n width: 100%;\n height: 100%;\n }\n\n activity-thread-timeline {\n margin: var(--spacing-large, 16px);\n }\n\n /*\n * 의견 칸 — 이 화면에서 **결재자가 유일하게 적는 자리**다.\n *\n * 화면 아래에 붙어 있어(sticky) 목록을 내려 읽는 동안에도 보인다. 그 자리를 지키되 모양은\n * 다른 절과 같은 카드로 둔다. 전에는 회색 면(surface-variant)에 다른 테두리라 이 화면에서\n * 혼자 다른 부품처럼 보였다.\n */\n /*\n * 의견 — 이 화면에서 **결재자가 유일하게 적는 자리**다.\n *\n * 화면 아래에 붙어 있어(sticky) 내용을 내려 읽는 동안에도 보인다. 그 자리를 지키되 모양은\n * 다른 절과 같은 카드로 둔다. 전에는 회색 면(surface-variant)에 다른 테두리라 이 화면에서\n * 혼자 다른 부품처럼 보였다.\n */\n div[comment] {\n position: sticky;\n bottom: 0;\n padding-bottom: var(--spacing-large, 16px);\n background: var(--ui-bg, #f0f2f4);\n }\n\n /*\n * 이 화면에서 **사용자가 유일하게 손대는 자리**라는 것을 모양으로 말한다.\n *\n * 나머지 절은 전부 읽는 것이고, 판단은 아래 툴바의 단추가 받는다. 그런데 의견 칸이 읽는\n * 절들과 똑같은 카드라 「내 차례가 어디인지」가 화면에 없었다. 왼쪽에 강조색 띠를 둔다 —\n * sticky 라 툴바 바로 위에 붙으므로 띠와 단추가 한 덩어리로 읽힌다.\n */\n div[comment] section {\n border-left: 3px solid var(--ui-accent, #00727e);\n }\n\n div[comment] textarea {\n display: block;\n box-sizing: border-box;\n width: 100%;\n height: 76px;\n padding: 10px 12px;\n background: var(--ui-panel, #ffffff);\n border: 1px solid var(--ui-line, #d5dce0);\n border-radius: var(--ui-r-small, 6px);\n color: var(--ui-ink, #17242c);\n font: inherit;\n font-size: var(--ui-t-body, 13px);\n resize: none;\n outline: none;\n }\n\n div[comment] textarea:focus {\n border-color: var(--ui-accent, #00727e);\n }\n\n div[comment] .hint {\n margin: 7px 0 0;\n font-size: var(--ui-t-small, 11.5px);\n color: var(--ui-faint, #8a959c);\n word-break: keep-all;\n }\n\n /*\n * The decision, drawn from the activity's declaration.\n *\n * The order is the declaration's and the weight descends with it: what is being asked reads\n * first at title size, then what it is about, then the words a person wrote, then what changes\n * on approval, and last why it came up at all.\n */\n section[decision] .headline {\n font-size: var(--ui-t-headline, 19px);\n font-weight: 600;\n line-height: 1.35;\n color: var(--ui-ink, #17242c);\n word-break: keep-all;\n }\n\n section[decision] .subject {\n margin-top: 3px;\n font-family: var(--ui-mono, ui-monospace, Menlo, monospace);\n font-size: var(--ui-t-body, 13px);\n color: var(--ui-muted, #57676f);\n }\n\n section[decision] .block {\n margin-top: 14px;\n }\n\n section[decision] .block > .label {\n margin-bottom: 4px;\n font-size: var(--ui-t-small, 11.5px);\n color: var(--ui-muted, #57676f);\n }\n\n /* What a person wrote is set apart, because it is the only part nobody computed. */\n section[decision] .said {\n padding: 9px 11px;\n border-left: 3px solid var(--ui-line, #d5dce0);\n background: var(--ui-line-soft, #f2f5f7);\n color: var(--ui-ink, #17242c);\n word-break: break-word;\n }\n\n section[decision] .none {\n color: var(--ui-faint, #8a959c);\n }\n\n section[decision] .consequence {\n margin-top: 8px;\n padding: 9px 11px;\n border: 1px solid var(--ui-line, #d5dce0);\n border-radius: var(--ui-r-small, 6px);\n }\n\n section[decision] .consequence > .label {\n margin-bottom: 3px;\n font-size: var(--ui-t-small, 11.5px);\n color: var(--ui-muted, #57676f);\n }\n\n /*\n * Whether approving can be undone reads as the frame around the decision, not as one of its\n * consequences. Among them it carries the same weight as \"four orders get pushed back\", and\n * on an approval that moves equipment it is the heaviest line on the screen.\n */\n section[decision] .reversibility {\n display: flex;\n align-items: center;\n gap: 6px;\n\n margin-top: 12px;\n padding: 8px 11px;\n border-radius: var(--ui-r-small, 6px);\n\n background: var(--ui-line-soft, #f2f5f7);\n color: var(--ui-muted, #57676f);\n font-size: var(--ui-t-small, 11.5px);\n }\n\n section[decision] .reversibility[irreversible] {\n background: var(--md-sys-color-error-container, #ffdad6);\n color: var(--md-sys-color-on-error-container, #410002);\n font-weight: 600;\n }\n\n section[decision] .reversibility md-icon {\n font-size: 1.15em;\n }\n\n /*\n * What the decision was made from. Set flatter than the consequences — it is the record the\n * approver checks, not something the approval brings about.\n */\n section[decision] .evidence {\n margin-top: 8px;\n padding: 7px 0 7px 11px;\n border-left: 2px solid var(--ui-line, #d5dce0);\n }\n\n section[decision] .evidence > .label {\n margin-bottom: 2px;\n font-size: var(--ui-t-small, 11.5px);\n color: var(--ui-muted, #57676f);\n }\n\n /*\n * What is true right now sits apart from what the approval would change. Sharing the box the\n * consequences use would say the approval causes these readings.\n */\n section[decision] .current-state {\n margin-top: 14px;\n padding: 9px 11px;\n border: 1px dashed var(--ui-line, #d5dce0);\n border-radius: var(--ui-r-small, 6px);\n }\n\n section[decision] .current-state > .label {\n margin-bottom: 3px;\n font-size: var(--ui-t-small, 11.5px);\n color: var(--ui-muted, #57676f);\n }\n\n section[decision] .policy {\n margin-top: 14px;\n padding-top: 11px;\n border-top: 1px solid var(--ui-line, #d5dce0);\n font-size: var(--ui-t-small, 11.5px);\n color: var(--ui-muted, #57676f);\n }\n `\n ]\n\n @state() activityApproval: any\n /**\n * 조회를 마쳤나 — **「아직 안 읽었다」와 「없다」는 다르다.**\n *\n * 전에는 값이 없으면 곧바로 「업무활동 정보가 없습니다」를 그렸다. 그런데 이 화면은 열리자마자\n * 조회를 시작하므로, 응답이 오기 전까지 **없다고 단언하는 화면**이 보인다. 목록에서 줄을 눌러\n * 들어온 사람은 방금 본 건이 없다는 말을 먼저 읽는다.\n *\n * 조회가 끝난 뒤에만 그 말을 한다. 그 전에는 아무 말도 하지 않는다.\n */\n @state() loaded = false\n\n @state() activityThread: any\n @state() board: any\n\n @query('textarea') commentInput!: HTMLTextAreaElement\n\n /**\n * Is the reader seated here as a reference — someone who comments and does not decide?\n *\n * The rule comes from organization's client types, the same function its own approval-line editor\n * and list use, so the two wire spellings of the enum are handled in one place. The approval line\n * answers rather than ActivityApproval.participation, matching what the server refuses on\n * (isReferenceOrder in approval-line.ts): the line decides who comes next, so letting the row\n * decide who may judge would leave two authorities with nothing to settle a disagreement.\n *\n * The value comes back false while the query is still out. That is the same answer as for an\n * approver, so the buttons show for a moment on a reference's screen — pressing one is refused by\n * the server, which is why the server closed first.\n */\n get isReference(): boolean {\n const approvalLine = this.activityThread?.activityInstance?.approvalLine\n const order = Number(this.activityApproval?.order ?? 0)\n\n return isReferenceStep(approvalLine?.[order - 1])\n }\n\n get context() { const judgment = this.activityApproval?.judgment\n\n return { title: this.lifecycle?.params?.['title'] || i18next.t('title.activity approval'),\n help: 'worklist/activity-approval',\n /*\n * 이 화면은 메뉴에 없다 — 「내 결재함」에서 줄을 눌러 들어온다. 그래서 왼쪽 메뉴가 가리킬\n * 항목이 없고, 표시가 사라져 들어온 사람이 자기가 어디에 있는지 잃는다.\n *\n * 어느 목록에서 열리는지는 이 화면이 안다. 그것을 적어 둔다.\n */\n menu: 'approval-pending-list',\n /*\n * A reference is offered neither approve nor reject.\n *\n * ActivityApprovalJudgment has carried Closed for this seat from the start — \"the case ended\"\n * rather than a judgment — so a reference row was never meant to end in approved or rejected.\n * The buttons were offered anyway, and the server accepted them until 2026-09-09.\n *\n * What stays is the note, because a comment is the whole point of the seat, and close. The\n * hint under the textarea says which seat this is; buttons that simply vanish leave the\n * reader looking for them.\n */\n actions: judgment\n ? [\n { title: i18next.t('button.close'),\n action: () => { history.back()\n },\n ...CommonButtonStyles.back\n }\n ]\n : this.isReference\n ? [\n {\n title: i18next.t('button.save-note'),\n action: this.saveActivityApproval.bind(this),\n icon: 'edit_note',\n emphasis: { raised: true, outlined: false, dense: false, danger: false }\n },\n {\n title: i18next.t('button.close'),\n action: () => {\n history.back()\n },\n ...CommonButtonStyles.back,\n icon: 'close'\n }\n ]\n : /*\n * ── 세 단추의 순서와 무게 (2026-09-06) ──────────────────────────\n * 전에는 반려가 첫 자리였고, 승인 · 반려 · 저장이 모두 같은 모양이었다. 되돌리기 어려운\n * 것이 앞에 서고 무엇이 주된 흐름인지 화면이 말하지 않았다.\n *\n * 승인이 주 동작이다 — 채운 단추 하나. 반려는 대등한 선택이지만 예외 경로라 테두리\n * 단추로 그 옆에 둔다.\n *\n * 「저장」은 이름이 뜻을 말하지 않았다. 이 단추가 저장하는 것은 **의견 하나**이고\n * (saveActivityApproval 은 id 와 comment 만 보낸다), 판단은 미뤄 둔다. 그리고 그 결과는\n * 목록에서 「메모 있음」 표식으로 나타난다(activity-cells 의 approvalMarks). 목록이\n * 부르는 이름과 같은 낱말로 맞춘다.\n */\n [\n { title: i18next.t('button.approve'),\n action: this.approveActivityApproval.bind(this),\n icon: 'approval',\n emphasis: { raised: true,\n outlined: false,\n dense: false,\n danger: false\n }\n },\n\n { title: i18next.t('button.reject'),\n action: this.rejectActivityApproval.bind(this),\n icon: 'assignment_return',\n emphasis: { raised: false,\n outlined: true,\n dense: false,\n danger: false\n }\n },\n\n { title: i18next.t('button.save-note'),\n action: this.saveActivityApproval.bind(this),\n icon: 'edit_note',\n emphasis: { raised: false,\n outlined: true,\n dense: false,\n danger: false\n }\n },\n { title: i18next.t('button.close'),\n action: () => { history.back()\n },\n ...CommonButtonStyles.back,\n icon: 'close'\n }\n ]\n // activityApproval: this.activityApproval\n }\n }\n\n render() { if (!this.activityThread) {\n return this.loaded\n ? html`<div empty>\n <span class=\"title\">${i18next.t('text.no activity thread info')}</span>\n <span class=\"why\">${i18next.t('text.no-activity-thread-why')}</span>\n </div>`\n : nothing\n }\n\n const { terminatedAt } = this.activityApproval\n const editable = !terminatedAt\n\n return html`\n <activity-approval-ribon .activityApproval=${this.activityApproval}></activity-approval-ribon>\n ${this.activityContent()}\n <!--\n 보일 항목이 하나도 없으면 타임라인을 편다 — 그때는 화면이 「아래 타임라인의 상신 사유와\n 이력을 보고 판단하세요」로 여기를 가리키므로, 접혀 있으면 그 안내가 거짓말이 된다.\n -->\n <activity-thread-timeline\n .activityThread=${this.activityThread}\n ?open=${!this.hasFields()}\n short-form\n ></activity-thread-timeline>\n ${editable\n ? html`\n <div comment>\n <section>\n <h2>${i18next.t('field.wl-comment')}</h2>\n <textarea\n placeholder=${String(\n i18next.t(\n this.isReference\n ? 'text.write-your-comment-as-reference'\n : 'text.explain the reason for approval/rejection'\n )\n )}\n .value=${this.activityApproval?.comment}\n @change=${(e: Event) => {\n this.activityApproval.comment = (e.target as HTMLTextAreaElement).value\n }}\n ></textarea>\n <!--\n 반려는 의견이 필수다(rejectActivityApproval). 전에는 그 규칙을 **누른 뒤에** 토스트로\n 알렸다. 되돌릴 수 없는 것과 뜻이 다른 동작은 하기 전에 말한다.\n\n A reference reads a different line: this one names the seat, because the approve\n and reject buttons are absent for them and a reader whose buttons are missing\n goes looking for them.\n -->\n <p class=\"hint\">\n ${i18next.t(this.isReference ? 'text.reference-comment-hint' : 'text.approval-comment-hint')}\n </p>\n </section>\n </div>\n `\n : nothing}\n `\n }\n\n /** 화면에 낼 항목이 하나라도 있나. 타임라인을 펴 둘지 정하는 자리가 쓴다. */\n hasFields(): boolean {\n const model = this.activityThread?.activityInstance?.activity?.model\n\n return inputSpecOf(model).length > 0 || outputSpecOf(model).length > 0\n }\n\n activityContent() { switch (this.activityThread?.activityInstance?.viewType) { case 'template':\n return this.hostedContent(this.templateContent())\n case 'generated':\n return this.generatedContent()\n /* board 는 전체 화면을 쓰는 캔버스라 카드에 담지 않는다(hostedContent 머리말). */\n case 'board':\n return this.boardContent()\n case 'custom-element':\n return this.hostedContent(this.customElementContent())\n case 'page':\n case 'external':\n return html``\n default:\n return this.generatedContent()\n }\n }\n\n /**\n * 화면 종류가 달라도 **같은 자리에 같은 모양으로 놓인다.**\n *\n * worklist 는 네 가지로 내용을 그린다(generated · custom-element · template · board). 그중\n * generated 만 절 카드 안에 있었고 나머지 셋은 면 위에 맨몸으로 놓였다. 그래서 같은 결재 화면이\n * 액티비티에 따라 카드였다가 아니었다가 했다 — 아래의 타임라인 · 의견은 늘 카드라 위계도 어긋났다.\n *\n * board 는 뺀다. 전체 폭 · 전체 높이를 쓰는 캔버스라 카드 안에 넣으면 여백이 두 겹이 되고 크기가\n * 어긋난다.\n *\n * 카드는 여백을 두지 않는다(padding: 0). 안에 들어오는 것이 자기 조판을 갖고 있고, 두 겹으로\n * 주면 안쪽 내용이 카드 가운데로 밀린다.\n */\n hostedContent(content: unknown) {\n return html`<section hosted>${content}</section>`\n }\n\n templateContent() { if (!this.activityApproval) { return html``\n }\n\n const { viewSource: template } = this.activityThread?.activityInstance\n return unsafeHTML(template)\n }\n\n /**\n * 결재자가 보는 내용 — **전부 읽기 전용이다.**\n *\n * 전에는 「Output」 절을 편집기로 그리고 변경을 activityApproval.output 에 적었다. 그런데\n * approveActivityApproval / rejectActivityApproval 은 id 와 comment 만 보낸다 — 그 값은 어디에도\n * 가지 않는다. 결재자가 적을 수 있는 것은 의견 하나이고, 그것은 화면 아래 칸이 받는다.\n */\n /**\n * The decision the activity declared, or nothing when it declared none.\n *\n * Returning nothing is how generatedContent knows to fall back to the model. An activity with no\n * decisionKeys draws exactly what it drew before.\n *\n * A slot whose path led nowhere is skipped rather than drawn empty. Older instances of an activity\n * predate a field the declaration names — plant hit that with its `policy` value — and an empty\n * bar on the screen would read as \"there is no reason\" when the truth is that this record has no\n * such value. What cannot be shown is left out; what is shown is only what the payload actually\n * carries.\n *\n * `reason` is the exception. Missing and blank mean the same thing to whoever is reading — nobody\n * wrote one — so both draw the grey line rather than disappearing. A reason that silently vanishes\n * would let an approver assume it was never asked for.\n */\n decisionContent() {\n const { activityInstance } = this.activityThread || {}\n const slots = decisionSlots(activityInstance?.activity?.decisionKeys, activityInstance?.input)\n\n if (!slots.length) {\n return nothing\n }\n\n const headline = slotOfRole(slots, 'headline')\n const subject = slotOfRole(slots, 'subject')\n const reason = slotOfRole(slots, 'reason')\n const consequences = slotsOfRole(slots, 'consequence').filter(slot => slot.found)\n const policy = slotOfRole(slots, 'policy')\n const evidence = slotsOfRole(slots, 'evidence').filter(slot => slot.found)\n const currentState = slotOfRole(slots, 'currentState')\n const reversibility = slotOfRole(slots, 'reversibility')\n\n const drawable =\n [headline, subject, policy, currentState].some(slot => slot?.found) ||\n !!reason ||\n consequences.length ||\n evidence.length ||\n reversibilityOf(reversibility) !== undefined\n\n /*\n * Every declared slot missed this payload. Saying so is not this screen's job — falling back to\n * the model at least shows the values that are there, and the reader is no worse off than before\n * the declaration existed.\n */\n if (!drawable) {\n return nothing\n }\n\n return keyed(\n this.activityApproval.id,\n html`\n <section decision>\n ${headline?.found ? html`<div class=\"headline\">${this.slotText(headline)}</div>` : ''}\n ${subject?.found ? html`<div class=\"subject\">${this.slotText(subject)}</div>` : ''}\n ${reason\n ? html`\n <div class=\"block\">\n <div class=\"label\">${i18next.t('field.reason')}</div>\n <div class=\"said ${this.hasWords(reason) ? '' : 'none'}\">\n ${this.hasWords(reason) ? this.slotText(reason) : i18next.t('text.no-reason-given')}\n </div>\n </div>\n `\n : ''}\n ${this.renderReversibility(reversibility)}\n ${evidence.length\n ? html`\n <div class=\"block\">\n <div class=\"label\">${i18next.t('label.what-it-was-judged-from')}</div>\n ${evidence.map(\n slot => html`\n <div class=\"evidence\">\n ${slot.tKey ? html`<div class=\"label\">${i18next.t(slot.tKey)}</div>` : ''}\n <div>${fieldValue(slot.value)}</div>\n </div>\n `\n )}\n </div>\n `\n : ''}\n ${currentState?.found\n ? html`\n <div class=\"current-state\">\n <div class=\"label\">${i18next.t(currentState.tKey || 'label.current-state')}</div>\n <div>${fieldValue(currentState.value)}</div>\n </div>\n `\n : ''}\n ${consequences.length\n ? html`\n <div class=\"block\">\n <div class=\"label\">${i18next.t('label.what-changes')}</div>\n ${consequences.map(\n slot => html`\n <div class=\"consequence\">\n ${slot.tKey ? html`<div class=\"label\">${i18next.t(slot.tKey)}</div>` : ''}\n <div>${fieldValue(slot.value)}</div>\n </div>\n `\n )}\n </div>\n `\n : ''}\n ${policy?.found\n ? html`\n <div class=\"policy\">\n ${i18next.t('label.why-approval')} — ${this.slotText(policy)}\n </div>\n `\n : ''}\n </section>\n `\n )\n }\n\n /**\n * Whether approving can be undone, drawn as the frame around the decision.\n *\n * Only an explicit true or false draws. Anything else — the path led nowhere, or the value is not\n * a boolean — draws nothing, because saying \"this can be undone\" on a screen that does not know is\n * the one mistake this line must never make.\n *\n * This is not rejectionIsFinal. That one says whether **rejecting** ends the case for good; this\n * says whether **approving** can be taken back. The twin actuation carries both, which is exactly\n * why they must not share a sentence.\n */\n private renderReversibility(slot?: DecisionSlot) {\n const reversible = reversibilityOf(slot)\n\n if (reversible === undefined) {\n return ''\n }\n\n return html`\n <div class=\"reversibility\" ?irreversible=${!reversible}>\n <md-icon>${reversible ? 'undo' : 'lock'}</md-icon>\n <span>${i18next.t(reversible ? 'text.approval-is-reversible' : 'text.approval-is-irreversible')}</span>\n </div>\n `\n }\n\n /**\n * One slot's value as something to read.\n *\n * A scalar prints with its unit when one was declared. Anything shaped — an object, a list — goes\n * through fieldValue, the same laying-out the model sections use, so a payload reads the same way\n * wherever it appears and a four-level object does not become one long line.\n */\n private slotText(slot: DecisionSlot): unknown {\n const scalar = slot.value !== null && slot.value !== undefined && typeof slot.value !== 'object'\n\n if (scalar && slot.unit) {\n return `${slot.value} ${slot.unit}`\n }\n\n return scalar ? String(slot.value) : fieldValue(slot.value)\n }\n\n /** Did a person actually write something here. Whitespace is not words. */\n private hasWords(slot: DecisionSlot): boolean {\n return typeof slot.value === 'string' ? slot.value.trim().length > 0 : slot.found && slot.value != null\n }\n\n generatedContent(): DirectiveResult { if (!this.activityApproval) { return html``\n }\n\n const { output, activityInstance } = this.activityThread || {}\n const { input } = activityInstance || {}\n\n /*\n * The declaration goes first. It answers \"what happens if I approve\", which is the question this\n * screen exists for; the model answers \"what are the values\", which is the fallback.\n */\n const decision = this.decisionContent()\n\n if (decision !== nothing) {\n return decision as DirectiveResult\n }\n\n const model = activityInstance?.activity?.model\n const inputSpec = inputSpecOf(model)\n const outputSpec = outputSpecOf(model)\n\n /*\n * **결재 화면에서 내용이 비어 있는 것은 경고다.**\n *\n * 업무 상세라면 「적을 것이 없다」로 끝난다. 여기서는 다르다 — 무엇을 승인하는지 모르는 채로\n * 승인 · 반려 버튼이 그대로 눌린다. 그 사실을 화면이 말하고, 대신 무엇을 보고 판단할지 알려\n * 준다(타임라인의 상신 사유).\n */\n if (!inputSpec.length && !outputSpec.length) {\n return keyed(\n this.activityApproval.id,\n html`<section empty>\n <span class=\"title\">${i18next.t('text.no-approval-content')}</span>\n <span class=\"why\">${i18next.t('text.no-approval-content-why')}</span>\n </section>`\n )\n }\n\n return keyed(\n this.activityApproval.id,\n html`\n ${inputSpec.length\n ? html`\n <section readonly>\n <h2>${i18next.t('label.activity-input')}</h2>\n ${renderGiven(inputSpec, input)}\n </section>\n `\n : ''}\n ${outputSpec.length\n ? html`\n <section readonly>\n <h2>${i18next.t('field.artifact')}</h2>\n ${renderGiven(outputSpec, output)}\n </section>\n `\n : ''}\n `\n )\n }\n\n boardContent(): DirectiveResult { if (!this.activityApproval) { return html``\n }\n\n const { output, activityInstance } = this.activityThread\n const { viewSource: boardId, input } = activityInstance || {}\n\n if (!this.board || this.board.id !== boardId) { this.board = { id: boardId\n }\n }\n\n return keyed(\n this.activityApproval.id,\n html`\n <ox-board-viewer\n style=\"background-color: white;\"\n .board=${this.board}\n .provider=${provider}\n .values=${{ ...input, ...output }}\n hide-fullscreen\n hide-navigation\n ></ox-board-viewer>\n `\n )\n }\n\n /**\n * The element the activity names, or a plain statement that it could not be loaded.\n *\n * document.createElement answers something for any name, so an activity pointing at an element\n * nobody registered used to produce an empty card. The approver got a screen with nothing on it\n * and the approve button still worked — plant shipped two such forms in one day and found them by\n * reading the file list, not by opening the screen.\n *\n * The reader is told what to judge by instead. Same shape as the empty generated screen: what is\n * missing, and where to look — the submission reason and the history in the timeline below.\n *\n * ── Waiting for a late definition ─────────────────────────────────────────\n * An element can be registered after this page renders, and answering \"not loaded\" forever in\n * that case would be a screen inventing a defect. whenDefined resolves whenever it arrives and\n * the page redraws; a name nobody ever registers simply never resolves, and the statement stands.\n */\n customElementContent() { if (!this.activityApproval) { return html``\n }\n\n const { output, activityInstance } = this.activityThread\n const { viewSource: tagName, input } = activityInstance || {}\n\n if (!tagName || !customElements.get(tagName)) {\n if (tagName) {\n customElements.whenDefined(tagName).then(() => this.requestUpdate())\n }\n\n return html`<section empty>\n <span class=\"title\">${i18next.t('text.approval-view-not-loaded')}</span>\n <span class=\"why\">${i18next.t('text.no-approval-content-why')}</span>\n </section>`\n }\n\n const element = document.createElement(tagName)\n element.id = 'custom-content'\n element.activityId = activityInstance.activity.id\n element.input = input\n element.output = output\n element.activityApproval = this.activityApproval\n\n return element\n }\n\n @query('ox-board-viewer') oxBoardViewer: any\n\n getOutputFromBoard() { const outputSpec = outputSpecOf(this.activityThread?.activityInstance?.activity?.model)\n const data = this.oxBoardViewer.getSceneValues()\n\n return outputSpec.reduce((output, spec) => { output[spec.name] = data[spec.name]\n return output\n }, {})\n }\n\n /**\n * 화면이 열리면 **의견 칸에 캐럿을 둔다.**\n *\n * 결재자가 이 화면에서 적는 것은 의견 하나다. 나머지는 전부 읽는 것이고, 판단은 아래 버튼이\n * 받는다. 그러면 열자마자 커서가 있어야 하는 자리는 하나뿐이다.\n *\n * 조건 둘을 지킨다.\n *\n * 활성 탭일 때만 MDI 라 뒤에 있는 탭이 응답을 받으면 앞 탭의 입력을 빼앗는다\n * 한 건에 한 번 갱신마다 focus 를 부르면 사용자가 옮긴 커서를 계속 되돌린다\n *\n * preventScroll 을 준다 — 화면을 아래로 끌어내리면 정작 무엇을 승인하는지가 위로 사라진다.\n */\n private focusedFor?: string\n\n private focusComment() {\n const id = this.activityApproval?.id\n\n if (!id || !this.active || this.activityApproval?.terminatedAt || this.focusedFor === id) {\n return\n }\n\n this.commentInput?.focus({ preventScroll: true })\n this.focusedFor = id\n }\n\n updated(changes) { if (changes.has('activityApproval')) { this.updateContext()\n this.focusComment()\n }\n }\n\n async pageUpdated(changes, lifecycle, changedBefore) { if (this.active && lifecycle.resourceId) { this.fetchActivityApproval(lifecycle.resourceId)\n }\n }\n\n async fetchActivityApproval(id) { const response = await client.query({ query: gql`\n query activityApproval($id: String!) { activityApproval(id: $id) ${ActivityApprovalFetchResult}\n }\n `,\n variables: { id\n }\n })\n\n this.activityApproval = response.data.activityApproval\n this.loaded = true\n this.activityThread = this.activityApproval.activityThread\n\n this.updateContext()\n }\n\n async rejectActivityApproval() { var { id, comment } = this.activityApproval\n\n if (!comment) { document.dispatchEvent(\n new CustomEvent('notify', { detail: { message: i18next.t('text.enter a comment')\n }\n })\n )\n this.commentInput.focus()\n return\n }\n\n const response = await client.mutate({ mutation: gql`\n mutation ($id: String!, $comment: String!) { rejectActivityApproval(id: $id, comment: $comment) ${ActivityApprovalFetchResult}\n }\n `,\n variables: { id,\n comment\n }\n })\n\n if (!response.errors) { this.activityApproval = response.data.rejectActivityApproval\n this.activityThread = this.activityApproval.activityThread\n\n this.updateContext()\n\n document.dispatchEvent(\n new CustomEvent('notify', { detail: { message: i18next.t('text.task_is_rejected_successfully')\n }\n })\n )\n }\n }\n\n async approveActivityApproval() { var { id, comment } = this.activityApproval\n\n const response = await client.mutate({ mutation: gql`\n mutation ($id: String!, $comment: String) { approveActivityApproval(id: $id, comment: $comment) ${ActivityApprovalFetchResult}\n }\n `,\n variables: { id,\n comment\n }\n })\n\n if (!response.errors) { this.activityApproval = response.data.approveActivityApproval\n this.activityThread = this.activityApproval.activityThread\n\n this.updateContext()\n\n document.dispatchEvent(\n new CustomEvent('notify', { detail: { message: i18next.t('text.task_is_approved_successfully')\n }\n })\n )\n }\n }\n\n async saveActivityApproval() { var { id, comment } = this.activityApproval\n\n const response = await client.mutate({ mutation: gql`\n mutation ($id: String!, $comment: String) { saveActivityApproval(id: $id, comment: $comment) ${ActivityApprovalFetchResult}\n }\n `,\n variables: { id,\n comment\n }\n })\n\n if (!response.errors) { this.activityApproval = response.data.saveActivityApproval\n this.activityThread = this.activityApproval.activityThread\n\n this.updateContext()\n\n document.dispatchEvent(\n new CustomEvent('notify', { detail: { message: i18next.t('text.task_is_saved_successfully')\n }\n })\n )\n }\n }\n}\n"]}
@@ -43,9 +43,33 @@ export declare class ActivityCatalogPage extends ActivityCatalogPage_base {
43
43
  * 없음」으로 남는 것은 화면 위쪽의 목적을 방해하지 않는다.
44
44
  */
45
45
  private renderBuild;
46
+ /**
47
+ * 무엇이 실제로 서 있나 — **선언과 정의를 가르는 줄이다.**
48
+ *
49
+ * 이 화면은 단계 이름 하나로 「계획」·「동작함」만 말했다. 그런데 사용자가 카탈로그를 보고 물은 것은
50
+ * 「화면 설정도 없이 이게 정의냐」였고, 화면이 그 칸을 안 보이니 세는 사람이 파일을 열어야 했다.
51
+ * 액티비티가 서려면 주고받는 값과 화면과 콜백이 있어야 하고, 선언만 된 항목에는 그중 아무것도 없다.
52
+ *
53
+ * 설치되지 않은 항목에는 그리지 않는다. 45건에 「없음 · 없음 · 없음」을 세 줄씩 붙이면 그 자체가
54
+ * 벽이고, 무엇이 없는지는 그 항목의 gaps 가 이미 사람 말로 적고 있다.
55
+ */
56
+ private renderBuilt;
46
57
  /** 잰 날짜를 수와 함께 낸다 — 손으로 적는 기록이라 낡는데, 날짜가 있으면 낡았다는 것을 안다. */
47
58
  private renderRun;
48
59
  pageUpdated(changes: any, lifecycle: any): Promise<void>;
60
+ /**
61
+ * 주소로 바로 들어온 경우 — **`pageUpdated` 가 안 온다.**
62
+ *
63
+ * 메뉴에서 눌러 들어오면 화면이 꺼졌다 켜지면서 `pageUpdated` 가 오고 거기서 읽는다. 그런데 주소를
64
+ * 직접 열면 이 요소가 **이미 active 인 채로** 만들어져서 그 전환이 없다. 실측했다: `active` 는
65
+ * 참인데 `loaded` 가 거짓이고, 화면은 아무것도 없이 조용했다 — 오류도 빈 화면 문구도 없다.
66
+ *
67
+ * 목록 화면들은 이 자리가 안 비어 있다. grist 가 첫 렌더에서 스스로 `fetchHandler` 를 부르기
68
+ * 때문이다. 이 화면은 grist 를 안 쓰니 부르는 사람이 없었다.
69
+ *
70
+ * 그래서 켜져 있는데 아직 안 읽었으면 여기서 읽는다. `loaded` 가 그 조건이라 두 번 읽지 않는다.
71
+ */
72
+ updated(changes: any): void;
49
73
  fetch(): Promise<void>;
50
74
  }
51
75
  export {};
@@ -37,8 +37,18 @@ const CatalogFetch = gql `
37
37
  provider
38
38
  release
39
39
  approvalSteps
40
+ uiType
41
+ viewType
42
+ viewSource
43
+ model {
44
+ inout
45
+ hidden
46
+ }
40
47
  activity {
41
48
  id
49
+ decisionKeys {
50
+ role
51
+ }
42
52
  }
43
53
  readiness {
44
54
  stage
@@ -67,8 +77,29 @@ const CatalogFetch = gql `
67
77
  * 정한 것이 곧 될 것처럼 보인다.
68
78
  */
69
79
  const STAGE_ORDER = ['working', 'partial', 'declared', 'planned', 'not-worklist'];
80
+ /**
81
+ * 전선에서 온 단계를 **선언된 값으로 되돌린다.**
82
+ *
83
+ * `readiness.stage` 는 `@Field(type => ActivityReadinessStage)` 로 선언돼 있고, registerEnumType 은
84
+ * enum 을 **key 로** 공개한다. 그래서 전선에 오는 것은 `Working` · `Planned` · `NotWorklist` 이고
85
+ * 값(`working` · `planned` · `not-worklist`)이 아니다.
86
+ *
87
+ * 소문자로만 내리면 넷은 우연히 맞고 하나가 틀린다 — `NotWorklist` 가 `notworklist` 가 되는데
88
+ * 값에는 하이픈이 있다. 그 하나 때문에 화면에서 세 가지가 한꺼번에 어긋났다: 원시 i18n 키가 그대로
89
+ * 뜨고, 단계별 수에서 그 넷이 빠지고, 차례가 「예정」보다 위로 올라가 **판단이 약속처럼** 보였다.
90
+ *
91
+ * 오늘 아침 organization 에서 같은 것을 고쳤다(`participation` 이 `Reference` 로 와서 `reference`
92
+ * 와 비교하면 언제나 거짓이던 것). 글자만 다르지 같은 함정이라, 여기서도 **경계에서 한 번 되돌린다.**
93
+ * 비교하는 자리마다 소문자를 부르는 대신 이 함수 하나를 지난다.
94
+ */
95
+ function canonicalStage(raw) {
96
+ const flat = String(raw || '')
97
+ .toLowerCase()
98
+ .replace(/[^a-z]/g, '');
99
+ return STAGE_ORDER.find(stage => stage.replace(/[^a-z]/g, '') === flat) || '';
100
+ }
70
101
  function stageRank(stage) {
71
- const at = STAGE_ORDER.indexOf(String(stage || '').toLowerCase());
102
+ const at = STAGE_ORDER.indexOf(canonicalStage(stage));
72
103
  /* 선언이 없는 것은 도는 것들 뒤, 예정 앞에 둔다 — 모른다는 것이 「없다」는 아니다. */
73
104
  return at < 0 ? STAGE_ORDER.indexOf('declared') : at;
74
105
  }
@@ -134,12 +165,22 @@ let ActivityCatalogPage = class ActivityCatalogPage extends localize(i18next)(Pa
134
165
  list-style: none;
135
166
  }
136
167
 
168
+ /*
169
+ * 카드는 **바탕보다 밝다** — 페이지에서 떠 있어야 스물여섯 장이 줄로 읽힌다.
170
+ *
171
+ * 처음엔 surface 를 썼는데, 이 테마에서 그 값이 background 와 **같다**(실측: 라이트 둘 다
172
+ * rgb(238 241 243), 다크 둘 다 rgb(13 18 22)). 그래서 카드가 1px 테두리로만 구분됐다.
173
+ *
174
+ * surface-container-low 가 두 테마에서 **같은 방향**으로 갈린다 — 라이트 246 248 249,
175
+ * 다크 20 27 33, 둘 다 바탕보다 밝다. surface-container-high 는 라이트에서 오히려 어두워져
176
+ * 카드가 눌린 것처럼 읽힌다. 뜨는 것과 눌리는 것은 다른 말이라 방향이 뒤집히면 안 된다.
177
+ */
137
178
  li {
138
179
  padding: 12px 14px;
139
180
  border: 1px solid var(--md-sys-color-outline-variant, #cac4d0);
140
181
  border-radius: 6px;
141
182
 
142
- background-color: var(--md-sys-color-surface, #fff);
183
+ background-color: var(--md-sys-color-surface-container-low, #f6f8f9);
143
184
  color: var(--md-sys-color-on-surface, #1d1b20);
144
185
  }
145
186
 
@@ -323,7 +364,7 @@ let ActivityCatalogPage = class ActivityCatalogPage extends localize(i18next)(Pa
323
364
  return html `
324
365
  <div counts>
325
366
  ${STAGE_ORDER.map(stage => {
326
- const n = this.items.filter(one => String(one.readiness?.stage || '').toLowerCase() == stage).length;
367
+ const n = this.items.filter(one => canonicalStage(one.readiness?.stage) == stage).length;
327
368
  return n ? html `<span>${i18next.t('label.readiness-' + stage)} <b>${n}</b></span>` : '';
328
369
  })}
329
370
  </div>
@@ -334,7 +375,7 @@ let ActivityCatalogPage = class ActivityCatalogPage extends localize(i18next)(Pa
334
375
  `;
335
376
  }
336
377
  renderOne(one) {
337
- const stage = String(one.readiness?.stage || '').toLowerCase();
378
+ const stage = canonicalStage(one.readiness?.stage);
338
379
  /*
339
380
  * 아직 만들지 않은 것은 **설치될 수가 없다.** 그런 카드에 「아직 사용 안 함」을 붙이면 「예정」과
340
381
  * 같은 말을 두 번 하는 것이고, 읽는 사람은 둘이 다른 뜻인 줄 알고 두 번 읽는다.
@@ -421,15 +462,18 @@ let ActivityCatalogPage = class ActivityCatalogPage extends localize(i18next)(Pa
421
462
  */
422
463
  renderBuild(one) {
423
464
  const readiness = one.readiness || {};
424
- const stage = readiness.stage ? String(readiness.stage).toLowerCase() : '';
465
+ const stage = canonicalStage(readiness.stage);
425
466
  const run = readiness.lastRun;
426
467
  const hasRun = run && typeof run.total == 'number';
427
- if (!stage && !readiness.tests?.length && !hasRun && !readiness.notes && !readiness.gaps?.length) {
468
+ const built = this.renderBuilt(one);
469
+ if (!stage && !built && !readiness.tests?.length && !hasRun && !readiness.notes && !readiness.gaps?.length) {
428
470
  return '';
429
471
  }
430
472
  return html `<details>
431
473
  <summary>${i18next.t('label.activity-build-info')}${stage ? ` · ${i18next.t('label.readiness-' + stage)}` : ''}</summary>
432
474
  <dl>
475
+ ${built ? html `<dt>${i18next.t('field.what-is-built')}</dt>
476
+ <dd>${built}</dd>` : ''}
433
477
  ${readiness.gaps?.length
434
478
  ? html `<dt>${i18next.t('field.readiness-gaps')}</dt>
435
479
  <dd>${readiness.gaps.join(' · ')}</dd>`
@@ -449,6 +493,40 @@ let ActivityCatalogPage = class ActivityCatalogPage extends localize(i18next)(Pa
449
493
  </dl>
450
494
  </details>`;
451
495
  }
496
+ /**
497
+ * 무엇이 실제로 서 있나 — **선언과 정의를 가르는 줄이다.**
498
+ *
499
+ * 이 화면은 단계 이름 하나로 「계획」·「동작함」만 말했다. 그런데 사용자가 카탈로그를 보고 물은 것은
500
+ * 「화면 설정도 없이 이게 정의냐」였고, 화면이 그 칸을 안 보이니 세는 사람이 파일을 열어야 했다.
501
+ * 액티비티가 서려면 주고받는 값과 화면과 콜백이 있어야 하고, 선언만 된 항목에는 그중 아무것도 없다.
502
+ *
503
+ * 설치되지 않은 항목에는 그리지 않는다. 45건에 「없음 · 없음 · 없음」을 세 줄씩 붙이면 그 자체가
504
+ * 벽이고, 무엇이 없는지는 그 항목의 gaps 가 이미 사람 말로 적고 있다.
505
+ */
506
+ renderBuilt(one) {
507
+ if (!one.activity?.id) {
508
+ return '';
509
+ }
510
+ const model = (one.model || []).filter((item) => !item?.hidden);
511
+ const taking = model.filter((item) => item?.inout == 'in' || item?.inout == 'inout').length;
512
+ const giving = model.filter((item) => item?.inout == 'out' || item?.inout == 'inout').length;
513
+ const decisions = (one.activity?.decisionKeys || []).length;
514
+ /*
515
+ * 결재 화면이 무엇으로 그려지나. 전용 요소는 이름까지 적는다 — 「전용 화면이 있다」만으로는 어느
516
+ * 것인지 못 찾고, 이 절을 읽는 사람은 그 파일을 열려는 사람이다.
517
+ *
518
+ * 선언이 채워지면 기본 화면도 판단을 그린다. 그래서 「기본 화면」 뒤에 판단 항목 수가 붙는다 —
519
+ * 0 이면 그 화면은 아직 칸 목록이다.
520
+ */
521
+ const screen = one.viewSource
522
+ ? html `${i18next.t('text.own-approval-view')} · <code>${one.viewSource}</code>`
523
+ : html `${i18next.t('text.generated-approval-view')}`;
524
+ return html `
525
+ <div>${i18next.t('text.model-in-out', { taking, giving })}</div>
526
+ <div>${i18next.t('field.approval-view')} — ${screen}</div>
527
+ <div>${i18next.t('text.decision-keys-count', { n: decisions })}</div>
528
+ `;
529
+ }
452
530
  /** 잰 날짜를 수와 함께 낸다 — 손으로 적는 기록이라 낡는데, 날짜가 있으면 낡았다는 것을 안다. */
453
531
  renderRun(run) {
454
532
  const at = run.at ? new Date(Date.parse(String(run.at))) : undefined;
@@ -471,6 +549,23 @@ let ActivityCatalogPage = class ActivityCatalogPage extends localize(i18next)(Pa
471
549
  await this.fetch();
472
550
  }
473
551
  }
552
+ /**
553
+ * 주소로 바로 들어온 경우 — **`pageUpdated` 가 안 온다.**
554
+ *
555
+ * 메뉴에서 눌러 들어오면 화면이 꺼졌다 켜지면서 `pageUpdated` 가 오고 거기서 읽는다. 그런데 주소를
556
+ * 직접 열면 이 요소가 **이미 active 인 채로** 만들어져서 그 전환이 없다. 실측했다: `active` 는
557
+ * 참인데 `loaded` 가 거짓이고, 화면은 아무것도 없이 조용했다 — 오류도 빈 화면 문구도 없다.
558
+ *
559
+ * 목록 화면들은 이 자리가 안 비어 있다. grist 가 첫 렌더에서 스스로 `fetchHandler` 를 부르기
560
+ * 때문이다. 이 화면은 grist 를 안 쓰니 부르는 사람이 없었다.
561
+ *
562
+ * 그래서 켜져 있는데 아직 안 읽었으면 여기서 읽는다. `loaded` 가 그 조건이라 두 번 읽지 않는다.
563
+ */
564
+ updated(changes) {
565
+ if (this.active && !this.loaded && !this.failed) {
566
+ this.fetch();
567
+ }
568
+ }
474
569
  async fetch() {
475
570
  const response = await client.query({ query: CatalogFetch, fetchPolicy: 'no-cache' });
476
571
  /*
@@ -1 +1 @@
1
- {"version":3,"file":"activity-catalog-page.js","sourceRoot":"","sources":["../../../client/pages/activity-catalog/activity-catalog-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { PageView } from '@operato/shell'\nimport { ScrollbarStyles } from '@operato/styles'\n\n/**\n * 업무 카탈로그 — **업무함에 올라오는 일이 무슨 일인지 읽는 자리.**\n *\n * ── 첫 판을 다시 만든 이유 (2026-09-08) ───────────────────────────────────\n * 처음 만든 화면은 사용자가 읽을 것이 없었다. 네 줄 중 세 줄이 「…선언되지 않았습니다」였고, 업무\n * 설명은 영어로 나왔고, 다크 테마에서는 글자가 뭉개졌다. 「덮는 시험」처럼 아무도 쓰지 않는 말을\n * 지어내기까지 했다. 개발자 덤프를 사용자 화면이라고 부른 셈이다.\n *\n * 그래서 층을 진짜로 가른다.\n *\n * - **사용자가 읽는 것**: 이 업무가 무엇이고, 여기서 쓰이고 있나. 그것만 크게.\n * - **개발 정보**: 어디까지 됐나 · 시험. **값이 있을 때만** 접어서 아래에 둔다. 없는 것을 줄줄이\n * 적지 않는다 — 빈 줄을 나열하는 것은 정직한 게 아니라 아무 말도 안 하는 것이다.\n *\n * 여전히 판단하지 않고 선언을 그린다. 어디까지 됐는지는 화면이 실행 중에 알 수 없고, 그 업무를\n * 등록한 모듈이 자기 코드 옆에 적는다(ActivityReadiness).\n */\nconst CatalogFetch = gql`\n query {\n responses: installableActivities {\n items {\n name\n label\n description\n guide\n category\n activityType\n provider\n release\n approvalSteps\n activity {\n id\n }\n readiness {\n stage\n gaps\n tests\n notes\n lastRun {\n passed\n total\n at\n command\n }\n }\n }\n total\n }\n }\n`\n\n/**\n * 카드 차례 — **쓸 수 있는 것이 위.**\n *\n * 사용자는 지금 도는 업무를 보러 오고, 우리는 남은 것을 보러 온다. 두 독자를 한 화면에 두면서\n * 순서로 가른다: 위쪽은 실제로 오는 업무, 아래쪽은 아직 없는 것과 여기 두지 않기로 한 것.\n *\n * **「업무함 아님」은 「예정」과 붙여 두지 않는다.** 섞이면 판단이 약속으로 읽힌다 — 안 만들기로\n * 정한 것이 곧 될 것처럼 보인다.\n */\nconst STAGE_ORDER = ['working', 'partial', 'declared', 'planned', 'not-worklist']\n\nfunction stageRank(stage?: string): number {\n const at = STAGE_ORDER.indexOf(String(stage || '').toLowerCase())\n\n /* 선언이 없는 것은 도는 것들 뒤, 예정 앞에 둔다 — 모른다는 것이 「없다」는 아니다. */\n return at < 0 ? STAGE_ORDER.indexOf('declared') : at\n}\n\n@customElement('activity-catalog-page')\nexport class ActivityCatalogPage extends localize(i18next)(PageView) {\n static styles = [\n ScrollbarStyles,\n css`\n /*\n * 색은 전부 테마 토큰으로 쓴다. 첫 판은 흰 카드와 연회색 글자를 값으로 박아서 다크 테마에서\n * 글자가 배경에 묻혔다.\n */\n :host {\n display: flex;\n flex-direction: column;\n\n width: 100%;\n overflow: auto;\n padding: var(--spacing-large, 12px);\n\n background-color: var(--md-sys-color-background);\n color: var(--md-sys-color-on-background);\n font-size: var(--ui-t-body, 13px);\n }\n\n /* 단계별 수. 설명이 아니라 자료라서 둔다 — 개발 기간에 이 수가 남은 일을 말한다. */\n [counts] {\n display: flex;\n flex-wrap: wrap;\n gap: 4px 14px;\n\n margin: 0 0 12px 0;\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n [counts] b {\n color: var(--md-sys-color-on-surface, #1d1b20);\n }\n\n [failed] {\n display: flex;\n align-items: center;\n gap: 6px;\n\n padding: 8px 10px;\n border-radius: 6px;\n\n background-color: var(--md-sys-color-error-container, #ffdad6);\n color: var(--md-sys-color-on-error-container, #410002);\n }\n\n ul {\n display: grid;\n gap: 10px;\n\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n li {\n padding: 12px 14px;\n border: 1px solid var(--md-sys-color-outline-variant, #cac4d0);\n border-radius: 6px;\n\n background-color: var(--md-sys-color-surface, #fff);\n color: var(--md-sys-color-on-surface, #1d1b20);\n }\n\n .head {\n display: flex;\n align-items: baseline;\n flex-wrap: wrap;\n gap: 8px;\n }\n\n .name {\n font-size: var(--ui-t-title, 15px);\n font-weight: 600;\n }\n\n /* 여기서 쓰이나 — 사용자에게 이 카드에서 가장 실질적인 사실이다. */\n .use {\n padding: 1px 7px;\n border-radius: 999px;\n font-size: 11px;\n white-space: nowrap;\n\n background-color: var(--md-sys-color-secondary-container, #e8def8);\n color: var(--md-sys-color-on-secondary-container, #1d192b);\n }\n\n .use[idle] {\n background-color: var(--md-sys-color-surface-variant, #e7e0ec);\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n /* 이 업무가 무엇인가. 카드에서 가장 먼저 읽히는 줄이다. */\n .guide {\n margin: 8px 0 0 0;\n line-height: 1.55;\n }\n\n .guide p {\n margin: 0 0 4px 0;\n }\n\n .unwritten {\n margin: 8px 0 0 0;\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n /*\n * 개발 정보. 값이 있을 때만 그린다. 사용자에게는 접힌 한 줄로만 보이고, 열면 우리가 볼 것이\n * 나온다.\n */\n /*\n * 단계 표. **철자를 하나만 쓴다.**\n *\n * 앞 판은 단계마다 boolean 속성을 뒀다. 그러면 하이픈 없는 두 번째 철자가 생기고\n * (notworklist) i18n 키(label.readiness-not-worklist)와 어긋난다. 값 하나를 data-stage 에\n * 실으면 선택자 · 키 꼬리 · 서버 enum 값이 **같은 글자**가 된다.\n *\n * 색과 말로 함께 말한다 — 색만 쓰면 색을 못 가리는 사람에게 아무 말도 하지 않는다.\n */\n .stage {\n padding: 1px 7px;\n border-radius: 999px;\n font-size: 11px;\n white-space: nowrap;\n\n background-color: var(--md-sys-color-surface-variant, #e7e0ec);\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n .stage[data-stage='working'] {\n background-color: var(--md-sys-color-secondary-container, #e8def8);\n color: var(--md-sys-color-on-secondary-container, #1d192b);\n }\n\n .stage[data-stage='partial'],\n .stage[data-stage='declared'] {\n background-color: var(--md-sys-color-tertiary-container, #ffd8e4);\n color: var(--md-sys-color-on-tertiary-container, #31111d);\n }\n\n /* 여기 두지 않기로 한 것. 테두리만 두어 만들 것들과 섞이지 않게 한다. */\n .stage[data-stage='not-worklist'] {\n background-color: transparent;\n border: 1px solid var(--md-sys-color-outline-variant, #cac4d0);\n }\n\n details {\n margin-top: 10px;\n padding-top: 8px;\n border-top: 1px solid var(--md-sys-color-outline-variant, #cac4d0);\n }\n\n summary {\n cursor: pointer;\n border-radius: 4px;\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n /*\n * 키보드로 여기 왔을 때 어디에 있는지 보여야 한다.\n *\n * summary 는 눌리는 것이라 tab 이 멈추는 자리다. 내가 이 절을 만들면서 표시를 안 줘서\n * plant 의 접근성 래칫 시험이 「포커스가 안 보이는 자리 7 → 8」로 잡아냈다. 화면을 하나\n * 더할 때마다 한 칸씩 늘어나는 것을 막는 시험이고, 허용 수를 올려 통과시킬 자리가 아니다.\n */\n summary:focus-visible {\n outline: 2px solid var(--md-sys-color-primary, #6750a4);\n outline-offset: 2px;\n }\n\n dl {\n display: grid;\n grid-template-columns: max-content 1fr;\n gap: 4px 12px;\n\n margin: 8px 0 0 0;\n }\n\n dt {\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n dd {\n margin: 0;\n }\n\n code {\n font-family: var(--ui-font-mono, monospace);\n font-size: 12px;\n word-break: break-all;\n }\n\n div[empty] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n\n div[empty] .title {\n font-size: var(--ui-t-title, 15px);\n }\n\n div[empty] .why {\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n @media (max-width: 480px) {\n dl {\n grid-template-columns: 1fr;\n gap: 0;\n }\n\n dt {\n margin-top: 6px;\n }\n }\n `\n ]\n\n @state() items: any[] = []\n @state() loaded = false\n @state() failed = false\n\n get context() {\n return {\n title: i18next.t('title.activity catalog'),\n help: 'worklist/activity-catalog-page'\n }\n }\n\n render() {\n if (this.failed) {\n return html`<div failed role=\"alert\">\n <md-icon>cloud_off</md-icon>\n <span>${i18next.t('text.catalog-not-loaded')}</span>\n </div>`\n }\n\n if (!this.loaded) {\n return html``\n }\n\n if (!this.items.length) {\n return html`<div empty>\n <span class=\"title\">${i18next.t('text.no-installable-activity')}</span>\n <span class=\"why\">${i18next.t('text.no-installable-activity-why')}</span>\n </div>`\n }\n\n return html`\n <div counts>\n ${STAGE_ORDER.map(stage => {\n const n = this.items.filter(one => String(one.readiness?.stage || '').toLowerCase() == stage).length\n return n ? html`<span>${i18next.t('label.readiness-' + stage)} <b>${n}</b></span>` : ''\n })}\n </div>\n\n <ul>\n ${this.items.map(one => this.renderOne(one))}\n </ul>\n `\n }\n\n private renderOne(one: any) {\n const stage = String(one.readiness?.stage || '').toLowerCase()\n\n /*\n * 아직 만들지 않은 것은 **설치될 수가 없다.** 그런 카드에 「아직 사용 안 함」을 붙이면 「예정」과\n * 같은 말을 두 번 하는 것이고, 읽는 사람은 둘이 다른 뜻인 줄 알고 두 번 읽는다.\n */\n const registered = !!stage && stage != 'planned' && stage != 'not-worklist'\n const inUse = !!one.activity?.id\n\n return html`<li>\n <div class=\"head\">\n <!--\n 이름은 label 이 있으면 label 이다. name 은 콜백을 찾는 키라서 사람이 읽는 말이 아닐 수\n 있다 — 한국어 스물셋 사이에 「MES Disposition Approval」 하나가 그렇게 떴다.\n -->\n <span class=\"name\">${one.label || one.name}</span>\n\n <!--\n 단계를 카드 머리에 둔다.\n 한 판에서 이것을 개발 정보 안으로 옮겼다가 되돌렸다. 업무가 마흔을 넘고 그중 대부분이 아직\n 안 만든 것이면, 접힌 절 안에 든 단계는 하나씩 펼쳐야 아는 값이 된다. 그러면 목록이 다\n 같아 보인다.\n -->\n ${stage\n ? html`<span class=\"stage\" data-stage=${stage}>${i18next.t('label.readiness-' + stage)}</span>`\n : ''}\n ${registered\n ? html`<span class=\"use\" ?idle=${!inUse}\n >${inUse ? i18next.t('text.activity-in-use-here') : i18next.t('text.activity-not-in-use-here')}</span\n >`\n : ''}\n </div>\n\n ${this.renderGuide(one)} ${registered ? this.renderApprovers(one) : ''} ${this.renderBuild(one)}\n </li>`\n }\n\n /**\n * 이 업무가 무엇인가.\n *\n * `guide` 가 그 자리다 — 받는 사람의 말로 쓴 문장이고, i18n 키를 넣어도 된다. `description` 은\n * 우리끼리 쓰는 영어 한 줄이라 여기에 그대로 내지 않는다. 한국어 화면에서 영어 한 줄은 설명이\n * 아니다.\n *\n * 없으면 **한 줄로** 없다고 말한다. 없는 것을 여러 줄로 늘리지 않는다.\n */\n private renderGuide(one: any) {\n const lines: string[] = (one.guide || []).map((line: string) => i18next.t(line, { defaultValue: line }))\n\n if (!lines.length) {\n return html`<p class=\"unwritten\">${i18next.t('text.activity-guide-unwritten')}</p>`\n }\n\n return html`<div class=\"guide\">${lines.map(line => html`<p>${line}</p>`)}</div>`\n }\n\n /**\n * 이 공장이 이 단계를 쓰나 — **결재선에 결재자가 있나.**\n *\n * 결재선은 양식이 아니라 그 현장이 정하는 것이라, 같은 업무가 어느 공장에서는 결재를 받고 어느\n * 공장에서는 그냥 지나간다. 그 사실이 지금까지 기동 로그 한 줄에만 있었다.\n *\n * **사람 수가 아니라 단계 수다** — 역할로 걸린 한 단계는 여러 사람이 본다. 그리고 비어 있다는 것이\n * 무슨 일을 뜻하는지는 업무마다 달라서(상신이 막히거나, 확인 없이 지나가거나) 여기서 결과를 말하지\n * 않는다. 그건 그 업무의 설명이 할 말이다.\n *\n * 「아직 사용 안 함」인 카드에는 그리지 않는다 — 세워지지 않은 양식에 결재선이 있을 수 없다.\n */\n private renderApprovers(one: any) {\n if (!one.activity?.id) {\n return ''\n }\n\n const steps = one.approvalSteps\n\n return html`<dl>\n <dt>${i18next.t('field.approval-line')}</dt>\n <dd>\n ${typeof steps != 'number'\n ? html`<span class=\"unwritten\">${i18next.t('text.approval-line-unknown')}</span>`\n : steps > 0\n ? i18next.t('text.approval-line-steps', { n: steps })\n : html`<span class=\"unwritten\">${i18next.t('text.approval-line-empty')}</span>`}\n </dd>\n </dl>`\n }\n\n /**\n * 개발 정보 — **값이 있을 때만.**\n *\n * 첫 판은 값이 없어도 「…선언되지 않았습니다」를 네 줄 그렸다. 사용자에게는 뜻 없는 벽이고 우리에게도\n * 아무 정보가 아니다. 아무것도 없으면 이 절 자체를 그리지 않는다 — 그 업무가 카탈로그에 「개발 정보\n * 없음」으로 남는 것은 화면 위쪽의 목적을 방해하지 않는다.\n */\n private renderBuild(one: any) {\n const readiness = one.readiness || {}\n const stage = readiness.stage ? String(readiness.stage).toLowerCase() : ''\n const run = readiness.lastRun\n const hasRun = run && typeof run.total == 'number'\n\n if (!stage && !readiness.tests?.length && !hasRun && !readiness.notes && !readiness.gaps?.length) {\n return ''\n }\n\n return html`<details>\n <summary>${i18next.t('label.activity-build-info')}${stage ? ` · ${i18next.t('label.readiness-' + stage)}` : ''}</summary>\n <dl>\n ${readiness.gaps?.length\n ? html`<dt>${i18next.t('field.readiness-gaps')}</dt>\n <dd>${readiness.gaps.join(' · ')}</dd>`\n : ''}\n ${readiness.tests?.length\n ? html`<dt>${i18next.t('field.covering-tests')}</dt>\n <dd>${readiness.tests.map((test: string) => html`<div><code>${test}</code></div>`)}</dd>`\n : ''}\n ${hasRun\n ? html`<dt>${i18next.t('field.last-test-run')}</dt>\n <dd>${this.renderRun(run)}</dd>`\n : ''}\n ${readiness.notes\n ? html`<dt>${i18next.t('field.readiness-notes')}</dt>\n <dd>${readiness.notes}</dd>`\n : ''}\n </dl>\n </details>`\n }\n\n /** 잰 날짜를 수와 함께 낸다 — 손으로 적는 기록이라 낡는데, 날짜가 있으면 낡았다는 것을 안다. */\n private renderRun(run: any) {\n const at = run.at ? new Date(Date.parse(String(run.at))) : undefined\n const when =\n at && Number.isFinite(at.getTime())\n ? at.toLocaleString(i18next.language || undefined, {\n year: 'numeric',\n month: 'numeric',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n hour12: false\n })\n : ''\n\n return html`${typeof run.passed == 'number' ? run.passed : '—'} / ${run.total}${when\n ? html` · ${when}`\n : ''}${run.command ? html`<div><code>${run.command}</code></div>` : ''}`\n }\n\n async pageUpdated(changes: any, lifecycle: any) {\n if (this.active) {\n await this.fetch()\n }\n }\n\n async fetch() {\n const response = await client.query({ query: CatalogFetch, fetchPolicy: 'no-cache' })\n\n /*\n * 이 client 는 errorPolicy: 'all' 이라 질의가 실패해도 거절되지 않는다. 그대로 읽으면 실패가\n * 「등록된 업무가 없다」로 그려진다.\n */\n const items = response.errors?.length ? undefined : response.data?.responses?.items\n\n if (!Array.isArray(items)) {\n this.failed = true\n this.loaded = true\n console.error('[activity-catalog]', response.errors || 'no data')\n return\n }\n\n this.failed = false\n this.items = [...items].sort(\n (a, b) =>\n stageRank(a.readiness?.stage) - stageRank(b.readiness?.stage) ||\n String(a.label || a.name).localeCompare(String(b.label || b.name))\n )\n this.loaded = true\n }\n}\n"]}
1
+ {"version":3,"file":"activity-catalog-page.js","sourceRoot":"","sources":["../../../client/pages/activity-catalog/activity-catalog-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { PageView } from '@operato/shell'\nimport { ScrollbarStyles } from '@operato/styles'\n\n/**\n * 업무 카탈로그 — **업무함에 올라오는 일이 무슨 일인지 읽는 자리.**\n *\n * ── 첫 판을 다시 만든 이유 (2026-09-08) ───────────────────────────────────\n * 처음 만든 화면은 사용자가 읽을 것이 없었다. 네 줄 중 세 줄이 「…선언되지 않았습니다」였고, 업무\n * 설명은 영어로 나왔고, 다크 테마에서는 글자가 뭉개졌다. 「덮는 시험」처럼 아무도 쓰지 않는 말을\n * 지어내기까지 했다. 개발자 덤프를 사용자 화면이라고 부른 셈이다.\n *\n * 그래서 층을 진짜로 가른다.\n *\n * - **사용자가 읽는 것**: 이 업무가 무엇이고, 여기서 쓰이고 있나. 그것만 크게.\n * - **개발 정보**: 어디까지 됐나 · 시험. **값이 있을 때만** 접어서 아래에 둔다. 없는 것을 줄줄이\n * 적지 않는다 — 빈 줄을 나열하는 것은 정직한 게 아니라 아무 말도 안 하는 것이다.\n *\n * 여전히 판단하지 않고 선언을 그린다. 어디까지 됐는지는 화면이 실행 중에 알 수 없고, 그 업무를\n * 등록한 모듈이 자기 코드 옆에 적는다(ActivityReadiness).\n */\nconst CatalogFetch = gql`\n query {\n responses: installableActivities {\n items {\n name\n label\n description\n guide\n category\n activityType\n provider\n release\n approvalSteps\n uiType\n viewType\n viewSource\n model {\n inout\n hidden\n }\n activity {\n id\n decisionKeys {\n role\n }\n }\n readiness {\n stage\n gaps\n tests\n notes\n lastRun {\n passed\n total\n at\n command\n }\n }\n }\n total\n }\n }\n`\n\n/**\n * 카드 차례 — **쓸 수 있는 것이 위.**\n *\n * 사용자는 지금 도는 업무를 보러 오고, 우리는 남은 것을 보러 온다. 두 독자를 한 화면에 두면서\n * 순서로 가른다: 위쪽은 실제로 오는 업무, 아래쪽은 아직 없는 것과 여기 두지 않기로 한 것.\n *\n * **「업무함 아님」은 「예정」과 붙여 두지 않는다.** 섞이면 판단이 약속으로 읽힌다 — 안 만들기로\n * 정한 것이 곧 될 것처럼 보인다.\n */\nconst STAGE_ORDER = ['working', 'partial', 'declared', 'planned', 'not-worklist']\n\n/**\n * 전선에서 온 단계를 **선언된 값으로 되돌린다.**\n *\n * `readiness.stage` 는 `@Field(type => ActivityReadinessStage)` 로 선언돼 있고, registerEnumType 은\n * enum 을 **key 로** 공개한다. 그래서 전선에 오는 것은 `Working` · `Planned` · `NotWorklist` 이고\n * 값(`working` · `planned` · `not-worklist`)이 아니다.\n *\n * 소문자로만 내리면 넷은 우연히 맞고 하나가 틀린다 — `NotWorklist` 가 `notworklist` 가 되는데\n * 값에는 하이픈이 있다. 그 하나 때문에 화면에서 세 가지가 한꺼번에 어긋났다: 원시 i18n 키가 그대로\n * 뜨고, 단계별 수에서 그 넷이 빠지고, 차례가 「예정」보다 위로 올라가 **판단이 약속처럼** 보였다.\n *\n * 오늘 아침 organization 에서 같은 것을 고쳤다(`participation` 이 `Reference` 로 와서 `reference`\n * 와 비교하면 언제나 거짓이던 것). 글자만 다르지 같은 함정이라, 여기서도 **경계에서 한 번 되돌린다.**\n * 비교하는 자리마다 소문자를 부르는 대신 이 함수 하나를 지난다.\n */\nfunction canonicalStage(raw?: string): string {\n const flat = String(raw || '')\n .toLowerCase()\n .replace(/[^a-z]/g, '')\n\n return STAGE_ORDER.find(stage => stage.replace(/[^a-z]/g, '') === flat) || ''\n}\n\nfunction stageRank(stage?: string): number {\n const at = STAGE_ORDER.indexOf(canonicalStage(stage))\n\n /* 선언이 없는 것은 도는 것들 뒤, 예정 앞에 둔다 — 모른다는 것이 「없다」는 아니다. */\n return at < 0 ? STAGE_ORDER.indexOf('declared') : at\n}\n\n@customElement('activity-catalog-page')\nexport class ActivityCatalogPage extends localize(i18next)(PageView) {\n static styles = [\n ScrollbarStyles,\n css`\n /*\n * 색은 전부 테마 토큰으로 쓴다. 첫 판은 흰 카드와 연회색 글자를 값으로 박아서 다크 테마에서\n * 글자가 배경에 묻혔다.\n */\n :host {\n display: flex;\n flex-direction: column;\n\n width: 100%;\n overflow: auto;\n padding: var(--spacing-large, 12px);\n\n background-color: var(--md-sys-color-background);\n color: var(--md-sys-color-on-background);\n font-size: var(--ui-t-body, 13px);\n }\n\n /* 단계별 수. 설명이 아니라 자료라서 둔다 — 개발 기간에 이 수가 남은 일을 말한다. */\n [counts] {\n display: flex;\n flex-wrap: wrap;\n gap: 4px 14px;\n\n margin: 0 0 12px 0;\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n [counts] b {\n color: var(--md-sys-color-on-surface, #1d1b20);\n }\n\n [failed] {\n display: flex;\n align-items: center;\n gap: 6px;\n\n padding: 8px 10px;\n border-radius: 6px;\n\n background-color: var(--md-sys-color-error-container, #ffdad6);\n color: var(--md-sys-color-on-error-container, #410002);\n }\n\n ul {\n display: grid;\n gap: 10px;\n\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n /*\n * 카드는 **바탕보다 밝다** — 페이지에서 떠 있어야 스물여섯 장이 줄로 읽힌다.\n *\n * 처음엔 surface 를 썼는데, 이 테마에서 그 값이 background 와 **같다**(실측: 라이트 둘 다\n * rgb(238 241 243), 다크 둘 다 rgb(13 18 22)). 그래서 카드가 1px 테두리로만 구분됐다.\n *\n * surface-container-low 가 두 테마에서 **같은 방향**으로 갈린다 — 라이트 246 248 249,\n * 다크 20 27 33, 둘 다 바탕보다 밝다. surface-container-high 는 라이트에서 오히려 어두워져\n * 카드가 눌린 것처럼 읽힌다. 뜨는 것과 눌리는 것은 다른 말이라 방향이 뒤집히면 안 된다.\n */\n li {\n padding: 12px 14px;\n border: 1px solid var(--md-sys-color-outline-variant, #cac4d0);\n border-radius: 6px;\n\n background-color: var(--md-sys-color-surface-container-low, #f6f8f9);\n color: var(--md-sys-color-on-surface, #1d1b20);\n }\n\n .head {\n display: flex;\n align-items: baseline;\n flex-wrap: wrap;\n gap: 8px;\n }\n\n .name {\n font-size: var(--ui-t-title, 15px);\n font-weight: 600;\n }\n\n /* 여기서 쓰이나 — 사용자에게 이 카드에서 가장 실질적인 사실이다. */\n .use {\n padding: 1px 7px;\n border-radius: 999px;\n font-size: 11px;\n white-space: nowrap;\n\n background-color: var(--md-sys-color-secondary-container, #e8def8);\n color: var(--md-sys-color-on-secondary-container, #1d192b);\n }\n\n .use[idle] {\n background-color: var(--md-sys-color-surface-variant, #e7e0ec);\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n /* 이 업무가 무엇인가. 카드에서 가장 먼저 읽히는 줄이다. */\n .guide {\n margin: 8px 0 0 0;\n line-height: 1.55;\n }\n\n .guide p {\n margin: 0 0 4px 0;\n }\n\n .unwritten {\n margin: 8px 0 0 0;\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n /*\n * 개발 정보. 값이 있을 때만 그린다. 사용자에게는 접힌 한 줄로만 보이고, 열면 우리가 볼 것이\n * 나온다.\n */\n /*\n * 단계 표. **철자를 하나만 쓴다.**\n *\n * 앞 판은 단계마다 boolean 속성을 뒀다. 그러면 하이픈 없는 두 번째 철자가 생기고\n * (notworklist) i18n 키(label.readiness-not-worklist)와 어긋난다. 값 하나를 data-stage 에\n * 실으면 선택자 · 키 꼬리 · 서버 enum 값이 **같은 글자**가 된다.\n *\n * 색과 말로 함께 말한다 — 색만 쓰면 색을 못 가리는 사람에게 아무 말도 하지 않는다.\n */\n .stage {\n padding: 1px 7px;\n border-radius: 999px;\n font-size: 11px;\n white-space: nowrap;\n\n background-color: var(--md-sys-color-surface-variant, #e7e0ec);\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n .stage[data-stage='working'] {\n background-color: var(--md-sys-color-secondary-container, #e8def8);\n color: var(--md-sys-color-on-secondary-container, #1d192b);\n }\n\n .stage[data-stage='partial'],\n .stage[data-stage='declared'] {\n background-color: var(--md-sys-color-tertiary-container, #ffd8e4);\n color: var(--md-sys-color-on-tertiary-container, #31111d);\n }\n\n /* 여기 두지 않기로 한 것. 테두리만 두어 만들 것들과 섞이지 않게 한다. */\n .stage[data-stage='not-worklist'] {\n background-color: transparent;\n border: 1px solid var(--md-sys-color-outline-variant, #cac4d0);\n }\n\n details {\n margin-top: 10px;\n padding-top: 8px;\n border-top: 1px solid var(--md-sys-color-outline-variant, #cac4d0);\n }\n\n summary {\n cursor: pointer;\n border-radius: 4px;\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n /*\n * 키보드로 여기 왔을 때 어디에 있는지 보여야 한다.\n *\n * summary 는 눌리는 것이라 tab 이 멈추는 자리다. 내가 이 절을 만들면서 표시를 안 줘서\n * plant 의 접근성 래칫 시험이 「포커스가 안 보이는 자리 7 → 8」로 잡아냈다. 화면을 하나\n * 더할 때마다 한 칸씩 늘어나는 것을 막는 시험이고, 허용 수를 올려 통과시킬 자리가 아니다.\n */\n summary:focus-visible {\n outline: 2px solid var(--md-sys-color-primary, #6750a4);\n outline-offset: 2px;\n }\n\n dl {\n display: grid;\n grid-template-columns: max-content 1fr;\n gap: 4px 12px;\n\n margin: 8px 0 0 0;\n }\n\n dt {\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n dd {\n margin: 0;\n }\n\n code {\n font-family: var(--ui-font-mono, monospace);\n font-size: 12px;\n word-break: break-all;\n }\n\n div[empty] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n\n div[empty] .title {\n font-size: var(--ui-t-title, 15px);\n }\n\n div[empty] .why {\n color: var(--md-sys-color-on-surface-variant, #49454f);\n }\n\n @media (max-width: 480px) {\n dl {\n grid-template-columns: 1fr;\n gap: 0;\n }\n\n dt {\n margin-top: 6px;\n }\n }\n `\n ]\n\n @state() items: any[] = []\n @state() loaded = false\n @state() failed = false\n\n get context() {\n return {\n title: i18next.t('title.activity catalog'),\n help: 'worklist/activity-catalog-page'\n }\n }\n\n render() {\n if (this.failed) {\n return html`<div failed role=\"alert\">\n <md-icon>cloud_off</md-icon>\n <span>${i18next.t('text.catalog-not-loaded')}</span>\n </div>`\n }\n\n if (!this.loaded) {\n return html``\n }\n\n if (!this.items.length) {\n return html`<div empty>\n <span class=\"title\">${i18next.t('text.no-installable-activity')}</span>\n <span class=\"why\">${i18next.t('text.no-installable-activity-why')}</span>\n </div>`\n }\n\n return html`\n <div counts>\n ${STAGE_ORDER.map(stage => {\n const n = this.items.filter(one => canonicalStage(one.readiness?.stage) == stage).length\n return n ? html`<span>${i18next.t('label.readiness-' + stage)} <b>${n}</b></span>` : ''\n })}\n </div>\n\n <ul>\n ${this.items.map(one => this.renderOne(one))}\n </ul>\n `\n }\n\n private renderOne(one: any) {\n const stage = canonicalStage(one.readiness?.stage)\n\n /*\n * 아직 만들지 않은 것은 **설치될 수가 없다.** 그런 카드에 「아직 사용 안 함」을 붙이면 「예정」과\n * 같은 말을 두 번 하는 것이고, 읽는 사람은 둘이 다른 뜻인 줄 알고 두 번 읽는다.\n */\n const registered = !!stage && stage != 'planned' && stage != 'not-worklist'\n const inUse = !!one.activity?.id\n\n return html`<li>\n <div class=\"head\">\n <!--\n 이름은 label 이 있으면 label 이다. name 은 콜백을 찾는 키라서 사람이 읽는 말이 아닐 수\n 있다 — 한국어 스물셋 사이에 「MES Disposition Approval」 하나가 그렇게 떴다.\n -->\n <span class=\"name\">${one.label || one.name}</span>\n\n <!--\n 단계를 카드 머리에 둔다.\n 한 판에서 이것을 개발 정보 안으로 옮겼다가 되돌렸다. 업무가 마흔을 넘고 그중 대부분이 아직\n 안 만든 것이면, 접힌 절 안에 든 단계는 하나씩 펼쳐야 아는 값이 된다. 그러면 목록이 다\n 같아 보인다.\n -->\n ${stage\n ? html`<span class=\"stage\" data-stage=${stage}>${i18next.t('label.readiness-' + stage)}</span>`\n : ''}\n ${registered\n ? html`<span class=\"use\" ?idle=${!inUse}\n >${inUse ? i18next.t('text.activity-in-use-here') : i18next.t('text.activity-not-in-use-here')}</span\n >`\n : ''}\n </div>\n\n ${this.renderGuide(one)} ${registered ? this.renderApprovers(one) : ''} ${this.renderBuild(one)}\n </li>`\n }\n\n /**\n * 이 업무가 무엇인가.\n *\n * `guide` 가 그 자리다 — 받는 사람의 말로 쓴 문장이고, i18n 키를 넣어도 된다. `description` 은\n * 우리끼리 쓰는 영어 한 줄이라 여기에 그대로 내지 않는다. 한국어 화면에서 영어 한 줄은 설명이\n * 아니다.\n *\n * 없으면 **한 줄로** 없다고 말한다. 없는 것을 여러 줄로 늘리지 않는다.\n */\n private renderGuide(one: any) {\n const lines: string[] = (one.guide || []).map((line: string) => i18next.t(line, { defaultValue: line }))\n\n if (!lines.length) {\n return html`<p class=\"unwritten\">${i18next.t('text.activity-guide-unwritten')}</p>`\n }\n\n return html`<div class=\"guide\">${lines.map(line => html`<p>${line}</p>`)}</div>`\n }\n\n /**\n * 이 공장이 이 단계를 쓰나 — **결재선에 결재자가 있나.**\n *\n * 결재선은 양식이 아니라 그 현장이 정하는 것이라, 같은 업무가 어느 공장에서는 결재를 받고 어느\n * 공장에서는 그냥 지나간다. 그 사실이 지금까지 기동 로그 한 줄에만 있었다.\n *\n * **사람 수가 아니라 단계 수다** — 역할로 걸린 한 단계는 여러 사람이 본다. 그리고 비어 있다는 것이\n * 무슨 일을 뜻하는지는 업무마다 달라서(상신이 막히거나, 확인 없이 지나가거나) 여기서 결과를 말하지\n * 않는다. 그건 그 업무의 설명이 할 말이다.\n *\n * 「아직 사용 안 함」인 카드에는 그리지 않는다 — 세워지지 않은 양식에 결재선이 있을 수 없다.\n */\n private renderApprovers(one: any) {\n if (!one.activity?.id) {\n return ''\n }\n\n const steps = one.approvalSteps\n\n return html`<dl>\n <dt>${i18next.t('field.approval-line')}</dt>\n <dd>\n ${typeof steps != 'number'\n ? html`<span class=\"unwritten\">${i18next.t('text.approval-line-unknown')}</span>`\n : steps > 0\n ? i18next.t('text.approval-line-steps', { n: steps })\n : html`<span class=\"unwritten\">${i18next.t('text.approval-line-empty')}</span>`}\n </dd>\n </dl>`\n }\n\n /**\n * 개발 정보 — **값이 있을 때만.**\n *\n * 첫 판은 값이 없어도 「…선언되지 않았습니다」를 네 줄 그렸다. 사용자에게는 뜻 없는 벽이고 우리에게도\n * 아무 정보가 아니다. 아무것도 없으면 이 절 자체를 그리지 않는다 — 그 업무가 카탈로그에 「개발 정보\n * 없음」으로 남는 것은 화면 위쪽의 목적을 방해하지 않는다.\n */\n private renderBuild(one: any) {\n const readiness = one.readiness || {}\n const stage = canonicalStage(readiness.stage)\n const run = readiness.lastRun\n const hasRun = run && typeof run.total == 'number'\n\n const built = this.renderBuilt(one)\n\n if (!stage && !built && !readiness.tests?.length && !hasRun && !readiness.notes && !readiness.gaps?.length) {\n return ''\n }\n\n return html`<details>\n <summary>${i18next.t('label.activity-build-info')}${stage ? ` · ${i18next.t('label.readiness-' + stage)}` : ''}</summary>\n <dl>\n ${built ? html`<dt>${i18next.t('field.what-is-built')}</dt>\n <dd>${built}</dd>` : ''}\n ${readiness.gaps?.length\n ? html`<dt>${i18next.t('field.readiness-gaps')}</dt>\n <dd>${readiness.gaps.join(' · ')}</dd>`\n : ''}\n ${readiness.tests?.length\n ? html`<dt>${i18next.t('field.covering-tests')}</dt>\n <dd>${readiness.tests.map((test: string) => html`<div><code>${test}</code></div>`)}</dd>`\n : ''}\n ${hasRun\n ? html`<dt>${i18next.t('field.last-test-run')}</dt>\n <dd>${this.renderRun(run)}</dd>`\n : ''}\n ${readiness.notes\n ? html`<dt>${i18next.t('field.readiness-notes')}</dt>\n <dd>${readiness.notes}</dd>`\n : ''}\n </dl>\n </details>`\n }\n\n /**\n * 무엇이 실제로 서 있나 — **선언과 정의를 가르는 줄이다.**\n *\n * 이 화면은 단계 이름 하나로 「계획」·「동작함」만 말했다. 그런데 사용자가 카탈로그를 보고 물은 것은\n * 「화면 설정도 없이 이게 정의냐」였고, 화면이 그 칸을 안 보이니 세는 사람이 파일을 열어야 했다.\n * 액티비티가 서려면 주고받는 값과 화면과 콜백이 있어야 하고, 선언만 된 항목에는 그중 아무것도 없다.\n *\n * 설치되지 않은 항목에는 그리지 않는다. 45건에 「없음 · 없음 · 없음」을 세 줄씩 붙이면 그 자체가\n * 벽이고, 무엇이 없는지는 그 항목의 gaps 가 이미 사람 말로 적고 있다.\n */\n private renderBuilt(one: any) {\n if (!one.activity?.id) {\n return ''\n }\n\n const model = (one.model || []).filter((item: any) => !item?.hidden)\n const taking = model.filter((item: any) => item?.inout == 'in' || item?.inout == 'inout').length\n const giving = model.filter((item: any) => item?.inout == 'out' || item?.inout == 'inout').length\n const decisions = (one.activity?.decisionKeys || []).length\n\n /*\n * 결재 화면이 무엇으로 그려지나. 전용 요소는 이름까지 적는다 — 「전용 화면이 있다」만으로는 어느\n * 것인지 못 찾고, 이 절을 읽는 사람은 그 파일을 열려는 사람이다.\n *\n * 선언이 채워지면 기본 화면도 판단을 그린다. 그래서 「기본 화면」 뒤에 판단 항목 수가 붙는다 —\n * 0 이면 그 화면은 아직 칸 목록이다.\n */\n const screen = one.viewSource\n ? html`${i18next.t('text.own-approval-view')} · <code>${one.viewSource}</code>`\n : html`${i18next.t('text.generated-approval-view')}`\n\n return html`\n <div>${i18next.t('text.model-in-out', { taking, giving })}</div>\n <div>${i18next.t('field.approval-view')} — ${screen}</div>\n <div>${i18next.t('text.decision-keys-count', { n: decisions })}</div>\n `\n }\n\n /** 잰 날짜를 수와 함께 낸다 — 손으로 적는 기록이라 낡는데, 날짜가 있으면 낡았다는 것을 안다. */\n private renderRun(run: any) {\n const at = run.at ? new Date(Date.parse(String(run.at))) : undefined\n const when =\n at && Number.isFinite(at.getTime())\n ? at.toLocaleString(i18next.language || undefined, {\n year: 'numeric',\n month: 'numeric',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n hour12: false\n })\n : ''\n\n return html`${typeof run.passed == 'number' ? run.passed : '—'} / ${run.total}${when\n ? html` · ${when}`\n : ''}${run.command ? html`<div><code>${run.command}</code></div>` : ''}`\n }\n\n async pageUpdated(changes: any, lifecycle: any) {\n if (this.active) {\n await this.fetch()\n }\n }\n\n /**\n * 주소로 바로 들어온 경우 — **`pageUpdated` 가 안 온다.**\n *\n * 메뉴에서 눌러 들어오면 화면이 꺼졌다 켜지면서 `pageUpdated` 가 오고 거기서 읽는다. 그런데 주소를\n * 직접 열면 이 요소가 **이미 active 인 채로** 만들어져서 그 전환이 없다. 실측했다: `active` 는\n * 참인데 `loaded` 가 거짓이고, 화면은 아무것도 없이 조용했다 — 오류도 빈 화면 문구도 없다.\n *\n * 목록 화면들은 이 자리가 안 비어 있다. grist 가 첫 렌더에서 스스로 `fetchHandler` 를 부르기\n * 때문이다. 이 화면은 grist 를 안 쓰니 부르는 사람이 없었다.\n *\n * 그래서 켜져 있는데 아직 안 읽었으면 여기서 읽는다. `loaded` 가 그 조건이라 두 번 읽지 않는다.\n */\n updated(changes: any) {\n if (this.active && !this.loaded && !this.failed) {\n this.fetch()\n }\n }\n\n async fetch() {\n const response = await client.query({ query: CatalogFetch, fetchPolicy: 'no-cache' })\n\n /*\n * 이 client 는 errorPolicy: 'all' 이라 질의가 실패해도 거절되지 않는다. 그대로 읽으면 실패가\n * 「등록된 업무가 없다」로 그려진다.\n */\n const items = response.errors?.length ? undefined : response.data?.responses?.items\n\n if (!Array.isArray(items)) {\n this.failed = true\n this.loaded = true\n console.error('[activity-catalog]', response.errors || 'no data')\n return\n }\n\n this.failed = false\n this.items = [...items].sort(\n (a, b) =>\n stageRank(a.readiness?.stage) - stageRank(b.readiness?.stage) ||\n String(a.label || a.name).localeCompare(String(b.label || b.name))\n )\n this.loaded = true\n }\n}\n"]}
@@ -32,7 +32,34 @@ export declare class ActivityTemplateListPage extends ActivityTemplateListPage_b
32
32
  total: any;
33
33
  records: any;
34
34
  }>;
35
+ /**
36
+ * Turning a template on for this domain.
37
+ *
38
+ * The result is read. Both mutations require `activity:mutation` as of 2026-09-11, and until then
39
+ * anything a signed-in user pressed went through, so this refusal path had never run.
40
+ *
41
+ * `mutate` is configured with `errorPolicy: 'all'`
42
+ * ([읽었음] operato/webcomponents/graphql/src/graphql-client.ts:18), so a refused mutation
43
+ * **resolves** with `errors` instead of throwing. Ignoring the result and re-reading the list
44
+ * showed the row unchanged and said nothing — the button looked broken rather than refused.
45
+ */
35
46
  activate(record: any): Promise<void>;
47
+ /** Turning it off. Heavier than turning it on — it stops the work this activity carries. */
36
48
  deactivate(record: any): Promise<void>;
49
+ /**
50
+ * Report the outcome, then re-read the list either way.
51
+ *
52
+ * The list is re-read even on a refusal: it is what shows the reader the row did not move. Saying
53
+ * "refused" while leaving a stale row on screen would be two statements that disagree.
54
+ *
55
+ * ── The cause is read, not guessed ────────────────────────────────────────
56
+ * The server marks a privilege refusal itself
57
+ * ([읽었음] auth-base/server/service/privilege/privilege-rejection.ts:61)
58
+ * with `extensions: { code: 'FORBIDDEN', requires: { category, privilege } }`. So this screen can
59
+ * tell "you are not allowed" from "it failed" without deciding which — the first is the server's
60
+ * own answer, and the second keeps the server's sentence rather than replacing it with a cause
61
+ * this screen does not know.
62
+ */
63
+ private saidWhatHappened;
37
64
  }
38
65
  export {};