@acorex/modules 21.0.0-next.5 → 21.0.0-next.8

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 (226) hide show
  1. package/application-management/index.d.ts +1 -0
  2. package/business-core/README.md +44 -1
  3. package/calendar-management/index.d.ts +6 -7
  4. package/document-management/index.d.ts +1544 -174
  5. package/fesm2022/acorex-modules-application-management.mjs +2 -0
  6. package/fesm2022/acorex-modules-application-management.mjs.map +1 -1
  7. package/fesm2022/{acorex-modules-assessment-management-acorex-modules-assessment-management-C4_2RPxG.mjs → acorex-modules-assessment-management-acorex-modules-assessment-management-7S277fXg.mjs} +23 -23
  8. package/fesm2022/acorex-modules-assessment-management-acorex-modules-assessment-management-7S277fXg.mjs.map +1 -0
  9. package/fesm2022/{acorex-modules-assessment-management-answers-viewer-widget-column.component-D2YRh7ro.mjs → acorex-modules-assessment-management-answers-viewer-widget-column.component-FnpwLbkS.mjs} +2 -2
  10. package/fesm2022/{acorex-modules-assessment-management-answers-viewer-widget-column.component-D2YRh7ro.mjs.map → acorex-modules-assessment-management-answers-viewer-widget-column.component-FnpwLbkS.mjs.map} +1 -1
  11. package/fesm2022/{acorex-modules-assessment-management-answers-viewer-widget-edit.component-B-S78gfQ.mjs → acorex-modules-assessment-management-answers-viewer-widget-edit.component-By0ETDZf.mjs} +2 -2
  12. package/fesm2022/{acorex-modules-assessment-management-answers-viewer-widget-edit.component-B-S78gfQ.mjs.map → acorex-modules-assessment-management-answers-viewer-widget-edit.component-By0ETDZf.mjs.map} +1 -1
  13. package/fesm2022/{acorex-modules-assessment-management-answers-viewer-widget-view.component-C1BTgRTR.mjs → acorex-modules-assessment-management-answers-viewer-widget-view.component-DxmjBgIo.mjs} +2 -2
  14. package/fesm2022/{acorex-modules-assessment-management-answers-viewer-widget-view.component-C1BTgRTR.mjs.map → acorex-modules-assessment-management-answers-viewer-widget-view.component-DxmjBgIo.mjs.map} +1 -1
  15. package/fesm2022/{acorex-modules-assessment-management-assessment-case.entity-DwTlClTz.mjs → acorex-modules-assessment-management-assessment-case.entity-CBjAGtV3.mjs} +2 -2
  16. package/fesm2022/{acorex-modules-assessment-management-assessment-case.entity-DwTlClTz.mjs.map → acorex-modules-assessment-management-assessment-case.entity-CBjAGtV3.mjs.map} +1 -1
  17. package/fesm2022/{acorex-modules-assessment-management-assessment-session.entity-BmvacBUU.mjs → acorex-modules-assessment-management-assessment-session.entity-CMnJ44gj.mjs} +2 -2
  18. package/fesm2022/{acorex-modules-assessment-management-assessment-session.entity-BmvacBUU.mjs.map → acorex-modules-assessment-management-assessment-session.entity-CMnJ44gj.mjs.map} +1 -1
  19. package/fesm2022/{acorex-modules-assessment-management-fill-assessment-session.command-D7ZNQBo8.mjs → acorex-modules-assessment-management-fill-assessment-session.command-8OhZEoAp.mjs} +3 -3
  20. package/fesm2022/{acorex-modules-assessment-management-fill-assessment-session.command-D7ZNQBo8.mjs.map → acorex-modules-assessment-management-fill-assessment-session.command-8OhZEoAp.mjs.map} +1 -1
  21. package/fesm2022/{acorex-modules-assessment-management-preview-questionnaire.command-BQxlJax7.mjs → acorex-modules-assessment-management-preview-questionnaire.command-CUybKZFY.mjs} +4 -4
  22. package/fesm2022/{acorex-modules-assessment-management-preview-questionnaire.command-BQxlJax7.mjs.map → acorex-modules-assessment-management-preview-questionnaire.command-CUybKZFY.mjs.map} +1 -1
  23. package/fesm2022/{acorex-modules-assessment-management-question-bank-item.entity-CIjS5M1b.mjs → acorex-modules-assessment-management-question-bank-item.entity-C9gxvSqN.mjs} +2 -2
  24. package/fesm2022/{acorex-modules-assessment-management-question-bank-item.entity-CIjS5M1b.mjs.map → acorex-modules-assessment-management-question-bank-item.entity-C9gxvSqN.mjs.map} +1 -1
  25. package/fesm2022/{acorex-modules-assessment-management-questionnaire-builder-edit.component-DAYiqBeA.mjs → acorex-modules-assessment-management-questionnaire-builder-edit.component-CUCT7Tcg.mjs} +2 -2
  26. package/fesm2022/{acorex-modules-assessment-management-questionnaire-builder-edit.component-DAYiqBeA.mjs.map → acorex-modules-assessment-management-questionnaire-builder-edit.component-CUCT7Tcg.mjs.map} +1 -1
  27. package/fesm2022/{acorex-modules-assessment-management-questionnaire-builder-view.component-BTXwZu9a.mjs → acorex-modules-assessment-management-questionnaire-builder-view.component-QhZAjnIv.mjs} +2 -2
  28. package/fesm2022/{acorex-modules-assessment-management-questionnaire-builder-view.component-BTXwZu9a.mjs.map → acorex-modules-assessment-management-questionnaire-builder-view.component-QhZAjnIv.mjs.map} +1 -1
  29. package/fesm2022/{acorex-modules-assessment-management-questionnaire-builder.component-BAR6Uee-.mjs → acorex-modules-assessment-management-questionnaire-builder.component-CvdVE1TW.mjs} +3 -3
  30. package/fesm2022/{acorex-modules-assessment-management-questionnaire-builder.component-BAR6Uee-.mjs.map → acorex-modules-assessment-management-questionnaire-builder.component-CvdVE1TW.mjs.map} +1 -1
  31. package/fesm2022/{acorex-modules-assessment-management-questionnaire-viewer-popup.component-DZ4TltLI.mjs → acorex-modules-assessment-management-questionnaire-viewer-popup.component-iDPvZ1Iu.mjs} +2 -2
  32. package/fesm2022/{acorex-modules-assessment-management-questionnaire-viewer-popup.component-DZ4TltLI.mjs.map → acorex-modules-assessment-management-questionnaire-viewer-popup.component-iDPvZ1Iu.mjs.map} +1 -1
  33. package/fesm2022/{acorex-modules-assessment-management-questionnaire-viewer.service-B2GV_e0o.mjs → acorex-modules-assessment-management-questionnaire-viewer.service-C2bz2R0N.mjs} +2 -2
  34. package/fesm2022/{acorex-modules-assessment-management-questionnaire-viewer.service-B2GV_e0o.mjs.map → acorex-modules-assessment-management-questionnaire-viewer.service-C2bz2R0N.mjs.map} +1 -1
  35. package/fesm2022/{acorex-modules-assessment-management-questionnaire.entity-mOtlUkUO.mjs → acorex-modules-assessment-management-questionnaire.entity-kvgtbI_h.mjs} +2 -2
  36. package/fesm2022/{acorex-modules-assessment-management-questionnaire.entity-mOtlUkUO.mjs.map → acorex-modules-assessment-management-questionnaire.entity-kvgtbI_h.mjs.map} +1 -1
  37. package/fesm2022/{acorex-modules-assessment-management-view-session-answers.command-BQ-3r9YQ.mjs → acorex-modules-assessment-management-view-session-answers.command-Dfl4QTDD.mjs} +3 -3
  38. package/fesm2022/{acorex-modules-assessment-management-view-session-answers.command-BQ-3r9YQ.mjs.map → acorex-modules-assessment-management-view-session-answers.command-Dfl4QTDD.mjs.map} +1 -1
  39. package/fesm2022/acorex-modules-assessment-management.mjs +1 -1
  40. package/fesm2022/{acorex-modules-auth-acorex-modules-auth-D5jGjm6i.mjs → acorex-modules-auth-acorex-modules-auth-8XP9xX7L.mjs} +95 -51
  41. package/fesm2022/acorex-modules-auth-acorex-modules-auth-8XP9xX7L.mjs.map +1 -0
  42. package/fesm2022/{acorex-modules-auth-app-chooser.component-BL3Fmc7y.mjs → acorex-modules-auth-app-chooser.component-BvbLYIXA.mjs} +6 -6
  43. package/fesm2022/acorex-modules-auth-app-chooser.component-BvbLYIXA.mjs.map +1 -0
  44. package/fesm2022/{acorex-modules-auth-login.module-D8-GN_Hx.mjs → acorex-modules-auth-login.module-DLWlieUn.mjs} +4 -4
  45. package/fesm2022/{acorex-modules-auth-login.module-D8-GN_Hx.mjs.map → acorex-modules-auth-login.module-DLWlieUn.mjs.map} +1 -1
  46. package/fesm2022/{acorex-modules-auth-master.layout-CgDrAbPS.mjs → acorex-modules-auth-master.layout-BzV1eUvM.mjs} +2 -2
  47. package/fesm2022/{acorex-modules-auth-master.layout-CgDrAbPS.mjs.map → acorex-modules-auth-master.layout-BzV1eUvM.mjs.map} +1 -1
  48. package/fesm2022/{acorex-modules-auth-oauth-callback.component-lEMWnVJL.mjs → acorex-modules-auth-oauth-callback.component-CqaXMQdp.mjs} +5 -5
  49. package/fesm2022/{acorex-modules-auth-oauth-callback.component-lEMWnVJL.mjs.map → acorex-modules-auth-oauth-callback.component-CqaXMQdp.mjs.map} +1 -1
  50. package/fesm2022/{acorex-modules-auth-password.component-BQII_ltO.mjs → acorex-modules-auth-password.component-BR2qrph-.mjs} +9 -9
  51. package/fesm2022/{acorex-modules-auth-password.component-BQII_ltO.mjs.map → acorex-modules-auth-password.component-BR2qrph-.mjs.map} +1 -1
  52. package/fesm2022/acorex-modules-auth-password.component-DMmRFHgO.mjs +563 -0
  53. package/fesm2022/acorex-modules-auth-password.component-DMmRFHgO.mjs.map +1 -0
  54. package/fesm2022/{acorex-modules-auth-routes-BGLnoGO4.mjs → acorex-modules-auth-routes-BRQJ6Mx_.mjs} +2 -2
  55. package/fesm2022/{acorex-modules-auth-routes-BGLnoGO4.mjs.map → acorex-modules-auth-routes-BRQJ6Mx_.mjs.map} +1 -1
  56. package/fesm2022/acorex-modules-auth-tenant-chooser.component-CptZLRwB.mjs +58 -0
  57. package/fesm2022/acorex-modules-auth-tenant-chooser.component-CptZLRwB.mjs.map +1 -0
  58. package/fesm2022/{acorex-modules-auth-two-factor-code.component-BmlUjtYC.mjs → acorex-modules-auth-two-factor-code.component-CvheFTK7.mjs} +6 -6
  59. package/fesm2022/{acorex-modules-auth-two-factor-code.component-BmlUjtYC.mjs.map → acorex-modules-auth-two-factor-code.component-CvheFTK7.mjs.map} +1 -1
  60. package/fesm2022/{acorex-modules-auth-two-factor.module-D1UjsoB8.mjs → acorex-modules-auth-two-factor.module-TGGOwEpP.mjs} +3 -3
  61. package/fesm2022/{acorex-modules-auth-two-factor.module-D1UjsoB8.mjs.map → acorex-modules-auth-two-factor.module-TGGOwEpP.mjs.map} +1 -1
  62. package/fesm2022/{acorex-modules-auth-user-sessions.component-CIlGFT7H.mjs → acorex-modules-auth-user-sessions.component-C_JzCXUy.mjs} +6 -6
  63. package/fesm2022/{acorex-modules-auth-user-sessions.component-CIlGFT7H.mjs.map → acorex-modules-auth-user-sessions.component-C_JzCXUy.mjs.map} +1 -1
  64. package/fesm2022/acorex-modules-auth.mjs +1 -1
  65. package/fesm2022/{acorex-modules-business-core-business-status.entity-DE3JJYdY.mjs → acorex-modules-business-core-business-status.entity-BYUneIcN.mjs} +2 -2
  66. package/fesm2022/acorex-modules-business-core-business-status.entity-BYUneIcN.mjs.map +1 -0
  67. package/fesm2022/{acorex-modules-business-core-business-type.entity-_IwOWQVA.mjs → acorex-modules-business-core-business-type.entity-DEy8LvEV.mjs} +2 -2
  68. package/fesm2022/acorex-modules-business-core-business-type.entity-DEy8LvEV.mjs.map +1 -0
  69. package/fesm2022/{acorex-modules-business-core-industry.entity-bwgPAZDk.mjs → acorex-modules-business-core-industry.entity-CGNfgpMs.mjs} +2 -2
  70. package/fesm2022/acorex-modules-business-core-industry.entity-CGNfgpMs.mjs.map +1 -0
  71. package/fesm2022/{acorex-modules-business-core-manufacturer.entity-CDlQlBUD.mjs → acorex-modules-business-core-manufacturer.entity-DhyMx-nJ.mjs} +2 -1
  72. package/fesm2022/acorex-modules-business-core-manufacturer.entity-DhyMx-nJ.mjs.map +1 -0
  73. package/fesm2022/acorex-modules-business-core.mjs +4 -4
  74. package/fesm2022/acorex-modules-calendar-management.mjs +46 -74
  75. package/fesm2022/acorex-modules-calendar-management.mjs.map +1 -1
  76. package/fesm2022/acorex-modules-common.mjs +6 -3
  77. package/fesm2022/acorex-modules-common.mjs.map +1 -1
  78. package/fesm2022/{acorex-modules-customer-management-customer-segment.entity-CUBg2GZp.mjs → acorex-modules-customer-management-customer-segment.entity-CoYAU5g3.mjs} +2 -1
  79. package/fesm2022/acorex-modules-customer-management-customer-segment.entity-CoYAU5g3.mjs.map +1 -0
  80. package/fesm2022/{acorex-modules-customer-management-customer-type.entity-rmq6BeCF.mjs → acorex-modules-customer-management-customer-type.entity-pt4gpOGq.mjs} +2 -1
  81. package/fesm2022/acorex-modules-customer-management-customer-type.entity-pt4gpOGq.mjs.map +1 -0
  82. package/fesm2022/acorex-modules-customer-management.mjs +2 -2
  83. package/fesm2022/{acorex-modules-document-management-attachment-widget.component-Bnp1l18X.mjs → acorex-modules-document-management-attachment-widget.component-zsWIFXD7.mjs} +2 -2
  84. package/fesm2022/{acorex-modules-document-management-attachment-widget.component-Bnp1l18X.mjs.map → acorex-modules-document-management-attachment-widget.component-zsWIFXD7.mjs.map} +1 -1
  85. package/fesm2022/{acorex-modules-document-management-details-view.component-TfRh2Jom.mjs → acorex-modules-document-management-details-view.component-DD7P_Xz7.mjs} +2 -2
  86. package/fesm2022/{acorex-modules-document-management-details-view.component-TfRh2Jom.mjs.map → acorex-modules-document-management-details-view.component-DD7P_Xz7.mjs.map} +1 -1
  87. package/fesm2022/{acorex-modules-document-management-document-signature-popup.component-nKUvSQuz.mjs → acorex-modules-document-management-document-signature-popup.component-DsCP-XfJ.mjs} +5 -5
  88. package/fesm2022/{acorex-modules-document-management-document-signature-popup.component-nKUvSQuz.mjs.map → acorex-modules-document-management-document-signature-popup.component-DsCP-XfJ.mjs.map} +1 -1
  89. package/fesm2022/{acorex-modules-document-management-drive-choose.component-CPQC_Qxe.mjs → acorex-modules-document-management-drive-choose.component-FUlvIsJu.mjs} +7 -7
  90. package/fesm2022/{acorex-modules-document-management-drive-choose.component-CPQC_Qxe.mjs.map → acorex-modules-document-management-drive-choose.component-FUlvIsJu.mjs.map} +1 -1
  91. package/fesm2022/{acorex-modules-document-management-large-icons-view.component-BP_4qwha.mjs → acorex-modules-document-management-large-icons-view.component-Dzc3SOKz.mjs} +2 -2
  92. package/fesm2022/{acorex-modules-document-management-large-icons-view.component-BP_4qwha.mjs.map → acorex-modules-document-management-large-icons-view.component-Dzc3SOKz.mjs.map} +1 -1
  93. package/fesm2022/{acorex-modules-document-management-large-tiles-view.component-CP9Ra0z9.mjs → acorex-modules-document-management-large-tiles-view.component-DrRbFkP4.mjs} +2 -2
  94. package/fesm2022/{acorex-modules-document-management-large-tiles-view.component-CP9Ra0z9.mjs.map → acorex-modules-document-management-large-tiles-view.component-DrRbFkP4.mjs.map} +1 -1
  95. package/fesm2022/{acorex-modules-document-management-link-dialog.component-nJmv07CR.mjs → acorex-modules-document-management-link-dialog.component-DKGpdhH1.mjs} +3 -3
  96. package/fesm2022/{acorex-modules-document-management-link-dialog.component-nJmv07CR.mjs.map → acorex-modules-document-management-link-dialog.component-DKGpdhH1.mjs.map} +1 -1
  97. package/fesm2022/{acorex-modules-document-management-list-view.component-LhSA_duB.mjs → acorex-modules-document-management-list-view.component-C7cR3m4S.mjs} +2 -2
  98. package/fesm2022/{acorex-modules-document-management-list-view.component-LhSA_duB.mjs.map → acorex-modules-document-management-list-view.component-C7cR3m4S.mjs.map} +1 -1
  99. package/fesm2022/{acorex-modules-document-management-share-dialog.component-DJABAVOV.mjs → acorex-modules-document-management-share-dialog.component-MK4UO_uy.mjs} +3 -3
  100. package/fesm2022/{acorex-modules-document-management-share-dialog.component-DJABAVOV.mjs.map → acorex-modules-document-management-share-dialog.component-MK4UO_uy.mjs.map} +1 -1
  101. package/fesm2022/{acorex-modules-document-management-share-email-dialog.component-Bh_FI1nk.mjs → acorex-modules-document-management-share-email-dialog.component-D5f4T_2K.mjs} +3 -3
  102. package/fesm2022/{acorex-modules-document-management-share-email-dialog.component-Bh_FI1nk.mjs.map → acorex-modules-document-management-share-email-dialog.component-D5f4T_2K.mjs.map} +1 -1
  103. package/fesm2022/{acorex-modules-document-management-small-icons-view.component-BOtJGiPU.mjs → acorex-modules-document-management-small-icons-view.component-BPWvSH3i.mjs} +2 -2
  104. package/fesm2022/{acorex-modules-document-management-small-icons-view.component-BOtJGiPU.mjs.map → acorex-modules-document-management-small-icons-view.component-BPWvSH3i.mjs.map} +1 -1
  105. package/fesm2022/{acorex-modules-document-management-small-tiles-view.component-BiKZ-FyZ.mjs → acorex-modules-document-management-small-tiles-view.component-fIQ4RY_F.mjs} +2 -2
  106. package/fesm2022/{acorex-modules-document-management-small-tiles-view.component-BiKZ-FyZ.mjs.map → acorex-modules-document-management-small-tiles-view.component-fIQ4RY_F.mjs.map} +1 -1
  107. package/fesm2022/acorex-modules-document-management.mjs +9329 -1
  108. package/fesm2022/acorex-modules-document-management.mjs.map +1 -1
  109. package/fesm2022/acorex-modules-financial-core.mjs +7 -5
  110. package/fesm2022/acorex-modules-financial-core.mjs.map +1 -1
  111. package/fesm2022/acorex-modules-human-capital-management-approve-leave-request.command-DN2T2hBp.mjs +59 -0
  112. package/fesm2022/acorex-modules-human-capital-management-approve-leave-request.command-DN2T2hBp.mjs.map +1 -0
  113. package/fesm2022/acorex-modules-human-capital-management-cancel-leave-request.command-CYMo0I8p.mjs +59 -0
  114. package/fesm2022/acorex-modules-human-capital-management-cancel-leave-request.command-CYMo0I8p.mjs.map +1 -0
  115. package/fesm2022/acorex-modules-human-capital-management-leave-request-task-popover.component-CR4xmtkI.mjs +381 -0
  116. package/fesm2022/acorex-modules-human-capital-management-leave-request-task-popover.component-CR4xmtkI.mjs.map +1 -0
  117. package/fesm2022/{acorex-modules-human-capital-management-leave-request.entity-BDh7IX7_.mjs → acorex-modules-human-capital-management-leave-request.entity-Dm_IKrVw.mjs} +1 -2
  118. package/fesm2022/acorex-modules-human-capital-management-leave-request.entity-Dm_IKrVw.mjs.map +1 -0
  119. package/fesm2022/{acorex-modules-human-capital-management-leave-type.entity-DlCdAtaz.mjs → acorex-modules-human-capital-management-leave-type.entity-CY81Nohl.mjs} +11 -3
  120. package/fesm2022/acorex-modules-human-capital-management-leave-type.entity-CY81Nohl.mjs.map +1 -0
  121. package/fesm2022/acorex-modules-human-capital-management-reject-leave-request.command-1Bn0gaZi.mjs +62 -0
  122. package/fesm2022/acorex-modules-human-capital-management-reject-leave-request.command-1Bn0gaZi.mjs.map +1 -0
  123. package/fesm2022/acorex-modules-human-capital-management.mjs +115 -36
  124. package/fesm2022/acorex-modules-human-capital-management.mjs.map +1 -1
  125. package/fesm2022/{acorex-modules-learning-management-certificate-definition.entity-BVvSzl2b.mjs → acorex-modules-learning-management-certificate-definition.entity-27VKYxw1.mjs} +2 -2
  126. package/fesm2022/acorex-modules-learning-management-certificate-definition.entity-27VKYxw1.mjs.map +1 -0
  127. package/fesm2022/{acorex-modules-learning-management-course.entity-BYb3Mgyi.mjs → acorex-modules-learning-management-course.entity-BN8XHAPz.mjs} +2 -2
  128. package/fesm2022/acorex-modules-learning-management-course.entity-BN8XHAPz.mjs.map +1 -0
  129. package/fesm2022/{acorex-modules-learning-management-skill.entity-CK93JIPg.mjs → acorex-modules-learning-management-skill.entity-rfMFaOAJ.mjs} +2 -1
  130. package/fesm2022/acorex-modules-learning-management-skill.entity-rfMFaOAJ.mjs.map +1 -0
  131. package/fesm2022/{acorex-modules-learning-management-training-definition.entity-C5RVLTy7.mjs → acorex-modules-learning-management-training-definition.entity-NQqJ5avw.mjs} +2 -2
  132. package/fesm2022/acorex-modules-learning-management-training-definition.entity-NQqJ5avw.mjs.map +1 -0
  133. package/fesm2022/{acorex-modules-learning-management-training.entity-KfxtUHEK.mjs → acorex-modules-learning-management-training.entity-DHGSlVR3.mjs} +2 -2
  134. package/fesm2022/acorex-modules-learning-management-training.entity-DHGSlVR3.mjs.map +1 -0
  135. package/fesm2022/acorex-modules-learning-management.mjs +5 -5
  136. package/fesm2022/acorex-modules-notification-management.mjs +34 -16
  137. package/fesm2022/acorex-modules-notification-management.mjs.map +1 -1
  138. package/fesm2022/acorex-modules-order-management.mjs +4 -0
  139. package/fesm2022/acorex-modules-order-management.mjs.map +1 -1
  140. package/fesm2022/{acorex-modules-organization-management-job-definition.entity-Cki_0gIY.mjs → acorex-modules-organization-management-job-definition.entity-s-TfP412.mjs} +2 -2
  141. package/fesm2022/acorex-modules-organization-management-job-definition.entity-s-TfP412.mjs.map +1 -0
  142. package/fesm2022/{acorex-modules-organization-management-position.entity-m7QrOTgN.mjs → acorex-modules-organization-management-position.entity-vbmjSfyb.mjs} +2 -2
  143. package/fesm2022/acorex-modules-organization-management-position.entity-vbmjSfyb.mjs.map +1 -0
  144. package/fesm2022/acorex-modules-organization-management.mjs +2 -2
  145. package/fesm2022/{acorex-modules-person-management-person.entity-DWfnmtVe.mjs → acorex-modules-person-management-person.entity-BnliZw-K.mjs} +35 -33
  146. package/fesm2022/acorex-modules-person-management-person.entity-BnliZw-K.mjs.map +1 -0
  147. package/fesm2022/acorex-modules-person-management.mjs +1 -1
  148. package/fesm2022/{acorex-modules-platform-management-acorex-modules-platform-management-BIq_sJye.mjs → acorex-modules-platform-management-acorex-modules-platform-management-CAntNN8Z.mjs} +4 -2
  149. package/fesm2022/{acorex-modules-platform-management-acorex-modules-platform-management-BIq_sJye.mjs.map → acorex-modules-platform-management-acorex-modules-platform-management-CAntNN8Z.mjs.map} +1 -1
  150. package/fesm2022/{acorex-modules-platform-management-menu-list.component-CL-zuLJ1.mjs → acorex-modules-platform-management-menu-list.component-CWutHAb3.mjs} +3 -3
  151. package/fesm2022/acorex-modules-platform-management-menu-list.component-CWutHAb3.mjs.map +1 -0
  152. package/fesm2022/acorex-modules-platform-management.mjs +1 -1
  153. package/fesm2022/{acorex-modules-product-catalog-brand.entity-DIv0bsiY.mjs → acorex-modules-product-catalog-brand.entity-C8VOfwF0.mjs} +2 -1
  154. package/fesm2022/acorex-modules-product-catalog-brand.entity-C8VOfwF0.mjs.map +1 -0
  155. package/fesm2022/{acorex-modules-product-catalog-product-sku.entity-CQw4VxjA.mjs → acorex-modules-product-catalog-product-sku.entity-Cxif--1E.mjs} +2 -1
  156. package/fesm2022/acorex-modules-product-catalog-product-sku.entity-Cxif--1E.mjs.map +1 -0
  157. package/fesm2022/{acorex-modules-product-catalog-product.entity-Cqye5OFr.mjs → acorex-modules-product-catalog-product.entity--aXivZUd.mjs} +2 -1
  158. package/fesm2022/acorex-modules-product-catalog-product.entity--aXivZUd.mjs.map +1 -0
  159. package/fesm2022/acorex-modules-product-catalog.mjs +3 -3
  160. package/fesm2022/acorex-modules-project-management.mjs +32 -1
  161. package/fesm2022/acorex-modules-project-management.mjs.map +1 -1
  162. package/fesm2022/{acorex-modules-report-management-report-runner-root-page.component-Cp5QCIll.mjs → acorex-modules-report-management-report-runner-root-page.component-DEX4VgHX.mjs} +9 -9
  163. package/fesm2022/acorex-modules-report-management-report-runner-root-page.component-DEX4VgHX.mjs.map +1 -0
  164. package/fesm2022/acorex-modules-report-management.mjs +2 -2
  165. package/fesm2022/acorex-modules-report-management.mjs.map +1 -1
  166. package/fesm2022/acorex-modules-security-management.mjs +3 -1
  167. package/fesm2022/acorex-modules-security-management.mjs.map +1 -1
  168. package/fesm2022/{acorex-modules-settings-management-acorex-modules-settings-management-gQ5Sk1Sj.mjs → acorex-modules-settings-management-acorex-modules-settings-management-R6m7cpPE.mjs} +18 -18
  169. package/fesm2022/{acorex-modules-settings-management-acorex-modules-settings-management-gQ5Sk1Sj.mjs.map → acorex-modules-settings-management-acorex-modules-settings-management-R6m7cpPE.mjs.map} +1 -1
  170. package/fesm2022/{acorex-modules-settings-management-permission-definition.provider-BEDGpTc8.mjs → acorex-modules-settings-management-permission-definition.provider-BNzuJQfL.mjs} +2 -2
  171. package/fesm2022/{acorex-modules-settings-management-permission-definition.provider-BEDGpTc8.mjs.map → acorex-modules-settings-management-permission-definition.provider-BNzuJQfL.mjs.map} +1 -1
  172. package/fesm2022/{acorex-modules-settings-management-setting-page.component-BsA1TfMG.mjs → acorex-modules-settings-management-setting-page.component-B1SnxHdd.mjs} +2 -2
  173. package/fesm2022/{acorex-modules-settings-management-setting-page.component-BsA1TfMG.mjs.map → acorex-modules-settings-management-setting-page.component-B1SnxHdd.mjs.map} +1 -1
  174. package/fesm2022/{acorex-modules-settings-management-setting-view.component-C282orx7.mjs → acorex-modules-settings-management-setting-view.component-BsuZ-NQK.mjs} +2 -2
  175. package/fesm2022/{acorex-modules-settings-management-setting-view.component-C282orx7.mjs.map → acorex-modules-settings-management-setting-view.component-BsuZ-NQK.mjs.map} +1 -1
  176. package/fesm2022/acorex-modules-settings-management.mjs +1 -1
  177. package/fesm2022/acorex-modules-subscription-management.mjs +3 -0
  178. package/fesm2022/acorex-modules-subscription-management.mjs.map +1 -1
  179. package/fesm2022/acorex-modules-supplier-management.mjs +1 -0
  180. package/fesm2022/acorex-modules-supplier-management.mjs.map +1 -1
  181. package/fesm2022/acorex-modules-task-management-task-board.page-6D76WpRB.mjs +2246 -0
  182. package/fesm2022/acorex-modules-task-management-task-board.page-6D76WpRB.mjs.map +1 -0
  183. package/fesm2022/acorex-modules-task-management.mjs +21 -8
  184. package/fesm2022/acorex-modules-task-management.mjs.map +1 -1
  185. package/fesm2022/acorex-modules-tenant-management.mjs +2 -0
  186. package/fesm2022/acorex-modules-tenant-management.mjs.map +1 -1
  187. package/fesm2022/acorex-modules-workflow-management.mjs +2074 -28
  188. package/fesm2022/acorex-modules-workflow-management.mjs.map +1 -1
  189. package/human-capital-management/index.d.ts +4 -1
  190. package/package.json +2 -2
  191. package/task-management/index.d.ts +32 -5
  192. package/workflow-management/index.d.ts +530 -8
  193. package/fesm2022/acorex-modules-assessment-management-acorex-modules-assessment-management-C4_2RPxG.mjs.map +0 -1
  194. package/fesm2022/acorex-modules-auth-acorex-modules-auth-D5jGjm6i.mjs.map +0 -1
  195. package/fesm2022/acorex-modules-auth-app-chooser.component-BL3Fmc7y.mjs.map +0 -1
  196. package/fesm2022/acorex-modules-auth-password.component-DKG8o8k8.mjs +0 -226
  197. package/fesm2022/acorex-modules-auth-password.component-DKG8o8k8.mjs.map +0 -1
  198. package/fesm2022/acorex-modules-auth-tenant-chooser.component-DNDhBKDp.mjs +0 -109
  199. package/fesm2022/acorex-modules-auth-tenant-chooser.component-DNDhBKDp.mjs.map +0 -1
  200. package/fesm2022/acorex-modules-business-core-business-status.entity-DE3JJYdY.mjs.map +0 -1
  201. package/fesm2022/acorex-modules-business-core-business-type.entity-_IwOWQVA.mjs.map +0 -1
  202. package/fesm2022/acorex-modules-business-core-industry.entity-bwgPAZDk.mjs.map +0 -1
  203. package/fesm2022/acorex-modules-business-core-manufacturer.entity-CDlQlBUD.mjs.map +0 -1
  204. package/fesm2022/acorex-modules-customer-management-customer-segment.entity-CUBg2GZp.mjs.map +0 -1
  205. package/fesm2022/acorex-modules-customer-management-customer-type.entity-rmq6BeCF.mjs.map +0 -1
  206. package/fesm2022/acorex-modules-document-management-acorex-modules-document-management-Dk4Z-JSv.mjs +0 -8995
  207. package/fesm2022/acorex-modules-document-management-acorex-modules-document-management-Dk4Z-JSv.mjs.map +0 -1
  208. package/fesm2022/acorex-modules-document-management-drive.component-BzpH_FSJ.mjs +0 -388
  209. package/fesm2022/acorex-modules-document-management-drive.component-BzpH_FSJ.mjs.map +0 -1
  210. package/fesm2022/acorex-modules-human-capital-management-leave-request.entity-BDh7IX7_.mjs.map +0 -1
  211. package/fesm2022/acorex-modules-human-capital-management-leave-type.entity-DlCdAtaz.mjs.map +0 -1
  212. package/fesm2022/acorex-modules-learning-management-certificate-definition.entity-BVvSzl2b.mjs.map +0 -1
  213. package/fesm2022/acorex-modules-learning-management-course.entity-BYb3Mgyi.mjs.map +0 -1
  214. package/fesm2022/acorex-modules-learning-management-skill.entity-CK93JIPg.mjs.map +0 -1
  215. package/fesm2022/acorex-modules-learning-management-training-definition.entity-C5RVLTy7.mjs.map +0 -1
  216. package/fesm2022/acorex-modules-learning-management-training.entity-KfxtUHEK.mjs.map +0 -1
  217. package/fesm2022/acorex-modules-organization-management-job-definition.entity-Cki_0gIY.mjs.map +0 -1
  218. package/fesm2022/acorex-modules-organization-management-position.entity-m7QrOTgN.mjs.map +0 -1
  219. package/fesm2022/acorex-modules-person-management-person.entity-DWfnmtVe.mjs.map +0 -1
  220. package/fesm2022/acorex-modules-platform-management-menu-list.component-CL-zuLJ1.mjs.map +0 -1
  221. package/fesm2022/acorex-modules-product-catalog-brand.entity-DIv0bsiY.mjs.map +0 -1
  222. package/fesm2022/acorex-modules-product-catalog-product-sku.entity-CQw4VxjA.mjs.map +0 -1
  223. package/fesm2022/acorex-modules-product-catalog-product.entity-Cqye5OFr.mjs.map +0 -1
  224. package/fesm2022/acorex-modules-report-management-report-runner-root-page.component-Cp5QCIll.mjs.map +0 -1
  225. package/fesm2022/acorex-modules-task-management-task-board.page-CKgZoOGI.mjs +0 -1364
  226. package/fesm2022/acorex-modules-task-management-task-board.page-CKgZoOGI.mjs.map +0 -1
@@ -0,0 +1,2246 @@
1
+ import * as i9 from '@acorex/cdk/accordion';
2
+ import { AXAccordionCdkModule } from '@acorex/cdk/accordion';
3
+ import { AXAccordionModule } from '@acorex/components/accordion';
4
+ import * as i8 from '@acorex/components/badge';
5
+ import { AXBadgeModule } from '@acorex/components/badge';
6
+ import { AXBreadcrumbsModule } from '@acorex/components/breadcrumbs';
7
+ import * as i3 from '@acorex/components/button';
8
+ import { AXButtonComponent, AXButtonModule } from '@acorex/components/button';
9
+ import { AXCalendarComponent } from '@acorex/components/calendar';
10
+ import { AXCheckBoxModule } from '@acorex/components/check-box';
11
+ import * as i5 from '@acorex/components/decorators';
12
+ import { AXDecoratorIconComponent, AXDecoratorModule } from '@acorex/components/decorators';
13
+ import * as i4 from '@acorex/components/dropdown';
14
+ import { AXDropdownModule, AXDropdownPanelComponent } from '@acorex/components/dropdown';
15
+ import { AXDropdownButtonModule } from '@acorex/components/dropdown-button';
16
+ import { AXFormFieldComponent, AXFormComponent, AXFormModule } from '@acorex/components/form';
17
+ import { AXLabelComponent, AXLabelModule } from '@acorex/components/label';
18
+ import * as i7 from '@acorex/components/loading';
19
+ import { AXLoadingModule } from '@acorex/components/loading';
20
+ import * as i3$1 from '@acorex/components/menu';
21
+ import { AXMenuModule } from '@acorex/components/menu';
22
+ import * as i2 from '@acorex/components/popover';
23
+ import { AXPopoverModule } from '@acorex/components/popover';
24
+ import * as i10 from '@acorex/components/selection-list';
25
+ import { AXSelectionListModule } from '@acorex/components/selection-list';
26
+ import { AXCalendarService } from '@acorex/core/date-time';
27
+ import { AXLocaleService } from '@acorex/core/locale';
28
+ import * as i5$1 from '@acorex/core/translation';
29
+ import { AXTranslatorPipe, AXTranslationModule } from '@acorex/core/translation';
30
+ import { AXUnsubscriber } from '@acorex/core/utils';
31
+ import { AXPPlatformScope, AXPDeviceService } from '@acorex/platform/core';
32
+ import { AXPStateMessageComponent, AXPThemeLayoutBlockComponent, AXPThemeLayoutStartSideComponent, AXPThemeLayoutHeaderComponent } from '@acorex/platform/layout/components';
33
+ import { AXPPageLayoutBaseComponent, AXPPageLayoutComponent, AXPPageLayoutBase } from '@acorex/platform/layout/views';
34
+ import * as i1$1 from '@angular/common';
35
+ import { AsyncPipe, CommonModule } from '@angular/common';
36
+ import * as i0 from '@angular/core';
37
+ import { computed, inject, signal, effect, ViewEncapsulation, ChangeDetectionStrategy, Component, input, output, viewChild, model, untracked } from '@angular/core';
38
+ import * as i1$3 from '@angular/forms';
39
+ import { FormsModule } from '@angular/forms';
40
+ import { Router, ActivatedRoute, NavigationEnd, RouterModule } from '@angular/router';
41
+ import { filter, startWith } from 'rxjs';
42
+ import { AXPTaskBoardService, RootConfig } from './acorex-modules-task-management.mjs';
43
+ import { AXFormatPipe } from '@acorex/core/format';
44
+ import * as i1 from '@acorex/platform/layout/widget-core';
45
+ import { AXPWidgetCoreModule, AXPWidgetsCatalog } from '@acorex/platform/layout/widget-core';
46
+ import { AXPSettingsService } from '@acorex/platform/common';
47
+ import { signalStore, withState, withComputed, withMethods, patchState } from '@ngrx/signals';
48
+ import { isEqual, sortBy } from 'lodash-es';
49
+ import { AXSchedulerService, AXSchedulerComponent } from '@acorex/components/scheduler';
50
+ import { AXPCommandService } from '@acorex/platform/runtime';
51
+ import { AXDataSource } from '@acorex/cdk/common';
52
+ import * as i1$2 from '@acorex/components/data-table';
53
+ import { AXDataTableModule } from '@acorex/components/data-table';
54
+ import { AXKanbanComponent } from '@acorex/components/kanban';
55
+
56
+ var AXMTaskBoardSettings;
57
+ (function (AXMTaskBoardSettings) {
58
+ AXMTaskBoardSettings["ViewMode"] = "taskboard.viewMode";
59
+ AXMTaskBoardSettings["DetailPanel"] = "taskboard.DetailPanel";
60
+ AXMTaskBoardSettings["DaysCount"] = "taskboard.calendar.daysCount";
61
+ AXMTaskBoardSettings["CurrentDate"] = "taskboard.calendar.currentDate";
62
+ AXMTaskBoardSettings["SelectedPriorities"] = "taskboard.filter.selectedPriorities";
63
+ AXMTaskBoardSettings["SelectedAssigneeIds"] = "taskboard.filter.selectedAssigneeIds";
64
+ AXMTaskBoardSettings["SelectedReporterIds"] = "taskboard.filter.selectedReporterIds";
65
+ AXMTaskBoardSettings["SelectedTaskTypeNames"] = "taskboard.filter.selectedTaskTypeNames";
66
+ AXMTaskBoardSettings["SelectedCalendarEventTypeIds"] = "taskboard.filter.selectedCalendarEventTypeIds";
67
+ })(AXMTaskBoardSettings || (AXMTaskBoardSettings = {}));
68
+
69
+ const AXMTaskBoardViewModel = signalStore({ providedIn: 'root' }, withState(() => ({
70
+ daysCount: 7,
71
+ taskTypes: [],
72
+ isLoading: true,
73
+ detailPanel: false,
74
+ selectedTask: null,
75
+ rangeStartDate: null,
76
+ currentDate: new Date(),
77
+ currentViewMode: 'month',
78
+ selectedTaskTypeNames: [],
79
+ selectedAssigneeIds: [],
80
+ selectedPriorities: [],
81
+ selectedReporterIds: [],
82
+ selectedCalendarEventTypeIds: [],
83
+ })), withComputed((store) => ({
84
+ selectedTaskTypes: computed(() => {
85
+ const names = store.selectedTaskTypeNames();
86
+ if (!names || names.length === 0) {
87
+ return [];
88
+ }
89
+ return store.taskTypes().filter((tt) => names.includes(tt.name));
90
+ }),
91
+ isTaskSelected: computed(() => store.selectedTask() !== null),
92
+ isDetailPanelOpen: computed(() => store.detailPanel()),
93
+ endDate: computed(() => {
94
+ const currentDate = store.currentDate();
95
+ const daysCount = store.daysCount();
96
+ return new Date(currentDate.getTime() + daysCount * 24 * 60 * 60 * 1000);
97
+ }),
98
+ activeFilterCount: computed(() => {
99
+ let count = 0;
100
+ if (store.currentViewMode() !== 'kanban' &&
101
+ store.currentViewMode() !== 'status-grouped-grid' &&
102
+ store.selectedTaskTypeNames().length > 0) {
103
+ count++;
104
+ }
105
+ if (store.selectedAssigneeIds().length > 0) {
106
+ count++;
107
+ }
108
+ if (store.selectedReporterIds().length > 0) {
109
+ count++;
110
+ }
111
+ if (store.selectedPriorities().length > 0) {
112
+ count++;
113
+ }
114
+ return count;
115
+ }),
116
+ })), withMethods((store, settingsService = inject(AXPSettingsService), taskBoardService = inject(AXPTaskBoardService)) => {
117
+ const userScopedSettings = () => settingsService.scope(AXPPlatformScope.User);
118
+ return {
119
+ async initialize() {
120
+ patchState(store, { isLoading: true });
121
+ try {
122
+ const taskTypes = await taskBoardService.getTaskTypes();
123
+ patchState(store, { taskTypes });
124
+ const [savedDaysCount, savedDateString, savedDetailPanel, savedViewMode, savedTaskTypeNames, savedAssigneeIds, savedReporterIds, savedPriorities, savedCalendarEventTypeIds,] = await Promise.all([
125
+ userScopedSettings().get(AXMTaskBoardSettings.DaysCount),
126
+ userScopedSettings().get(AXMTaskBoardSettings.CurrentDate),
127
+ userScopedSettings().get(AXMTaskBoardSettings.DetailPanel),
128
+ userScopedSettings().get(AXMTaskBoardSettings.ViewMode),
129
+ userScopedSettings().get(AXMTaskBoardSettings.SelectedTaskTypeNames),
130
+ userScopedSettings().get(AXMTaskBoardSettings.SelectedAssigneeIds),
131
+ userScopedSettings().get(AXMTaskBoardSettings.SelectedReporterIds),
132
+ userScopedSettings().get(AXMTaskBoardSettings.SelectedPriorities),
133
+ userScopedSettings().get(AXMTaskBoardSettings.SelectedCalendarEventTypeIds),
134
+ ]);
135
+ // Ensure currentDate is always a valid Date
136
+ let currentDate;
137
+ if (savedDateString) {
138
+ const parsedDate = new Date(savedDateString);
139
+ currentDate = isNaN(parsedDate.getTime()) ? new Date() : parsedDate;
140
+ }
141
+ else {
142
+ currentDate = new Date();
143
+ }
144
+ patchState(store, {
145
+ daysCount: savedDaysCount || 7,
146
+ detailPanel: savedDetailPanel || false,
147
+ currentViewMode: savedViewMode || 'month',
148
+ currentDate,
149
+ selectedTaskTypeNames: savedTaskTypeNames || [],
150
+ selectedAssigneeIds: savedAssigneeIds || [],
151
+ selectedReporterIds: savedReporterIds || [],
152
+ selectedPriorities: savedPriorities || [],
153
+ selectedCalendarEventTypeIds: savedCalendarEventTypeIds || [],
154
+ isLoading: false,
155
+ });
156
+ }
157
+ catch (error) {
158
+ console.error('Error initializing TaskBoard ViewModel:', error);
159
+ patchState(store, {
160
+ detailPanel: false,
161
+ currentViewMode: 'month',
162
+ currentDate: new Date(),
163
+ selectedTaskTypeNames: [],
164
+ selectedAssigneeIds: [],
165
+ selectedPriorities: [],
166
+ selectedReporterIds: [],
167
+ selectedCalendarEventTypeIds: [],
168
+ taskTypes: store.taskTypes(),
169
+ isLoading: false,
170
+ });
171
+ }
172
+ },
173
+ setViewMode(mode) {
174
+ if ((mode === 'kanban' || mode === 'status-grouped-grid') && store.selectedTaskTypeNames().length === 0) {
175
+ const firstTaskType = store.taskTypes()[0];
176
+ if (firstTaskType) {
177
+ this.setSelectedTaskTypeNames([firstTaskType.name]);
178
+ }
179
+ }
180
+ if ((mode === 'kanban' || mode === 'status-grouped-grid') && store.selectedTaskTypeNames().length > 1) {
181
+ this.setSelectedTaskTypeNames([store.selectedTaskTypeNames()[0]]);
182
+ }
183
+ patchState(store, { currentViewMode: mode });
184
+ userScopedSettings()
185
+ .set(AXMTaskBoardSettings.ViewMode, mode)
186
+ .catch((error) => console.error('Error saving calendar view mode:', error));
187
+ },
188
+ setCurrentDate(date) {
189
+ patchState(store, { currentDate: new Date(date) });
190
+ userScopedSettings()
191
+ .set(AXMTaskBoardSettings.CurrentDate, date.toISOString())
192
+ .catch((error) => console.error('Error saving current date:', error));
193
+ },
194
+ setSelectedTaskTypeNames(taskTypeNames, isQueryParam = false) {
195
+ patchState(store, { selectedTaskTypeNames: taskTypeNames });
196
+ if (isQueryParam)
197
+ return;
198
+ userScopedSettings()
199
+ .set(AXMTaskBoardSettings.SelectedTaskTypeNames, taskTypeNames)
200
+ .catch((error) => console.error('Error saving selected task type filter:', error));
201
+ },
202
+ setSelectedAssigneeIds(assigneeIds, isQueryParam = false) {
203
+ patchState(store, { selectedAssigneeIds: assigneeIds });
204
+ if (isQueryParam)
205
+ return;
206
+ userScopedSettings()
207
+ .set(AXMTaskBoardSettings.SelectedAssigneeIds, assigneeIds)
208
+ .catch((error) => console.error('Error saving selected assignee filter:', error));
209
+ },
210
+ setSelectedReporterIds(reporterIds, isQueryParam = false) {
211
+ patchState(store, { selectedReporterIds: reporterIds });
212
+ if (isQueryParam)
213
+ return;
214
+ userScopedSettings()
215
+ .set(AXMTaskBoardSettings.SelectedReporterIds, reporterIds)
216
+ .catch((error) => console.error('Error saving selected reporter filter:', error));
217
+ },
218
+ setSelectedPriorities(priorities, isQueryParam = false) {
219
+ patchState(store, { selectedPriorities: priorities });
220
+ if (isQueryParam)
221
+ return;
222
+ userScopedSettings()
223
+ .set(AXMTaskBoardSettings.SelectedPriorities, priorities)
224
+ .catch((error) => console.error('Error saving selected priority filter:', error));
225
+ },
226
+ setSelectedCalendarEventTypeIds(eventTypeIds, isQueryParam = false) {
227
+ patchState(store, { selectedCalendarEventTypeIds: eventTypeIds });
228
+ if (isQueryParam)
229
+ return;
230
+ userScopedSettings()
231
+ .set(AXMTaskBoardSettings.SelectedCalendarEventTypeIds, eventTypeIds)
232
+ .catch((error) => console.error('Error saving selected calendar event type filter:', error));
233
+ },
234
+ /**
235
+ * Sets the currently selected task. Pass `null` to clear the selection.
236
+ * @param task The task to select, or null.
237
+ */
238
+ selectTask(task) {
239
+ patchState(store, { selectedTask: task });
240
+ },
241
+ /**
242
+ * A convenience method to clear the currently selected task.
243
+ */
244
+ clearSelectedTask() {
245
+ patchState(store, { selectedTask: null });
246
+ },
247
+ openDetailPanel() {
248
+ patchState(store, { detailPanel: true });
249
+ userScopedSettings()
250
+ .set(AXMTaskBoardSettings.DetailPanel, true)
251
+ .catch((error) => console.error('Error saving detail panel:', error));
252
+ },
253
+ closeDetailPanel() {
254
+ patchState(store, { detailPanel: false });
255
+ userScopedSettings()
256
+ .set(AXMTaskBoardSettings.DetailPanel, false)
257
+ .catch((error) => console.error('Error saving detail panel:', error));
258
+ },
259
+ toggleDetailPanel() {
260
+ const detailPanel = !store.detailPanel();
261
+ patchState(store, { detailPanel: detailPanel });
262
+ userScopedSettings()
263
+ .set(AXMTaskBoardSettings.DetailPanel, detailPanel)
264
+ .catch((error) => console.error('Error saving detail panel:', error));
265
+ },
266
+ async getStatusName(key, provider) {
267
+ return taskBoardService.getStatusName(key, provider);
268
+ },
269
+ /**
270
+ * Sets the start date for a new range selection.
271
+ * Pass `null` to clear the selection.
272
+ * @param date The start date of the range.
273
+ */
274
+ setRangeStartDate(date) {
275
+ patchState(store, { rangeStartDate: date });
276
+ },
277
+ setDaysCount(days) {
278
+ const count = Math.max(1, days);
279
+ patchState(store, { daysCount: count });
280
+ userScopedSettings()
281
+ .set(AXMTaskBoardSettings.DaysCount, count)
282
+ .catch((error) => console.error('Error saving days count:', error));
283
+ },
284
+ };
285
+ }));
286
+
287
+ class AXMTaskBoardDetailPanel {
288
+ constructor() {
289
+ this.rootConfig = RootConfig;
290
+ this.vm = inject(AXMTaskBoardViewModel);
291
+ this.localeService = inject(AXLocaleService);
292
+ this.taskBoardService = inject(AXPTaskBoardService);
293
+ this.statusName = signal('', ...(ngDevMode ? [{ debugName: "statusName" }] : []));
294
+ this.extraFields = signal([], ...(ngDevMode ? [{ debugName: "extraFields" }] : []));
295
+ this.#selectedTaskChanged = effect(async () => {
296
+ const selectedTask = this.vm.selectedTask();
297
+ const key = selectedTask?.status.id;
298
+ const provider = selectedTask?.provider;
299
+ if (!provider)
300
+ return;
301
+ const name = await this.vm.getStatusName(key, provider);
302
+ if (name)
303
+ this.statusName.set(name);
304
+ }, ...(ngDevMode ? [{ debugName: "#selectedTaskChanged" }] : []));
305
+ this.#selectedTaskTypeChanged = effect(async () => {
306
+ const selectedTask = this.vm.selectedTask();
307
+ const selectedTaskType = this.taskBoardService.getProvider(selectedTask?.provider);
308
+ const extraFields = await selectedTaskType?.getExtraFields();
309
+ if (!extraFields) {
310
+ this.extraFields.set([]);
311
+ return;
312
+ }
313
+ this.extraFields.set(extraFields);
314
+ }, ...(ngDevMode ? [{ debugName: "#selectedTaskTypeChanged" }] : []));
315
+ }
316
+ #selectedTaskChanged;
317
+ #selectedTaskTypeChanged;
318
+ capitalizeFirstLetter(text) {
319
+ return String(text).charAt(0).toUpperCase() + String(text).slice(1);
320
+ }
321
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMTaskBoardDetailPanel, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
322
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXMTaskBoardDetailPanel, isStandalone: true, selector: "axm-task-board-detail-panel", ngImport: i0, template: "@if (vm.isTaskSelected()) {\n @let nodeInfo = vm.selectedTask();\n <div class=\"__header\">\n <div class=\"__title\">\n <span>{{ nodeInfo?.title }}</span>\n </div>\n <ax-button [look]=\"'blank'\" class=\"ax-sm ax-rounded-full\" (onClick)=\"vm.closeDetailPanel()\">\n <ax-icon icon=\"fa-solid fa-xmark\"></ax-icon>\n </ax-button>\n </div>\n\n <div class=\"__content\">\n <div class=\"__section\">\n <div class=\"__title\">\n <span>{{ '@task-management:task-board.detail-panel.title' | translate | async }}</span>\n </div>\n <div class=\"__content\">\n @if (nodeInfo?.description) {\n <div class=\"__row\">\n <div class=\"__title\">\n <span>\n {{ '@task-management:task-board.detail-panel.description' | translate | async }}\n </span>\n </div>\n <div class=\"__content\">{{ nodeInfo?.description }}</div>\n </div>\n }\n <div class=\"__row\">\n <div class=\"__title\">\n <span>\n {{ '@task-management:task-board.detail-panel.start-date' | translate | async }}\n </span>\n </div>\n <div class=\"__content\">\n {{\n nodeInfo?.startDate\n | format: 'datetime' : { format: 'short', calendar: localeService.activeProfile().calendar.system }\n | async\n }}\n </div>\n </div>\n <div class=\"__row\">\n <div class=\"__title\">\n <span>{{ '@task-management:task-board.detail-panel.end-date' | translate | async }}</span>\n </div>\n <div class=\"__content\">\n {{\n nodeInfo?.endDate\n | format: 'datetime' : { format: 'short', calendar: localeService.activeProfile().calendar.system }\n | async\n }}\n </div>\n </div>\n <div class=\"__row\">\n <div class=\"__title\">\n <span>{{ '@task-management:task-board.detail-panel.reporter' | translate | async }}</span>\n </div>\n <div class=\"__content\">\n {{ nodeInfo?.reporter?.fullName }}\n </div>\n </div>\n @if (nodeInfo?.assignee) {\n <div class=\"__row\">\n <div class=\"__title\">\n <span>{{ '@task-management:task-board.detail-panel.assignee' | translate | async }}</span>\n </div>\n <div class=\"__content\">{{ nodeInfo?.assignee?.fullName }}</div>\n </div>\n }\n @if (statusName()) {\n <div class=\"__row\">\n <div class=\"__title\">\n <span>{{ '@task-management:task-board.detail-panel.status' | translate | async }}</span>\n </div>\n <div class=\"__content\">{{ statusName() }}</div>\n </div>\n }\n @if (nodeInfo?.priority) {\n <div class=\"__row\">\n <div class=\"__title\">\n <span>\n {{ '@task-management:task-board.detail-panel.priority' | translate | async }}\n </span>\n </div>\n <div class=\"__content\">{{ capitalizeFirstLetter(nodeInfo?.priority ?? '') }}</div>\n </div>\n }\n @if (extraFields() && extraFields().length) {\n <div class=\"__row\">\n <axp-widgets-container [context]=\"nodeInfo\">\n @for (extraField of extraFields(); track extraField) {\n <div class=\"__title\">\n <span>\n {{ extraField.title | translate | async }}\n </span>\n </div>\n <div class=\"__content\">\n <ng-container axp-widget-renderer [node]=\"extraField.widget\" [mode]=\"'view'\"> </ng-container>\n </div>\n }\n </axp-widgets-container>\n </div>\n }\n </div>\n </div>\n </div>\n} @else {\n <div class=\"__header\">\n <div class=\"__title\">\n <span>\n {{ '@task-management:task-board.detail-panel.title' | translate | async }}\n </span>\n </div>\n <ax-button [look]=\"'blank'\" class=\"ax-sm ax-rounded-full\" (onClick)=\"vm.closeDetailPanel()\">\n <ax-icon icon=\"fa-solid fa-xmark\"></ax-icon>\n </ax-button>\n </div>\n\n <div class=\"__content ax-flex ax-items-center ax-justify-center\">\n <axp-state-message\n icon=\"fa-light fa-clipboard-list-check\"\n [title]=\"'@task-management:task-board.detail-panel.no-task-selected.title'\"\n [description]=\"'@task-management:task-board.detail-panel.no-task-selected.description'\"\n >\n </axp-state-message>\n </div>\n}\n", styles: ["axm-task-board-detail-panel{display:flex;flex-direction:column;border-radius:.5rem;border-width:1px;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}@media (min-width: 1024px){axm-task-board-detail-panel{width:24rem}}axm-task-board-detail-panel>.__header{display:flex;flex-direction:row;align-items:center;justify-content:space-between;border-bottom-width:1px;padding:1rem}@media (min-width: 1024px){axm-task-board-detail-panel>.__header{width:20rem}}axm-task-board-detail-panel>.__header>.__title{display:flex;width:90%;flex-direction:row;align-items:center;gap:.5rem}axm-task-board-detail-panel>.__header>.__title span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:start;font-weight:600;line-height:1.625}axm-task-board-detail-panel>.__content{display:flex;flex-direction:column}axm-task-board-detail-panel>.__content>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}axm-task-board-detail-panel>.__content>.__section{display:flex;flex-direction:column;padding:1rem}axm-task-board-detail-panel>.__content>.__section>.__title{margin-bottom:1rem;font-size:.875rem;line-height:1.25rem;font-weight:700}axm-task-board-detail-panel>.__content>.__section>.__content{display:flex;flex-direction:column;gap:1rem}axm-task-board-detail-panel>.__content>.__section>.__content>.__row{display:flex;flex-direction:column;gap:.25rem}axm-task-board-detail-panel>.__content>.__section>.__content>.__row>.__title{display:flex;font-size:.875rem;line-height:1.25rem;font-weight:600;opacity:.9}axm-task-board-detail-panel>.__content>.__section>.__content>.__row>.__content{display:flex;flex-direction:row;align-items:center;gap:.5rem}axm-task-board-detail-panel>.__content>.__section>.__content>.__row>.__content span{opacity:.7}\n"], dependencies: [{ kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "variant"] }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i1.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "component", type: AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: AXFormatPipe, name: "format" }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
323
+ }
324
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMTaskBoardDetailPanel, decorators: [{
325
+ type: Component,
326
+ args: [{ selector: 'axm-task-board-detail-panel', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
327
+ AsyncPipe,
328
+ AXFormatPipe,
329
+ AXTranslatorPipe,
330
+ AXButtonComponent,
331
+ AXPStateMessageComponent,
332
+ AXPWidgetCoreModule,
333
+ AXDecoratorIconComponent,
334
+ ], template: "@if (vm.isTaskSelected()) {\n @let nodeInfo = vm.selectedTask();\n <div class=\"__header\">\n <div class=\"__title\">\n <span>{{ nodeInfo?.title }}</span>\n </div>\n <ax-button [look]=\"'blank'\" class=\"ax-sm ax-rounded-full\" (onClick)=\"vm.closeDetailPanel()\">\n <ax-icon icon=\"fa-solid fa-xmark\"></ax-icon>\n </ax-button>\n </div>\n\n <div class=\"__content\">\n <div class=\"__section\">\n <div class=\"__title\">\n <span>{{ '@task-management:task-board.detail-panel.title' | translate | async }}</span>\n </div>\n <div class=\"__content\">\n @if (nodeInfo?.description) {\n <div class=\"__row\">\n <div class=\"__title\">\n <span>\n {{ '@task-management:task-board.detail-panel.description' | translate | async }}\n </span>\n </div>\n <div class=\"__content\">{{ nodeInfo?.description }}</div>\n </div>\n }\n <div class=\"__row\">\n <div class=\"__title\">\n <span>\n {{ '@task-management:task-board.detail-panel.start-date' | translate | async }}\n </span>\n </div>\n <div class=\"__content\">\n {{\n nodeInfo?.startDate\n | format: 'datetime' : { format: 'short', calendar: localeService.activeProfile().calendar.system }\n | async\n }}\n </div>\n </div>\n <div class=\"__row\">\n <div class=\"__title\">\n <span>{{ '@task-management:task-board.detail-panel.end-date' | translate | async }}</span>\n </div>\n <div class=\"__content\">\n {{\n nodeInfo?.endDate\n | format: 'datetime' : { format: 'short', calendar: localeService.activeProfile().calendar.system }\n | async\n }}\n </div>\n </div>\n <div class=\"__row\">\n <div class=\"__title\">\n <span>{{ '@task-management:task-board.detail-panel.reporter' | translate | async }}</span>\n </div>\n <div class=\"__content\">\n {{ nodeInfo?.reporter?.fullName }}\n </div>\n </div>\n @if (nodeInfo?.assignee) {\n <div class=\"__row\">\n <div class=\"__title\">\n <span>{{ '@task-management:task-board.detail-panel.assignee' | translate | async }}</span>\n </div>\n <div class=\"__content\">{{ nodeInfo?.assignee?.fullName }}</div>\n </div>\n }\n @if (statusName()) {\n <div class=\"__row\">\n <div class=\"__title\">\n <span>{{ '@task-management:task-board.detail-panel.status' | translate | async }}</span>\n </div>\n <div class=\"__content\">{{ statusName() }}</div>\n </div>\n }\n @if (nodeInfo?.priority) {\n <div class=\"__row\">\n <div class=\"__title\">\n <span>\n {{ '@task-management:task-board.detail-panel.priority' | translate | async }}\n </span>\n </div>\n <div class=\"__content\">{{ capitalizeFirstLetter(nodeInfo?.priority ?? '') }}</div>\n </div>\n }\n @if (extraFields() && extraFields().length) {\n <div class=\"__row\">\n <axp-widgets-container [context]=\"nodeInfo\">\n @for (extraField of extraFields(); track extraField) {\n <div class=\"__title\">\n <span>\n {{ extraField.title | translate | async }}\n </span>\n </div>\n <div class=\"__content\">\n <ng-container axp-widget-renderer [node]=\"extraField.widget\" [mode]=\"'view'\"> </ng-container>\n </div>\n }\n </axp-widgets-container>\n </div>\n }\n </div>\n </div>\n </div>\n} @else {\n <div class=\"__header\">\n <div class=\"__title\">\n <span>\n {{ '@task-management:task-board.detail-panel.title' | translate | async }}\n </span>\n </div>\n <ax-button [look]=\"'blank'\" class=\"ax-sm ax-rounded-full\" (onClick)=\"vm.closeDetailPanel()\">\n <ax-icon icon=\"fa-solid fa-xmark\"></ax-icon>\n </ax-button>\n </div>\n\n <div class=\"__content ax-flex ax-items-center ax-justify-center\">\n <axp-state-message\n icon=\"fa-light fa-clipboard-list-check\"\n [title]=\"'@task-management:task-board.detail-panel.no-task-selected.title'\"\n [description]=\"'@task-management:task-board.detail-panel.no-task-selected.description'\"\n >\n </axp-state-message>\n </div>\n}\n", styles: ["axm-task-board-detail-panel{display:flex;flex-direction:column;border-radius:.5rem;border-width:1px;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface))}@media (min-width: 1024px){axm-task-board-detail-panel{width:24rem}}axm-task-board-detail-panel>.__header{display:flex;flex-direction:row;align-items:center;justify-content:space-between;border-bottom-width:1px;padding:1rem}@media (min-width: 1024px){axm-task-board-detail-panel>.__header{width:20rem}}axm-task-board-detail-panel>.__header>.__title{display:flex;width:90%;flex-direction:row;align-items:center;gap:.5rem}axm-task-board-detail-panel>.__header>.__title span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:start;font-weight:600;line-height:1.625}axm-task-board-detail-panel>.__content{display:flex;flex-direction:column}axm-task-board-detail-panel>.__content>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}axm-task-board-detail-panel>.__content>.__section{display:flex;flex-direction:column;padding:1rem}axm-task-board-detail-panel>.__content>.__section>.__title{margin-bottom:1rem;font-size:.875rem;line-height:1.25rem;font-weight:700}axm-task-board-detail-panel>.__content>.__section>.__content{display:flex;flex-direction:column;gap:1rem}axm-task-board-detail-panel>.__content>.__section>.__content>.__row{display:flex;flex-direction:column;gap:.25rem}axm-task-board-detail-panel>.__content>.__section>.__content>.__row>.__title{display:flex;font-size:.875rem;line-height:1.25rem;font-weight:600;opacity:.9}axm-task-board-detail-panel>.__content>.__section>.__content>.__row>.__content{display:flex;flex-direction:row;align-items:center;gap:.5rem}axm-task-board-detail-panel>.__content>.__section>.__content>.__row>.__content span{opacity:.7}\n"] }]
335
+ }] });
336
+
337
+ class AXMTaskBoardFiltersComponent {
338
+ constructor() {
339
+ this.rootConfig = RootConfig;
340
+ this.vm = inject(AXMTaskBoardViewModel);
341
+ this.isQueryParam = input(false, ...(ngDevMode ? [{ debugName: "isQueryParam" }] : []));
342
+ this.excludeTaskType = input(false, ...(ngDevMode ? [{ debugName: "excludeTaskType" }] : []));
343
+ this.applyClicked = output();
344
+ this.context = signal({}, ...(ngDevMode ? [{ debugName: "context" }] : []));
345
+ this.isInitialized = false;
346
+ this.#init = effect(() => {
347
+ const isLoading = this.vm.isLoading();
348
+ if (!isLoading && !this.isInitialized) {
349
+ this.resetContextToViewModel();
350
+ this.isInitialized = true;
351
+ }
352
+ }, ...(ngDevMode ? [{ debugName: "#init" }] : []));
353
+ this.VALID_PRIORITIES = [
354
+ { title: 'Highest', name: 'highest' },
355
+ { title: 'High', name: 'high' },
356
+ { title: 'Medium', name: 'medium' },
357
+ { title: 'Low', name: 'low' },
358
+ { title: 'Lowest', name: 'lowest' },
359
+ { title: 'No Priority', name: 'no_priority' },
360
+ ];
361
+ this.isMultiSelectEnabled = computed(() => {
362
+ const viewMode = this.vm.currentViewMode();
363
+ return viewMode !== 'kanban' && viewMode !== 'status-grouped-grid';
364
+ }, ...(ngDevMode ? [{ debugName: "isMultiSelectEnabled" }] : []));
365
+ this.nodes = computed(() => {
366
+ const allNodes = [];
367
+ if (!this.excludeTaskType()) {
368
+ allNodes.push({
369
+ name: 'taskType',
370
+ path: 'options.taskType',
371
+ type: AXPWidgetsCatalog.select,
372
+ options: {
373
+ valueField: 'name',
374
+ textField: 'title',
375
+ dataSource: 'task-types',
376
+ placeholder: 'Select Task Type',
377
+ multiple: this.isMultiSelectEnabled(),
378
+ allowClear: this.isMultiSelectEnabled(),
379
+ },
380
+ meta: {
381
+ title: 'task-board.filter.task-type',
382
+ },
383
+ });
384
+ }
385
+ allNodes.push({
386
+ name: 'assignee',
387
+ path: 'options.assignee',
388
+ type: AXPWidgetsCatalog.select,
389
+ options: {
390
+ multiple: true,
391
+ valueField: 'id',
392
+ allowSearch: true,
393
+ dataSource: 'users',
394
+ textField: 'displayName',
395
+ placeholder: 'Select Assignee',
396
+ },
397
+ meta: {
398
+ title: 'task-board.filter.assignee',
399
+ },
400
+ }, {
401
+ name: 'reporter',
402
+ path: 'options.reporter',
403
+ type: AXPWidgetsCatalog.select,
404
+ options: {
405
+ multiple: true,
406
+ valueField: 'id',
407
+ allowSearch: true,
408
+ dataSource: 'users',
409
+ textField: 'displayName',
410
+ placeholder: 'Select Reporter',
411
+ },
412
+ meta: {
413
+ title: 'task-board.filter.reporter',
414
+ },
415
+ }, {
416
+ name: 'priority',
417
+ path: 'options.priority',
418
+ type: AXPWidgetsCatalog.select,
419
+ options: {
420
+ multiple: true,
421
+ valueField: 'name',
422
+ textField: 'title',
423
+ direction: 'horizontal',
424
+ placeholder: 'Select Priority',
425
+ dataSource: this.VALID_PRIORITIES,
426
+ },
427
+ meta: {
428
+ title: 'task-board.filter.priority',
429
+ },
430
+ });
431
+ return allNodes;
432
+ }, ...(ngDevMode ? [{ debugName: "nodes" }] : []));
433
+ }
434
+ #init;
435
+ resetContextToViewModel() {
436
+ const vmTaskTypeNames = this.vm.selectedTaskTypeNames();
437
+ const vmAssigneeIds = this.vm.selectedAssigneeIds();
438
+ const vmReporterIds = this.vm.selectedReporterIds();
439
+ const vmPriorities = this.vm.selectedPriorities();
440
+ const currentViewIsMulti = this.isMultiSelectEnabled();
441
+ const taskTypeContextValue = currentViewIsMulti
442
+ ? vmTaskTypeNames
443
+ : vmTaskTypeNames.length > 0
444
+ ? vmTaskTypeNames[0]
445
+ : null;
446
+ const contextOptions = {
447
+ priority: vmPriorities,
448
+ assignee: vmAssigneeIds,
449
+ reporter: vmReporterIds,
450
+ };
451
+ if (!this.excludeTaskType()) {
452
+ contextOptions.taskType = taskTypeContextValue;
453
+ }
454
+ this.context.set({
455
+ options: contextOptions,
456
+ });
457
+ }
458
+ handleContextChanged(e) {
459
+ this.context.set(e.data);
460
+ }
461
+ handleApply() {
462
+ if (!this.excludeTaskType()) {
463
+ this.syncTaskTypesToViewModel(this.context()?.options?.taskType);
464
+ }
465
+ this.syncAssigneesToViewModel(this.context()?.options?.assignee);
466
+ this.syncReportersToViewModel(this.context()?.options?.reporter);
467
+ this.syncPrioritiesToViewModel(this.context()?.options?.priority);
468
+ this.applyClicked.emit();
469
+ }
470
+ syncTaskTypesToViewModel(selectedValue) {
471
+ let newNames = [];
472
+ if (Array.isArray(selectedValue)) {
473
+ newNames = selectedValue.filter((v) => v != null).map((t) => (typeof t === 'string' ? t : t.name));
474
+ }
475
+ else if (selectedValue) {
476
+ newNames = [typeof selectedValue === 'string' ? selectedValue : selectedValue.name];
477
+ }
478
+ const currentNames = this.vm.selectedTaskTypeNames();
479
+ if (!isEqual(sortBy(currentNames), sortBy(newNames))) {
480
+ this.vm.setSelectedTaskTypeNames(newNames, this.isQueryParam());
481
+ }
482
+ }
483
+ syncAssigneesToViewModel(selectedAssignees) {
484
+ let newIds = [];
485
+ if (Array.isArray(selectedAssignees)) {
486
+ newIds = selectedAssignees
487
+ .filter((v) => v != null)
488
+ .map((t) => (typeof t === 'string' || typeof t === 'number' ? t : t.id));
489
+ }
490
+ const currentIds = this.vm.selectedAssigneeIds();
491
+ if (!isEqual(sortBy(currentIds), sortBy(newIds))) {
492
+ this.vm.setSelectedAssigneeIds(newIds, this.isQueryParam());
493
+ }
494
+ }
495
+ syncReportersToViewModel(selectedReporters) {
496
+ let newIds = [];
497
+ if (Array.isArray(selectedReporters)) {
498
+ newIds = selectedReporters
499
+ .filter((v) => v != null)
500
+ .map((t) => (typeof t === 'string' || typeof t === 'number' ? t : t.id));
501
+ }
502
+ const currentIds = this.vm.selectedReporterIds();
503
+ if (!isEqual(sortBy(currentIds), sortBy(newIds))) {
504
+ this.vm.setSelectedReporterIds(newIds, this.isQueryParam());
505
+ }
506
+ }
507
+ syncPrioritiesToViewModel(selectedPriorities) {
508
+ let newNames = [];
509
+ if (Array.isArray(selectedPriorities)) {
510
+ newNames = selectedPriorities
511
+ .filter((v) => v != null)
512
+ .map((t) => (typeof t === 'string' ? t : t.name));
513
+ }
514
+ const currentNames = this.vm.selectedPriorities();
515
+ if (!isEqual(sortBy(currentNames), sortBy(newNames))) {
516
+ this.vm.setSelectedPriorities(newNames, this.isQueryParam());
517
+ }
518
+ }
519
+ handleReset() {
520
+ if (this.vm.currentViewMode() === 'kanban' || this.vm.currentViewMode() === 'status-grouped-grid') {
521
+ const currentOptions = this.context();
522
+ const contextOptions = {};
523
+ if (!this.excludeTaskType()) {
524
+ contextOptions.taskType = currentOptions?.options?.taskType;
525
+ }
526
+ this.context.set({
527
+ options: contextOptions,
528
+ });
529
+ return;
530
+ }
531
+ this.context.set({});
532
+ }
533
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMTaskBoardFiltersComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
534
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXMTaskBoardFiltersComponent, isStandalone: true, selector: "axm-task-board-filters", inputs: { isQueryParam: { classPropertyName: "isQueryParam", publicName: "isQueryParam", isSignal: true, isRequired: false, transformFunction: null }, excludeTaskType: { classPropertyName: "excludeTaskType", publicName: "excludeTaskType", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { applyClicked: "applyClicked" }, ngImport: i0, template: "<div class=\"ax-px-4 ax-py-3 ax-flex ax-flex-col ax-gap-2 ax-sm ax-w-[20rem]\">\n <axp-widgets-container [context]=\"context()\" (onContextChanged)=\"handleContextChanged($event)\">\n <ax-form>\n <div class=\"ax-flex ax-flex-col ax-gap-4\">\n @for (node of nodes(); track $index) {\n <ax-form-field>\n @if (node.meta?.['title']) {\n <ax-label>\n {{ node.meta?.['title'] | translate: { scope: rootConfig.config.i18n } | async }}\n </ax-label>\n }\n <ng-container axp-widget-renderer [node]=\"node\" [mode]=\"'edit'\"></ng-container>\n </ax-form-field>\n }\n </div>\n <div class=\"ax-flex ax-gap-2 ax-mt-6 ax-mb-1\">\n <ax-button\n (onClick)=\"handleReset()\"\n class=\"ax-w-full\"\n [text]=\"'@general:actions.clear.title' | translate | async\"\n ></ax-button>\n <ax-button\n color=\"primary\"\n [type]=\"'submit'\"\n (onClick)=\"handleApply()\"\n class=\"ax-w-full\"\n [text]=\"'@general:actions.apply.title' | translate | async\"\n ></ax-button>\n </div>\n </ax-form>\n </axp-widgets-container>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AXFormFieldComponent, selector: "ax-form-field", inputs: ["labelMode"] }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i1.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "component", type: AXFormComponent, selector: "ax-form", inputs: ["disabled", "readonly", "labelMode", "look", "messageStyle", "updateOn"], outputs: ["onValidate", "updateOnChange"] }, { kind: "component", type: AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
535
+ }
536
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMTaskBoardFiltersComponent, decorators: [{
537
+ type: Component,
538
+ args: [{ selector: 'axm-task-board-filters', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
539
+ CommonModule,
540
+ AXFormFieldComponent,
541
+ AXPWidgetCoreModule,
542
+ AXFormComponent,
543
+ AXLabelComponent,
544
+ AXButtonComponent,
545
+ AXTranslatorPipe,
546
+ AsyncPipe,
547
+ ], template: "<div class=\"ax-px-4 ax-py-3 ax-flex ax-flex-col ax-gap-2 ax-sm ax-w-[20rem]\">\n <axp-widgets-container [context]=\"context()\" (onContextChanged)=\"handleContextChanged($event)\">\n <ax-form>\n <div class=\"ax-flex ax-flex-col ax-gap-4\">\n @for (node of nodes(); track $index) {\n <ax-form-field>\n @if (node.meta?.['title']) {\n <ax-label>\n {{ node.meta?.['title'] | translate: { scope: rootConfig.config.i18n } | async }}\n </ax-label>\n }\n <ng-container axp-widget-renderer [node]=\"node\" [mode]=\"'edit'\"></ng-container>\n </ax-form-field>\n }\n </div>\n <div class=\"ax-flex ax-gap-2 ax-mt-6 ax-mb-1\">\n <ax-button\n (onClick)=\"handleReset()\"\n class=\"ax-w-full\"\n [text]=\"'@general:actions.clear.title' | translate | async\"\n ></ax-button>\n <ax-button\n color=\"primary\"\n [type]=\"'submit'\"\n (onClick)=\"handleApply()\"\n class=\"ax-w-full\"\n [text]=\"'@general:actions.apply.title' | translate | async\"\n ></ax-button>\n </div>\n </ax-form>\n </axp-widgets-container>\n</div>\n" }]
548
+ }], propDecorators: { isQueryParam: [{ type: i0.Input, args: [{ isSignal: true, alias: "isQueryParam", required: false }] }], excludeTaskType: [{ type: i0.Input, args: [{ isSignal: true, alias: "excludeTaskType", required: false }] }], applyClicked: [{ type: i0.Output, args: ["applyClicked"] }] } });
549
+
550
+ class AXMTaskBoardCalendarViewComponent {
551
+ constructor() {
552
+ this.vm = inject(AXMTaskBoardViewModel);
553
+ this.calendarService = inject(AXCalendarService);
554
+ this.taskBoardService = inject(AXPTaskBoardService);
555
+ this.settingService = inject(AXPSettingsService);
556
+ this.commandService = inject(AXPCommandService);
557
+ this.schedulerService = inject(AXSchedulerService);
558
+ this.schedulerComponent = viewChild(AXSchedulerComponent, ...(ngDevMode ? [{ debugName: "schedulerComponent" }] : []));
559
+ this.taskPopover = viewChild('taskPopover', ...(ngDevMode ? [{ debugName: "taskPopover" }] : []));
560
+ this.selectedTask = signal(null, ...(ngDevMode ? [{ debugName: "selectedTask" }] : []));
561
+ this.popoverTarget = signal(null, ...(ngDevMode ? [{ debugName: "popoverTarget" }] : []));
562
+ this.taskActions = signal([], ...(ngDevMode ? [{ debugName: "taskActions" }] : []));
563
+ this.customComponentType = signal(null, ...(ngDevMode ? [{ debugName: "customComponentType" }] : []));
564
+ // Separate primary and secondary actions
565
+ this.primaryActions = computed(() => {
566
+ return this.taskActions().filter((action) => (action.priority ?? 'secondary') === 'primary');
567
+ }, ...(ngDevMode ? [{ debugName: "primaryActions" }] : []));
568
+ this.secondaryActions = computed(() => {
569
+ return this.taskActions().filter((action) => (action.priority ?? 'secondary') === 'secondary');
570
+ }, ...(ngDevMode ? [{ debugName: "secondaryActions" }] : []));
571
+ this.customComponentInputs = computed(() => {
572
+ const task = this.selectedTask();
573
+ if (!task)
574
+ return null;
575
+ return { task };
576
+ }, ...(ngDevMode ? [{ debugName: "customComponentInputs" }] : []));
577
+ this.resources = input([], ...(ngDevMode ? [{ debugName: "resources" }] : []));
578
+ this.startingDate = input(new Date(), ...(ngDevMode ? [{ debugName: "startingDate" }] : []));
579
+ this.selectedView = input('month', ...(ngDevMode ? [{ debugName: "selectedView" }] : []));
580
+ this.dataSource = input.required(...(ngDevMode ? [{ debugName: "dataSource" }] : []));
581
+ this.firstDayOfWeek = signal('monday', ...(ngDevMode ? [{ debugName: "firstDayOfWeek" }] : []));
582
+ this.weekendDays = signal([0, 6], ...(ngDevMode ? [{ debugName: "weekendDays" }] : []));
583
+ this.holidays = (range) => {
584
+ const selectedEventTypeIds = this.vm.selectedCalendarEventTypeIds();
585
+ // Pass selected calendar IDs (can be empty array to show no events)
586
+ return this.taskBoardService.getEvents(range, selectedEventTypeIds);
587
+ };
588
+ this.currentSchedulerView = computed(() => this.selectedView() === 'kanban' || this.selectedView() === 'grid'
589
+ ? 'month'
590
+ : this.selectedView(), ...(ngDevMode ? [{ debugName: "currentSchedulerView" }] : []));
591
+ this.onTaskClick = output();
592
+ this.onTaskChanged = output();
593
+ this.onMonthSlotDblClicked = output();
594
+ this.onActionClick = output();
595
+ this.component = output();
596
+ this.onTaskRightClick = output();
597
+ this.onRangeChanged = output();
598
+ }
599
+ // async ngOnInit(): Promise<void> {
600
+ // const firstDayOfWeek = await this.settingsService.get(AXPRegionalSetting.FirstDayOfWeek) as unknown as number;
601
+ // const weekDays = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
602
+ // this.firstDayOfWeek.set(weekDays[firstDayOfWeek] as unknown as AXDayOfWeekName);
603
+ // this.weekendDays.set((await this.settingsService.get(AXPRegionalSetting.WeekendDays)) as unknown as number[]);
604
+ // }
605
+ async ngAfterViewInit() {
606
+ if (this.schedulerComponent()) {
607
+ this.component.emit(this.schedulerComponent());
608
+ }
609
+ }
610
+ onTaskDrop(event) {
611
+ // Check if dropped on the same slot (agenda view)
612
+ if (event.slot.view === 'agenda' && event.isSameSlotDrop) {
613
+ return;
614
+ }
615
+ // Use the scheduler service utility to calculate the new appointment data
616
+ const dropResult = this.schedulerService.calculateAppointmentDropResult(event);
617
+ // If dropped on the same slot, no action needed
618
+ if (dropResult.isSameSlotDrop) {
619
+ return;
620
+ }
621
+ // Get the original task (before modification)
622
+ const originalTask = event.appointment;
623
+ // Apply the drop result to create an updated task object
624
+ // This uses the scheduler's internal utility for consistent date handling
625
+ const updatedTask = this.schedulerService.applyDropResult({ ...originalTask }, dropResult);
626
+ // Persist the change to the backend via taskBoardService
627
+ this.taskBoardService
628
+ .updateTaskDateRange(originalTask, {
629
+ from: dropResult.startDate,
630
+ end: dropResult.endDate,
631
+ })
632
+ .then((persistedTask) => {
633
+ // Emit the change event so parent can update its state
634
+ this.onTaskChanged.emit(persistedTask);
635
+ // Refresh the scheduler to reflect the persisted data
636
+ // This ensures the scheduler's internal state is synchronized with the backend
637
+ this.schedulerComponent()?.refresh();
638
+ })
639
+ .catch((error) => {
640
+ console.error('[TaskBoardCalendar] Failed to update task date range:', error);
641
+ // Revert the visual change if persistence fails by refreshing from backend
642
+ this.schedulerComponent()?.refresh();
643
+ });
644
+ }
645
+ onTaskRightClickHandler(event) {
646
+ this.onTaskRightClick.emit({ nativeEvent: event.nativeEvent, task: event.appointment });
647
+ }
648
+ onSlotDblClicked(event) {
649
+ if (event.sender.selectedView() === 'month') {
650
+ this.onMonthSlotDblClicked.emit(event.slot.startDate.date);
651
+ }
652
+ }
653
+ async handleRangeChanged(event) {
654
+ this.onRangeChanged.emit(event);
655
+ }
656
+ handleActionClick(event) {
657
+ this.onActionClick.emit({ nativeEvent: event.nativeEvent, task: event.appointment });
658
+ }
659
+ async onTaskClickHandler(event) {
660
+ const task = event.appointment;
661
+ // Find the appointment container element
662
+ let targetElement = event.nativeEvent.currentTarget || event.nativeEvent.target;
663
+ // Traverse up to find the appointment container
664
+ let element = targetElement;
665
+ const maxDepth = 10;
666
+ let depth = 0;
667
+ while (element && element !== document.body && depth < maxDepth) {
668
+ depth++;
669
+ const isAppointment = element.classList?.contains('dx-scheduler-appointment') ||
670
+ element.classList?.contains('ax-scheduler-appointment') ||
671
+ element.hasAttribute('data-appointment-id');
672
+ if (isAppointment) {
673
+ targetElement = element;
674
+ break;
675
+ }
676
+ const parent = element.parentElement;
677
+ if (parent) {
678
+ const isParentAppointment = parent.classList?.contains('dx-scheduler-appointment') ||
679
+ parent.classList?.contains('ax-scheduler-appointment');
680
+ if (isParentAppointment) {
681
+ targetElement = parent;
682
+ break;
683
+ }
684
+ }
685
+ element = element.parentElement;
686
+ }
687
+ // Set the selected task and target element
688
+ this.selectedTask.set(task);
689
+ this.popoverTarget.set(targetElement);
690
+ // Check if provider has a custom component
691
+ await this.loadCustomComponent(task);
692
+ // Load actions for the task
693
+ await this.loadTaskActions(task);
694
+ // Open the popover
695
+ setTimeout(() => {
696
+ if (this.taskPopover() && targetElement) {
697
+ this.taskPopover().target = targetElement;
698
+ this.taskPopover().open();
699
+ }
700
+ }, 0);
701
+ // Still emit the event for backward compatibility
702
+ this.onTaskClick.emit(task);
703
+ }
704
+ async loadTaskActions(task) {
705
+ try {
706
+ const providerName = task.provider;
707
+ if (!providerName) {
708
+ this.taskActions.set([]);
709
+ return;
710
+ }
711
+ const provider = this.taskBoardService.getProvider(providerName);
712
+ if (!provider) {
713
+ this.taskActions.set([]);
714
+ return;
715
+ }
716
+ const actions = await provider.getActions(task);
717
+ // Ensure all actions have a priority (default to 'secondary' if not specified)
718
+ const actionsWithPriority = (actions || []).map((action) => ({
719
+ ...action,
720
+ priority: action.priority ?? 'secondary',
721
+ }));
722
+ this.taskActions.set(actionsWithPriority);
723
+ }
724
+ catch (error) {
725
+ console.error('Failed to load task actions:', error);
726
+ this.taskActions.set([]);
727
+ }
728
+ }
729
+ getActionColor(action) {
730
+ return action.color;
731
+ }
732
+ async executeAction(action) {
733
+ const task = this.selectedTask();
734
+ if (!task || !action.command)
735
+ return;
736
+ try {
737
+ const providerName = task.provider;
738
+ if (!providerName)
739
+ return;
740
+ await this.taskBoardService.executeCommand(action.command, providerName);
741
+ this.closePopover();
742
+ }
743
+ catch (error) {
744
+ console.error('Failed to execute action:', error);
745
+ }
746
+ }
747
+ async openTaskDetails() {
748
+ const task = this.selectedTask();
749
+ if (!task)
750
+ return;
751
+ try {
752
+ await this.commandService.execute('Entity:OpenDetails', {
753
+ entity: `${RootConfig.module.name}.${RootConfig.entities.task.name}`,
754
+ data: { id: task.id },
755
+ });
756
+ this.closePopover();
757
+ }
758
+ catch (error) {
759
+ console.error('Failed to open task details:', error);
760
+ }
761
+ }
762
+ async loadCustomComponent(task) {
763
+ if (!task.provider) {
764
+ console.log('[TaskPopover] No provider on task:', task);
765
+ this.customComponentType.set(null);
766
+ return;
767
+ }
768
+ const provider = this.taskBoardService.getProvider(task.provider);
769
+ if (!provider) {
770
+ console.log('[TaskPopover] Provider not found:', task.provider);
771
+ this.customComponentType.set(null);
772
+ return;
773
+ }
774
+ const componentGetter = provider.getComponent?.();
775
+ if (!componentGetter) {
776
+ console.log('[TaskPopover] No component getter on provider:', task.provider);
777
+ this.customComponentType.set(null);
778
+ return;
779
+ }
780
+ console.log('[TaskPopover] Component getter found:', componentGetter, 'Type:', typeof componentGetter);
781
+ try {
782
+ let componentType;
783
+ // Check if it's a lazy loading function or direct component type
784
+ // A lazy loader is a function that returns a Promise
785
+ // A component type is a class constructor (also a function, but used differently)
786
+ if (typeof componentGetter === 'function') {
787
+ // Try calling it to see if it returns a Promise (lazy loader)
788
+ const testCall = componentGetter;
789
+ let result;
790
+ try {
791
+ result = testCall();
792
+ }
793
+ catch (e) {
794
+ // If calling throws (e.g., class constructor without 'new'), use it directly
795
+ console.log('[TaskPopover] Component getter is a class constructor, using directly');
796
+ componentType = componentGetter;
797
+ this.customComponentType.set(componentType);
798
+ return;
799
+ }
800
+ if (result instanceof Promise) {
801
+ // It's a lazy loading function
802
+ console.log('[TaskPopover] Component getter is a lazy loader');
803
+ componentType = await result;
804
+ }
805
+ else if (result) {
806
+ // It returned a component type directly
807
+ console.log('[TaskPopover] Component getter returned component type directly');
808
+ componentType = result;
809
+ }
810
+ else {
811
+ // Result is undefined, use the original as component type
812
+ console.log('[TaskPopover] Component getter returned undefined, using original as component type');
813
+ componentType = componentGetter;
814
+ }
815
+ }
816
+ else {
817
+ console.log('[TaskPopover] Component getter is not a function');
818
+ this.customComponentType.set(null);
819
+ return;
820
+ }
821
+ console.log('[TaskPopover] Component type loaded successfully:', componentType?.name);
822
+ this.customComponentType.set(componentType);
823
+ }
824
+ catch (error) {
825
+ console.error('[TaskPopover] Failed to load custom task popover component:', error);
826
+ this.customComponentType.set(null);
827
+ }
828
+ }
829
+ closePopover() {
830
+ this.taskPopover()?.close();
831
+ this.customComponentType.set(null);
832
+ this.selectedTask.set(null);
833
+ this.popoverTarget.set(null);
834
+ this.taskActions.set([]);
835
+ }
836
+ formatTime(date) {
837
+ return this.calendarService.create(date).format('HH:mm');
838
+ }
839
+ formatDate(date) {
840
+ return this.calendarService.create(date).format('MMM DD, YYYY');
841
+ }
842
+ formatDateTime(date) {
843
+ return this.calendarService.create(date).format('MMM DD, YYYY HH:mm');
844
+ }
845
+ isMultiDay(task) {
846
+ if (task.allDay) {
847
+ const start = this.calendarService.create(task.startDate);
848
+ const end = this.calendarService.create(task.endDate);
849
+ return start.date.getTime() !== end.date.getTime();
850
+ }
851
+ // Check if start and end are on different days
852
+ const start = this.calendarService.create(task.startDate);
853
+ const end = this.calendarService.create(task.endDate);
854
+ const startDay = start.date.getDate();
855
+ const endDay = end.date.getDate();
856
+ const startMonth = start.date.getMonth();
857
+ const endMonth = end.date.getMonth();
858
+ const startYear = start.date.getFullYear();
859
+ const endYear = end.date.getFullYear();
860
+ return startDay !== endDay || startMonth !== endMonth || startYear !== endYear;
861
+ }
862
+ formatDateRange(task) {
863
+ if (task.allDay) {
864
+ const start = this.calendarService.create(task.startDate);
865
+ const end = this.calendarService.create(task.endDate);
866
+ // Same day
867
+ if (start.date.getTime() === end.date.getTime()) {
868
+ return this.formatDate(task.startDate);
869
+ }
870
+ // Different days - show range
871
+ const startFormatted = this.formatDate(task.startDate);
872
+ const endFormatted = this.formatDate(task.endDate);
873
+ // Same month and year
874
+ if (start.date.getMonth() === end.date.getMonth() && start.date.getFullYear() === end.date.getFullYear()) {
875
+ const startDay = start.date.getDate();
876
+ const endDay = end.date.getDate();
877
+ const monthYear = start.format('MMM YYYY');
878
+ return `${startDay} - ${endDay}, ${monthYear}`;
879
+ }
880
+ // Different months or years
881
+ return `${startFormatted} - ${endFormatted}`;
882
+ }
883
+ // Not all-day
884
+ if (this.isMultiDay(task)) {
885
+ const startFormatted = this.formatDateTime(task.startDate);
886
+ const endFormatted = this.formatDateTime(task.endDate);
887
+ return `${startFormatted} - ${endFormatted}`;
888
+ }
889
+ // Same day, show date with time range
890
+ const dateFormatted = this.formatDate(task.startDate);
891
+ const timeRange = `${this.formatTime(task.startDate)} - ${this.formatTime(task.endDate)}`;
892
+ return `${dateFormatted} ${timeRange}`;
893
+ }
894
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMTaskBoardCalendarViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
895
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXMTaskBoardCalendarViewComponent, isStandalone: true, selector: "axm-task-board-calendar-view", inputs: { resources: { classPropertyName: "resources", publicName: "resources", isSignal: true, isRequired: false, transformFunction: null }, startingDate: { classPropertyName: "startingDate", publicName: "startingDate", isSignal: true, isRequired: false, transformFunction: null }, selectedView: { classPropertyName: "selectedView", publicName: "selectedView", isSignal: true, isRequired: false, transformFunction: null }, dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { onTaskClick: "onTaskClick", onTaskChanged: "onTaskChanged", onMonthSlotDblClicked: "onMonthSlotDblClicked", onActionClick: "onActionClick", component: "component", onTaskRightClick: "onTaskRightClick", onRangeChanged: "onRangeChanged" }, viewQueries: [{ propertyName: "schedulerComponent", first: true, predicate: AXSchedulerComponent, descendants: true, isSignal: true }, { propertyName: "taskPopover", first: true, predicate: ["taskPopover"], descendants: true, isSignal: true }], ngImport: i0, template: "<ax-scheduler\n [hasHeader]=\"false\"\n [holidays]=\"holidays\"\n [resources]=\"resources()\"\n [dataSource]=\"dataSource()\"\n [startingDate]=\"startingDate()\"\n [selectedView]=\"currentSchedulerView()\"\n [multiDayViewDaysCount]=\"vm.daysCount()\"\n (onAppointmentDrop)=\"onTaskDrop($event)\"\n (onActionClick)=\"handleActionClick($event)\"\n (onRangeChanged)=\"handleRangeChanged($event)\"\n (onSlotDblClicked)=\"onSlotDblClicked($event)\"\n (onAppointmentClicked)=\"onTaskClickHandler($event)\"\n [weekend]=\"weekendDays()\"\n [firstDayOfWeek]=\"firstDayOfWeek()\"\n></ax-scheduler>\n\n<!-- Task Detail Popover (Modern Google Calendar Style) -->\n<ax-popover\n #taskPopover\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [offsetY]=\"12\"\n [offsetX]=\"12\"\n [adaptivityEnabled]=\"true\"\n>\n @if (selectedTask()) {\n <div class=\"task-popover ax-shadow-md ax-border\">\n <!-- Header Section -->\n <div class=\"task-popover__header\">\n <div class=\"task-popover__title-section\">\n <div class=\"task-popover__title-row\">\n <h3 class=\"task-popover__title\" [title]=\"selectedTask()!.title\">{{ selectedTask()!.title }}</h3>\n <button type=\"button\" class=\"task-popover__close-btn\" (click)=\"closePopover()\" aria-label=\"Close\">\n <ax-icon class=\"ax-icon ax-icon-close\"></ax-icon>\n </button>\n </div>\n @if (selectedTask()!.description && !customComponentType()) {\n <p class=\"task-popover__description\">{{ selectedTask()!.description }}</p>\n }\n </div>\n </div>\n\n <!-- Custom Component or Default Content -->\n @if (customComponentType()) {\n <!-- Custom Component from Provider -->\n <div class=\"task-popover__custom-content\">\n <ng-container *ngComponentOutlet=\"customComponentType()!; inputs: customComponentInputs()!\"></ng-container>\n </div>\n } @else {\n <!-- Default Content Section -->\n <div class=\"task-popover__content\">\n <!-- Time -->\n <div class=\"task-popover__info-item\">\n <div class=\"task-popover__icon\">\n <i class=\"fa-light fa-clock\"></i>\n </div>\n <div class=\"task-popover__info-content\">\n <span class=\"task-popover__info-text\">{{ formatDateRange(selectedTask()!) }}</span>\n </div>\n </div>\n\n <!-- Status -->\n @if (selectedTask()!.status) {\n <div class=\"task-popover__info-item\">\n <div class=\"task-popover__icon\">\n <i class=\"fa-light fa-flag\"></i>\n </div>\n <div class=\"task-popover__info-content\">\n <span class=\"task-popover__info-text\">{{ selectedTask()!.status.title }}</span>\n </div>\n </div>\n }\n\n <!-- Assignee -->\n @if (selectedTask()!.assignee) {\n <div class=\"task-popover__info-item\">\n <div class=\"task-popover__icon\">\n <i class=\"fa-light fa-user\"></i>\n </div>\n <div class=\"task-popover__info-content\">\n <span class=\"task-popover__info-text\">{{\n selectedTask()!.assignee?.fullName || selectedTask()!.assignee?.username || 'Unassigned'\n }}</span>\n </div>\n </div>\n }\n\n <!-- Priority -->\n @if (selectedTask()!.priority) {\n <div class=\"task-popover__info-item\">\n <div\n class=\"task-popover__icon task-popover__icon--priority\"\n [attr.data-priority]=\"selectedTask()!.priority\"\n >\n <i class=\"fa-light fa-exclamation-circle\"></i>\n </div>\n <div class=\"task-popover__info-content\">\n <span\n class=\"task-popover__info-text task-popover__priority\"\n [attr.data-priority]=\"selectedTask()!.priority\"\n >\n {{ selectedTask()!.priority }}\n </span>\n </div>\n </div>\n }\n </div>\n\n <!-- Actions Section -->\n <div class=\"task-popover__actions\">\n <!-- Task Actions from Provider -->\n @if (taskActions().length > 0) {\n <div class=\"task-popover__actions-group\">\n <!-- Primary Actions: Icon-only buttons -->\n @if (primaryActions().length > 0) {\n @for (action of primaryActions(); track action.name || action.title) {\n <ax-button\n [look]=\"'solid'\"\n [color]=\"getActionColor(action)\"\n (onClick)=\"executeAction(action)\"\n [disabled]=\"action.disabled === true\"\n [text]=\"action.title\"\n >\n @if (action.icon) {\n <ax-prefix>\n <ax-icon>\n <i [class]=\"action.icon\"></i>\n </ax-icon>\n </ax-prefix>\n }\n </ax-button>\n }\n }\n\n <!-- Secondary Actions: Dropdown with \"...\" button -->\n @if (secondaryActions().length > 0) {\n <ax-button [look]=\"'blank'\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-ellipsis-vertical\"></ax-icon>\n </ax-prefix>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (action of secondaryActions(); track action.name || action.title) {\n <ax-button-item\n [text]=\"action.title\"\n [disabled]=\"action.disabled === true\"\n (onClick)=\"executeAction(action)\"\n >\n @if (action.icon) {\n <ax-prefix>\n <ax-icon>\n <i [class]=\"action.icon\"></i>\n </ax-icon>\n </ax-prefix>\n }\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n</ax-popover>\n", styles: ["ax-scheduler{line-height:1.5;background-color:rgba(var(--ax-sys-color-lightest-surface))!important}.task-popover{background:rgba(var(--ax-sys-color-lightest-surface));border-radius:12px;overflow:hidden;display:flex;flex-direction:column}.task-popover__header{padding:20px 20px 16px;border-bottom:1px solid var(--ax-sys-color-border);background:linear-gradient(to bottom,var(--ax-sys-color-lightest-surface),var(--ax-sys-color-lighter-surface))}.task-popover__title-section{display:flex;flex-direction:column;gap:8px}.task-popover__title-row{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.task-popover__title{font-size:18px;font-weight:600;line-height:1.4;color:var(--ax-sys-color-text-primary);margin:0;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.task-popover__close-btn{flex-shrink:0;background:none;border:none;padding:4px;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--ax-sys-color-text-neutral-600);transition:color .2s ease;border-radius:4px}.task-popover__close-btn:hover{color:var(--ax-sys-color-text-primary);background:var(--ax-sys-color-lighter-surface)}.task-popover__close-btn:active{background:var(--ax-sys-color-light-surface)}.task-popover__close-btn ax-icon{display:block;width:16px;height:16px}.task-popover__description{font-size:14px;line-height:1.5;color:var(--ax-sys-color-text-secondary);margin:0;display:-webkit-box;-webkit-line-clamp:3;line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis}.task-popover__content{padding:16px 20px;display:flex;flex-direction:column;gap:12px;flex:1}.task-popover__info-item{display:flex;align-items:flex-start;gap:12px;min-height:24px}.task-popover__icon{width:20px;height:20px;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:2px;color:var(--ax-sys-color-text-neutral-600);font-size:14px}.task-popover__icon i{display:block}.task-popover__icon--priority[data-priority=highest]{color:var(--ax-sys-color-danger)}.task-popover__icon--priority[data-priority=high]{color:var(--ax-sys-color-warning)}.task-popover__icon--priority[data-priority=medium]{color:var(--ax-sys-color-info)}.task-popover__icon--priority[data-priority=low],.task-popover__icon--priority[data-priority=lowest]{color:var(--ax-sys-color-text-neutral-500)}.task-popover__info-content{flex:1;min-width:0;display:flex;align-items:center}.task-popover__info-text{font-size:14px;line-height:1.5;color:var(--ax-sys-color-text-primary);word-wrap:break-word}.task-popover__time{font-weight:500;color:var(--ax-sys-color-text-primary);margin-left:4px}.task-popover__priority{text-transform:capitalize;font-weight:500}.task-popover__priority[data-priority=highest]{color:var(--ax-sys-color-danger)}.task-popover__priority[data-priority=high]{color:var(--ax-sys-color-warning)}.task-popover__priority[data-priority=medium]{color:var(--ax-sys-color-info)}.task-popover__priority[data-priority=low],.task-popover__priority[data-priority=lowest]{color:var(--ax-sys-color-text-neutral-600)}.task-popover__actions{padding:12px 20px 16px;border-top:1px solid var(--ax-sys-color-border);display:flex;flex-direction:column;gap:8px;background:var(--ax-sys-color-lighter-surface)}.task-popover__actions-group{display:flex;justify-content:flex-end;gap:8px;flex-wrap:wrap}.task-popover__actions-group--default{margin-top:4px;padding-top:8px;border-top:1px solid var(--ax-sys-color-border)}.task-popover__action-divider{width:100%;height:1px;background:var(--ax-sys-color-border);margin:4px 0}.task-popover__action-btn{min-width:100px;white-space:nowrap}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: AXSchedulerComponent, selector: "ax-scheduler", inputs: ["calendar", "startingDate", "endDayHour", "startDayHour", "hasHeader", "readonly", "draggable", "hasActions", "dragStartDelay", "weekend", "allowFullScreen", "multiDayViewDaysCount", "showResourceHeaders", "showCurrentTimeIndicator", "showUnassignedAppointments", "resources", "resourceTemplate", "firstDayOfWeek", "tooltipTemplate", "dataSource", "holidays", "views", "selectedView"], outputs: ["selectedViewChange", "onDataLoaded", "onRangeChanged", "onSlotClicked", "onSlotDblClicked", "onSlotRightClick", "onAppointmentDrop", "onActionClick", "onAppointmentClicked", "onAppointmentDblClicked", "onAppointmentRightClick"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i3.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i3.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i4.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i5.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i5.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXTranslationModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
896
+ }
897
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMTaskBoardCalendarViewComponent, decorators: [{
898
+ type: Component,
899
+ args: [{ selector: 'axm-task-board-calendar-view', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
900
+ CommonModule,
901
+ AXSchedulerComponent,
902
+ AXPopoverModule,
903
+ AXButtonModule,
904
+ AXDropdownModule,
905
+ AXDecoratorModule,
906
+ AXTranslationModule,
907
+ ], template: "<ax-scheduler\n [hasHeader]=\"false\"\n [holidays]=\"holidays\"\n [resources]=\"resources()\"\n [dataSource]=\"dataSource()\"\n [startingDate]=\"startingDate()\"\n [selectedView]=\"currentSchedulerView()\"\n [multiDayViewDaysCount]=\"vm.daysCount()\"\n (onAppointmentDrop)=\"onTaskDrop($event)\"\n (onActionClick)=\"handleActionClick($event)\"\n (onRangeChanged)=\"handleRangeChanged($event)\"\n (onSlotDblClicked)=\"onSlotDblClicked($event)\"\n (onAppointmentClicked)=\"onTaskClickHandler($event)\"\n [weekend]=\"weekendDays()\"\n [firstDayOfWeek]=\"firstDayOfWeek()\"\n></ax-scheduler>\n\n<!-- Task Detail Popover (Modern Google Calendar Style) -->\n<ax-popover\n #taskPopover\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [offsetY]=\"12\"\n [offsetX]=\"12\"\n [adaptivityEnabled]=\"true\"\n>\n @if (selectedTask()) {\n <div class=\"task-popover ax-shadow-md ax-border\">\n <!-- Header Section -->\n <div class=\"task-popover__header\">\n <div class=\"task-popover__title-section\">\n <div class=\"task-popover__title-row\">\n <h3 class=\"task-popover__title\" [title]=\"selectedTask()!.title\">{{ selectedTask()!.title }}</h3>\n <button type=\"button\" class=\"task-popover__close-btn\" (click)=\"closePopover()\" aria-label=\"Close\">\n <ax-icon class=\"ax-icon ax-icon-close\"></ax-icon>\n </button>\n </div>\n @if (selectedTask()!.description && !customComponentType()) {\n <p class=\"task-popover__description\">{{ selectedTask()!.description }}</p>\n }\n </div>\n </div>\n\n <!-- Custom Component or Default Content -->\n @if (customComponentType()) {\n <!-- Custom Component from Provider -->\n <div class=\"task-popover__custom-content\">\n <ng-container *ngComponentOutlet=\"customComponentType()!; inputs: customComponentInputs()!\"></ng-container>\n </div>\n } @else {\n <!-- Default Content Section -->\n <div class=\"task-popover__content\">\n <!-- Time -->\n <div class=\"task-popover__info-item\">\n <div class=\"task-popover__icon\">\n <i class=\"fa-light fa-clock\"></i>\n </div>\n <div class=\"task-popover__info-content\">\n <span class=\"task-popover__info-text\">{{ formatDateRange(selectedTask()!) }}</span>\n </div>\n </div>\n\n <!-- Status -->\n @if (selectedTask()!.status) {\n <div class=\"task-popover__info-item\">\n <div class=\"task-popover__icon\">\n <i class=\"fa-light fa-flag\"></i>\n </div>\n <div class=\"task-popover__info-content\">\n <span class=\"task-popover__info-text\">{{ selectedTask()!.status.title }}</span>\n </div>\n </div>\n }\n\n <!-- Assignee -->\n @if (selectedTask()!.assignee) {\n <div class=\"task-popover__info-item\">\n <div class=\"task-popover__icon\">\n <i class=\"fa-light fa-user\"></i>\n </div>\n <div class=\"task-popover__info-content\">\n <span class=\"task-popover__info-text\">{{\n selectedTask()!.assignee?.fullName || selectedTask()!.assignee?.username || 'Unassigned'\n }}</span>\n </div>\n </div>\n }\n\n <!-- Priority -->\n @if (selectedTask()!.priority) {\n <div class=\"task-popover__info-item\">\n <div\n class=\"task-popover__icon task-popover__icon--priority\"\n [attr.data-priority]=\"selectedTask()!.priority\"\n >\n <i class=\"fa-light fa-exclamation-circle\"></i>\n </div>\n <div class=\"task-popover__info-content\">\n <span\n class=\"task-popover__info-text task-popover__priority\"\n [attr.data-priority]=\"selectedTask()!.priority\"\n >\n {{ selectedTask()!.priority }}\n </span>\n </div>\n </div>\n }\n </div>\n\n <!-- Actions Section -->\n <div class=\"task-popover__actions\">\n <!-- Task Actions from Provider -->\n @if (taskActions().length > 0) {\n <div class=\"task-popover__actions-group\">\n <!-- Primary Actions: Icon-only buttons -->\n @if (primaryActions().length > 0) {\n @for (action of primaryActions(); track action.name || action.title) {\n <ax-button\n [look]=\"'solid'\"\n [color]=\"getActionColor(action)\"\n (onClick)=\"executeAction(action)\"\n [disabled]=\"action.disabled === true\"\n [text]=\"action.title\"\n >\n @if (action.icon) {\n <ax-prefix>\n <ax-icon>\n <i [class]=\"action.icon\"></i>\n </ax-icon>\n </ax-prefix>\n }\n </ax-button>\n }\n }\n\n <!-- Secondary Actions: Dropdown with \"...\" button -->\n @if (secondaryActions().length > 0) {\n <ax-button [look]=\"'blank'\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-ellipsis-vertical\"></ax-icon>\n </ax-prefix>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (action of secondaryActions(); track action.name || action.title) {\n <ax-button-item\n [text]=\"action.title\"\n [disabled]=\"action.disabled === true\"\n (onClick)=\"executeAction(action)\"\n >\n @if (action.icon) {\n <ax-prefix>\n <ax-icon>\n <i [class]=\"action.icon\"></i>\n </ax-icon>\n </ax-prefix>\n }\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n</ax-popover>\n", styles: ["ax-scheduler{line-height:1.5;background-color:rgba(var(--ax-sys-color-lightest-surface))!important}.task-popover{background:rgba(var(--ax-sys-color-lightest-surface));border-radius:12px;overflow:hidden;display:flex;flex-direction:column}.task-popover__header{padding:20px 20px 16px;border-bottom:1px solid var(--ax-sys-color-border);background:linear-gradient(to bottom,var(--ax-sys-color-lightest-surface),var(--ax-sys-color-lighter-surface))}.task-popover__title-section{display:flex;flex-direction:column;gap:8px}.task-popover__title-row{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.task-popover__title{font-size:18px;font-weight:600;line-height:1.4;color:var(--ax-sys-color-text-primary);margin:0;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.task-popover__close-btn{flex-shrink:0;background:none;border:none;padding:4px;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--ax-sys-color-text-neutral-600);transition:color .2s ease;border-radius:4px}.task-popover__close-btn:hover{color:var(--ax-sys-color-text-primary);background:var(--ax-sys-color-lighter-surface)}.task-popover__close-btn:active{background:var(--ax-sys-color-light-surface)}.task-popover__close-btn ax-icon{display:block;width:16px;height:16px}.task-popover__description{font-size:14px;line-height:1.5;color:var(--ax-sys-color-text-secondary);margin:0;display:-webkit-box;-webkit-line-clamp:3;line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis}.task-popover__content{padding:16px 20px;display:flex;flex-direction:column;gap:12px;flex:1}.task-popover__info-item{display:flex;align-items:flex-start;gap:12px;min-height:24px}.task-popover__icon{width:20px;height:20px;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:2px;color:var(--ax-sys-color-text-neutral-600);font-size:14px}.task-popover__icon i{display:block}.task-popover__icon--priority[data-priority=highest]{color:var(--ax-sys-color-danger)}.task-popover__icon--priority[data-priority=high]{color:var(--ax-sys-color-warning)}.task-popover__icon--priority[data-priority=medium]{color:var(--ax-sys-color-info)}.task-popover__icon--priority[data-priority=low],.task-popover__icon--priority[data-priority=lowest]{color:var(--ax-sys-color-text-neutral-500)}.task-popover__info-content{flex:1;min-width:0;display:flex;align-items:center}.task-popover__info-text{font-size:14px;line-height:1.5;color:var(--ax-sys-color-text-primary);word-wrap:break-word}.task-popover__time{font-weight:500;color:var(--ax-sys-color-text-primary);margin-left:4px}.task-popover__priority{text-transform:capitalize;font-weight:500}.task-popover__priority[data-priority=highest]{color:var(--ax-sys-color-danger)}.task-popover__priority[data-priority=high]{color:var(--ax-sys-color-warning)}.task-popover__priority[data-priority=medium]{color:var(--ax-sys-color-info)}.task-popover__priority[data-priority=low],.task-popover__priority[data-priority=lowest]{color:var(--ax-sys-color-text-neutral-600)}.task-popover__actions{padding:12px 20px 16px;border-top:1px solid var(--ax-sys-color-border);display:flex;flex-direction:column;gap:8px;background:var(--ax-sys-color-lighter-surface)}.task-popover__actions-group{display:flex;justify-content:flex-end;gap:8px;flex-wrap:wrap}.task-popover__actions-group--default{margin-top:4px;padding-top:8px;border-top:1px solid var(--ax-sys-color-border)}.task-popover__action-divider{width:100%;height:1px;background:var(--ax-sys-color-border);margin:4px 0}.task-popover__action-btn{min-width:100px;white-space:nowrap}\n"] }]
908
+ }], propDecorators: { schedulerComponent: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXSchedulerComponent), { isSignal: true }] }], taskPopover: [{ type: i0.ViewChild, args: ['taskPopover', { isSignal: true }] }], resources: [{ type: i0.Input, args: [{ isSignal: true, alias: "resources", required: false }] }], startingDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "startingDate", required: false }] }], selectedView: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedView", required: false }] }], dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: true }] }], onTaskClick: [{ type: i0.Output, args: ["onTaskClick"] }], onTaskChanged: [{ type: i0.Output, args: ["onTaskChanged"] }], onMonthSlotDblClicked: [{ type: i0.Output, args: ["onMonthSlotDblClicked"] }], onActionClick: [{ type: i0.Output, args: ["onActionClick"] }], component: [{ type: i0.Output, args: ["component"] }], onTaskRightClick: [{ type: i0.Output, args: ["onTaskRightClick"] }], onRangeChanged: [{ type: i0.Output, args: ["onRangeChanged"] }] } });
909
+
910
+ class AXMTaskBoardGridViewComponent {
911
+ constructor() {
912
+ this.vm = inject(AXMTaskBoardViewModel);
913
+ this.localeService = inject(AXLocaleService);
914
+ this.calendarService = inject(AXCalendarService);
915
+ this.taskBoardService = inject(AXPTaskBoardService);
916
+ this.dataSource = input.required(...(ngDevMode ? [{ debugName: "dataSource" }] : []));
917
+ this.onTaskClick = output();
918
+ this.onActionClick = output();
919
+ this.fetchedTasks = signal([], ...(ngDevMode ? [{ debugName: "fetchedTasks" }] : []));
920
+ this.columns = signal([], ...(ngDevMode ? [{ debugName: "columns" }] : []));
921
+ this.tasksDataSource = computed(() => {
922
+ const parentDataSource = this.dataSource();
923
+ return new AXDataSource({
924
+ load: async (e) => {
925
+ const result = await parentDataSource({ skip: e.skip, take: e.take });
926
+ this.fetchedTasks.set(result.items);
927
+ const mappedItems = result.items.map((task) => ({
928
+ id: task.id,
929
+ data: task.data,
930
+ title: task.title,
931
+ priority: task.priority,
932
+ description: task.description,
933
+ statusTitle: task.status.title,
934
+ reporter: task.reporter.fullName ?? '-',
935
+ assignee: task.assignee?.fullName ?? 'unassigned',
936
+ type: this.taskBoardService.getProvider(task.provider)?.title,
937
+ endDate: this.calendarService.format(task.endDate, 'DD/MM/YYYY HH:mm', {
938
+ locale: this.localeService.activeProfile().calendar.system,
939
+ }),
940
+ startDate: this.calendarService.format(task.startDate, 'DD/MM/YYYY HH:mm', {
941
+ locale: this.localeService.activeProfile().calendar.system,
942
+ }),
943
+ }));
944
+ return { items: mappedItems, total: result.total };
945
+ },
946
+ pageSize: 10,
947
+ key: 'id',
948
+ byKey: async (key) => {
949
+ return this.fetchedTasks().find((task) => task.id === key);
950
+ },
951
+ });
952
+ }, ...(ngDevMode ? [{ debugName: "tasksDataSource" }] : []));
953
+ this.#dataSourceChanged = effect(() => {
954
+ this.tasksDataSource().refresh();
955
+ }, ...(ngDevMode ? [{ debugName: "#dataSourceChanged" }] : []));
956
+ this.#providerChanged = effect(async () => {
957
+ const taskType = this.vm.selectedTaskTypes()[0];
958
+ if (!taskType) {
959
+ this.columns.set([]);
960
+ return;
961
+ }
962
+ taskType.getExtraFields().then((extraFields) => {
963
+ if (extraFields) {
964
+ this.columns.set(extraFields);
965
+ }
966
+ });
967
+ }, ...(ngDevMode ? [{ debugName: "#providerChanged" }] : []));
968
+ }
969
+ #dataSourceChanged;
970
+ #providerChanged;
971
+ handleRowClick(event) {
972
+ if (event.data) {
973
+ this.onTaskClick.emit(event.data);
974
+ }
975
+ }
976
+ onActionClickHandler(e) {
977
+ const task = this.fetchedTasks().find((task) => task.id === e.data.id);
978
+ if (!task)
979
+ return;
980
+ this.onActionClick.emit({ nativeEvent: e.nativeEvent, task });
981
+ }
982
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMTaskBoardGridViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
983
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXMTaskBoardGridViewComponent, isStandalone: true, selector: "axm-task-board-grid-view", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { onTaskClick: "onTaskClick", onActionClick: "onActionClick" }, ngImport: i0, template: "<ax-data-table\n [fetchDataMode]=\"'manual'\"\n [dataSource]=\"tasksDataSource()\"\n (onRowClick)=\"handleRowClick($event)\"\n [loading]=\"{ enabled: true, animation: true }\"\n>\n <ax-text-column dataField=\"title\" caption=\"title\" [width]=\"'350px'\"></ax-text-column>\n <ax-text-column dataField=\"description\" caption=\"description\" [width]=\"'500px'\"></ax-text-column>\n <ax-text-column dataField=\"startDate\" caption=\"Start Date\" [width]=\"'150px'\"></ax-text-column>\n <ax-text-column dataField=\"endDate\" caption=\"Due Date\" [width]=\"'150px'\"></ax-text-column>\n <ax-text-column dataField=\"priority\" caption=\"priority\" [width]=\"'125px'\"></ax-text-column>\n <ax-text-column dataField=\"reporter\" caption=\"Reporter\" [width]=\"'125px'\"></ax-text-column>\n <ax-text-column dataField=\"assignee\" caption=\"Assignee\" [width]=\"'125px'\"></ax-text-column>\n <ax-text-column dataField=\"statusTitle\" caption=\"status\" [width]=\"'125px'\"></ax-text-column>\n <ax-text-column dataField=\"type\" caption=\"type\" [width]=\"'150px'\"></ax-text-column>\n\n @if (columns().length) {\n <ng-container>\n @for (column of columns(); track column) {\n <axp-widget-column-renderer\n [node]=\"column.widget\"\n [caption]=\"(column.title | translate | async)!\"\n ></axp-widget-column-renderer>\n }\n </ng-container>\n }\n\n <ax-command-column\n fixed=\"end\"\n [width]=\"'60px'\"\n (onItemClick)=\"onActionClickHandler($event)\"\n [items]=\"[{ name: 'view', text: 'View', icon: 'ax-icon ax-icon-more-horizontal' }]\"\n ></ax-command-column>\n</ax-data-table>\n", styles: ["ax-kanban{--ax-comp-kanban-status-min-width: 25rem;height:100%;line-height:1.5}\n"], dependencies: [{ kind: "ngmodule", type: AXDataTableModule }, { kind: "component", type: i1$2.AXDataTableComponent, selector: "ax-data-table", inputs: ["dataSource", "selectedRows", "parentField", "rowDetailsTemplate", "rowTemplate", "emptyTemplate", "noDataTemplate", "alternative", "showHeader", "fixedHeader", "showFooter", "fixedFooter", "itemHeight", "allowReordering", "paging", "fetchDataMode", "loading", "focusedRow"], outputs: ["selectedRowsChange", "focusedRowChange", "onRowClick", "onRowDbClick", "onColumnsOrderChanged", "onColumnSizeChanged", "onPageChanged"] }, { kind: "component", type: i1$2.AXDataTableTextColumnComponent, selector: "ax-text-column", inputs: ["width", "caption", "allowSorting", "allowResizing", "fixed", "customExpandIcon", "customCollapseIcon", "dataField", "expandHandler", "wrapText", "cellTemplate", "footerTemplate", "headerTemplate", "format", "formatOptions"] }, { kind: "component", type: i1$2.AXRowCommandColumnComponent, selector: "ax-command-column", inputs: ["width", "caption", "fixed", "footerTemplate", "items"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i1.AXPWidgetColumnRendererComponent, selector: "axp-widget-column-renderer", inputs: ["caption", "customExpandIcon", "customCollapseIcon", "customWidth", "node", "footerTemplate", "expandHandler", "cellTemplate", "headerTemplate"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
984
+ }
985
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMTaskBoardGridViewComponent, decorators: [{
986
+ type: Component,
987
+ args: [{ selector: 'axm-task-board-grid-view', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [AXDataTableModule, AXTranslatorPipe, AsyncPipe, AXPWidgetCoreModule], template: "<ax-data-table\n [fetchDataMode]=\"'manual'\"\n [dataSource]=\"tasksDataSource()\"\n (onRowClick)=\"handleRowClick($event)\"\n [loading]=\"{ enabled: true, animation: true }\"\n>\n <ax-text-column dataField=\"title\" caption=\"title\" [width]=\"'350px'\"></ax-text-column>\n <ax-text-column dataField=\"description\" caption=\"description\" [width]=\"'500px'\"></ax-text-column>\n <ax-text-column dataField=\"startDate\" caption=\"Start Date\" [width]=\"'150px'\"></ax-text-column>\n <ax-text-column dataField=\"endDate\" caption=\"Due Date\" [width]=\"'150px'\"></ax-text-column>\n <ax-text-column dataField=\"priority\" caption=\"priority\" [width]=\"'125px'\"></ax-text-column>\n <ax-text-column dataField=\"reporter\" caption=\"Reporter\" [width]=\"'125px'\"></ax-text-column>\n <ax-text-column dataField=\"assignee\" caption=\"Assignee\" [width]=\"'125px'\"></ax-text-column>\n <ax-text-column dataField=\"statusTitle\" caption=\"status\" [width]=\"'125px'\"></ax-text-column>\n <ax-text-column dataField=\"type\" caption=\"type\" [width]=\"'150px'\"></ax-text-column>\n\n @if (columns().length) {\n <ng-container>\n @for (column of columns(); track column) {\n <axp-widget-column-renderer\n [node]=\"column.widget\"\n [caption]=\"(column.title | translate | async)!\"\n ></axp-widget-column-renderer>\n }\n </ng-container>\n }\n\n <ax-command-column\n fixed=\"end\"\n [width]=\"'60px'\"\n (onItemClick)=\"onActionClickHandler($event)\"\n [items]=\"[{ name: 'view', text: 'View', icon: 'ax-icon ax-icon-more-horizontal' }]\"\n ></ax-command-column>\n</ax-data-table>\n", styles: ["ax-kanban{--ax-comp-kanban-status-min-width: 25rem;height:100%;line-height:1.5}\n"] }]
988
+ }], propDecorators: { dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: true }] }], onTaskClick: [{ type: i0.Output, args: ["onTaskClick"] }], onActionClick: [{ type: i0.Output, args: ["onActionClick"] }] } });
989
+
990
+ class AXMTaskBoardKanbanViewComponent {
991
+ constructor() {
992
+ this.vm = inject(AXMTaskBoardViewModel);
993
+ this.taskBoardService = inject(AXPTaskBoardService);
994
+ this.calendarService = inject(AXCalendarService);
995
+ this.settingService = inject(AXPSettingsService);
996
+ this.commandService = inject(AXPCommandService);
997
+ this.kanbanComponent = viewChild(AXKanbanComponent, ...(ngDevMode ? [{ debugName: "kanbanComponent" }] : []));
998
+ this.taskPopover = viewChild('taskPopover', ...(ngDevMode ? [{ debugName: "taskPopover" }] : []));
999
+ this.selectedTask = signal(null, ...(ngDevMode ? [{ debugName: "selectedTask" }] : []));
1000
+ this.popoverTarget = signal(null, ...(ngDevMode ? [{ debugName: "popoverTarget" }] : []));
1001
+ this.taskActions = signal([], ...(ngDevMode ? [{ debugName: "taskActions" }] : []));
1002
+ this.customComponentType = signal(null, ...(ngDevMode ? [{ debugName: "customComponentType" }] : []));
1003
+ // Separate primary and secondary actions
1004
+ this.primaryActions = computed(() => {
1005
+ return this.taskActions().filter((action) => (action.priority ?? 'secondary') === 'primary');
1006
+ }, ...(ngDevMode ? [{ debugName: "primaryActions" }] : []));
1007
+ this.secondaryActions = computed(() => {
1008
+ return this.taskActions().filter((action) => (action.priority ?? 'secondary') === 'secondary');
1009
+ }, ...(ngDevMode ? [{ debugName: "secondaryActions" }] : []));
1010
+ this.customComponentInputs = computed(() => {
1011
+ const task = this.selectedTask();
1012
+ if (!task)
1013
+ return null;
1014
+ return { task };
1015
+ }, ...(ngDevMode ? [{ debugName: "customComponentInputs" }] : []));
1016
+ this.tasks = model.required(...(ngDevMode ? [{ debugName: "tasks" }] : []));
1017
+ this.onTaskClick = output();
1018
+ this.onTaskChanged = output();
1019
+ this.component = output();
1020
+ this.onActionClick = output();
1021
+ this.statuses = signal([], ...(ngDevMode ? [{ debugName: "statuses" }] : []));
1022
+ this.stableTasks = computed(() => this.tasks(), ...(ngDevMode ? [{ debugName: "stableTasks", equal: isEqual }] : [{ equal: isEqual }]));
1023
+ this.kanbanTasks = computed(() => {
1024
+ return this.stableTasks().map((task) => ({
1025
+ id: task.id,
1026
+ title: task.title,
1027
+ index: task.index,
1028
+ cssClass: task.cssClass,
1029
+ priority: task.priority,
1030
+ statusKey: task.status.id,
1031
+ description: task.description,
1032
+ }));
1033
+ }, ...(ngDevMode ? [{ debugName: "kanbanTasks" }] : []));
1034
+ this.#providerChanged = effect(async () => {
1035
+ const taskType = this.vm.selectedTaskTypes()[0];
1036
+ if (!taskType) {
1037
+ this.statuses.set([]);
1038
+ return;
1039
+ }
1040
+ taskType.getStatuses().then((statuses) => {
1041
+ if (statuses) {
1042
+ this.statuses.set(statuses);
1043
+ }
1044
+ });
1045
+ }, ...(ngDevMode ? [{ debugName: "#providerChanged" }] : []));
1046
+ }
1047
+ ngAfterViewInit() {
1048
+ if (this.kanbanComponent()) {
1049
+ this.component.emit(this.kanbanComponent());
1050
+ }
1051
+ }
1052
+ #providerChanged;
1053
+ //#region ---- Drag & Drop Handling ----
1054
+ /**
1055
+ * Handles the onBeforeDrop event from the kanban component.
1056
+ * Uses event.wait() to register async operations that the kanban will await.
1057
+ * If action is cancelled/failed, we set event.canceled = true to prevent the drop.
1058
+ */
1059
+ onBeforeDrop(event) {
1060
+ // If no status change, allow the drop (just reordering)
1061
+ if (event.previousStatusKey === event.currentStatusKey) {
1062
+ return;
1063
+ }
1064
+ // Find the task being moved
1065
+ const task = this.stableTasks().find((t) => t.id === event.item?.id);
1066
+ if (!task || !task.provider) {
1067
+ // Allow drop if task not found or no provider
1068
+ return;
1069
+ }
1070
+ // Get the provider
1071
+ const provider = this.taskBoardService.getProvider(task.provider);
1072
+ if (!provider) {
1073
+ return;
1074
+ }
1075
+ // Register the async operation using event.wait()
1076
+ // The kanban component will await this promise before proceeding
1077
+ // Check if wait method exists (it should after kanban package is rebuilt)
1078
+ const eventWithWait = event;
1079
+ if (typeof eventWithWait.wait === 'function') {
1080
+ eventWithWait.wait(this.executeDropAction(event, task, provider));
1081
+ }
1082
+ else {
1083
+ // Fallback: This should not happen if kanban package is rebuilt
1084
+ console.error('[KanbanDrop] event.wait() not available! Kanban package needs to be rebuilt.');
1085
+ console.error('[KanbanDrop] Falling back to synchronous execution (may cause issues)');
1086
+ // Execute synchronously - this won't wait for async operations!
1087
+ this.executeDropAction(event, task, provider).catch((error) => {
1088
+ console.error('[KanbanDrop] Error in fallback execution:', error);
1089
+ event.canceled = true;
1090
+ });
1091
+ }
1092
+ }
1093
+ /**
1094
+ * Executes the action for a drop operation.
1095
+ * Sets event.canceled = true if action fails or is cancelled.
1096
+ * IMPORTANT: Do NOT update the task status in dataSource here - let the kanban handle the move.
1097
+ * The kanban will update the status in onSortChanged, and we'll sync with backend there.
1098
+ */
1099
+ async executeDropAction(event, task, provider) {
1100
+ if (!provider) {
1101
+ return;
1102
+ }
1103
+ try {
1104
+ // Get available actions for the task
1105
+ const actions = await provider.getActions(task);
1106
+ if (!actions || actions.length === 0) {
1107
+ // No actions available, allow the drop
1108
+ return;
1109
+ }
1110
+ // Find action that matches the new status
1111
+ const matchingAction = this.findActionForStatus(actions, event.currentStatusKey);
1112
+ if (!matchingAction || !matchingAction.command) {
1113
+ // No matching action found, allow the drop
1114
+ return;
1115
+ }
1116
+ // Execute the action and check result
1117
+ const result = await this.taskBoardService.executeCommand(matchingAction.command, task.provider);
1118
+ // Check if action was successful (not cancelled or failed)
1119
+ if (result?.success === false || result === null) {
1120
+ // Action was cancelled or failed - prevent the drop
1121
+ event.canceled = true;
1122
+ return;
1123
+ }
1124
+ // Action succeeded - allow the drop to proceed
1125
+ // The kanban will handle the visual move, and onSortChanged will sync with backend
1126
+ }
1127
+ catch (error) {
1128
+ console.error('[KanbanDrop] Failed to execute action during drop:', error);
1129
+ // On error, prevent the drop to be safe
1130
+ event.canceled = true;
1131
+ }
1132
+ }
1133
+ /**
1134
+ * Finds an action that corresponds to the target status.
1135
+ * Matches actions by name patterns (e.g., "approve" action for "approved" status).
1136
+ */
1137
+ findActionForStatus(actions, targetStatus) {
1138
+ const targetStatusStr = String(targetStatus).toLowerCase();
1139
+ // Common status-to-action mappings
1140
+ const statusActionMap = {
1141
+ approved: ['approve'],
1142
+ rejected: ['reject'],
1143
+ cancelled: ['cancel'],
1144
+ completed: ['complete', 'finish'],
1145
+ done: ['complete', 'finish'],
1146
+ inprogress: ['start', 'begin'],
1147
+ 'in-progress': ['start', 'begin'],
1148
+ blocked: ['block'],
1149
+ unblocked: ['unblock'],
1150
+ };
1151
+ // Check direct mappings first
1152
+ const possibleActionNames = statusActionMap[targetStatusStr] || [];
1153
+ for (const actionName of possibleActionNames) {
1154
+ const action = actions.find((a) => a.name?.toLowerCase().includes(actionName));
1155
+ if (action) {
1156
+ return action;
1157
+ }
1158
+ }
1159
+ // Try to find action by name containing status keywords
1160
+ const statusKeywords = targetStatusStr.split(/[-_\s]+/);
1161
+ for (const keyword of statusKeywords) {
1162
+ if (keyword.length < 3)
1163
+ continue; // Skip very short keywords
1164
+ const action = actions.find((a) => {
1165
+ const actionName = a.name?.toLowerCase() || '';
1166
+ return actionName.includes(keyword) || keyword.includes(actionName);
1167
+ });
1168
+ if (action) {
1169
+ return action;
1170
+ }
1171
+ }
1172
+ // Try exact match with action name
1173
+ const exactMatch = actions.find((a) => a.name?.toLowerCase() === targetStatusStr);
1174
+ if (exactMatch) {
1175
+ return exactMatch;
1176
+ }
1177
+ // Try partial match (status contains action name or vice versa)
1178
+ for (const action of actions) {
1179
+ const actionName = action.name?.toLowerCase() || '';
1180
+ if (targetStatusStr.includes(actionName) || actionName.includes(targetStatusStr)) {
1181
+ return action;
1182
+ }
1183
+ }
1184
+ return null;
1185
+ }
1186
+ //#endregion
1187
+ onSortChanged(event) {
1188
+ const tasks = this.tasks().map((item) => {
1189
+ const task = event.allItems.find((t) => t.id === item.id);
1190
+ if (task) {
1191
+ const status = this.statuses().find((s) => s.key === task.statusKey);
1192
+ return { ...item, index: task.index, status: { id: status.key, title: status.title } };
1193
+ }
1194
+ return item;
1195
+ });
1196
+ this.taskBoardService
1197
+ .updateTasks(tasks)
1198
+ .then((updatedTasks) => {
1199
+ this.tasks.set(updatedTasks);
1200
+ })
1201
+ .catch((error) => {
1202
+ console.error('[KanbanSort] Failed to update tasks:', error);
1203
+ });
1204
+ }
1205
+ async handleItemClick(event) {
1206
+ const task = this.stableTasks().find((task) => task.id === event.item.id);
1207
+ if (!task)
1208
+ return;
1209
+ // Find the kanban item container element
1210
+ let targetElement = event.nativeEvent.currentTarget || event.nativeEvent.target;
1211
+ // Traverse up to find the kanban item container
1212
+ let element = targetElement;
1213
+ const maxDepth = 10;
1214
+ let depth = 0;
1215
+ while (element && element !== document.body && depth < maxDepth) {
1216
+ depth++;
1217
+ const isKanbanItem = element.classList?.contains('dx-kanban-item') ||
1218
+ element.classList?.contains('ax-kanban-item') ||
1219
+ element.hasAttribute('data-item-id');
1220
+ if (isKanbanItem) {
1221
+ targetElement = element;
1222
+ break;
1223
+ }
1224
+ element = element.parentElement;
1225
+ }
1226
+ // Set the selected task and target element
1227
+ this.selectedTask.set(task);
1228
+ this.popoverTarget.set(targetElement);
1229
+ // Check if provider has a custom component
1230
+ await this.loadCustomComponent(task);
1231
+ // Load actions for the task
1232
+ await this.loadTaskActions(task);
1233
+ // Open the popover
1234
+ setTimeout(() => {
1235
+ if (this.taskPopover() && targetElement) {
1236
+ this.taskPopover().target = targetElement;
1237
+ this.taskPopover().open();
1238
+ }
1239
+ }, 0);
1240
+ // Still emit the event for backward compatibility
1241
+ this.onTaskClick.emit(task);
1242
+ }
1243
+ handleActionClick(event) {
1244
+ const task = this.stableTasks().find((task) => task.id === event.item.id);
1245
+ if (task) {
1246
+ this.onActionClick.emit({ nativeEvent: event.nativeEvent, task: task });
1247
+ }
1248
+ }
1249
+ async loadTaskActions(task) {
1250
+ try {
1251
+ const providerName = task.provider;
1252
+ if (!providerName) {
1253
+ this.taskActions.set([]);
1254
+ return;
1255
+ }
1256
+ const provider = this.taskBoardService.getProvider(providerName);
1257
+ if (!provider) {
1258
+ this.taskActions.set([]);
1259
+ return;
1260
+ }
1261
+ const actions = await provider.getActions(task);
1262
+ // Ensure all actions have a priority (default to 'secondary' if not specified)
1263
+ const actionsWithPriority = (actions || []).map((action) => ({
1264
+ ...action,
1265
+ priority: action.priority ?? 'secondary',
1266
+ }));
1267
+ this.taskActions.set(actionsWithPriority);
1268
+ }
1269
+ catch (error) {
1270
+ console.error('Failed to load task actions:', error);
1271
+ this.taskActions.set([]);
1272
+ }
1273
+ }
1274
+ getActionColor(action) {
1275
+ return action.color;
1276
+ }
1277
+ //#region ---- Action Execution ----
1278
+ /**
1279
+ * Executes an action when user clicks on an action button in the popover.
1280
+ * If action succeeds, moves the item to the appropriate status using kanban.moveItem().
1281
+ */
1282
+ async executeAction(action) {
1283
+ const task = this.selectedTask();
1284
+ if (!task || !action.command)
1285
+ return;
1286
+ // Store task info before closing popover
1287
+ const taskId = task.id;
1288
+ const providerName = task.provider;
1289
+ const currentStatusKey = task.status.id;
1290
+ if (!providerName)
1291
+ return;
1292
+ try {
1293
+ const result = await this.taskBoardService.executeCommand(action.command, providerName);
1294
+ // Check if action was successful
1295
+ if (result?.success === false || result === null) {
1296
+ // Action was cancelled or failed - don't close popover, don't move item
1297
+ return;
1298
+ }
1299
+ // Action succeeded - close popover first
1300
+ this.closePopover();
1301
+ // Refresh tasks to get updated status and move item if status changed
1302
+ await this.refreshAndMoveItem(taskId, providerName, currentStatusKey);
1303
+ }
1304
+ catch (error) {
1305
+ console.error('Failed to execute action:', error);
1306
+ }
1307
+ }
1308
+ /**
1309
+ * Refreshes tasks from the provider and moves the item if status changed.
1310
+ */
1311
+ async refreshAndMoveItem(taskId, providerName, previousStatusKey) {
1312
+ try {
1313
+ const provider = this.taskBoardService.getProvider(providerName);
1314
+ if (!provider) {
1315
+ return;
1316
+ }
1317
+ // Get updated tasks from provider
1318
+ const result = await provider.getTasks();
1319
+ const updatedTasks = result.items.map((t) => ({ ...t, provider: providerName }));
1320
+ // Find the updated task to get its new status
1321
+ const updatedTask = updatedTasks.find((t) => t.id === taskId);
1322
+ if (!updatedTask) {
1323
+ return;
1324
+ }
1325
+ const newStatusKey = updatedTask.status.id;
1326
+ // Check if status actually changed
1327
+ if (newStatusKey !== previousStatusKey) {
1328
+ // Move the item programmatically to the new status using kanban API
1329
+ const kanban = this.kanbanComponent();
1330
+ if (kanban) {
1331
+ await kanban.moveItem(taskId, newStatusKey);
1332
+ }
1333
+ }
1334
+ // Update the tasks signal with merged data
1335
+ const currentTasks = this.tasks();
1336
+ const updatedTasksMap = new Map(updatedTasks.map((t) => [t.id, t]));
1337
+ const mergedTasks = currentTasks.map((t) => {
1338
+ const updated = updatedTasksMap.get(t.id);
1339
+ return updated ? { ...updated } : t;
1340
+ });
1341
+ // Add any new tasks
1342
+ const existingIds = new Set(currentTasks.map((t) => t.id));
1343
+ const newTasks = updatedTasks.filter((t) => !existingIds.has(t.id)).map((t) => ({ ...t }));
1344
+ mergedTasks.push(...newTasks);
1345
+ this.tasks.set([...mergedTasks]);
1346
+ }
1347
+ catch (error) {
1348
+ console.error('Failed to refresh tasks:', error);
1349
+ }
1350
+ }
1351
+ //#endregion
1352
+ async loadCustomComponent(task) {
1353
+ if (!task.provider) {
1354
+ this.customComponentType.set(null);
1355
+ return;
1356
+ }
1357
+ const provider = this.taskBoardService.getProvider(task.provider);
1358
+ if (!provider) {
1359
+ this.customComponentType.set(null);
1360
+ return;
1361
+ }
1362
+ const componentGetter = provider.getComponent?.();
1363
+ if (!componentGetter) {
1364
+ this.customComponentType.set(null);
1365
+ return;
1366
+ }
1367
+ try {
1368
+ let componentType;
1369
+ // Check if it's a lazy loading function or direct component type
1370
+ if (typeof componentGetter === 'function') {
1371
+ const testCall = componentGetter;
1372
+ let result;
1373
+ try {
1374
+ result = testCall();
1375
+ }
1376
+ catch (e) {
1377
+ componentType = componentGetter;
1378
+ this.customComponentType.set(componentType);
1379
+ return;
1380
+ }
1381
+ if (result instanceof Promise) {
1382
+ componentType = await result;
1383
+ }
1384
+ else if (result) {
1385
+ componentType = result;
1386
+ }
1387
+ else {
1388
+ componentType = componentGetter;
1389
+ }
1390
+ }
1391
+ else {
1392
+ this.customComponentType.set(null);
1393
+ return;
1394
+ }
1395
+ this.customComponentType.set(componentType);
1396
+ }
1397
+ catch (error) {
1398
+ console.error('[TaskPopover] Failed to load custom task popover component:', error);
1399
+ this.customComponentType.set(null);
1400
+ }
1401
+ }
1402
+ closePopover() {
1403
+ this.taskPopover()?.close();
1404
+ this.customComponentType.set(null);
1405
+ this.selectedTask.set(null);
1406
+ this.popoverTarget.set(null);
1407
+ this.taskActions.set([]);
1408
+ }
1409
+ formatTime(date) {
1410
+ return this.calendarService.create(date).format('HH:mm');
1411
+ }
1412
+ formatDate(date) {
1413
+ return this.calendarService.create(date).format('MMM DD, YYYY');
1414
+ }
1415
+ formatDateTime(date) {
1416
+ return this.calendarService.create(date).format('MMM DD, YYYY HH:mm');
1417
+ }
1418
+ isMultiDay(task) {
1419
+ if (task.allDay) {
1420
+ const start = this.calendarService.create(task.startDate);
1421
+ const end = this.calendarService.create(task.endDate);
1422
+ return start.date.getTime() !== end.date.getTime();
1423
+ }
1424
+ const start = this.calendarService.create(task.startDate);
1425
+ const end = this.calendarService.create(task.endDate);
1426
+ const startDay = start.date.getDate();
1427
+ const endDay = end.date.getDate();
1428
+ const startMonth = start.date.getMonth();
1429
+ const endMonth = end.date.getMonth();
1430
+ const startYear = start.date.getFullYear();
1431
+ const endYear = end.date.getFullYear();
1432
+ return startDay !== endDay || startMonth !== endMonth || startYear !== endYear;
1433
+ }
1434
+ formatDateRange(task) {
1435
+ if (task.allDay) {
1436
+ const start = this.calendarService.create(task.startDate);
1437
+ const end = this.calendarService.create(task.endDate);
1438
+ if (start.date.getTime() === end.date.getTime()) {
1439
+ return this.formatDate(task.startDate);
1440
+ }
1441
+ const startFormatted = this.formatDate(task.startDate);
1442
+ const endFormatted = this.formatDate(task.endDate);
1443
+ if (start.date.getMonth() === end.date.getMonth() && start.date.getFullYear() === end.date.getFullYear()) {
1444
+ const startDay = start.date.getDate();
1445
+ const endDay = end.date.getDate();
1446
+ const monthYear = start.format('MMM YYYY');
1447
+ return `${startDay} - ${endDay}, ${monthYear}`;
1448
+ }
1449
+ return `${startFormatted} - ${endFormatted}`;
1450
+ }
1451
+ if (this.isMultiDay(task)) {
1452
+ const startFormatted = this.formatDateTime(task.startDate);
1453
+ const endFormatted = this.formatDateTime(task.endDate);
1454
+ return `${startFormatted} - ${endFormatted}`;
1455
+ }
1456
+ const dateFormatted = this.formatDate(task.startDate);
1457
+ const timeRange = `${this.formatTime(task.startDate)} - ${this.formatTime(task.endDate)}`;
1458
+ return `${dateFormatted} ${timeRange}`;
1459
+ }
1460
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMTaskBoardKanbanViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1461
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXMTaskBoardKanbanViewComponent, isStandalone: true, selector: "axm-task-board-kanban-view", inputs: { tasks: { classPropertyName: "tasks", publicName: "tasks", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { tasks: "tasksChange", onTaskClick: "onTaskClick", onTaskChanged: "onTaskChanged", component: "component", onActionClick: "onActionClick" }, viewQueries: [{ propertyName: "kanbanComponent", first: true, predicate: AXKanbanComponent, descendants: true, isSignal: true }, { propertyName: "taskPopover", first: true, predicate: ["taskPopover"], descendants: true, isSignal: true }], ngImport: i0, template: "<ax-kanban\n [statuses]=\"statuses()\"\n [dataSource]=\"kanbanTasks()\"\n (onItemClick)=\"handleItemClick($event)\"\n (onBeforeDrop)=\"onBeforeDrop($event)\"\n (onSortChanged)=\"onSortChanged($event)\"\n></ax-kanban>\n\n<!-- Task Detail Popover (Modern Google Calendar Style) -->\n<ax-popover\n #taskPopover\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [offsetY]=\"12\"\n [offsetX]=\"12\"\n [adaptivityEnabled]=\"true\"\n>\n @if (selectedTask()) {\n <div class=\"task-popover ax-shadow-md ax-border\">\n <!-- Header Section -->\n <div class=\"task-popover__header\">\n <div class=\"task-popover__title-section\">\n <div class=\"task-popover__title-row\">\n <h3 class=\"task-popover__title\" [title]=\"selectedTask()!.title\">{{ selectedTask()!.title }}</h3>\n <button type=\"button\" class=\"task-popover__close-btn\" (click)=\"closePopover()\" aria-label=\"Close\">\n <ax-icon class=\"ax-icon ax-icon-close\"></ax-icon>\n </button>\n </div>\n @if (selectedTask()!.description && !customComponentType()) {\n <p class=\"task-popover__description\">{{ selectedTask()!.description }}</p>\n }\n </div>\n </div>\n\n <!-- Custom Component or Default Content -->\n @if (customComponentType()) {\n <!-- Custom Component from Provider -->\n <div class=\"task-popover__custom-content\">\n <ng-container *ngComponentOutlet=\"customComponentType()!; inputs: customComponentInputs()!\"></ng-container>\n </div>\n } @else {\n <!-- Default Content Section -->\n <div class=\"task-popover__content\">\n <!-- Time -->\n <div class=\"task-popover__info-item\">\n <div class=\"task-popover__icon\">\n <i class=\"fa-light fa-clock\"></i>\n </div>\n <div class=\"task-popover__info-content\">\n <span class=\"task-popover__info-text\">{{ formatDateRange(selectedTask()!) }}</span>\n </div>\n </div>\n\n <!-- Status -->\n @if (selectedTask()!.status) {\n <div class=\"task-popover__info-item\">\n <div class=\"task-popover__icon\">\n <i class=\"fa-light fa-flag\"></i>\n </div>\n <div class=\"task-popover__info-content\">\n <span class=\"task-popover__info-text\">{{ selectedTask()!.status.title }}</span>\n </div>\n </div>\n }\n\n <!-- Assignee -->\n @if (selectedTask()!.assignee) {\n <div class=\"task-popover__info-item\">\n <div class=\"task-popover__icon\">\n <i class=\"fa-light fa-user\"></i>\n </div>\n <div class=\"task-popover__info-content\">\n <span class=\"task-popover__info-text\">{{\n selectedTask()!.assignee?.fullName || selectedTask()!.assignee?.username || 'Unassigned'\n }}</span>\n </div>\n </div>\n }\n\n <!-- Priority -->\n @if (selectedTask()!.priority) {\n <div class=\"task-popover__info-item\">\n <div\n class=\"task-popover__icon task-popover__icon--priority\"\n [attr.data-priority]=\"selectedTask()!.priority\"\n >\n <i class=\"fa-light fa-exclamation-circle\"></i>\n </div>\n <div class=\"task-popover__info-content\">\n <span\n class=\"task-popover__info-text task-popover__priority\"\n [attr.data-priority]=\"selectedTask()!.priority\"\n >\n {{ selectedTask()!.priority }}\n </span>\n </div>\n </div>\n }\n </div>\n\n <!-- Actions Section -->\n <div class=\"task-popover__actions\">\n <!-- Task Actions from Provider -->\n @if (taskActions().length > 0) {\n <div class=\"task-popover__actions-group\">\n <!-- Primary Actions: Icon-only buttons -->\n @if (primaryActions().length > 0) {\n @for (action of primaryActions(); track action.name || action.title) {\n <ax-button\n [look]=\"'solid'\"\n [color]=\"getActionColor(action)\"\n (onClick)=\"executeAction(action)\"\n [disabled]=\"action.disabled === true\"\n [text]=\"action.title\"\n >\n @if (action.icon) {\n <ax-prefix>\n <ax-icon>\n <i [class]=\"action.icon\"></i>\n </ax-icon>\n </ax-prefix>\n }\n </ax-button>\n }\n }\n\n <!-- Secondary Actions: Dropdown with \"...\" button -->\n @if (secondaryActions().length > 0) {\n <ax-button [look]=\"'blank'\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-ellipsis-vertical\"></ax-icon>\n </ax-prefix>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (action of secondaryActions(); track action.name || action.title) {\n <ax-button-item\n [text]=\"action.title\"\n [disabled]=\"action.disabled === true\"\n (onClick)=\"executeAction(action)\"\n >\n @if (action.icon) {\n <ax-prefix>\n <ax-icon>\n <i [class]=\"action.icon\"></i>\n </ax-icon>\n </ax-prefix>\n }\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n</ax-popover>\n", styles: ["ax-kanban{--ax-comp-kanban-status-min-height: 100%;--ax-comp-kanban-status-min-width: 25rem;height:100%;line-height:1.5;background-color:rgba(var(--ax-sys-color-lightest-surface))!important}.task-popover{background:rgba(var(--ax-sys-color-lightest-surface));border-radius:12px;overflow:hidden;display:flex;flex-direction:column}.task-popover__header{padding:20px 20px 16px;border-bottom:1px solid var(--ax-sys-color-border);background:linear-gradient(to bottom,var(--ax-sys-color-lightest-surface),var(--ax-sys-color-lighter-surface))}.task-popover__title-section{display:flex;flex-direction:column;gap:8px}.task-popover__title-row{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.task-popover__title{font-size:18px;font-weight:600;line-height:1.4;color:var(--ax-sys-color-text-primary);margin:0;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.task-popover__close-btn{flex-shrink:0;background:none;border:none;padding:4px;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--ax-sys-color-text-neutral-600);transition:color .2s ease;border-radius:4px}.task-popover__close-btn:hover{color:var(--ax-sys-color-text-primary);background:var(--ax-sys-color-lighter-surface)}.task-popover__close-btn:active{background:var(--ax-sys-color-light-surface)}.task-popover__close-btn ax-icon{display:block;width:16px;height:16px}.task-popover__description{font-size:14px;line-height:1.5;color:var(--ax-sys-color-text-secondary);margin:0;display:-webkit-box;-webkit-line-clamp:3;line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis}.task-popover__content{padding:16px 20px;display:flex;flex-direction:column;gap:12px;flex:1}.task-popover__info-item{display:flex;align-items:flex-start;gap:12px;min-height:24px}.task-popover__icon{width:20px;height:20px;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:2px;color:var(--ax-sys-color-text-neutral-600);font-size:14px}.task-popover__icon i{display:block}.task-popover__icon--priority[data-priority=highest]{color:var(--ax-sys-color-danger)}.task-popover__icon--priority[data-priority=high]{color:var(--ax-sys-color-warning)}.task-popover__icon--priority[data-priority=medium]{color:var(--ax-sys-color-info)}.task-popover__icon--priority[data-priority=low],.task-popover__icon--priority[data-priority=lowest]{color:var(--ax-sys-color-text-neutral-500)}.task-popover__info-content{flex:1;min-width:0;display:flex;align-items:center}.task-popover__info-text{font-size:14px;line-height:1.5;color:var(--ax-sys-color-text-primary);word-wrap:break-word}.task-popover__time{font-weight:500;color:var(--ax-sys-color-text-primary);margin-left:4px}.task-popover__priority{text-transform:capitalize;font-weight:500}.task-popover__priority[data-priority=highest]{color:var(--ax-sys-color-danger)}.task-popover__priority[data-priority=high]{color:var(--ax-sys-color-warning)}.task-popover__priority[data-priority=medium]{color:var(--ax-sys-color-info)}.task-popover__priority[data-priority=low],.task-popover__priority[data-priority=lowest]{color:var(--ax-sys-color-text-neutral-600)}.task-popover__actions{padding:12px 20px 16px;border-top:1px solid var(--ax-sys-color-border);display:flex;flex-direction:column;gap:8px;background:var(--ax-sys-color-lighter-surface)}.task-popover__actions-group{display:flex;justify-content:flex-end;gap:8px;flex-wrap:wrap}.task-popover__actions-group--default{margin-top:4px;padding-top:8px;border-top:1px solid var(--ax-sys-color-border)}.task-popover__action-divider{width:100%;height:1px;background:var(--ax-sys-color-border);margin:4px 0}.task-popover__action-btn{min-width:100px;white-space:nowrap}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: AXKanbanComponent, selector: "ax-kanban", inputs: ["hasActions", "dragStartDelay", "statuses", "itemTemplate", "dataSource", "keyField", "indexField", "titleField", "cssClassField", "priorityField", "statusKeyField", "descriptionField", "emptyTemplate", "headerTemplate", "footerTemplate", "contentFooterTemplate", "tooltipTemplate"], outputs: ["onBeforeDrop", "onSortChanged", "onItemClick", "onActionClick", "onItemDblClick", "onItemRightClick"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i3.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i3.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i4.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i5.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i5.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXTranslationModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1462
+ }
1463
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMTaskBoardKanbanViewComponent, decorators: [{
1464
+ type: Component,
1465
+ args: [{ selector: 'axm-task-board-kanban-view', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
1466
+ CommonModule,
1467
+ AXKanbanComponent,
1468
+ AXPopoverModule,
1469
+ AXButtonModule,
1470
+ AXDropdownModule,
1471
+ AXDecoratorModule,
1472
+ AXTranslationModule,
1473
+ ], template: "<ax-kanban\n [statuses]=\"statuses()\"\n [dataSource]=\"kanbanTasks()\"\n (onItemClick)=\"handleItemClick($event)\"\n (onBeforeDrop)=\"onBeforeDrop($event)\"\n (onSortChanged)=\"onSortChanged($event)\"\n></ax-kanban>\n\n<!-- Task Detail Popover (Modern Google Calendar Style) -->\n<ax-popover\n #taskPopover\n [openOn]=\"'manual'\"\n [closeOn]=\"'clickOut'\"\n [offsetY]=\"12\"\n [offsetX]=\"12\"\n [adaptivityEnabled]=\"true\"\n>\n @if (selectedTask()) {\n <div class=\"task-popover ax-shadow-md ax-border\">\n <!-- Header Section -->\n <div class=\"task-popover__header\">\n <div class=\"task-popover__title-section\">\n <div class=\"task-popover__title-row\">\n <h3 class=\"task-popover__title\" [title]=\"selectedTask()!.title\">{{ selectedTask()!.title }}</h3>\n <button type=\"button\" class=\"task-popover__close-btn\" (click)=\"closePopover()\" aria-label=\"Close\">\n <ax-icon class=\"ax-icon ax-icon-close\"></ax-icon>\n </button>\n </div>\n @if (selectedTask()!.description && !customComponentType()) {\n <p class=\"task-popover__description\">{{ selectedTask()!.description }}</p>\n }\n </div>\n </div>\n\n <!-- Custom Component or Default Content -->\n @if (customComponentType()) {\n <!-- Custom Component from Provider -->\n <div class=\"task-popover__custom-content\">\n <ng-container *ngComponentOutlet=\"customComponentType()!; inputs: customComponentInputs()!\"></ng-container>\n </div>\n } @else {\n <!-- Default Content Section -->\n <div class=\"task-popover__content\">\n <!-- Time -->\n <div class=\"task-popover__info-item\">\n <div class=\"task-popover__icon\">\n <i class=\"fa-light fa-clock\"></i>\n </div>\n <div class=\"task-popover__info-content\">\n <span class=\"task-popover__info-text\">{{ formatDateRange(selectedTask()!) }}</span>\n </div>\n </div>\n\n <!-- Status -->\n @if (selectedTask()!.status) {\n <div class=\"task-popover__info-item\">\n <div class=\"task-popover__icon\">\n <i class=\"fa-light fa-flag\"></i>\n </div>\n <div class=\"task-popover__info-content\">\n <span class=\"task-popover__info-text\">{{ selectedTask()!.status.title }}</span>\n </div>\n </div>\n }\n\n <!-- Assignee -->\n @if (selectedTask()!.assignee) {\n <div class=\"task-popover__info-item\">\n <div class=\"task-popover__icon\">\n <i class=\"fa-light fa-user\"></i>\n </div>\n <div class=\"task-popover__info-content\">\n <span class=\"task-popover__info-text\">{{\n selectedTask()!.assignee?.fullName || selectedTask()!.assignee?.username || 'Unassigned'\n }}</span>\n </div>\n </div>\n }\n\n <!-- Priority -->\n @if (selectedTask()!.priority) {\n <div class=\"task-popover__info-item\">\n <div\n class=\"task-popover__icon task-popover__icon--priority\"\n [attr.data-priority]=\"selectedTask()!.priority\"\n >\n <i class=\"fa-light fa-exclamation-circle\"></i>\n </div>\n <div class=\"task-popover__info-content\">\n <span\n class=\"task-popover__info-text task-popover__priority\"\n [attr.data-priority]=\"selectedTask()!.priority\"\n >\n {{ selectedTask()!.priority }}\n </span>\n </div>\n </div>\n }\n </div>\n\n <!-- Actions Section -->\n <div class=\"task-popover__actions\">\n <!-- Task Actions from Provider -->\n @if (taskActions().length > 0) {\n <div class=\"task-popover__actions-group\">\n <!-- Primary Actions: Icon-only buttons -->\n @if (primaryActions().length > 0) {\n @for (action of primaryActions(); track action.name || action.title) {\n <ax-button\n [look]=\"'solid'\"\n [color]=\"getActionColor(action)\"\n (onClick)=\"executeAction(action)\"\n [disabled]=\"action.disabled === true\"\n [text]=\"action.title\"\n >\n @if (action.icon) {\n <ax-prefix>\n <ax-icon>\n <i [class]=\"action.icon\"></i>\n </ax-icon>\n </ax-prefix>\n }\n </ax-button>\n }\n }\n\n <!-- Secondary Actions: Dropdown with \"...\" button -->\n @if (secondaryActions().length > 0) {\n <ax-button [look]=\"'blank'\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-ellipsis-vertical\"></ax-icon>\n </ax-prefix>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (action of secondaryActions(); track action.name || action.title) {\n <ax-button-item\n [text]=\"action.title\"\n [disabled]=\"action.disabled === true\"\n (onClick)=\"executeAction(action)\"\n >\n @if (action.icon) {\n <ax-prefix>\n <ax-icon>\n <i [class]=\"action.icon\"></i>\n </ax-icon>\n </ax-prefix>\n }\n </ax-button-item>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n</ax-popover>\n", styles: ["ax-kanban{--ax-comp-kanban-status-min-height: 100%;--ax-comp-kanban-status-min-width: 25rem;height:100%;line-height:1.5;background-color:rgba(var(--ax-sys-color-lightest-surface))!important}.task-popover{background:rgba(var(--ax-sys-color-lightest-surface));border-radius:12px;overflow:hidden;display:flex;flex-direction:column}.task-popover__header{padding:20px 20px 16px;border-bottom:1px solid var(--ax-sys-color-border);background:linear-gradient(to bottom,var(--ax-sys-color-lightest-surface),var(--ax-sys-color-lighter-surface))}.task-popover__title-section{display:flex;flex-direction:column;gap:8px}.task-popover__title-row{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.task-popover__title{font-size:18px;font-weight:600;line-height:1.4;color:var(--ax-sys-color-text-primary);margin:0;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.task-popover__close-btn{flex-shrink:0;background:none;border:none;padding:4px;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--ax-sys-color-text-neutral-600);transition:color .2s ease;border-radius:4px}.task-popover__close-btn:hover{color:var(--ax-sys-color-text-primary);background:var(--ax-sys-color-lighter-surface)}.task-popover__close-btn:active{background:var(--ax-sys-color-light-surface)}.task-popover__close-btn ax-icon{display:block;width:16px;height:16px}.task-popover__description{font-size:14px;line-height:1.5;color:var(--ax-sys-color-text-secondary);margin:0;display:-webkit-box;-webkit-line-clamp:3;line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis}.task-popover__content{padding:16px 20px;display:flex;flex-direction:column;gap:12px;flex:1}.task-popover__info-item{display:flex;align-items:flex-start;gap:12px;min-height:24px}.task-popover__icon{width:20px;height:20px;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:2px;color:var(--ax-sys-color-text-neutral-600);font-size:14px}.task-popover__icon i{display:block}.task-popover__icon--priority[data-priority=highest]{color:var(--ax-sys-color-danger)}.task-popover__icon--priority[data-priority=high]{color:var(--ax-sys-color-warning)}.task-popover__icon--priority[data-priority=medium]{color:var(--ax-sys-color-info)}.task-popover__icon--priority[data-priority=low],.task-popover__icon--priority[data-priority=lowest]{color:var(--ax-sys-color-text-neutral-500)}.task-popover__info-content{flex:1;min-width:0;display:flex;align-items:center}.task-popover__info-text{font-size:14px;line-height:1.5;color:var(--ax-sys-color-text-primary);word-wrap:break-word}.task-popover__time{font-weight:500;color:var(--ax-sys-color-text-primary);margin-left:4px}.task-popover__priority{text-transform:capitalize;font-weight:500}.task-popover__priority[data-priority=highest]{color:var(--ax-sys-color-danger)}.task-popover__priority[data-priority=high]{color:var(--ax-sys-color-warning)}.task-popover__priority[data-priority=medium]{color:var(--ax-sys-color-info)}.task-popover__priority[data-priority=low],.task-popover__priority[data-priority=lowest]{color:var(--ax-sys-color-text-neutral-600)}.task-popover__actions{padding:12px 20px 16px;border-top:1px solid var(--ax-sys-color-border);display:flex;flex-direction:column;gap:8px;background:var(--ax-sys-color-lighter-surface)}.task-popover__actions-group{display:flex;justify-content:flex-end;gap:8px;flex-wrap:wrap}.task-popover__actions-group--default{margin-top:4px;padding-top:8px;border-top:1px solid var(--ax-sys-color-border)}.task-popover__action-divider{width:100%;height:1px;background:var(--ax-sys-color-border);margin:4px 0}.task-popover__action-btn{min-width:100px;white-space:nowrap}\n"] }]
1474
+ }], propDecorators: { kanbanComponent: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXKanbanComponent), { isSignal: true }] }], taskPopover: [{ type: i0.ViewChild, args: ['taskPopover', { isSignal: true }] }], tasks: [{ type: i0.Input, args: [{ isSignal: true, alias: "tasks", required: true }] }, { type: i0.Output, args: ["tasksChange"] }], onTaskClick: [{ type: i0.Output, args: ["onTaskClick"] }], onTaskChanged: [{ type: i0.Output, args: ["onTaskChanged"] }], component: [{ type: i0.Output, args: ["component"] }], onActionClick: [{ type: i0.Output, args: ["onActionClick"] }] } });
1475
+
1476
+ class AXMTaskBoardStatusGroupedGridViewComponent {
1477
+ constructor() {
1478
+ this.vm = inject(AXMTaskBoardViewModel);
1479
+ this.localeService = inject(AXLocaleService);
1480
+ this.calendarService = inject(AXCalendarService);
1481
+ this.provider = input(...(ngDevMode ? [undefined, { debugName: "provider" }] : []));
1482
+ this.dataSource = input.required(...(ngDevMode ? [{ debugName: "dataSource" }] : []));
1483
+ this.onActionClick = output();
1484
+ this.groupedTasks = signal([], ...(ngDevMode ? [{ debugName: "groupedTasks" }] : []));
1485
+ this.allFetchedTasks = signal([], ...(ngDevMode ? [{ debugName: "allFetchedTasks" }] : []));
1486
+ this.columns = signal([], ...(ngDevMode ? [{ debugName: "columns" }] : []));
1487
+ this.statuses = signal([], ...(ngDevMode ? [{ debugName: "statuses" }] : []));
1488
+ this.#dataChanged = effect(async () => {
1489
+ const parentDataSource = this.dataSource();
1490
+ const allStatuses = this.statuses();
1491
+ if (!parentDataSource || allStatuses.length === 0) {
1492
+ this.groupedTasks.set([]);
1493
+ this.allFetchedTasks.set([]);
1494
+ return;
1495
+ }
1496
+ const result = await parentDataSource();
1497
+ this.allFetchedTasks.set(result.items);
1498
+ const allTasks = result.items;
1499
+ const statusGroups = allStatuses.map((status) => {
1500
+ const tasksForStatus = allTasks.filter((task) => task.status.id === status.key);
1501
+ return {
1502
+ statusInfo: status,
1503
+ tasks: this.createTaskDataSourceForGroup(tasksForStatus),
1504
+ };
1505
+ });
1506
+ this.groupedTasks.set(statusGroups);
1507
+ untracked(() => {
1508
+ setTimeout(() => {
1509
+ this.groupedTasks()?.forEach((group) => {
1510
+ group.tasks.refresh();
1511
+ });
1512
+ });
1513
+ });
1514
+ }, ...(ngDevMode ? [{ debugName: "#dataChanged" }] : []));
1515
+ this.#providerChanged = effect(async () => {
1516
+ const provider = this.vm.selectedTaskTypes()[0];
1517
+ provider?.getExtraFields().then((extraFields) => {
1518
+ if (extraFields) {
1519
+ this.columns.set(extraFields);
1520
+ }
1521
+ });
1522
+ provider?.getStatuses().then((statuses) => {
1523
+ if (statuses) {
1524
+ this.statuses.set(statuses);
1525
+ }
1526
+ });
1527
+ }, ...(ngDevMode ? [{ debugName: "#providerChanged" }] : []));
1528
+ }
1529
+ #dataChanged;
1530
+ #providerChanged;
1531
+ createTaskDataSourceForGroup(tasks) {
1532
+ return new AXDataSource({
1533
+ load: async (e) => {
1534
+ const items = tasks.map((task) => ({
1535
+ id: task.id,
1536
+ data: task.data,
1537
+ title: task.title,
1538
+ priority: task.priority,
1539
+ description: task.description,
1540
+ reporter: task.reporter.fullName ?? '-',
1541
+ assignee: task.assignee?.fullName ?? 'unassigned',
1542
+ endDate: this.calendarService.format(task.endDate, 'DD/MM/YYYY HH:mm', {
1543
+ locale: this.localeService.activeProfile().calendar.system,
1544
+ }),
1545
+ startDate: this.calendarService.format(task.startDate, 'DD/MM/YYYY HH:mm', {
1546
+ locale: this.localeService.activeProfile().calendar.system,
1547
+ }),
1548
+ }));
1549
+ return {
1550
+ items: items.slice(e.skip, e.skip + e.take),
1551
+ total: items.length,
1552
+ };
1553
+ },
1554
+ pageSize: 5,
1555
+ key: 'id',
1556
+ byKey: async (key) => {
1557
+ return tasks.find((task) => task.id === key);
1558
+ },
1559
+ });
1560
+ }
1561
+ onActionClickHandler(e) {
1562
+ const task = this.allFetchedTasks().find((task) => task.id === e.data.id);
1563
+ if (!task)
1564
+ return;
1565
+ this.onActionClick.emit({ nativeEvent: e.nativeEvent, task });
1566
+ }
1567
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMTaskBoardStatusGroupedGridViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1568
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXMTaskBoardStatusGroupedGridViewComponent, isStandalone: true, selector: "axm-task-board-status-grouped-grid-view", inputs: { provider: { classPropertyName: "provider", publicName: "provider", isSignal: true, isRequired: false, transformFunction: null }, dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { onActionClick: "onActionClick" }, ngImport: i0, template: "@for (group of groupedTasks(); track group) {\n <h1 class=\"ax-text-xl ax-font-bold\">{{ group.statusInfo.title }}</h1>\n <ax-data-table\n class=\"ax-h-[300px]\"\n [fetchDataMode]=\"'manual'\"\n [dataSource]=\"group.tasks\"\n [loading]=\"{ enabled: true, animation: true }\"\n >\n <ax-text-column dataField=\"title\" caption=\"title\" [width]=\"'350px'\"></ax-text-column>\n <ax-text-column dataField=\"description\" caption=\"description\" [width]=\"'500px'\"></ax-text-column>\n <ax-text-column dataField=\"startDate\" caption=\"Start Date\" [width]=\"'150px'\"></ax-text-column>\n <ax-text-column dataField=\"endDate\" caption=\"Due Date\" [width]=\"'150px'\"></ax-text-column>\n <ax-text-column dataField=\"priority\" caption=\"priority\" [width]=\"'125px'\"></ax-text-column>\n <ax-text-column dataField=\"reporter\" caption=\"Reporter\" [width]=\"'125px'\"></ax-text-column>\n <ax-text-column dataField=\"assignee\" caption=\"Assignee\" [width]=\"'125px'\"></ax-text-column>\n <ax-text-column dataField=\"priority\" caption=\"priority\" [width]=\"'125px'\"></ax-text-column>\n\n @for (column of columns(); track column) {\n <axp-widget-column-renderer\n [node]=\"column.widget\"\n [caption]=\"(column.title | translate | async)!\"\n ></axp-widget-column-renderer>\n }\n\n <ax-command-column\n fixed=\"end\"\n [width]=\"'60px'\"\n (onItemClick)=\"onActionClickHandler($event)\"\n [items]=\"[{ name: 'view', text: 'View', icon: 'ax-icon ax-icon-more-horizontal' }]\"\n ></ax-command-column>\n </ax-data-table>\n}\n", styles: ["ax-kanban{--ax-comp-kanban-status-min-width: 25rem;height:100%;line-height:1.5}\n"], dependencies: [{ kind: "ngmodule", type: AXDataTableModule }, { kind: "component", type: i1$2.AXDataTableComponent, selector: "ax-data-table", inputs: ["dataSource", "selectedRows", "parentField", "rowDetailsTemplate", "rowTemplate", "emptyTemplate", "noDataTemplate", "alternative", "showHeader", "fixedHeader", "showFooter", "fixedFooter", "itemHeight", "allowReordering", "paging", "fetchDataMode", "loading", "focusedRow"], outputs: ["selectedRowsChange", "focusedRowChange", "onRowClick", "onRowDbClick", "onColumnsOrderChanged", "onColumnSizeChanged", "onPageChanged"] }, { kind: "component", type: i1$2.AXDataTableTextColumnComponent, selector: "ax-text-column", inputs: ["width", "caption", "allowSorting", "allowResizing", "fixed", "customExpandIcon", "customCollapseIcon", "dataField", "expandHandler", "wrapText", "cellTemplate", "footerTemplate", "headerTemplate", "format", "formatOptions"] }, { kind: "component", type: i1$2.AXRowCommandColumnComponent, selector: "ax-command-column", inputs: ["width", "caption", "fixed", "footerTemplate", "items"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i1.AXPWidgetColumnRendererComponent, selector: "axp-widget-column-renderer", inputs: ["caption", "customExpandIcon", "customCollapseIcon", "customWidth", "node", "footerTemplate", "expandHandler", "cellTemplate", "headerTemplate"] }, { kind: "pipe", type: AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1569
+ }
1570
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMTaskBoardStatusGroupedGridViewComponent, decorators: [{
1571
+ type: Component,
1572
+ args: [{ selector: 'axm-task-board-status-grouped-grid-view', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [AXDataTableModule, AXTranslatorPipe, AsyncPipe, AXPWidgetCoreModule], template: "@for (group of groupedTasks(); track group) {\n <h1 class=\"ax-text-xl ax-font-bold\">{{ group.statusInfo.title }}</h1>\n <ax-data-table\n class=\"ax-h-[300px]\"\n [fetchDataMode]=\"'manual'\"\n [dataSource]=\"group.tasks\"\n [loading]=\"{ enabled: true, animation: true }\"\n >\n <ax-text-column dataField=\"title\" caption=\"title\" [width]=\"'350px'\"></ax-text-column>\n <ax-text-column dataField=\"description\" caption=\"description\" [width]=\"'500px'\"></ax-text-column>\n <ax-text-column dataField=\"startDate\" caption=\"Start Date\" [width]=\"'150px'\"></ax-text-column>\n <ax-text-column dataField=\"endDate\" caption=\"Due Date\" [width]=\"'150px'\"></ax-text-column>\n <ax-text-column dataField=\"priority\" caption=\"priority\" [width]=\"'125px'\"></ax-text-column>\n <ax-text-column dataField=\"reporter\" caption=\"Reporter\" [width]=\"'125px'\"></ax-text-column>\n <ax-text-column dataField=\"assignee\" caption=\"Assignee\" [width]=\"'125px'\"></ax-text-column>\n <ax-text-column dataField=\"priority\" caption=\"priority\" [width]=\"'125px'\"></ax-text-column>\n\n @for (column of columns(); track column) {\n <axp-widget-column-renderer\n [node]=\"column.widget\"\n [caption]=\"(column.title | translate | async)!\"\n ></axp-widget-column-renderer>\n }\n\n <ax-command-column\n fixed=\"end\"\n [width]=\"'60px'\"\n (onItemClick)=\"onActionClickHandler($event)\"\n [items]=\"[{ name: 'view', text: 'View', icon: 'ax-icon ax-icon-more-horizontal' }]\"\n ></ax-command-column>\n </ax-data-table>\n}\n", styles: ["ax-kanban{--ax-comp-kanban-status-min-width: 25rem;height:100%;line-height:1.5}\n"] }]
1573
+ }], propDecorators: { provider: [{ type: i0.Input, args: [{ isSignal: true, alias: "provider", required: false }] }], dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: true }] }], onActionClick: [{ type: i0.Output, args: ["onActionClick"] }] } });
1574
+
1575
+ class AXMTaskBoardPage extends AXPPageLayoutBaseComponent {
1576
+ constructor() {
1577
+ super(...arguments);
1578
+ this.router = inject(Router);
1579
+ this.rootConfig = RootConfig;
1580
+ this.deviceService = inject(AXPDeviceService);
1581
+ this.vm = inject(AXMTaskBoardViewModel);
1582
+ this.unsubscribe = inject(AXUnsubscriber);
1583
+ this.activatedRoute = inject(ActivatedRoute);
1584
+ this.localeService = inject(AXLocaleService);
1585
+ this.calendarService = inject(AXCalendarService);
1586
+ this.taskBoardService = inject(AXPTaskBoardService);
1587
+ this.popover = viewChild('popover', ...(ngDevMode ? [{ debugName: "popover" }] : []));
1588
+ this.calendar = viewChild('calendar', ...(ngDevMode ? [{ debugName: "calendar" }] : []));
1589
+ this.sidebarCalendar = viewChild('sidebarCalendar', ...(ngDevMode ? [{ debugName: "sidebarCalendar" }] : []));
1590
+ this.isReady = signal(false, ...(ngDevMode ? [{ debugName: "isReady" }] : []));
1591
+ this.taskTypes = signal([], ...(ngDevMode ? [{ debugName: "taskTypes" }] : []));
1592
+ this.calendarEventTypes = signal([], ...(ngDevMode ? [{ debugName: "calendarEventTypes" }] : []));
1593
+ this.resources = signal([], ...(ngDevMode ? [{ debugName: "resources" }] : []));
1594
+ this.isQueryParam = signal(false, ...(ngDevMode ? [{ debugName: "isQueryParam" }] : []));
1595
+ this.taskTypeAccordionCollapsed = signal(false, ...(ngDevMode ? [{ debugName: "taskTypeAccordionCollapsed" }] : []));
1596
+ this.calendarEventTypeAccordionCollapsed = signal(false, ...(ngDevMode ? [{ debugName: "calendarEventTypeAccordionCollapsed" }] : []));
1597
+ this.currentTask = signal(null, ...(ngDevMode ? [{ debugName: "currentTask" }] : []));
1598
+ this.currentViewMode = signal('calendar', ...(ngDevMode ? [{ debugName: "currentViewMode" }] : []));
1599
+ this.schedulerComponent = signal(null, ...(ngDevMode ? [{ debugName: "schedulerComponent" }] : []));
1600
+ this.dayCellTemplateRef = viewChild('dayCellTemplate', ...(ngDevMode ? [{ debugName: "dayCellTemplateRef" }] : []));
1601
+ this.dayCellTemplate = computed(() => this.dayCellTemplateRef(), ...(ngDevMode ? [{ debugName: "dayCellTemplate" }] : []));
1602
+ this.dayDataCache = signal(new Map(), ...(ngDevMode ? [{ debugName: "dayDataCache" }] : []));
1603
+ this.menuItems = signal([
1604
+ {
1605
+ key: 'calendar',
1606
+ text: 'calendar',
1607
+ icon: 'fa-light fa-calendar-day',
1608
+ children: [
1609
+ { key: 'day', text: 'daily', icon: 'fa-light fa-calendar-day' },
1610
+ { key: 'week', text: 'weekly', icon: 'fa-light fa-calendar-week' },
1611
+ { key: 'month', text: 'monthly', icon: 'fa-light fa-calendar-alt' },
1612
+ { key: 'agenda', text: 'agenda', icon: 'fa-light fa-calendar-range' },
1613
+ ],
1614
+ },
1615
+ {
1616
+ key: 'timeline',
1617
+ text: 'timeline',
1618
+ icon: 'fa-light fa-list-timeline',
1619
+ children: [
1620
+ { key: 'timeline-day', text: 'daily-timeline', icon: 'fa-light fa-calendar-day' },
1621
+ { key: 'timeline-multi-day', text: 'multi-day-timeline', icon: 'fa-light fa-calendar-week' },
1622
+ { key: 'timeline-month', text: 'monthly-timeline', icon: 'fa-light fa-calendar-alt' },
1623
+ { key: 'timeline-year', text: 'yearly-timeline', icon: 'fa-light fa-calendar-range' },
1624
+ ],
1625
+ },
1626
+ {
1627
+ key: 'table',
1628
+ text: 'table',
1629
+ icon: 'fa-light fa-table',
1630
+ children: [
1631
+ { key: 'grid', text: 'grid', icon: 'fa-light fa-table' },
1632
+ { key: 'status-grouped-grid', text: 'status-grouped-grid', icon: 'fa-light fa-table' },
1633
+ ],
1634
+ },
1635
+ { key: 'kanban', text: 'kanban', icon: 'fa-light fa-chart-kanban' },
1636
+ ], ...(ngDevMode ? [{ debugName: "menuItems" }] : []));
1637
+ this.calendarType = computed(() => this.localeService.activeProfile().calendar.system, ...(ngDevMode ? [{ debugName: "calendarType" }] : []));
1638
+ this.todayButtonText = computed(() => {
1639
+ switch (this.vm.currentViewMode()) {
1640
+ case 'day':
1641
+ case 'grid':
1642
+ case 'agenda':
1643
+ case 'kanban':
1644
+ case 'timeline-day':
1645
+ case 'timeline-multi-day':
1646
+ case 'status-grouped-grid':
1647
+ return 'Today';
1648
+ case 'week':
1649
+ return 'Current week';
1650
+ case 'month':
1651
+ case 'timeline-month':
1652
+ return 'Current month';
1653
+ case 'timeline-year':
1654
+ return 'Current year';
1655
+ }
1656
+ }, ...(ngDevMode ? [{ debugName: "todayButtonText" }] : []));
1657
+ this.timeText = computed(() => {
1658
+ if (this.vm.currentViewMode() === 'grid' ||
1659
+ this.vm.currentViewMode() === 'kanban' ||
1660
+ this.vm.currentViewMode() === 'status-grouped-grid') {
1661
+ const currentDate = this.vm.currentDate();
1662
+ if (!currentDate) {
1663
+ return '';
1664
+ }
1665
+ const start = this.calendarService.create(currentDate, this.localeService.activeProfile().calendar.system);
1666
+ const end = start.add('day', this.vm.daysCount() - 1);
1667
+ const startText = start.format('DD MMMM yyyy', { locale: this.localeService.activeProfile().calendar.system });
1668
+ const endText = end.format('DD MMMM yyyy', { locale: this.localeService.activeProfile().calendar.system });
1669
+ return `${startText} - ${endText}`;
1670
+ }
1671
+ return this.schedulerComponent()?.currentDateText() || '';
1672
+ }, ...(ngDevMode ? [{ debugName: "timeText" }] : []));
1673
+ this.calendarDepth = computed(() => {
1674
+ if (this.vm.currentViewMode() === 'grid' ||
1675
+ this.vm.currentViewMode() === 'kanban' ||
1676
+ this.vm.currentViewMode() === 'status-grouped-grid') {
1677
+ return 'day';
1678
+ }
1679
+ return this.schedulerComponent()?.calendarDepth() || 'day';
1680
+ }, ...(ngDevMode ? [{ debugName: "calendarDepth" }] : []));
1681
+ this.currentDateForCalendar = computed(() => {
1682
+ const date = this.vm.currentDate();
1683
+ return date || new Date();
1684
+ }, ...(ngDevMode ? [{ debugName: "currentDateForCalendar" }] : []));
1685
+ this.selectedViewMode = computed(() => {
1686
+ const currentMode = this.vm.currentViewMode();
1687
+ for (const category of this.menuItems()) {
1688
+ if (category.key === currentMode) {
1689
+ return { key: category.key, text: category.text, icon: category.icon };
1690
+ }
1691
+ if (category.children) {
1692
+ const foundChild = category.children.find((child) => child.key === currentMode);
1693
+ if (foundChild) {
1694
+ return foundChild;
1695
+ }
1696
+ }
1697
+ }
1698
+ const firstCategory = this.menuItems()[0];
1699
+ return firstCategory.children
1700
+ ? firstCategory.children[0]
1701
+ : { key: firstCategory.key, text: firstCategory.text, icon: firstCategory.icon };
1702
+ }, ...(ngDevMode ? [{ debugName: "selectedViewMode" }] : []));
1703
+ this.filter = computed(() => {
1704
+ const taskTypeNames = this.vm.selectedTaskTypeNames();
1705
+ // When nothing is selected (empty array), we want to show NO types
1706
+ // The service treats empty/undefined types as "show all providers"
1707
+ // To show none when nothing is selected, we pass a non-existent type name
1708
+ // This ensures filteredProviders.length === 0, resulting in empty results
1709
+ const types = taskTypeNames.length > 0 ? taskTypeNames : ['__NONE__'];
1710
+ const assigneeIds = this.vm.selectedAssigneeIds();
1711
+ const reporterIds = this.vm.selectedReporterIds();
1712
+ const priorities = this.vm.selectedPriorities();
1713
+ const currentDate = this.vm.currentDate() || new Date();
1714
+ let from = this.calendarService.create(currentDate, this.localeService.activeProfile().calendar.system);
1715
+ let end;
1716
+ const currentView = this.vm.currentViewMode();
1717
+ if (currentView === 'grid' ||
1718
+ currentView === 'kanban' ||
1719
+ currentView === 'agenda' ||
1720
+ currentView === 'timeline-multi-day' ||
1721
+ currentView === 'status-grouped-grid') {
1722
+ end = from.add('day', this.vm.daysCount() - 1);
1723
+ }
1724
+ else if (currentView === 'month' || currentView === 'timeline-month') {
1725
+ from = from.startOf('month');
1726
+ end = from.endOf('month');
1727
+ }
1728
+ else {
1729
+ end = from.endOf('day');
1730
+ }
1731
+ return {
1732
+ // Always include types - empty array means show no types, non-empty means show only selected types
1733
+ types,
1734
+ ...(assigneeIds.length > 0 && { assigneeIds }),
1735
+ ...(reporterIds.length > 0 && { reporterIds }),
1736
+ ...(priorities.length > 0 && { priorities }),
1737
+ range: { from: from.date, end: end.date },
1738
+ };
1739
+ }, ...(ngDevMode ? [{ debugName: "filter" }] : []));
1740
+ this.contextMenu = viewChild('rootContextMenu', ...(ngDevMode ? [{ debugName: "contextMenu" }] : []));
1741
+ this.schedulerDataSource = (filter) => {
1742
+ const finalFilter = { ...this.filter(), ...filter };
1743
+ return this.taskBoardService.getTasks(finalFilter).then((result) => {
1744
+ this.validateSelectedTask(result.items);
1745
+ return result.items;
1746
+ });
1747
+ };
1748
+ this.gridDataSource = (filter) => {
1749
+ const finalFilter = { ...this.filter(), ...filter };
1750
+ return this.taskBoardService.getTasks(finalFilter).then((result) => {
1751
+ this.validateSelectedTask(result.items);
1752
+ return result;
1753
+ });
1754
+ };
1755
+ this.resolvedTasks = signal([], ...(ngDevMode ? [{ debugName: "resolvedTasks" }] : []));
1756
+ this.eff = effect(async () => {
1757
+ const viewMode = this.vm.currentViewMode();
1758
+ const filter = this.filter();
1759
+ if (viewMode === 'kanban') {
1760
+ await this.taskResolveHandler(filter);
1761
+ }
1762
+ }, ...(ngDevMode ? [{ debugName: "eff" }] : []));
1763
+ this.refreshEffect = effect(() => {
1764
+ this.vm.selectedTaskTypeNames();
1765
+ this.getResources();
1766
+ this.schedulerComponent()?.refresh();
1767
+ }, ...(ngDevMode ? [{ debugName: "refreshEffect" }] : []));
1768
+ this.calendarEventTypeRefreshEffect = effect(() => {
1769
+ this.vm.selectedCalendarEventTypeIds();
1770
+ // Refresh calendar view to update holidays when event types change
1771
+ this.schedulerComponent()?.refresh();
1772
+ }, ...(ngDevMode ? [{ debugName: "calendarEventTypeRefreshEffect" }] : []));
1773
+ this.dayDataCacheEffect = effect(async () => {
1774
+ // Update cache when filters or date change
1775
+ this.vm.currentDate();
1776
+ this.vm.selectedTaskTypeNames();
1777
+ this.vm.selectedCalendarEventTypeIds();
1778
+ await this.updateDayDataCache();
1779
+ }, ...(ngDevMode ? [{ debugName: "dayDataCacheEffect" }] : []));
1780
+ this.rangeBasedViews = [
1781
+ 'grid',
1782
+ 'kanban',
1783
+ 'agenda',
1784
+ 'status-grouped-grid',
1785
+ 'timeline-multi-day',
1786
+ ];
1787
+ this.getCellClass = (date) => {
1788
+ const currentView = this.vm.currentViewMode();
1789
+ const selectionStartDate = this.vm.rangeStartDate();
1790
+ if (this.rangeBasedViews.includes(currentView)) {
1791
+ if (selectionStartDate) {
1792
+ const axSelectionStartDate = this.calendarService.create(selectionStartDate);
1793
+ if (date.equal(axSelectionStartDate, 'day')) {
1794
+ return 'ax-range-start ax-range-end';
1795
+ }
1796
+ return null;
1797
+ }
1798
+ const fromRange = this.calendarService.create(this.vm.currentDate());
1799
+ const endRange = fromRange.add('day', this.vm.daysCount() - 1);
1800
+ const isStart = date.equal(fromRange, 'day');
1801
+ const isEnd = date.equal(endRange, 'day');
1802
+ if (isStart && isEnd)
1803
+ return 'ax-range-start ax-range-end';
1804
+ if (isStart)
1805
+ return 'ax-range-start';
1806
+ if (isEnd)
1807
+ return 'ax-range-end';
1808
+ if (date.compare(fromRange, 'day') > 0 && date.compare(endRange, 'day') < 0) {
1809
+ return 'ax-range-between';
1810
+ }
1811
+ return null;
1812
+ }
1813
+ if (currentView === 'week') {
1814
+ const from = this.calendarService.create(this.vm.currentDate());
1815
+ const end = from.add('day', 6);
1816
+ if (date.equal(from, 'day'))
1817
+ return 'ax-range-start';
1818
+ if (date.equal(end, 'day'))
1819
+ return 'ax-range-end';
1820
+ if (date.compare(from, 'day') > 0 && date.compare(end, 'day') < 0) {
1821
+ return 'ax-range-between';
1822
+ }
1823
+ }
1824
+ return null;
1825
+ };
1826
+ this.taskTypeItems = computed(() => {
1827
+ return this.taskTypes().map((taskType) => ({
1828
+ id: taskType.name,
1829
+ text: taskType.title,
1830
+ icon: taskType.icon,
1831
+ }));
1832
+ }, ...(ngDevMode ? [{ debugName: "taskTypeItems" }] : []));
1833
+ // Check if current view mode is kanban, grid, or status-grouped-grid
1834
+ this.isNonCalendarView = computed(() => {
1835
+ const mode = this.vm.currentViewMode();
1836
+ return mode === 'kanban' || mode === 'grid' || mode === 'status-grouped-grid';
1837
+ }, ...(ngDevMode ? [{ debugName: "isNonCalendarView" }] : []));
1838
+ this.selectedTaskTypeValues = computed(() => {
1839
+ const values = this.vm.selectedTaskTypeNames();
1840
+ // If in radio mode (non-calendar view), return only the first value or empty array
1841
+ if (this.isNonCalendarView() && values.length > 0) {
1842
+ return [values[0]];
1843
+ }
1844
+ return values;
1845
+ }, ...(ngDevMode ? [{ debugName: "selectedTaskTypeValues" }] : []));
1846
+ this.calendarEventTypeItems = computed(() => {
1847
+ return this.calendarEventTypes().map((eventType) => ({
1848
+ id: eventType.id,
1849
+ text: eventType.title,
1850
+ icon: eventType.icon,
1851
+ color: eventType.color,
1852
+ }));
1853
+ }, ...(ngDevMode ? [{ debugName: "calendarEventTypeItems" }] : []));
1854
+ this.selectedCalendarEventTypeValues = computed(() => {
1855
+ return this.vm.selectedCalendarEventTypeIds();
1856
+ }, ...(ngDevMode ? [{ debugName: "selectedCalendarEventTypeValues" }] : []));
1857
+ }
1858
+ async ngOnInit() {
1859
+ await super.ngOnInit();
1860
+ await this.vm.initialize();
1861
+ // Load task types for checkbox filter
1862
+ const types = await this.taskBoardService.getTaskTypes();
1863
+ this.taskTypes.set(types);
1864
+ // Load calendar event types for checkbox filter
1865
+ const eventTypes = await this.taskBoardService.getCalendarEventTypes();
1866
+ this.calendarEventTypes.set(eventTypes.map((et) => ({
1867
+ id: et.id,
1868
+ title: et.title,
1869
+ })));
1870
+ // Initialize day data cache
1871
+ await this.updateDayDataCache();
1872
+ this.router.events
1873
+ .pipe(this.unsubscribe.takeUntilDestroy, filter((event) => event instanceof NavigationEnd), startWith(null))
1874
+ .subscribe(async () => {
1875
+ await this.loadFromRoute();
1876
+ if (!this.isReady()) {
1877
+ this.isReady.set(true);
1878
+ }
1879
+ });
1880
+ this.taskBoardService.refresh$.subscribe(async () => {
1881
+ await this.taskResolveHandler();
1882
+ await this.getResources();
1883
+ });
1884
+ }
1885
+ async getPageTitle() {
1886
+ return await this.translateService.translateAsync('@task-management:task-board.page-title');
1887
+ }
1888
+ async getPageBreadcrumbs() {
1889
+ return [
1890
+ {
1891
+ title: await this.translateService.translateAsync('@task-management:root-menu'),
1892
+ },
1893
+ ];
1894
+ }
1895
+ async taskResolveHandler(filter = this.filter()) {
1896
+ const result = await this.taskBoardService.getTasks(filter);
1897
+ this.validateSelectedTask(result.items);
1898
+ this.resolvedTasks.set(result.items);
1899
+ }
1900
+ schedulerComponentChanged(component) {
1901
+ this.schedulerComponent.set(component);
1902
+ }
1903
+ async handleContextMenuOnOpening(event) {
1904
+ const currentTask = this.currentTask();
1905
+ if (!currentTask)
1906
+ return;
1907
+ const providerName = currentTask.provider;
1908
+ if (!providerName)
1909
+ return;
1910
+ const provider = this.taskBoardService.getProvider(providerName);
1911
+ if (!provider)
1912
+ return;
1913
+ const actions = await provider.getActions(currentTask);
1914
+ for (const item of actions) {
1915
+ event.items.push({
1916
+ text: item.title,
1917
+ icon: item.icon,
1918
+ color: item.color,
1919
+ break: item.break,
1920
+ data: {
1921
+ command: item.command,
1922
+ },
1923
+ });
1924
+ }
1925
+ }
1926
+ handleContextMenu(event) {
1927
+ this.currentTask.set(event.task);
1928
+ const x = event.nativeEvent.clientX;
1929
+ const y = event.nativeEvent.clientY;
1930
+ const element = event.nativeEvent.target;
1931
+ this.contextMenu()?.showAt({ x, y }, element);
1932
+ }
1933
+ handleMonthSlotDblClicked(date) {
1934
+ this.vm.setCurrentDate(date);
1935
+ this.vm.setViewMode('day');
1936
+ }
1937
+ handleViewChange(view, dropdownPanel) {
1938
+ this.router.navigate([], { queryParams: { view } });
1939
+ this.vm.setViewMode(view);
1940
+ this.popover()?.close();
1941
+ dropdownPanel.close();
1942
+ }
1943
+ async updateDayDataCache() {
1944
+ const currentDate = this.vm.currentDate();
1945
+ const monthStart = this.calendarService.create(currentDate).startOf('month').date;
1946
+ const monthEnd = this.calendarService.create(currentDate).endOf('month').date;
1947
+ // Get tasks for the month
1948
+ const tasks = await this.taskBoardService.getTasks({
1949
+ ...this.filter(),
1950
+ range: { from: monthStart, end: monthEnd },
1951
+ });
1952
+ // Get events for the month
1953
+ const selectedEventTypeIds = this.vm.selectedCalendarEventTypeIds();
1954
+ // Pass selected calendar IDs (can be empty array to show no events)
1955
+ const events = await this.taskBoardService.getEvents({ from: monthStart, end: monthEnd }, selectedEventTypeIds);
1956
+ // Create a map of day -> count
1957
+ const dayCountMap = new Map();
1958
+ // Count tasks per day
1959
+ tasks.items.forEach((task) => {
1960
+ const taskStart = new Date(task.startDate);
1961
+ const taskEnd = new Date(task.endDate);
1962
+ const startDay = this.calendarService.create(taskStart).startOf('day');
1963
+ const endDay = this.calendarService.create(taskEnd).startOf('day');
1964
+ let currentDay = startDay;
1965
+ while (currentDay.compare(endDay, 'day') <= 0) {
1966
+ const dayKey = currentDay.format('YYYY-MM-DD');
1967
+ dayCountMap.set(dayKey, (dayCountMap.get(dayKey) || 0) + 1);
1968
+ currentDay = currentDay.add('day', 1);
1969
+ }
1970
+ });
1971
+ // Count events per day
1972
+ events.forEach((event) => {
1973
+ const eventDate = new Date(event.date);
1974
+ const dayKey = this.calendarService.create(eventDate).format('YYYY-MM-DD');
1975
+ dayCountMap.set(dayKey, (dayCountMap.get(dayKey) || 0) + 1);
1976
+ });
1977
+ this.dayDataCache.set(dayCountMap);
1978
+ this.sidebarCalendar()?.render();
1979
+ }
1980
+ getDayDataCount(date) {
1981
+ if (!date) {
1982
+ return 0;
1983
+ }
1984
+ try {
1985
+ // Get the native Date object from AXDateTime
1986
+ const dateObj = date.date || date._date;
1987
+ if (!dateObj) {
1988
+ return 0;
1989
+ }
1990
+ // Create a new AXDateTime from the date object for consistent formatting
1991
+ const nativeDate = dateObj instanceof Date ? dateObj : new Date(dateObj);
1992
+ const axDate = this.calendarService.create(nativeDate);
1993
+ const dayKey = axDate.format('YYYY-MM-DD');
1994
+ return this.dayDataCache().get(dayKey) || 0;
1995
+ }
1996
+ catch (error) {
1997
+ console.warn('Error getting day data count:', error);
1998
+ return 0;
1999
+ }
2000
+ }
2001
+ handleContextMenuItemClick(event) {
2002
+ this.taskBoardService.executeCommand(event.item.data?.command, this.currentTask()?.provider ?? '');
2003
+ }
2004
+ changeDate(forward) {
2005
+ const date = this.calendarService.create(this.vm.currentDate(), this.localeService.activeProfile().calendar.system);
2006
+ switch (this.vm.currentViewMode()) {
2007
+ case 'day':
2008
+ case 'timeline-day':
2009
+ this.vm.setCurrentDate(date.add('day', forward ? 1 : -1).date);
2010
+ break;
2011
+ case 'week':
2012
+ this.vm.setCurrentDate(date.add('week', forward ? 1 : -1).date);
2013
+ break;
2014
+ case 'grid':
2015
+ case 'agenda':
2016
+ case 'kanban':
2017
+ case 'timeline-multi-day':
2018
+ case 'status-grouped-grid':
2019
+ this.vm.setCurrentDate(date.add('day', forward ? this.vm.daysCount() : -this.vm.daysCount()).date);
2020
+ break;
2021
+ case 'month':
2022
+ case 'timeline-month':
2023
+ this.vm.setCurrentDate(date.add('month', forward ? 1 : -1).date);
2024
+ break;
2025
+ case 'timeline-year':
2026
+ this.vm.setCurrentDate(date.add('year', forward ? 1 : -1).date);
2027
+ break;
2028
+ }
2029
+ this.popover()?.close();
2030
+ this.calendar()?.render();
2031
+ this.sidebarCalendar()?.render();
2032
+ }
2033
+ handleCalendarSlotClick(event) {
2034
+ if (event.component.activeView !== event.component.depth)
2035
+ return;
2036
+ const clickedDate = event.item;
2037
+ const currentView = this.vm.currentViewMode();
2038
+ if (this.rangeBasedViews.includes(currentView)) {
2039
+ const selectionStartDate = this.vm.rangeStartDate();
2040
+ if (!selectionStartDate) {
2041
+ this.vm.setRangeStartDate(clickedDate);
2042
+ this.calendar()?.render();
2043
+ this.sidebarCalendar()?.render();
2044
+ return;
2045
+ }
2046
+ const date1 = selectionStartDate.getTime();
2047
+ const date2 = clickedDate.getTime();
2048
+ const newStartDate = new Date(Math.min(date1, date2));
2049
+ const newEndDate = new Date(Math.max(date1, date2));
2050
+ const differenceInDays = this.calculateDifferenceInDays(newStartDate, newEndDate);
2051
+ this.vm.setCurrentDate(newStartDate);
2052
+ this.vm.setDaysCount(differenceInDays);
2053
+ this.vm.setRangeStartDate(null);
2054
+ this.calendar()?.render();
2055
+ this.sidebarCalendar()?.render();
2056
+ this.popover()?.close();
2057
+ return;
2058
+ }
2059
+ let dateToSet = new Date(clickedDate);
2060
+ if (currentView === 'week') {
2061
+ const day = dateToSet.getDay();
2062
+ const weekStart = this.localeService.activeProfile().calendar.week.startsOn;
2063
+ let daysToSubtract = day - weekStart;
2064
+ if (daysToSubtract < 0) {
2065
+ daysToSubtract += 7;
2066
+ }
2067
+ dateToSet.setDate(dateToSet.getDate() - daysToSubtract);
2068
+ }
2069
+ this.vm.setCurrentDate(dateToSet);
2070
+ this.popover()?.close();
2071
+ this.calendar()?.render();
2072
+ this.sidebarCalendar()?.render();
2073
+ }
2074
+ /**
2075
+ * Helper function to calculate the difference in whole days between two dates.
2076
+ * The result is inclusive (e.g., May 5 to May 6 is a 2-day range).
2077
+ */
2078
+ calculateDifferenceInDays(start, end) {
2079
+ if (!start || !end) {
2080
+ return 1;
2081
+ }
2082
+ const startDate = new Date(start.getFullYear(), start.getMonth(), start.getDate());
2083
+ const endDate = new Date(end.getFullYear(), end.getMonth(), end.getDate());
2084
+ const timeDifference = endDate.getTime() - startDate.getTime();
2085
+ const daysDifference = Math.round(timeDifference / (1000 * 3600 * 24));
2086
+ return daysDifference + 1;
2087
+ }
2088
+ handleTodayClick() {
2089
+ this.vm.setRangeStartDate(null);
2090
+ let currentDate;
2091
+ if (this.vm.currentViewMode() === 'week') {
2092
+ currentDate = this.calendarService
2093
+ .create(new Date(), this.localeService.activeProfile().calendar.system)
2094
+ .startOf('week').date;
2095
+ }
2096
+ else {
2097
+ currentDate = new Date();
2098
+ }
2099
+ this.vm.setCurrentDate(currentDate);
2100
+ this.popover()?.close();
2101
+ this.calendar()?.render();
2102
+ this.sidebarCalendar()?.render();
2103
+ }
2104
+ handleTaskTypeSelectionChange(selectedValues) {
2105
+ // Convert single value to array if needed (for radio mode)
2106
+ const values = Array.isArray(selectedValues) ? selectedValues : selectedValues ? [selectedValues] : [];
2107
+ // If nothing is selected, pass empty array to show no types
2108
+ this.vm.setSelectedTaskTypeNames(values, this.isQueryParam());
2109
+ }
2110
+ handleCalendarEventTypeSelectionChange(selectedValues) {
2111
+ // If nothing is selected, pass empty array to show no types
2112
+ this.vm.setSelectedCalendarEventTypeIds(selectedValues || [], this.isQueryParam());
2113
+ // Refresh calendar view to update holidays
2114
+ this.schedulerComponent()?.refresh();
2115
+ }
2116
+ async loadFromRoute() {
2117
+ const snapshot = this.activatedRoute.snapshot.queryParamMap;
2118
+ const view = snapshot.get('view') ?? null;
2119
+ const allValidViews = this.menuItems().flatMap((c) => (c.children ? c.children.map((child) => child.key) : c.key));
2120
+ if (view && allValidViews.includes(view)) {
2121
+ this.vm.setViewMode(view);
2122
+ }
2123
+ else if (!this.vm.currentViewMode()) {
2124
+ this.vm.setViewMode('day');
2125
+ }
2126
+ const type = snapshot.getAll('type');
2127
+ const assignee = snapshot.getAll('assignee');
2128
+ const reporter = snapshot.getAll('reporter');
2129
+ const priority = snapshot.getAll('priority');
2130
+ if (type.length || assignee.length || priority.length || reporter.length) {
2131
+ this.isQueryParam.set(true);
2132
+ this.vm.setSelectedTaskTypeNames(type, true);
2133
+ this.vm.setSelectedAssigneeIds(assignee, true);
2134
+ this.vm.setSelectedReporterIds(reporter, true);
2135
+ this.vm.setSelectedPriorities(priority, true);
2136
+ }
2137
+ const dateRange = snapshot.get('dateRange');
2138
+ if (dateRange) {
2139
+ const range = this.taskBoardService.rangeCalculator(dateRange);
2140
+ if (range) {
2141
+ this.vm.setCurrentDate(range.from);
2142
+ this.vm.setDaysCount(this.calculateDifferenceInDays(range.from, range.end));
2143
+ switch (dateRange) {
2144
+ case 'today':
2145
+ this.vm.setViewMode('day');
2146
+ break;
2147
+ case 'this-week':
2148
+ this.vm.setViewMode('week');
2149
+ this.vm.setRangeStartDate(range.from);
2150
+ break;
2151
+ case 'this-month':
2152
+ this.vm.setViewMode('month');
2153
+ break;
2154
+ }
2155
+ }
2156
+ }
2157
+ }
2158
+ /**
2159
+ * Checks if the currently selected task is still present in the list of visible tasks.
2160
+ * If not, it clears the selection to prevent showing details for a hidden task.
2161
+ * @param visibleTasks The new array of tasks that will be displayed.
2162
+ */
2163
+ validateSelectedTask(visibleTasks) {
2164
+ const currentSelectedTask = this.vm.selectedTask();
2165
+ // Proceed only if a task is actually selected
2166
+ if (currentSelectedTask) {
2167
+ // Check if any task in the new list has the same ID as the selected one
2168
+ const isSelectedTaskVisible = visibleTasks.some((task) => task.id === currentSelectedTask.id);
2169
+ // If the selected task is NOT in the new list, clear the selection.
2170
+ if (!isSelectedTaskVisible) {
2171
+ this.vm.selectTask(null);
2172
+ }
2173
+ }
2174
+ }
2175
+ async getResources() {
2176
+ if (this.vm.selectedTaskTypeNames().length !== 1) {
2177
+ this.resources.set([]);
2178
+ return;
2179
+ }
2180
+ const resources = await this.taskBoardService.getResources(this.vm.selectedTaskTypeNames()[0] ?? '');
2181
+ this.resources.set(resources);
2182
+ }
2183
+ log(message) {
2184
+ console.log(message);
2185
+ }
2186
+ // protected layout = viewChild(AXPPageLayoutComponent);
2187
+ toggleStartSide() {
2188
+ this.layout()?.toggleStartSide();
2189
+ }
2190
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMTaskBoardPage, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2191
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXMTaskBoardPage, isStandalone: true, selector: "ng-component", providers: [
2192
+ {
2193
+ provide: AXPPageLayoutBase,
2194
+ useExisting: AXMTaskBoardPage,
2195
+ },
2196
+ ], viewQueries: [{ propertyName: "popover", first: true, predicate: ["popover"], descendants: true, isSignal: true }, { propertyName: "calendar", first: true, predicate: ["calendar"], descendants: true, isSignal: true }, { propertyName: "sidebarCalendar", first: true, predicate: ["sidebarCalendar"], descendants: true, isSignal: true }, { propertyName: "dayCellTemplateRef", first: true, predicate: ["dayCellTemplate"], descendants: true, isSignal: true }, { propertyName: "contextMenu", first: true, predicate: ["rootContextMenu"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<axp-page-layout *translate=\"let t\">\n <axp-layout-start-side class=\"ax-border-e ax-lightest-surface ax-h-full\">\n <axp-layout-header class=\"ax-p-4 ax-border-b\">\n <ng-container *ngTemplateOutlet=\"viewSelectorTemplate; context: { location: 'sidebar' }\"></ng-container>\n </axp-layout-header>\n\n <axp-layout-content class=\"ax-flex ax-flex-col ax-min-h-0 ax-overflow-y-auto\">\n <div class=\"ax-p-4 ax-flex ax-flex-col ax-gap-6\">\n <div class=\"ax-flex ax-flex-col ax-gap-3\">\n <!-- <h3 class=\"ax-text-sm ax-font-semibold ax-text-neutral-800 ax-uppercase ax-tracking-wide\">\n {{ (t('task-board.terms.calendar', { scope: rootConfig.config.i18n}) | async) }}\n </h3> -->\n <ax-calendar\n #sidebarCalendar\n [type]=\"calendarType()\"\n [depth]=\"calendarDepth()\"\n [cellClass]=\"getCellClass\"\n [ngModel]=\"currentDateForCalendar()\"\n [dayCellTemplate]=\"dayCellTemplate\"\n class=\"ax-single-range-calendar ax-border ax-rounded-lg\"\n (onSlotClick)=\"handleCalendarSlotClick($event)\"\n >\n </ax-calendar>\n </div>\n\n <div axAccordionGroup [accordion]=\"false\">\n <div\n class=\"ax-mb-2 ax-w-full ax-border ax-p-2 ax-rounded-lg\"\n axAccordionItem\n #taskTypeAccordion=\"axAccordionItem\"\n >\n <div\n class=\"ax-flex ax-items-center ax-justify-between ax-gap-2 ax-select-none ax-cursor-pointer\"\n axAccordionItemHeader\n >\n <h3 class=\"ax-text-sm ax-font-semibold\">\n {{ (t('task-board.filter.task-type', { scope: rootConfig.config.i18n}) | async)! }}\n </h3>\n <ax-icon\n [icon]=\"taskTypeAccordion?.isCollapsed() ? 'fa-light fa-chevron-down' : 'fa-light fa-chevron-up'\"\n class=\"ax-transition-transform\"\n ></ax-icon>\n </div>\n <div axAccordionItemContent>\n <div class=\"ax-pt-2\">\n <ax-selection-list\n [items]=\"taskTypeItems()\"\n [ngModel]=\"selectedTaskTypeValues()\"\n (onValueChanged)=\"handleTaskTypeSelectionChange($event.value)\"\n direction=\"vertical\"\n [multiple]=\"!isNonCalendarView()\"\n [showControl]=\"true\"\n valueField=\"id\"\n textField=\"text\"\n >\n <ng-template #itemTemplate let-item>\n <div class=\"ax-flex ax-items-center\">\n @if (item.icon) {\n <i [class]=\"item.icon\"></i>\n }\n <span [class]=\"item.icon ? 'ax-ml-2' : ''\">{{ item.text }}</span>\n </div>\n </ng-template>\n </ax-selection-list>\n </div>\n </div>\n </div>\n\n @if (!isNonCalendarView()) {\n <div\n class=\"ax-mb-2 ax-w-full ax-border ax-p-2 ax-rounded-lg\"\n axAccordionItem\n #calendarEventTypeAccordion=\"axAccordionItem\"\n >\n <div\n class=\"ax-flex ax-items-center ax-justify-between ax-gap-2 ax-select-none ax-cursor-pointer\"\n axAccordionItemHeader\n >\n <h3 class=\"ax-text-sm ax-font-semibold\">\n {{ ('@task-management:task-board.filter.calendars' | translate | async)! }}\n </h3>\n <ax-icon\n [icon]=\"calendarEventTypeAccordion?.isCollapsed() ? 'fa-light fa-chevron-down' : 'fa-light fa-chevron-up'\"\n class=\"ax-transition-transform\"\n ></ax-icon>\n </div>\n <div axAccordionItemContent>\n <div class=\"ax-pt-2\">\n <ax-selection-list\n [items]=\"calendarEventTypeItems()\"\n [ngModel]=\"selectedCalendarEventTypeValues()\"\n (onValueChanged)=\"handleCalendarEventTypeSelectionChange($event.value)\"\n direction=\"vertical\"\n [multiple]=\"true\"\n [showControl]=\"true\"\n valueField=\"id\"\n textField=\"text\"\n >\n <ng-template #itemTemplate let-item>\n <div class=\"ax-flex ax-items-center\">\n @if (item.icon) {\n <i [class]=\"item.icon\"></i>\n }\n <span [class]=\"item.icon ? 'ax-ml-2' : ''\">{{ item.text }}</span>\n </div>\n </ng-template>\n </ax-selection-list>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </axp-layout-content>\n </axp-layout-start-side>\n <axp-page-toolbar>\n <axp-layout-prefix class=\"sm:ax-flex-row ax-flex-col ax-items-start\">\n <div class=\"ax-scheduler-header ax-w-max ax-sm sm:ax-md\">\n <ax-button look=\"blank\" (onClick)=\"changeDate(false)\">\n <ax-icon class=\"ax-icon ax-text-xl ax-icon-chevron-left arrow-icon\"></ax-icon>\n </ax-button>\n <ax-button look=\"blank\" [text]=\"timeText()\" #date></ax-button>\n <ax-button look=\"blank\" (onClick)=\"changeDate(true)\">\n <ax-icon class=\"ax-icon ax-text-xl ax-icon-chevron-right arrow-icon\"></ax-icon>\n </ax-button>\n <!-- <ax-popover [target]=\"date\" [placement]=\"'bottom'\" #popover [adaptivityEnabled]=\"true\">\n <div class=\"ax-overlay-pane\">\n <ax-calendar\n #calendar\n [type]=\"calendarType()\"\n [depth]=\"calendarDepth()\"\n [cellClass]=\"getCellClass\"\n [ngModel]=\"vm.currentDate()\"\n class=\"ax-single-range-calendar\"\n (onSlotClick)=\"handleCalendarSlotClick($event)\"\n >\n <ax-footer>\n <ax-button\n look=\"link\"\n color=\"primary\"\n [text]=\"todayButtonText()\"\n (onClick)=\"handleTodayClick()\"\n ></ax-button>\n </ax-footer>\n </ax-calendar>\n </div>\n </ax-popover> -->\n </div>\n </axp-layout-prefix>\n\n <axp-layout-suffix>\n @if (deviceService.isSmall()) {\n <ax-button id=\"axp-toolbar-btn-filters\" (onClick)=\"toggleStartSide()\" [iconOnly]=\"true\" [color]=\"'default'\">\n <i class=\"fa-light fa-bars\"></i>\n </ax-button>\n }\n <!-- @if (!deviceService.isSmall()) {\n <ng-container *ngTemplateOutlet=\"viewSelectorTemplate; context: { location: 'toolbar' }\"></ng-container>\n } -->\n <ax-button [text]=\"t('task-board.filter.title', { scope: rootConfig.config.i18n }) | async\">\n <ax-prefix><ax-icon icon=\"fa-{{vm.activeFilterCount()?'solid':'light'}} fa-filter\"></ax-icon></ax-prefix>\n <ax-dropdown-panel #filterDropdownPanel (onOpened)=\"filtersComponent.resetContextToViewModel()\">\n <axm-task-board-filters\n #filtersComponent\n [isQueryParam]=\"isQueryParam()\"\n [excludeTaskType]=\"true\"\n (applyClicked)=\"filterDropdownPanel.close()\"\n ></axm-task-board-filters>\n </ax-dropdown-panel>\n </ax-button>\n\n <!-- @if(deviceService.isLarge()) {\n <ax-button (onClick)=\"vm.toggleDetailPanel()\">\n <ax-icon icon=\"{{ vm.isDetailPanelOpen() ? 'fa-solid fa-square-info' : 'fa-light fa-square-info' }}\"></ax-icon>\n </ax-button>\n } -->\n </axp-layout-suffix>\n </axp-page-toolbar>\n <axp-page-content class=\"ax-flex ax-flex-row ax-gap-2\">\n @if (isReady()) { @switch(vm.currentViewMode()) { @case('kanban') {\n <axm-task-board-kanban-view\n class=\"axp-kanban-container ax-h-full ax-w-full ax-min-w-0\"\n [tasks]=\"resolvedTasks()\"\n (onTaskClick)=\"vm.selectTask($event)\"\n (onActionClick)=\"handleContextMenu($event)\"\n ></axm-task-board-kanban-view>\n } @case('grid') {\n <axm-task-board-grid-view\n class=\"ax-h-full ax-w-full ax-min-w-0\"\n [dataSource]=\"gridDataSource\"\n (onTaskClick)=\"vm.selectTask($event)\"\n (onActionClick)=\"handleContextMenu($event)\"\n ></axm-task-board-grid-view>\n } @case('status-grouped-grid') {\n <axm-task-board-status-grouped-grid-view\n class=\"ax-flex ax-flex-col ax-gap-2 ax-w-full ax-min-w-0\"\n [dataSource]=\"gridDataSource\"\n (onActionClick)=\"handleContextMenu($event)\"\n ></axm-task-board-status-grouped-grid-view>\n } @default {\n <axm-task-board-calendar-view\n class=\"axp-scheduler-container ax-h-full ax-w-full ax-min-w-0\"\n [resources]=\"resources()\"\n [startingDate]=\"vm.currentDate()\"\n [dataSource]=\"schedulerDataSource\"\n (onTaskClick)=\"vm.selectTask($event)\"\n [selectedView]=\"vm.currentViewMode()\"\n (onActionClick)=\"handleContextMenu($event)\"\n (onTaskRightClick)=\"handleContextMenu($event)\"\n (component)=\"schedulerComponentChanged($event)\"\n (onMonthSlotDblClicked)=\"handleMonthSlotDblClicked($event)\"\n ></axm-task-board-calendar-view>\n } }\n <ax-context-menu\n #rootContextMenu\n [closeOn]=\"'leave'\"\n [orientation]=\"'vertical'\"\n (onOpening)=\"handleContextMenuOnOpening($event)\"\n (onItemClick)=\"handleContextMenuItemClick($event)\"\n >\n </ax-context-menu>\n @if (vm.isDetailPanelOpen() && deviceService.isLarge()) {\n <axm-task-board-detail-panel></axm-task-board-detail-panel>\n } } @else {\n <div class=\"ax-flex ax-items-center ax-justify-center ax-w-full ax-h-full\">\n <ax-loading></ax-loading>\n </div>\n }\n </axp-page-content>\n</axp-page-layout>\n\n<ng-template #viewSelectorTemplate let-location=\"location\">\n @if (location === 'sidebar') {\n <ax-button\n [text]=\"('@task-management:task-board.view.' + selectedViewMode().text | translate | async)!\"\n class=\"ax-w-full\"\n >\n <ax-prefix><ax-icon [icon]=\"selectedViewMode().icon\"></ax-icon></ax-prefix>\n <ax-dropdown-panel #sidebarDropdownPanel>\n <ax-menu [orientation]=\"'vertical'\" class=\"ax-menu-container\">\n @for (category of menuItems(); track category.key) {\n <ng-container>\n @if (category.children && category.children.length > 0) {\n <ax-menu-item>\n <ax-prefix>\n <ax-icon [icon]=\"category.icon\"></ax-icon>\n </ax-prefix>\n <ax-text>{{ ('@task-management:task-board.' + category.text | translate | async)! }}</ax-text>\n @for (child of category.children; track child.key) {\n <ax-menu-item (onClick)=\"handleViewChange(child.key, sidebarDropdownPanel)\">\n <ax-prefix>\n <ax-icon [icon]=\"child.icon\"></ax-icon>\n </ax-prefix>\n <ax-text>{{ ('@task-management:task-board.view.' + child.text | translate | async)! }}</ax-text>\n </ax-menu-item>\n }\n </ax-menu-item>\n } @else {\n <ax-menu-item (onClick)=\"handleViewChange(category.key, sidebarDropdownPanel)\">\n <ax-prefix>\n <ax-icon [icon]=\"category.icon\"></ax-icon>\n </ax-prefix>\n <ax-text>{{ ('@task-management:task-board.' + category.text | translate | async)! }}</ax-text>\n </ax-menu-item>\n }\n </ng-container>\n }\n </ax-menu>\n </ax-dropdown-panel>\n <ax-suffix>\n <ax-icon icon=\"fa-light fa-caret-down\"></ax-icon>\n </ax-suffix>\n </ax-button>\n } @else {\n <ax-button [text]=\"('@task-management:task-board.view.' + selectedViewMode().text | translate | async)!\">\n <ax-prefix><ax-icon [icon]=\"selectedViewMode().icon\"></ax-icon></ax-prefix>\n <ax-dropdown-panel #toolbarDropdownPanel>\n <ax-menu [orientation]=\"'vertical'\" class=\"ax-menu-container\">\n @for (category of menuItems(); track category.key) {\n <ng-container>\n @if (category.children && category.children.length > 0) {\n <ax-menu-item>\n <ax-prefix>\n <ax-icon [icon]=\"category.icon\"></ax-icon>\n </ax-prefix>\n <ax-text>{{ ('@task-management:task-board.' + category.text | translate | async)! }}</ax-text>\n @for (child of category.children; track child.key) {\n <ax-menu-item (onClick)=\"handleViewChange(child.key, toolbarDropdownPanel)\">\n <ax-prefix>\n <ax-icon [icon]=\"child.icon\"></ax-icon>\n </ax-prefix>\n <ax-text>{{ ('@task-management:task-board.view.' + child.text | translate | async)! }}</ax-text>\n </ax-menu-item>\n }\n </ax-menu-item>\n } @else {\n <ax-menu-item (onClick)=\"handleViewChange(category.key, toolbarDropdownPanel)\">\n <ax-prefix>\n <ax-icon [icon]=\"category.icon\"></ax-icon>\n </ax-prefix>\n <ax-text>{{ ('@task-management:task-board.' + category.text | translate | async)! }}</ax-text>\n </ax-menu-item>\n }\n </ng-container>\n }\n </ax-menu>\n </ax-dropdown-panel>\n <ax-suffix>\n <ax-icon icon=\"fa-light fa-caret-down\"></ax-icon>\n </ax-suffix>\n </ax-button>\n }\n</ng-template>\n\n<ng-template #dayCellTemplate let-slot>\n <div\n class=\"ax-flex ax-flex-col ax-items-center ax-justify-between ax-w-full ax-gap-1\"\n [style.padding-bottom]=\"'0.25rem'\"\n >\n <span class=\"ax-flex-1 ax-text-center\">{{ slot.slot.text ?? slot.slot.date?.day ?? '' }}</span>\n @if (slot.slot.date && getDayDataCount(slot.slot.date) > 0) {\n <ax-badge color=\"warning\"></ax-badge>\n }\n </div>\n</ng-template>\n", styles: ["html[dir=rtl] axp-page-layout axp-page-toolbar axp-layout-prefix .ax-scheduler-header .arrow-icon:before{-moz-transform:scale(-1,1);-webkit-transform:scale(-1,1);-o-transform:scale(-1,1);-ms-transform:scale(-1,1);transform:scaleX(-1)}.ax-single-range-calendar .ax-range-start,.ax-single-range-calendar .ax-range-end{color:rgba(var(--ax-sys-color-on-primary-surface))!important;background-color:rgba(var(--ax-sys-color-primary-surface),.85)!important}.ax-single-range-calendar .ax-range-start:hover,.ax-single-range-calendar .ax-range-end:hover{background-color:rgba(var(--ax-sys-color-primary-surface))!important}.ax-single-range-calendar .ax-range-start.ax-state-holiday,.ax-single-range-calendar .ax-range-end.ax-state-holiday{background-color:rgba(var(--ax-sys-color-danger-surface),.85)!important}.ax-single-range-calendar .ax-range-between{color:rgba(var(--ax-sys-color-on-primary-surface))!important;background-color:rgba(var(--ax-sys-color-primary-surface),.65)}.ax-single-range-calendar .ax-range-between.ax-state-holiday{background-color:rgba(var(--ax-sys-color-danger-surface),.65)}.ax-single-range-calendar ax-footer{display:flex;justify-content:center;border-color:rgba(var(--ax-comp-calendar-view-header-border-color));border-top-width:var(--ax-comp-calendar-view-header-border-width, 1px)}axp-page-content:not(:has(axm-task-board-status-grouped-grid-view,axm-task-board-time-grouped-grid-view)){overflow-y:hidden}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type:
2197
+ //
2198
+ AXMenuModule }, { kind: "component", type: i3$1.AXMenuItemComponent, selector: "ax-menu-item", inputs: ["name", "data", "disabled", "color"], outputs: ["onClick"] }, { kind: "component", type: i3$1.AXMenuComponent, selector: "ax-menu", inputs: ["orientation", "openOn", "closeOn", "items", "hasArrow"], outputs: ["onItemClick"] }, { kind: "component", type: i3$1.AXContextMenuComponent, selector: "ax-context-menu", inputs: ["orientation", "openOn", "closeOn", "items", "target"], outputs: ["onItemClick", "onOpening"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: i5$1.AXTranslatorDirective, selector: "[translate]" }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i5.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i5.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i7.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXBreadcrumbsModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i8.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXAccordionModule }, { kind: "ngmodule", type: AXAccordionCdkModule }, { kind: "directive", type: i9.AXAccordionGroupDirective, selector: "[axAccordionGroup]", inputs: ["accordion", "activeIndex", "collapsedOnItemClick"], exportAs: ["axAccordionGroup"] }, { kind: "directive", type: i9.AXAccordionItemContentDirective, selector: "[axAccordionItemContent]", inputs: ["transition"], exportAs: ["axAccordionItemContent"] }, { kind: "directive", type: i9.AXAccordionItemHeaderDirective, selector: "[axAccordionItemHeader]", exportAs: ["axAccordionItemHeader"] }, { kind: "directive", type: i9.AXAccordionItemDirective, selector: "[axAccordionItem]", inputs: ["isCollapsed"], outputs: ["isCollapsedChange", "onClick"], exportAs: ["axAccordionItem"] }, { kind: "component", type:
2199
+ //
2200
+ AXPThemeLayoutBlockComponent, selector: " axp-page-content, axp-page-footer-container, axp-page-footer, axp-page-header, axp-page-header-container, axp-page-toolbar, axp-layout-content, axp-layout-page-content, axp-layout-sections, axp-layout-body, axp-layout-page-body, axp-layout-prefix, axp-layout-suffix, axp-layout-title-bar, axp-layout-title, axp-layout-title-actions, axp-layout-nav-button, axp-layout-description, axp-layout-breadcrumbs, axp-layout-list-action, " }, { kind: "component", type: AXPPageLayoutComponent, selector: "axp-page-layout" }, { kind: "component", type: AXMTaskBoardCalendarViewComponent, selector: "axm-task-board-calendar-view", inputs: ["resources", "startingDate", "selectedView", "dataSource"], outputs: ["onTaskClick", "onTaskChanged", "onMonthSlotDblClicked", "onActionClick", "component", "onTaskRightClick", "onRangeChanged"] }, { kind: "component", type: AXMTaskBoardKanbanViewComponent, selector: "axm-task-board-kanban-view", inputs: ["tasks"], outputs: ["tasksChange", "onTaskClick", "onTaskChanged", "component", "onActionClick"] }, { kind: "component", type: AXMTaskBoardGridViewComponent, selector: "axm-task-board-grid-view", inputs: ["dataSource"], outputs: ["onTaskClick", "onActionClick"] }, { kind: "component", type: AXMTaskBoardStatusGroupedGridViewComponent, selector: "axm-task-board-status-grouped-grid-view", inputs: ["provider", "dataSource"], outputs: ["onActionClick"] }, { kind: "component", type: AXMTaskBoardDetailPanel, selector: "axm-task-board-detail-panel" }, { kind: "component", type: AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: AXCalendarComponent, selector: "ax-calendar", inputs: ["rtl", "readonly", "value", "name", "disabled", "depth", "activeView", "minValue", "maxValue", "disabledDates", "holidayDates", "type", "dayCellTemplate", "monthCellTemplate", "yearCellTemplate", "cellClass", "showNavigation", "count", "id", "weekend", "weekdays"], outputs: ["onOptionChanged", "valueChange", "onValueChanged", "minValueChange", "maxValueChange", "onBlur", "onFocus", "depthChange", "typeChange", "activeViewChange", "disabledDatesChange", "holidayDatesChange", "onNavigate", "onSlotClick", "countChange"] }, { kind: "component", type: AXMTaskBoardFiltersComponent, selector: "axm-task-board-filters", inputs: ["isQueryParam", "excludeTaskType"], outputs: ["applyClicked"] }, { kind: "ngmodule", type: AXCheckBoxModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "ngmodule", type: AXLabelModule }, { kind: "ngmodule", type: AXSelectionListModule }, { kind: "component", type: i10.AXSelectionListComponent, selector: "ax-selection-list", inputs: ["id", "name", "disabled", "readonly", "tabIndex", "size", "value", "valueField", "textField", "disabledField", "readonlyField", "multiple", "direction", "customTemplate", "showControl", "items", "look"], outputs: ["onValueChanged", "onBlur", "onFocus"] }, { kind: "component", type: AXPThemeLayoutStartSideComponent, selector: "axp-layout-page-start-side, axp-layout-start-side" }, { kind: "component", type: AXPThemeLayoutHeaderComponent, selector: "axp-layout-header" }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i5$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
2201
+ }
2202
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXMTaskBoardPage, decorators: [{
2203
+ type: Component,
2204
+ args: [{ imports: [
2205
+ FormsModule,
2206
+ CommonModule,
2207
+ RouterModule,
2208
+ //
2209
+ AXMenuModule,
2210
+ AXButtonModule,
2211
+ AXDropdownButtonModule,
2212
+ AXTranslationModule,
2213
+ AXDecoratorModule,
2214
+ AXLoadingModule,
2215
+ AXBreadcrumbsModule,
2216
+ AXBadgeModule,
2217
+ AXAccordionModule,
2218
+ AXAccordionCdkModule,
2219
+ //
2220
+ AXPThemeLayoutBlockComponent,
2221
+ AXPPageLayoutComponent,
2222
+ AXMTaskBoardCalendarViewComponent,
2223
+ AXMTaskBoardKanbanViewComponent,
2224
+ AXMTaskBoardGridViewComponent,
2225
+ AXMTaskBoardStatusGroupedGridViewComponent,
2226
+ AXMTaskBoardDetailPanel,
2227
+ AXDropdownPanelComponent,
2228
+ AXPopoverModule,
2229
+ AXCalendarComponent,
2230
+ AXMTaskBoardFiltersComponent,
2231
+ AXCheckBoxModule,
2232
+ AXFormModule,
2233
+ AXLabelModule,
2234
+ AXSelectionListModule,
2235
+ AXPThemeLayoutStartSideComponent,
2236
+ AXPThemeLayoutHeaderComponent,
2237
+ ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
2238
+ {
2239
+ provide: AXPPageLayoutBase,
2240
+ useExisting: AXMTaskBoardPage,
2241
+ },
2242
+ ], template: "<axp-page-layout *translate=\"let t\">\n <axp-layout-start-side class=\"ax-border-e ax-lightest-surface ax-h-full\">\n <axp-layout-header class=\"ax-p-4 ax-border-b\">\n <ng-container *ngTemplateOutlet=\"viewSelectorTemplate; context: { location: 'sidebar' }\"></ng-container>\n </axp-layout-header>\n\n <axp-layout-content class=\"ax-flex ax-flex-col ax-min-h-0 ax-overflow-y-auto\">\n <div class=\"ax-p-4 ax-flex ax-flex-col ax-gap-6\">\n <div class=\"ax-flex ax-flex-col ax-gap-3\">\n <!-- <h3 class=\"ax-text-sm ax-font-semibold ax-text-neutral-800 ax-uppercase ax-tracking-wide\">\n {{ (t('task-board.terms.calendar', { scope: rootConfig.config.i18n}) | async) }}\n </h3> -->\n <ax-calendar\n #sidebarCalendar\n [type]=\"calendarType()\"\n [depth]=\"calendarDepth()\"\n [cellClass]=\"getCellClass\"\n [ngModel]=\"currentDateForCalendar()\"\n [dayCellTemplate]=\"dayCellTemplate\"\n class=\"ax-single-range-calendar ax-border ax-rounded-lg\"\n (onSlotClick)=\"handleCalendarSlotClick($event)\"\n >\n </ax-calendar>\n </div>\n\n <div axAccordionGroup [accordion]=\"false\">\n <div\n class=\"ax-mb-2 ax-w-full ax-border ax-p-2 ax-rounded-lg\"\n axAccordionItem\n #taskTypeAccordion=\"axAccordionItem\"\n >\n <div\n class=\"ax-flex ax-items-center ax-justify-between ax-gap-2 ax-select-none ax-cursor-pointer\"\n axAccordionItemHeader\n >\n <h3 class=\"ax-text-sm ax-font-semibold\">\n {{ (t('task-board.filter.task-type', { scope: rootConfig.config.i18n}) | async)! }}\n </h3>\n <ax-icon\n [icon]=\"taskTypeAccordion?.isCollapsed() ? 'fa-light fa-chevron-down' : 'fa-light fa-chevron-up'\"\n class=\"ax-transition-transform\"\n ></ax-icon>\n </div>\n <div axAccordionItemContent>\n <div class=\"ax-pt-2\">\n <ax-selection-list\n [items]=\"taskTypeItems()\"\n [ngModel]=\"selectedTaskTypeValues()\"\n (onValueChanged)=\"handleTaskTypeSelectionChange($event.value)\"\n direction=\"vertical\"\n [multiple]=\"!isNonCalendarView()\"\n [showControl]=\"true\"\n valueField=\"id\"\n textField=\"text\"\n >\n <ng-template #itemTemplate let-item>\n <div class=\"ax-flex ax-items-center\">\n @if (item.icon) {\n <i [class]=\"item.icon\"></i>\n }\n <span [class]=\"item.icon ? 'ax-ml-2' : ''\">{{ item.text }}</span>\n </div>\n </ng-template>\n </ax-selection-list>\n </div>\n </div>\n </div>\n\n @if (!isNonCalendarView()) {\n <div\n class=\"ax-mb-2 ax-w-full ax-border ax-p-2 ax-rounded-lg\"\n axAccordionItem\n #calendarEventTypeAccordion=\"axAccordionItem\"\n >\n <div\n class=\"ax-flex ax-items-center ax-justify-between ax-gap-2 ax-select-none ax-cursor-pointer\"\n axAccordionItemHeader\n >\n <h3 class=\"ax-text-sm ax-font-semibold\">\n {{ ('@task-management:task-board.filter.calendars' | translate | async)! }}\n </h3>\n <ax-icon\n [icon]=\"calendarEventTypeAccordion?.isCollapsed() ? 'fa-light fa-chevron-down' : 'fa-light fa-chevron-up'\"\n class=\"ax-transition-transform\"\n ></ax-icon>\n </div>\n <div axAccordionItemContent>\n <div class=\"ax-pt-2\">\n <ax-selection-list\n [items]=\"calendarEventTypeItems()\"\n [ngModel]=\"selectedCalendarEventTypeValues()\"\n (onValueChanged)=\"handleCalendarEventTypeSelectionChange($event.value)\"\n direction=\"vertical\"\n [multiple]=\"true\"\n [showControl]=\"true\"\n valueField=\"id\"\n textField=\"text\"\n >\n <ng-template #itemTemplate let-item>\n <div class=\"ax-flex ax-items-center\">\n @if (item.icon) {\n <i [class]=\"item.icon\"></i>\n }\n <span [class]=\"item.icon ? 'ax-ml-2' : ''\">{{ item.text }}</span>\n </div>\n </ng-template>\n </ax-selection-list>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </axp-layout-content>\n </axp-layout-start-side>\n <axp-page-toolbar>\n <axp-layout-prefix class=\"sm:ax-flex-row ax-flex-col ax-items-start\">\n <div class=\"ax-scheduler-header ax-w-max ax-sm sm:ax-md\">\n <ax-button look=\"blank\" (onClick)=\"changeDate(false)\">\n <ax-icon class=\"ax-icon ax-text-xl ax-icon-chevron-left arrow-icon\"></ax-icon>\n </ax-button>\n <ax-button look=\"blank\" [text]=\"timeText()\" #date></ax-button>\n <ax-button look=\"blank\" (onClick)=\"changeDate(true)\">\n <ax-icon class=\"ax-icon ax-text-xl ax-icon-chevron-right arrow-icon\"></ax-icon>\n </ax-button>\n <!-- <ax-popover [target]=\"date\" [placement]=\"'bottom'\" #popover [adaptivityEnabled]=\"true\">\n <div class=\"ax-overlay-pane\">\n <ax-calendar\n #calendar\n [type]=\"calendarType()\"\n [depth]=\"calendarDepth()\"\n [cellClass]=\"getCellClass\"\n [ngModel]=\"vm.currentDate()\"\n class=\"ax-single-range-calendar\"\n (onSlotClick)=\"handleCalendarSlotClick($event)\"\n >\n <ax-footer>\n <ax-button\n look=\"link\"\n color=\"primary\"\n [text]=\"todayButtonText()\"\n (onClick)=\"handleTodayClick()\"\n ></ax-button>\n </ax-footer>\n </ax-calendar>\n </div>\n </ax-popover> -->\n </div>\n </axp-layout-prefix>\n\n <axp-layout-suffix>\n @if (deviceService.isSmall()) {\n <ax-button id=\"axp-toolbar-btn-filters\" (onClick)=\"toggleStartSide()\" [iconOnly]=\"true\" [color]=\"'default'\">\n <i class=\"fa-light fa-bars\"></i>\n </ax-button>\n }\n <!-- @if (!deviceService.isSmall()) {\n <ng-container *ngTemplateOutlet=\"viewSelectorTemplate; context: { location: 'toolbar' }\"></ng-container>\n } -->\n <ax-button [text]=\"t('task-board.filter.title', { scope: rootConfig.config.i18n }) | async\">\n <ax-prefix><ax-icon icon=\"fa-{{vm.activeFilterCount()?'solid':'light'}} fa-filter\"></ax-icon></ax-prefix>\n <ax-dropdown-panel #filterDropdownPanel (onOpened)=\"filtersComponent.resetContextToViewModel()\">\n <axm-task-board-filters\n #filtersComponent\n [isQueryParam]=\"isQueryParam()\"\n [excludeTaskType]=\"true\"\n (applyClicked)=\"filterDropdownPanel.close()\"\n ></axm-task-board-filters>\n </ax-dropdown-panel>\n </ax-button>\n\n <!-- @if(deviceService.isLarge()) {\n <ax-button (onClick)=\"vm.toggleDetailPanel()\">\n <ax-icon icon=\"{{ vm.isDetailPanelOpen() ? 'fa-solid fa-square-info' : 'fa-light fa-square-info' }}\"></ax-icon>\n </ax-button>\n } -->\n </axp-layout-suffix>\n </axp-page-toolbar>\n <axp-page-content class=\"ax-flex ax-flex-row ax-gap-2\">\n @if (isReady()) { @switch(vm.currentViewMode()) { @case('kanban') {\n <axm-task-board-kanban-view\n class=\"axp-kanban-container ax-h-full ax-w-full ax-min-w-0\"\n [tasks]=\"resolvedTasks()\"\n (onTaskClick)=\"vm.selectTask($event)\"\n (onActionClick)=\"handleContextMenu($event)\"\n ></axm-task-board-kanban-view>\n } @case('grid') {\n <axm-task-board-grid-view\n class=\"ax-h-full ax-w-full ax-min-w-0\"\n [dataSource]=\"gridDataSource\"\n (onTaskClick)=\"vm.selectTask($event)\"\n (onActionClick)=\"handleContextMenu($event)\"\n ></axm-task-board-grid-view>\n } @case('status-grouped-grid') {\n <axm-task-board-status-grouped-grid-view\n class=\"ax-flex ax-flex-col ax-gap-2 ax-w-full ax-min-w-0\"\n [dataSource]=\"gridDataSource\"\n (onActionClick)=\"handleContextMenu($event)\"\n ></axm-task-board-status-grouped-grid-view>\n } @default {\n <axm-task-board-calendar-view\n class=\"axp-scheduler-container ax-h-full ax-w-full ax-min-w-0\"\n [resources]=\"resources()\"\n [startingDate]=\"vm.currentDate()\"\n [dataSource]=\"schedulerDataSource\"\n (onTaskClick)=\"vm.selectTask($event)\"\n [selectedView]=\"vm.currentViewMode()\"\n (onActionClick)=\"handleContextMenu($event)\"\n (onTaskRightClick)=\"handleContextMenu($event)\"\n (component)=\"schedulerComponentChanged($event)\"\n (onMonthSlotDblClicked)=\"handleMonthSlotDblClicked($event)\"\n ></axm-task-board-calendar-view>\n } }\n <ax-context-menu\n #rootContextMenu\n [closeOn]=\"'leave'\"\n [orientation]=\"'vertical'\"\n (onOpening)=\"handleContextMenuOnOpening($event)\"\n (onItemClick)=\"handleContextMenuItemClick($event)\"\n >\n </ax-context-menu>\n @if (vm.isDetailPanelOpen() && deviceService.isLarge()) {\n <axm-task-board-detail-panel></axm-task-board-detail-panel>\n } } @else {\n <div class=\"ax-flex ax-items-center ax-justify-center ax-w-full ax-h-full\">\n <ax-loading></ax-loading>\n </div>\n }\n </axp-page-content>\n</axp-page-layout>\n\n<ng-template #viewSelectorTemplate let-location=\"location\">\n @if (location === 'sidebar') {\n <ax-button\n [text]=\"('@task-management:task-board.view.' + selectedViewMode().text | translate | async)!\"\n class=\"ax-w-full\"\n >\n <ax-prefix><ax-icon [icon]=\"selectedViewMode().icon\"></ax-icon></ax-prefix>\n <ax-dropdown-panel #sidebarDropdownPanel>\n <ax-menu [orientation]=\"'vertical'\" class=\"ax-menu-container\">\n @for (category of menuItems(); track category.key) {\n <ng-container>\n @if (category.children && category.children.length > 0) {\n <ax-menu-item>\n <ax-prefix>\n <ax-icon [icon]=\"category.icon\"></ax-icon>\n </ax-prefix>\n <ax-text>{{ ('@task-management:task-board.' + category.text | translate | async)! }}</ax-text>\n @for (child of category.children; track child.key) {\n <ax-menu-item (onClick)=\"handleViewChange(child.key, sidebarDropdownPanel)\">\n <ax-prefix>\n <ax-icon [icon]=\"child.icon\"></ax-icon>\n </ax-prefix>\n <ax-text>{{ ('@task-management:task-board.view.' + child.text | translate | async)! }}</ax-text>\n </ax-menu-item>\n }\n </ax-menu-item>\n } @else {\n <ax-menu-item (onClick)=\"handleViewChange(category.key, sidebarDropdownPanel)\">\n <ax-prefix>\n <ax-icon [icon]=\"category.icon\"></ax-icon>\n </ax-prefix>\n <ax-text>{{ ('@task-management:task-board.' + category.text | translate | async)! }}</ax-text>\n </ax-menu-item>\n }\n </ng-container>\n }\n </ax-menu>\n </ax-dropdown-panel>\n <ax-suffix>\n <ax-icon icon=\"fa-light fa-caret-down\"></ax-icon>\n </ax-suffix>\n </ax-button>\n } @else {\n <ax-button [text]=\"('@task-management:task-board.view.' + selectedViewMode().text | translate | async)!\">\n <ax-prefix><ax-icon [icon]=\"selectedViewMode().icon\"></ax-icon></ax-prefix>\n <ax-dropdown-panel #toolbarDropdownPanel>\n <ax-menu [orientation]=\"'vertical'\" class=\"ax-menu-container\">\n @for (category of menuItems(); track category.key) {\n <ng-container>\n @if (category.children && category.children.length > 0) {\n <ax-menu-item>\n <ax-prefix>\n <ax-icon [icon]=\"category.icon\"></ax-icon>\n </ax-prefix>\n <ax-text>{{ ('@task-management:task-board.' + category.text | translate | async)! }}</ax-text>\n @for (child of category.children; track child.key) {\n <ax-menu-item (onClick)=\"handleViewChange(child.key, toolbarDropdownPanel)\">\n <ax-prefix>\n <ax-icon [icon]=\"child.icon\"></ax-icon>\n </ax-prefix>\n <ax-text>{{ ('@task-management:task-board.view.' + child.text | translate | async)! }}</ax-text>\n </ax-menu-item>\n }\n </ax-menu-item>\n } @else {\n <ax-menu-item (onClick)=\"handleViewChange(category.key, toolbarDropdownPanel)\">\n <ax-prefix>\n <ax-icon [icon]=\"category.icon\"></ax-icon>\n </ax-prefix>\n <ax-text>{{ ('@task-management:task-board.' + category.text | translate | async)! }}</ax-text>\n </ax-menu-item>\n }\n </ng-container>\n }\n </ax-menu>\n </ax-dropdown-panel>\n <ax-suffix>\n <ax-icon icon=\"fa-light fa-caret-down\"></ax-icon>\n </ax-suffix>\n </ax-button>\n }\n</ng-template>\n\n<ng-template #dayCellTemplate let-slot>\n <div\n class=\"ax-flex ax-flex-col ax-items-center ax-justify-between ax-w-full ax-gap-1\"\n [style.padding-bottom]=\"'0.25rem'\"\n >\n <span class=\"ax-flex-1 ax-text-center\">{{ slot.slot.text ?? slot.slot.date?.day ?? '' }}</span>\n @if (slot.slot.date && getDayDataCount(slot.slot.date) > 0) {\n <ax-badge color=\"warning\"></ax-badge>\n }\n </div>\n</ng-template>\n", styles: ["html[dir=rtl] axp-page-layout axp-page-toolbar axp-layout-prefix .ax-scheduler-header .arrow-icon:before{-moz-transform:scale(-1,1);-webkit-transform:scale(-1,1);-o-transform:scale(-1,1);-ms-transform:scale(-1,1);transform:scaleX(-1)}.ax-single-range-calendar .ax-range-start,.ax-single-range-calendar .ax-range-end{color:rgba(var(--ax-sys-color-on-primary-surface))!important;background-color:rgba(var(--ax-sys-color-primary-surface),.85)!important}.ax-single-range-calendar .ax-range-start:hover,.ax-single-range-calendar .ax-range-end:hover{background-color:rgba(var(--ax-sys-color-primary-surface))!important}.ax-single-range-calendar .ax-range-start.ax-state-holiday,.ax-single-range-calendar .ax-range-end.ax-state-holiday{background-color:rgba(var(--ax-sys-color-danger-surface),.85)!important}.ax-single-range-calendar .ax-range-between{color:rgba(var(--ax-sys-color-on-primary-surface))!important;background-color:rgba(var(--ax-sys-color-primary-surface),.65)}.ax-single-range-calendar .ax-range-between.ax-state-holiday{background-color:rgba(var(--ax-sys-color-danger-surface),.65)}.ax-single-range-calendar ax-footer{display:flex;justify-content:center;border-color:rgba(var(--ax-comp-calendar-view-header-border-color));border-top-width:var(--ax-comp-calendar-view-header-border-width, 1px)}axp-page-content:not(:has(axm-task-board-status-grouped-grid-view,axm-task-board-time-grouped-grid-view)){overflow-y:hidden}\n"] }]
2243
+ }], propDecorators: { popover: [{ type: i0.ViewChild, args: ['popover', { isSignal: true }] }], calendar: [{ type: i0.ViewChild, args: ['calendar', { isSignal: true }] }], sidebarCalendar: [{ type: i0.ViewChild, args: ['sidebarCalendar', { isSignal: true }] }], dayCellTemplateRef: [{ type: i0.ViewChild, args: ['dayCellTemplate', { isSignal: true }] }], contextMenu: [{ type: i0.ViewChild, args: ['rootContextMenu', { isSignal: true }] }] } });
2244
+
2245
+ export { AXMTaskBoardPage };
2246
+ //# sourceMappingURL=acorex-modules-task-management-task-board.page-6D76WpRB.mjs.map