@acorex/modules 20.2.0-next.2 → 20.2.0-next.3
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.
- package/auth/index.d.ts +1 -0
- package/common/index.d.ts +1 -8
- package/contact-management/index.d.ts +69 -2
- package/conversation/README.md +1 -1
- package/conversation/index.d.ts +180 -121
- package/data-management/index.d.ts +5 -12
- package/document-management/index.d.ts +51 -4
- package/fesm2022/{acorex-modules-application-management-module-designer.component-udoks-Ef.mjs → acorex-modules-application-management-module-designer.component-CsZjqUAj.mjs} +7 -7
- package/fesm2022/{acorex-modules-application-management-module-designer.component-udoks-Ef.mjs.map → acorex-modules-application-management-module-designer.component-CsZjqUAj.mjs.map} +1 -1
- package/fesm2022/acorex-modules-application-management.mjs +41 -41
- package/fesm2022/acorex-modules-application-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-auth-acorex-modules-auth-BxqN76H7.mjs → acorex-modules-auth-acorex-modules-auth-tDyQQDnk.mjs} +50 -49
- package/fesm2022/acorex-modules-auth-acorex-modules-auth-tDyQQDnk.mjs.map +1 -0
- package/fesm2022/{acorex-modules-auth-app-chooser.component-5FbgqbVo.mjs → acorex-modules-auth-app-chooser.component-yu1DJZKN.mjs} +5 -5
- package/fesm2022/{acorex-modules-auth-app-chooser.component-5FbgqbVo.mjs.map → acorex-modules-auth-app-chooser.component-yu1DJZKN.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-blank.layout-C8NsXB9K.mjs → acorex-modules-auth-blank.layout-ZjroQcdq.mjs} +4 -4
- package/fesm2022/{acorex-modules-auth-blank.layout-C8NsXB9K.mjs.map → acorex-modules-auth-blank.layout-ZjroQcdq.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-login.module-CmMM4TpQ.mjs → acorex-modules-auth-login.module-D1aa1F6G.mjs} +8 -8
- package/fesm2022/{acorex-modules-auth-login.module-CmMM4TpQ.mjs.map → acorex-modules-auth-login.module-D1aa1F6G.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-master.layout-eX5-7AeO.mjs → acorex-modules-auth-master.layout-CGQmSlGQ.mjs} +5 -5
- package/fesm2022/{acorex-modules-auth-master.layout-eX5-7AeO.mjs.map → acorex-modules-auth-master.layout-CGQmSlGQ.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-oauth-callback.component-C9s-5c7F.mjs → acorex-modules-auth-oauth-callback.component-m9YiJ4e9.mjs} +5 -5
- package/fesm2022/{acorex-modules-auth-oauth-callback.component-C9s-5c7F.mjs.map → acorex-modules-auth-oauth-callback.component-m9YiJ4e9.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-password.component-CDrYHh1x.mjs → acorex-modules-auth-password.component-Cb3FJ1DZ.mjs} +5 -5
- package/fesm2022/{acorex-modules-auth-password.component-CDrYHh1x.mjs.map → acorex-modules-auth-password.component-Cb3FJ1DZ.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-password.component-r_Lh8oGN.mjs → acorex-modules-auth-password.component-CiWdX7f_.mjs} +5 -5
- package/fesm2022/{acorex-modules-auth-password.component-r_Lh8oGN.mjs.map → acorex-modules-auth-password.component-CiWdX7f_.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-routes-CMdsDZud.mjs → acorex-modules-auth-routes-pae8qpX9.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-routes-CMdsDZud.mjs.map → acorex-modules-auth-routes-pae8qpX9.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-tenant-chooser.component-BdK5T-8X.mjs → acorex-modules-auth-tenant-chooser.component-Bk0l3XoV.mjs} +4 -4
- package/fesm2022/{acorex-modules-auth-tenant-chooser.component-BdK5T-8X.mjs.map → acorex-modules-auth-tenant-chooser.component-Bk0l3XoV.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-two-factor-code.component-DSWd06bn.mjs → acorex-modules-auth-two-factor-code.component-DDEIajiI.mjs} +4 -4
- package/fesm2022/{acorex-modules-auth-two-factor-code.component-DSWd06bn.mjs.map → acorex-modules-auth-two-factor-code.component-DDEIajiI.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-two-factor.module-YV9pDOnB.mjs → acorex-modules-auth-two-factor.module-DtcoHPH4.mjs} +7 -7
- package/fesm2022/{acorex-modules-auth-two-factor.module-YV9pDOnB.mjs.map → acorex-modules-auth-two-factor.module-DtcoHPH4.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-user-sessions.component-KI9dYs78.mjs → acorex-modules-auth-user-sessions.component-sI6P2joA.mjs} +5 -5
- package/fesm2022/{acorex-modules-auth-user-sessions.component-KI9dYs78.mjs.map → acorex-modules-auth-user-sessions.component-sI6P2joA.mjs.map} +1 -1
- package/fesm2022/acorex-modules-auth.mjs +1 -1
- package/fesm2022/acorex-modules-calendar-management.mjs +22 -22
- package/fesm2022/acorex-modules-calendar-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-common-search-popup.component-DbTj01Wz.mjs → acorex-modules-common-search-popup.component-D7Y4T3Rp.mjs} +8 -8
- package/fesm2022/{acorex-modules-common-search-popup.component-DbTj01Wz.mjs.map → acorex-modules-common-search-popup.component-D7Y4T3Rp.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-common-timeline-version-history-popup.component-D_6STmWm.mjs → acorex-modules-common-timeline-version-history-popup.component-ceEtE6qB.mjs} +7 -7
- package/fesm2022/{acorex-modules-common-timeline-version-history-popup.component-D_6STmWm.mjs.map → acorex-modules-common-timeline-version-history-popup.component-ceEtE6qB.mjs.map} +1 -1
- package/fesm2022/acorex-modules-common.mjs +1222 -1
- package/fesm2022/acorex-modules-common.mjs.map +1 -1
- package/fesm2022/{acorex-modules-contact-management-acorex-modules-contact-management-CM72FkGM.mjs → acorex-modules-contact-management-acorex-modules-contact-management-Co0tt3cj.mjs} +281 -54
- package/fesm2022/acorex-modules-contact-management-acorex-modules-contact-management-Co0tt3cj.mjs.map +1 -0
- package/fesm2022/{acorex-modules-contact-management-address-type.entity-CW0fx3v8.mjs → acorex-modules-contact-management-address-type.entity-DQZwgXki.mjs} +2 -2
- package/fesm2022/{acorex-modules-contact-management-address-type.entity-CW0fx3v8.mjs.map → acorex-modules-contact-management-address-type.entity-DQZwgXki.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-contact-management-contact-address.entity-D5OGWsSx.mjs → acorex-modules-contact-management-contact-address.entity-CFfRywsB.mjs} +2 -2
- package/fesm2022/{acorex-modules-contact-management-contact-address.entity-D5OGWsSx.mjs.map → acorex-modules-contact-management-contact-address.entity-CFfRywsB.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-contact-management-contact-method.entity-Cpdd-Xwb.mjs → acorex-modules-contact-management-contact-method.entity-Ci93_mb9.mjs} +2 -2
- package/fesm2022/{acorex-modules-contact-management-contact-method.entity-Cpdd-Xwb.mjs.map → acorex-modules-contact-management-contact-method.entity-Ci93_mb9.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-contact-management-contact-relationship.entity-B_gQ7mEo.mjs → acorex-modules-contact-management-contact-relationship.entity-CqdXpqLN.mjs} +2 -2
- package/fesm2022/{acorex-modules-contact-management-contact-relationship.entity-B_gQ7mEo.mjs.map → acorex-modules-contact-management-contact-relationship.entity-CqdXpqLN.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-contact-management-contact-source.entity-BwYBaS8B.mjs → acorex-modules-contact-management-contact-source.entity-BsF9p0GK.mjs} +2 -2
- package/fesm2022/{acorex-modules-contact-management-contact-source.entity-BwYBaS8B.mjs.map → acorex-modules-contact-management-contact-source.entity-BsF9p0GK.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-contact-management-emergency-contact-category.entity-CDbm4Rq3.mjs → acorex-modules-contact-management-emergency-contact-category.entity-DjOm8qQb.mjs} +2 -2
- package/fesm2022/{acorex-modules-contact-management-emergency-contact-category.entity-CDbm4Rq3.mjs.map → acorex-modules-contact-management-emergency-contact-category.entity-DjOm8qQb.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-contact-management-emergency-contact.entity-BpNDJPVs.mjs → acorex-modules-contact-management-emergency-contact.entity-BQyjzPR8.mjs} +2 -2
- package/fesm2022/{acorex-modules-contact-management-emergency-contact.entity-BpNDJPVs.mjs.map → acorex-modules-contact-management-emergency-contact.entity-BQyjzPR8.mjs.map} +1 -1
- package/fesm2022/acorex-modules-contact-management.mjs +1 -1
- package/fesm2022/acorex-modules-content-management.mjs +14 -36
- package/fesm2022/acorex-modules-content-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-conversation.mjs +1549 -1324
- package/fesm2022/acorex-modules-conversation.mjs.map +1 -1
- package/fesm2022/acorex-modules-dashboard-management.mjs +76 -75
- package/fesm2022/acorex-modules-dashboard-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-data-management.mjs +140 -126
- package/fesm2022/acorex-modules-data-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-document-management-acorex-modules-document-management-C7ot6PfT.mjs → acorex-modules-document-management-acorex-modules-document-management-DXGX-riG.mjs} +1402 -389
- package/fesm2022/acorex-modules-document-management-acorex-modules-document-management-DXGX-riG.mjs.map +1 -0
- package/fesm2022/{acorex-modules-document-management-attachment-widget.component-C6pop0RM.mjs → acorex-modules-document-management-attachment-widget.component-NaY7Mn95.mjs} +5 -5
- package/fesm2022/{acorex-modules-document-management-attachment-widget.component-C6pop0RM.mjs.map → acorex-modules-document-management-attachment-widget.component-NaY7Mn95.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-create-folder-dialog.component-ga7fuY4H.mjs → acorex-modules-document-management-create-folder-dialog.component-epxEuBU5.mjs} +5 -5
- package/fesm2022/{acorex-modules-document-management-create-folder-dialog.component-ga7fuY4H.mjs.map → acorex-modules-document-management-create-folder-dialog.component-epxEuBU5.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-details-view.component-CzTg3hha.mjs → acorex-modules-document-management-details-view.component-CMI2Eokj.mjs} +5 -5
- package/fesm2022/{acorex-modules-document-management-details-view.component-CzTg3hha.mjs.map → acorex-modules-document-management-details-view.component-CMI2Eokj.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-drive-choose.component-BB5d32EI.mjs → acorex-modules-document-management-drive-choose.component-DBKgwm70.mjs} +5 -5
- package/fesm2022/{acorex-modules-document-management-drive-choose.component-BB5d32EI.mjs.map → acorex-modules-document-management-drive-choose.component-DBKgwm70.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-drive.component-TzRLr7rb.mjs → acorex-modules-document-management-drive.component-DoGdTL3n.mjs} +11 -10
- package/fesm2022/acorex-modules-document-management-drive.component-DoGdTL3n.mjs.map +1 -0
- package/fesm2022/{acorex-modules-document-management-large-icons-view.component-BeKFvgYU.mjs → acorex-modules-document-management-large-icons-view.component-BRsTSoln.mjs} +5 -5
- package/fesm2022/{acorex-modules-document-management-large-icons-view.component-BeKFvgYU.mjs.map → acorex-modules-document-management-large-icons-view.component-BRsTSoln.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-large-tiles-view.component-CQyiGE99.mjs → acorex-modules-document-management-large-tiles-view.component-CpYeYyR5.mjs} +5 -5
- package/fesm2022/{acorex-modules-document-management-large-tiles-view.component-CQyiGE99.mjs.map → acorex-modules-document-management-large-tiles-view.component-CpYeYyR5.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-link-dialog.component-CPuOuvu-.mjs → acorex-modules-document-management-link-dialog.component-ZteosW8O.mjs} +4 -4
- package/fesm2022/{acorex-modules-document-management-link-dialog.component-CPuOuvu-.mjs.map → acorex-modules-document-management-link-dialog.component-ZteosW8O.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-list-view.component-CWGGArxw.mjs → acorex-modules-document-management-list-view.component-C4VFnACA.mjs} +5 -5
- package/fesm2022/{acorex-modules-document-management-list-view.component-CWGGArxw.mjs.map → acorex-modules-document-management-list-view.component-C4VFnACA.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-meta-choose-popup.component-C7ounW6N.mjs → acorex-modules-document-management-meta-choose-popup.component-D5Csi3A3.mjs} +4 -4
- package/fesm2022/{acorex-modules-document-management-meta-choose-popup.component-C7ounW6N.mjs.map → acorex-modules-document-management-meta-choose-popup.component-D5Csi3A3.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-meta-selector-widget-column.component-C_J1rPak.mjs → acorex-modules-document-management-meta-selector-widget-column.component-OXeS0kW8.mjs} +4 -4
- package/fesm2022/{acorex-modules-document-management-meta-selector-widget-column.component-C_J1rPak.mjs.map → acorex-modules-document-management-meta-selector-widget-column.component-OXeS0kW8.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-meta-selector-widget-designer.component-By_NgUX6.mjs → acorex-modules-document-management-meta-selector-widget-designer.component-BdVSGb3M.mjs} +4 -4
- package/fesm2022/{acorex-modules-document-management-meta-selector-widget-designer.component-By_NgUX6.mjs.map → acorex-modules-document-management-meta-selector-widget-designer.component-BdVSGb3M.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-meta-selector-widget-view.component-zwCw3v1w.mjs → acorex-modules-document-management-meta-selector-widget-view.component-B-Vos30P.mjs} +4 -4
- package/fesm2022/{acorex-modules-document-management-meta-selector-widget-view.component-zwCw3v1w.mjs.map → acorex-modules-document-management-meta-selector-widget-view.component-B-Vos30P.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-permission-definition.provider-s0P0M8p2.mjs → acorex-modules-document-management-permission-definition.provider-Bc7rbWwN.mjs} +10 -2
- package/fesm2022/acorex-modules-document-management-permission-definition.provider-Bc7rbWwN.mjs.map +1 -0
- package/fesm2022/{acorex-modules-document-management-rename-node-dialog.component-MPkYZl2p.mjs → acorex-modules-document-management-rename-node-dialog.component-DWUVMrVt.mjs} +5 -5
- package/fesm2022/{acorex-modules-document-management-rename-node-dialog.component-MPkYZl2p.mjs.map → acorex-modules-document-management-rename-node-dialog.component-DWUVMrVt.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-share-dialog.component-CLF6b1Io.mjs → acorex-modules-document-management-share-dialog.component-CkyuEAwV.mjs} +4 -4
- package/fesm2022/{acorex-modules-document-management-share-dialog.component-CLF6b1Io.mjs.map → acorex-modules-document-management-share-dialog.component-CkyuEAwV.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-share-email-dialog.component-B8zNvOUv.mjs → acorex-modules-document-management-share-email-dialog.component-DXjcTOny.mjs} +4 -4
- package/fesm2022/{acorex-modules-document-management-share-email-dialog.component-B8zNvOUv.mjs.map → acorex-modules-document-management-share-email-dialog.component-DXjcTOny.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-small-icons-view.component-DRVLlW1e.mjs → acorex-modules-document-management-small-icons-view.component-CCirsfoz.mjs} +5 -5
- package/fesm2022/{acorex-modules-document-management-small-icons-view.component-DRVLlW1e.mjs.map → acorex-modules-document-management-small-icons-view.component-CCirsfoz.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-document-management-small-tiles-view.component-C1E8RKYM.mjs → acorex-modules-document-management-small-tiles-view.component-58KZSQC4.mjs} +5 -5
- package/fesm2022/{acorex-modules-document-management-small-tiles-view.component-C1E8RKYM.mjs.map → acorex-modules-document-management-small-tiles-view.component-58KZSQC4.mjs.map} +1 -1
- package/fesm2022/acorex-modules-document-management.mjs +1 -1
- package/fesm2022/{acorex-modules-form-template-management-acorex-modules-form-template-management-zz8KU2BM.mjs → acorex-modules-form-template-management-acorex-modules-form-template-management-DxSYInAR.mjs} +65 -67
- package/fesm2022/acorex-modules-form-template-management-acorex-modules-form-template-management-DxSYInAR.mjs.map +1 -0
- package/fesm2022/{acorex-modules-form-template-management-category.entity-g5YGQjj3.mjs → acorex-modules-form-template-management-category.entity-DeCfvNqF.mjs} +2 -2
- package/fesm2022/{acorex-modules-form-template-management-category.entity-g5YGQjj3.mjs.map → acorex-modules-form-template-management-category.entity-DeCfvNqF.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-form-template-management-designer.page-DQorNK3f.mjs → acorex-modules-form-template-management-designer.page-BsjFGFOD.mjs} +4 -4
- package/fesm2022/{acorex-modules-form-template-management-designer.page-DQorNK3f.mjs.map → acorex-modules-form-template-management-designer.page-BsjFGFOD.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-form-template-management-permission-definition.provider-BFPqDVO3.mjs → acorex-modules-form-template-management-permission-definition.provider-CsjgxSgC.mjs} +2 -2
- package/fesm2022/{acorex-modules-form-template-management-permission-definition.provider-BFPqDVO3.mjs.map → acorex-modules-form-template-management-permission-definition.provider-CsjgxSgC.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-form-template-management-settings.provider-DYbrgJI7.mjs → acorex-modules-form-template-management-settings.provider-_BIGyRt8.mjs} +2 -2
- package/fesm2022/{acorex-modules-form-template-management-settings.provider-DYbrgJI7.mjs.map → acorex-modules-form-template-management-settings.provider-_BIGyRt8.mjs.map} +1 -1
- package/fesm2022/acorex-modules-form-template-management-template-picker.component-BCg756yD.mjs +224 -0
- package/fesm2022/acorex-modules-form-template-management-template-picker.component-BCg756yD.mjs.map +1 -0
- package/fesm2022/{acorex-modules-form-template-management-template-widget-edit.component-CCL7xNSm.mjs → acorex-modules-form-template-management-template-widget-edit.component-DkqRsXMq.mjs} +5 -5
- package/fesm2022/{acorex-modules-form-template-management-template-widget-edit.component-CCL7xNSm.mjs.map → acorex-modules-form-template-management-template-widget-edit.component-DkqRsXMq.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-form-template-management-template.entity-XNBsmQZY.mjs → acorex-modules-form-template-management-template.entity-CQm29n5v.mjs} +2 -2
- package/fesm2022/{acorex-modules-form-template-management-template.entity-XNBsmQZY.mjs.map → acorex-modules-form-template-management-template.entity-CQm29n5v.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-form-template-management-viewer-popup.component-Bw9VbGx7.mjs → acorex-modules-form-template-management-viewer-popup.component-DW2Z5EcJ.mjs} +12 -19
- package/fesm2022/acorex-modules-form-template-management-viewer-popup.component-DW2Z5EcJ.mjs.map +1 -0
- package/fesm2022/acorex-modules-form-template-management.mjs +1 -1
- package/fesm2022/{acorex-modules-issue-management-acorex-modules-issue-management-ITP4K-tZ.mjs → acorex-modules-issue-management-acorex-modules-issue-management-a_wcGVPh.mjs} +31 -35
- package/fesm2022/acorex-modules-issue-management-acorex-modules-issue-management-a_wcGVPh.mjs.map +1 -0
- package/fesm2022/{acorex-modules-issue-management-capture-screen.component-C1USFJeP.mjs → acorex-modules-issue-management-capture-screen.component-CsahsE-E.mjs} +5 -5
- package/fesm2022/{acorex-modules-issue-management-capture-screen.component-C1USFJeP.mjs.map → acorex-modules-issue-management-capture-screen.component-CsahsE-E.mjs.map} +1 -1
- package/fesm2022/acorex-modules-issue-management.mjs +1 -1
- package/fesm2022/acorex-modules-locale-management-acorex-modules-locale-management-CfaOC6U5.mjs +1975 -0
- package/fesm2022/acorex-modules-locale-management-acorex-modules-locale-management-CfaOC6U5.mjs.map +1 -0
- package/fesm2022/acorex-modules-locale-management-profiles-MJ9xFTtp.mjs +19 -0
- package/fesm2022/acorex-modules-locale-management-profiles-MJ9xFTtp.mjs.map +1 -0
- package/fesm2022/{acorex-modules-common-settings.provider-DPVsF4c9.mjs → acorex-modules-locale-management-settings.provider-PKnqTses.mjs} +6 -6
- package/fesm2022/acorex-modules-locale-management-settings.provider-PKnqTses.mjs.map +1 -0
- package/fesm2022/acorex-modules-locale-management.mjs +2 -0
- package/fesm2022/acorex-modules-locale-management.mjs.map +1 -0
- package/fesm2022/acorex-modules-location-management.mjs +3139 -0
- package/fesm2022/acorex-modules-location-management.mjs.map +1 -0
- package/fesm2022/acorex-modules-log-management.mjs +160 -35
- package/fesm2022/acorex-modules-log-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-notification-management.mjs +149 -123
- package/fesm2022/acorex-modules-notification-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-organization-management-add-item.component-Dr-bwC4K.mjs → acorex-modules-organization-management-add-item.component-CzIIXsRJ.mjs} +4 -4
- package/fesm2022/{acorex-modules-organization-management-add-item.component-Dr-bwC4K.mjs.map → acorex-modules-organization-management-add-item.component-CzIIXsRJ.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-organization-management-org-chart-configuration.page-a2JPiCy9.mjs → acorex-modules-organization-management-org-chart-configuration.page-XXAEpYNo.mjs} +5 -5
- package/fesm2022/{acorex-modules-organization-management-org-chart-configuration.page-a2JPiCy9.mjs.map → acorex-modules-organization-management-org-chart-configuration.page-XXAEpYNo.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-organization-management-org-chart-configuration.service-BkfSow3s.mjs → acorex-modules-organization-management-org-chart-configuration.service-CIveMQUH.mjs} +4 -4
- package/fesm2022/{acorex-modules-organization-management-org-chart-configuration.service-BkfSow3s.mjs.map → acorex-modules-organization-management-org-chart-configuration.service-CIveMQUH.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-organization-management-org-chart.page-CXhtYrCS.mjs → acorex-modules-organization-management-org-chart.page-UqJ1VOJ-.mjs} +15 -14
- package/fesm2022/acorex-modules-organization-management-org-chart.page-UqJ1VOJ-.mjs.map +1 -0
- package/fesm2022/{acorex-modules-organization-management-settings.provider-hlbUXugb.mjs → acorex-modules-organization-management-settings.provider-feVwZnkw.mjs} +6 -30
- package/fesm2022/acorex-modules-organization-management-settings.provider-feVwZnkw.mjs.map +1 -0
- package/fesm2022/acorex-modules-organization-management.mjs +128 -124
- package/fesm2022/acorex-modules-organization-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-platform-management-list-version.component-BOfUQDwo.mjs → acorex-modules-platform-management-list-version.component-wqhq6ek4.mjs} +4 -4
- package/fesm2022/{acorex-modules-platform-management-list-version.component-BOfUQDwo.mjs.map → acorex-modules-platform-management-list-version.component-wqhq6ek4.mjs.map} +1 -1
- package/fesm2022/acorex-modules-platform-management.mjs +91 -303
- package/fesm2022/acorex-modules-platform-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-project-management.mjs +232 -453
- package/fesm2022/acorex-modules-project-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-report-management-report-create-root.component-Cv88TDx7.mjs → acorex-modules-report-management-report-create-root.component-CFNtnshF.mjs} +4 -4
- package/fesm2022/{acorex-modules-report-management-report-create-root.component-Cv88TDx7.mjs.map → acorex-modules-report-management-report-create-root.component-CFNtnshF.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-report-management-report-runner-root-page.component-DHu-kyCd.mjs → acorex-modules-report-management-report-runner-root-page.component-CbfJ_7Da.mjs} +7 -7
- package/fesm2022/{acorex-modules-report-management-report-runner-root-page.component-DHu-kyCd.mjs.map → acorex-modules-report-management-report-runner-root-page.component-CbfJ_7Da.mjs.map} +1 -1
- package/fesm2022/acorex-modules-report-management.mjs +24 -24
- package/fesm2022/acorex-modules-report-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-scheduler-job-management.mjs +14 -14
- package/fesm2022/acorex-modules-scheduler-job-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-security-management.mjs +97 -61
- package/fesm2022/acorex-modules-security-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-settings-management-setting-page.component-cG4ykm2g.mjs → acorex-modules-settings-management-setting-page.component-BhF5x-8D.mjs} +12 -6
- package/fesm2022/acorex-modules-settings-management-setting-page.component-BhF5x-8D.mjs.map +1 -0
- package/fesm2022/{acorex-modules-settings-management-setting-view.component-CrEK2N1U.mjs → acorex-modules-settings-management-setting-view.component-Do_gNJ2t.mjs} +4 -4
- package/fesm2022/{acorex-modules-settings-management-setting-view.component-CrEK2N1U.mjs.map → acorex-modules-settings-management-setting-view.component-Do_gNJ2t.mjs.map} +1 -1
- package/fesm2022/acorex-modules-settings-management.mjs +9 -7
- package/fesm2022/acorex-modules-settings-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-task-management.mjs +5937 -0
- package/fesm2022/acorex-modules-task-management.mjs.map +1 -0
- package/fesm2022/acorex-modules-text-template-management.mjs +24 -24
- package/fesm2022/acorex-modules-text-template-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-training-management.mjs +43 -43
- package/fesm2022/acorex-modules-training-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-workflow-management-acorex-modules-workflow-management-DnSdOSmj.mjs → acorex-modules-workflow-management-acorex-modules-workflow-management-DC7jdoqZ.mjs} +60 -29
- package/fesm2022/acorex-modules-workflow-management-acorex-modules-workflow-management-DC7jdoqZ.mjs.map +1 -0
- package/fesm2022/{acorex-modules-workflow-management-task-board.page-Bzu4j4VW.mjs → acorex-modules-workflow-management-task-board.page-Bv2GAPaN.mjs} +197 -183
- package/fesm2022/acorex-modules-workflow-management-task-board.page-Bv2GAPaN.mjs.map +1 -0
- package/fesm2022/acorex-modules-workflow-management.mjs +1 -1
- package/locale-management/README.md +3 -0
- package/locale-management/index.d.ts +182 -0
- package/location-management/README.md +3 -0
- package/location-management/index.d.ts +166 -0
- package/notification-management/index.d.ts +14 -5
- package/package.json +17 -5
- package/task-management/README.md +189 -0
- package/task-management/index.d.ts +320 -0
- package/workflow-management/index.d.ts +8 -3
- package/fesm2022/acorex-modules-auth-acorex-modules-auth-BxqN76H7.mjs.map +0 -1
- package/fesm2022/acorex-modules-common-acorex-modules-common-D06CT4CO.mjs +0 -1657
- package/fesm2022/acorex-modules-common-acorex-modules-common-D06CT4CO.mjs.map +0 -1
- package/fesm2022/acorex-modules-common-settings.provider-DPVsF4c9.mjs.map +0 -1
- package/fesm2022/acorex-modules-contact-management-acorex-modules-contact-management-CM72FkGM.mjs.map +0 -1
- package/fesm2022/acorex-modules-document-management-acorex-modules-document-management-C7ot6PfT.mjs.map +0 -1
- package/fesm2022/acorex-modules-document-management-drive.component-TzRLr7rb.mjs.map +0 -1
- package/fesm2022/acorex-modules-document-management-permission-definition.provider-s0P0M8p2.mjs.map +0 -1
- package/fesm2022/acorex-modules-form-template-management-acorex-modules-form-template-management-zz8KU2BM.mjs.map +0 -1
- package/fesm2022/acorex-modules-form-template-management-template-picker.component-DgH_DUIB.mjs +0 -196
- package/fesm2022/acorex-modules-form-template-management-template-picker.component-DgH_DUIB.mjs.map +0 -1
- package/fesm2022/acorex-modules-form-template-management-viewer-popup.component-Bw9VbGx7.mjs.map +0 -1
- package/fesm2022/acorex-modules-issue-management-acorex-modules-issue-management-ITP4K-tZ.mjs.map +0 -1
- package/fesm2022/acorex-modules-organization-management-org-chart.page-CXhtYrCS.mjs.map +0 -1
- package/fesm2022/acorex-modules-organization-management-settings.provider-hlbUXugb.mjs.map +0 -1
- package/fesm2022/acorex-modules-settings-management-setting-page.component-cG4ykm2g.mjs.map +0 -1
- package/fesm2022/acorex-modules-workflow-management-acorex-modules-workflow-management-DnSdOSmj.mjs.map +0 -1
- package/fesm2022/acorex-modules-workflow-management-task-board.page-Bzu4j4VW.mjs.map +0 -1
|
@@ -6,14 +6,16 @@ import { AXPRootLayoutComponent } from '@acorex/platform/themes/default';
|
|
|
6
6
|
import * as i1$2 from '@angular/common';
|
|
7
7
|
import { AsyncPipe, CommonModule, DatePipe } from '@angular/common';
|
|
8
8
|
import * as i0 from '@angular/core';
|
|
9
|
-
import { Injectable, inject, input, signal, viewChild, DestroyRef, ChangeDetectionStrategy, Component, ViewEncapsulation, computed, output, effect, HostListener, afterNextRender, importProvidersFrom, NgModule } from '@angular/core';
|
|
9
|
+
import { Injectable, inject, input, signal, viewChild, DestroyRef, ChangeDetectionStrategy, Component, ViewEncapsulation, computed, output, effect, HostListener, afterNextRender, Injector, importProvidersFrom, NgModule } from '@angular/core';
|
|
10
10
|
import * as i2$3 from '@angular/router';
|
|
11
|
-
import {
|
|
11
|
+
import { Router, ActivatedRoute, NavigationEnd, RouterModule, ROUTES } from '@angular/router';
|
|
12
12
|
import { createAllQueryView, AXPEntityCommandScope, AXPEntityQueryType, AXPFilterOperatorMiddlewareService, AXP_MENU_PROVIDER } from '@acorex/platform/common';
|
|
13
13
|
import * as i2$1 from '@acorex/platform/layout/builder';
|
|
14
14
|
import { AXPWidgetsCatalog, AXPLayoutBuilderModule, AXPValueWidgetComponent, AXPWidgetGroupEnum } from '@acorex/platform/layout/builder';
|
|
15
15
|
import * as i2$5 from '@acorex/platform/workflow';
|
|
16
16
|
import { AXPWorkflowAction, AXPWorkflowModule } from '@acorex/platform/workflow';
|
|
17
|
+
import { AXMUsersEntityService } from '@acorex/modules/security-management';
|
|
18
|
+
import { Subject, filter, startWith, debounceTime } from 'rxjs';
|
|
17
19
|
import * as i3 from '@acorex/components/avatar';
|
|
18
20
|
import { AXAvatarModule } from '@acorex/components/avatar';
|
|
19
21
|
import * as i2$2 from '@acorex/components/badge';
|
|
@@ -53,14 +55,12 @@ import { AXFormatModule } from '@acorex/core/format';
|
|
|
53
55
|
import * as i4$1 from '@acorex/core/translation';
|
|
54
56
|
import { AXTranslationModule, AXTranslationService } from '@acorex/core/translation';
|
|
55
57
|
import { AXUnsubscriber } from '@acorex/core/utils';
|
|
56
|
-
import {
|
|
58
|
+
import { AXMNotificationConnectorService, AXP_NOTIFICATION_DEFINITION_PROVIDER } from '@acorex/modules/notification-management';
|
|
57
59
|
import { AXPUserAvatarComponent, AXPThemeLayoutBlockComponent, AXPThemeLayoutStartSideComponent, AXPThemeLayoutHeaderComponent, AXPThemeLayoutToolbarComponent } from '@acorex/platform/layout/components';
|
|
58
60
|
import { AXPPageLayoutBaseComponent, AXPPageLayoutComponent, AXPPageLayoutBase } from '@acorex/platform/layout/views';
|
|
59
61
|
import { trigger, transition, style, animate } from '@angular/animations';
|
|
60
62
|
import * as i10 from '@angular/forms';
|
|
61
63
|
import { FormsModule } from '@angular/forms';
|
|
62
|
-
import { Subject, filter, startWith } from 'rxjs';
|
|
63
|
-
import { AXMUsersEntityService } from '@acorex/modules/security-management';
|
|
64
64
|
import { AXToastService } from '@acorex/components/toast';
|
|
65
65
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
66
66
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
@@ -109,10 +109,10 @@ class AXMMessageServiceImpl extends AXMMessageService {
|
|
|
109
109
|
constructor() {
|
|
110
110
|
super(`${RootConfig.module.name}.${RootConfig.entities.message.name}`);
|
|
111
111
|
}
|
|
112
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
113
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.
|
|
112
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMMessageServiceImpl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
113
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMMessageServiceImpl }); }
|
|
114
114
|
}
|
|
115
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
115
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMMessageServiceImpl, decorators: [{
|
|
116
116
|
type: Injectable
|
|
117
117
|
}], ctorParameters: () => [] });
|
|
118
118
|
|
|
@@ -387,10 +387,10 @@ class AXMRoomServiceImpl extends AXMRoomService {
|
|
|
387
387
|
constructor() {
|
|
388
388
|
super(`${RootConfig.module.name}.${RootConfig.entities.room.name}`);
|
|
389
389
|
}
|
|
390
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
391
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.
|
|
390
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMRoomServiceImpl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
391
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMRoomServiceImpl }); }
|
|
392
392
|
}
|
|
393
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
393
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMRoomServiceImpl, decorators: [{
|
|
394
394
|
type: Injectable
|
|
395
395
|
}], ctorParameters: () => [] });
|
|
396
396
|
|
|
@@ -663,10 +663,10 @@ class AXMConversationTabServiceImpl extends AXMConversationTabService {
|
|
|
663
663
|
constructor() {
|
|
664
664
|
super(`${RootConfig.module.name}.${RootConfig.entities.tab.name}`);
|
|
665
665
|
}
|
|
666
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
667
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.
|
|
666
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMConversationTabServiceImpl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
667
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMConversationTabServiceImpl }); }
|
|
668
668
|
}
|
|
669
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
669
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMConversationTabServiceImpl, decorators: [{
|
|
670
670
|
type: Injectable
|
|
671
671
|
}], ctorParameters: () => [] });
|
|
672
672
|
|
|
@@ -908,10 +908,10 @@ class AXMConversationModuleEntityProvider {
|
|
|
908
908
|
return null;
|
|
909
909
|
}
|
|
910
910
|
}
|
|
911
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
912
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.
|
|
911
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMConversationModuleEntityProvider, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
912
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMConversationModuleEntityProvider }); }
|
|
913
913
|
}
|
|
914
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
914
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMConversationModuleEntityProvider, decorators: [{
|
|
915
915
|
type: Injectable
|
|
916
916
|
}], ctorParameters: () => [{ type: i0.Injector }] });
|
|
917
917
|
|
|
@@ -932,192 +932,189 @@ class AXMMenuProvider {
|
|
|
932
932
|
},
|
|
933
933
|
]);
|
|
934
934
|
}
|
|
935
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
936
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.
|
|
935
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMMenuProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
936
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMMenuProvider }); }
|
|
937
937
|
}
|
|
938
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
938
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMMenuProvider, decorators: [{
|
|
939
939
|
type: Injectable
|
|
940
940
|
}] });
|
|
941
941
|
|
|
942
|
-
class
|
|
942
|
+
class AXMChatRealtimeService {
|
|
943
943
|
}
|
|
944
|
-
class
|
|
944
|
+
class AXMChatRealtimeServiceImpl extends AXMChatRealtimeService {
|
|
945
945
|
constructor() {
|
|
946
946
|
super(...arguments);
|
|
947
|
-
this.
|
|
948
|
-
this.
|
|
949
|
-
this.
|
|
950
|
-
this.
|
|
947
|
+
this._room$ = new Subject();
|
|
948
|
+
this.room$ = this._room$.asObservable();
|
|
949
|
+
this._message$ = new Subject();
|
|
950
|
+
this.message$ = this._message$.asObservable();
|
|
951
|
+
this._tab$ = new Subject();
|
|
952
|
+
this.tab$ = this._tab$.asObservable();
|
|
953
|
+
this._typingStatus$ = new Subject();
|
|
954
|
+
this.typingStatus$ = this._typingStatus$.asObservable();
|
|
951
955
|
}
|
|
952
|
-
|
|
953
|
-
this.
|
|
956
|
+
notifyRoom(event) {
|
|
957
|
+
this._room$.next(event);
|
|
954
958
|
}
|
|
955
|
-
|
|
956
|
-
this.
|
|
959
|
+
notifyMessage(event) {
|
|
960
|
+
this._message$.next(event);
|
|
961
|
+
}
|
|
962
|
+
notifyTab(event) {
|
|
963
|
+
this._tab$.next(event);
|
|
964
|
+
}
|
|
965
|
+
startTyping(user, roomId) {
|
|
966
|
+
this._typingStatus$.next({ roomId, user, isTyping: true });
|
|
967
|
+
}
|
|
968
|
+
stopTyping(user, roomId) {
|
|
969
|
+
this._typingStatus$.next({ roomId, user, isTyping: false });
|
|
957
970
|
}
|
|
958
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
959
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.
|
|
971
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMChatRealtimeServiceImpl, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
972
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMChatRealtimeServiceImpl, providedIn: 'root' }); }
|
|
960
973
|
}
|
|
961
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
974
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMChatRealtimeServiceImpl, decorators: [{
|
|
962
975
|
type: Injectable,
|
|
963
976
|
args: [{
|
|
964
977
|
providedIn: 'root',
|
|
965
978
|
}]
|
|
966
979
|
}] });
|
|
967
980
|
|
|
968
|
-
|
|
969
|
-
class AXMCommentService {
|
|
981
|
+
class AXMChatService {
|
|
970
982
|
}
|
|
971
|
-
|
|
972
|
-
class AXMCommentServiceImpl {
|
|
983
|
+
class AXMChatServiceImpl {
|
|
973
984
|
constructor() {
|
|
974
985
|
this.roomService = inject(AXMRoomService);
|
|
975
986
|
this.messageService = inject(AXMMessageService);
|
|
976
|
-
this.
|
|
987
|
+
this.tabService = inject(AXMConversationTabService);
|
|
977
988
|
}
|
|
978
|
-
|
|
989
|
+
createRoom(members, title, currentUser) {
|
|
979
990
|
const room = {
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
members: [creatorUser],
|
|
984
|
-
entityRef: entityRef,
|
|
985
|
-
createdBy: creatorUser.id,
|
|
991
|
+
members,
|
|
992
|
+
title: title,
|
|
993
|
+
topic: members.length > 2 ? 'group' : 'personal',
|
|
986
994
|
createdAt: new Date(),
|
|
995
|
+
updatedAt: new Date(),
|
|
996
|
+
type: 'chat',
|
|
997
|
+
createdBy: currentUser.id,
|
|
998
|
+
updatedBy: currentUser.id,
|
|
987
999
|
};
|
|
988
|
-
|
|
989
|
-
return this.roomService.getOne(newRoomId);
|
|
1000
|
+
return this.roomService.insertOne(room).then((id) => this.roomService.getOne(id));
|
|
990
1001
|
}
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
skip: 0,
|
|
994
|
-
take: 1,
|
|
995
|
-
filter: {
|
|
996
|
-
logic: 'and',
|
|
997
|
-
filters: [
|
|
998
|
-
{
|
|
999
|
-
field: 'entityRef.id',
|
|
1000
|
-
value: entityRef.id,
|
|
1001
|
-
operator: this.filterService.getOperator('equal'),
|
|
1002
|
-
},
|
|
1003
|
-
{
|
|
1004
|
-
field: 'entityRef.type',
|
|
1005
|
-
value: entityRef.type,
|
|
1006
|
-
operator: this.filterService.getOperator('equal'),
|
|
1007
|
-
},
|
|
1008
|
-
{
|
|
1009
|
-
field: 'topic',
|
|
1010
|
-
value: topic,
|
|
1011
|
-
operator: this.filterService.getOperator('equal'),
|
|
1012
|
-
},
|
|
1013
|
-
],
|
|
1014
|
-
},
|
|
1015
|
-
});
|
|
1016
|
-
return items[0] || null;
|
|
1002
|
+
getRoom(roomId) {
|
|
1003
|
+
return this.roomService.getOne(roomId);
|
|
1017
1004
|
}
|
|
1018
|
-
async
|
|
1019
|
-
|
|
1020
|
-
skip
|
|
1021
|
-
take
|
|
1022
|
-
filter: {
|
|
1023
|
-
logic: 'and',
|
|
1024
|
-
filters: [
|
|
1025
|
-
{
|
|
1026
|
-
field: 'entityRef.id',
|
|
1027
|
-
value: entityRef.id,
|
|
1028
|
-
operator: this.filterService.getOperator('equal'),
|
|
1029
|
-
},
|
|
1030
|
-
{
|
|
1031
|
-
field: 'entityRef.type',
|
|
1032
|
-
value: entityRef.type,
|
|
1033
|
-
operator: this.filterService.getOperator('equal'),
|
|
1034
|
-
},
|
|
1035
|
-
{
|
|
1036
|
-
field: 'topic',
|
|
1037
|
-
value: topic,
|
|
1038
|
-
operator: this.filterService.getOperator('equal'),
|
|
1039
|
-
},
|
|
1040
|
-
],
|
|
1041
|
-
},
|
|
1005
|
+
async listRooms(skip = 0, take = 100) {
|
|
1006
|
+
return this.roomService.query({
|
|
1007
|
+
skip,
|
|
1008
|
+
take,
|
|
1009
|
+
filter: { field: 'type', value: 'chat', operator: { type: 'equal' } },
|
|
1042
1010
|
});
|
|
1043
|
-
return items;
|
|
1044
1011
|
}
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
return this.roomService.
|
|
1012
|
+
updateRoom(roomId, data, currentUser) {
|
|
1013
|
+
const update = { ...data, updatedAt: new Date(), updatedBy: currentUser.id };
|
|
1014
|
+
return this.roomService.updateOne(roomId, update);
|
|
1048
1015
|
}
|
|
1049
|
-
async
|
|
1050
|
-
await this.roomService.deleteOne(
|
|
1016
|
+
async deleteRoom(roomId) {
|
|
1017
|
+
await this.roomService.deleteOne(roomId);
|
|
1051
1018
|
return true;
|
|
1052
1019
|
}
|
|
1053
|
-
|
|
1020
|
+
createTab(data) {
|
|
1021
|
+
return this.tabService.insertOne(data).then((id) => this.tabService.getOne(id));
|
|
1022
|
+
}
|
|
1023
|
+
getTab(tabId) {
|
|
1024
|
+
return this.tabService.getOne(tabId);
|
|
1025
|
+
}
|
|
1026
|
+
listTabs(skip = 0, take = 100) {
|
|
1027
|
+
return this.tabService.query({ skip, take });
|
|
1028
|
+
}
|
|
1029
|
+
updateTab(tabId, data) {
|
|
1030
|
+
return this.tabService.updateOne(tabId, data);
|
|
1031
|
+
}
|
|
1032
|
+
async deleteTab(tabId) {
|
|
1033
|
+
await this.tabService.deleteOne(tabId);
|
|
1034
|
+
return true;
|
|
1035
|
+
}
|
|
1036
|
+
sendMessage(roomId, content, author, contentType = 'text', replyId) {
|
|
1054
1037
|
const messageContent = { content, contentType };
|
|
1055
1038
|
const message = {
|
|
1056
|
-
roomId
|
|
1039
|
+
roomId,
|
|
1057
1040
|
message: messageContent,
|
|
1058
1041
|
author,
|
|
1059
|
-
replyId
|
|
1042
|
+
replyId,
|
|
1043
|
+
createdAt: new Date(),
|
|
1044
|
+
updatedAt: new Date(),
|
|
1045
|
+
createdBy: author.id,
|
|
1046
|
+
updatedBy: author.id,
|
|
1060
1047
|
reactions: [],
|
|
1061
1048
|
seen: [],
|
|
1062
|
-
createdBy: author.id,
|
|
1063
|
-
createdAt: new Date(),
|
|
1064
1049
|
};
|
|
1065
|
-
|
|
1066
|
-
return this.messageService.getOne(messageId);
|
|
1050
|
+
return this.messageService.insertOne({ ...message }).then((id) => this.messageService.getOne(id));
|
|
1067
1051
|
}
|
|
1068
|
-
async
|
|
1069
|
-
|
|
1070
|
-
skip
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1052
|
+
async getMessages(roomId, skip = 0, take = 99) {
|
|
1053
|
+
return this.messageService.query({
|
|
1054
|
+
skip,
|
|
1055
|
+
take,
|
|
1056
|
+
filter: { field: 'roomId', value: roomId, operator: { type: 'equal' } },
|
|
1057
|
+
sort: [{ field: 'createdAt', dir: 'desc' }],
|
|
1074
1058
|
});
|
|
1075
|
-
return items;
|
|
1076
1059
|
}
|
|
1077
|
-
|
|
1078
|
-
return this.messageService.getOne(
|
|
1060
|
+
getMessage(messageId) {
|
|
1061
|
+
return this.messageService.getOne(messageId);
|
|
1079
1062
|
}
|
|
1080
|
-
|
|
1063
|
+
editMessage(messageId, content, currentUser, contentType = 'text') {
|
|
1081
1064
|
const messageContent = { content, contentType };
|
|
1082
|
-
|
|
1065
|
+
return this.messageService.updateOne(messageId, {
|
|
1083
1066
|
message: messageContent,
|
|
1084
1067
|
updatedAt: new Date(),
|
|
1085
|
-
updatedBy:
|
|
1068
|
+
updatedBy: currentUser.id,
|
|
1086
1069
|
});
|
|
1087
|
-
return this.messageService.getOne(commentId);
|
|
1088
1070
|
}
|
|
1089
|
-
async
|
|
1090
|
-
await this.messageService.deleteOne(
|
|
1071
|
+
async deleteMessage(messageId) {
|
|
1072
|
+
await this.messageService.deleteOne(messageId);
|
|
1091
1073
|
return true;
|
|
1092
1074
|
}
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1075
|
+
pinMessage(messageId, isPinned, currentUser) {
|
|
1076
|
+
return this.messageService.updateOne(messageId, {
|
|
1077
|
+
isPinned,
|
|
1078
|
+
updatedAt: new Date(),
|
|
1079
|
+
updatedBy: currentUser.id,
|
|
1080
|
+
});
|
|
1096
1081
|
}
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1082
|
+
updateReactions(messageId, reactions, currentUser) {
|
|
1083
|
+
return this.messageService.updateOne(messageId, {
|
|
1084
|
+
reactions,
|
|
1085
|
+
updatedAt: new Date(),
|
|
1086
|
+
updatedBy: currentUser.id,
|
|
1087
|
+
});
|
|
1100
1088
|
}
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1089
|
+
getReactions(messageId) {
|
|
1090
|
+
return this.messageService.getOne(messageId).then((m) => m.reactions || []);
|
|
1091
|
+
}
|
|
1092
|
+
updateSeen(messageId, seen, currentUser) {
|
|
1093
|
+
return this.messageService.updateOne(messageId, {
|
|
1094
|
+
seen,
|
|
1095
|
+
updatedAt: new Date(),
|
|
1096
|
+
updatedBy: currentUser.id,
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
getSeenBy(messageId) {
|
|
1100
|
+
return this.messageService.getOne(messageId).then((m) => m.seen || []);
|
|
1104
1101
|
}
|
|
1105
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
1106
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.
|
|
1102
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMChatServiceImpl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1103
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMChatServiceImpl, providedIn: 'root' }); }
|
|
1107
1104
|
}
|
|
1108
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
1105
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMChatServiceImpl, decorators: [{
|
|
1109
1106
|
type: Injectable,
|
|
1110
1107
|
args: [{
|
|
1111
1108
|
providedIn: 'root',
|
|
1112
1109
|
}]
|
|
1113
1110
|
}] });
|
|
1114
1111
|
|
|
1115
|
-
class
|
|
1112
|
+
class AXMChatManagementService {
|
|
1116
1113
|
constructor() {
|
|
1117
|
-
this.
|
|
1114
|
+
this.chatImplService = inject(AXMChatServiceImpl);
|
|
1118
1115
|
this.sessionService = inject(AXPSessionService);
|
|
1119
1116
|
this.usersService = inject(AXMUsersEntityService);
|
|
1120
|
-
this.realtimeService = inject(
|
|
1117
|
+
this.realtimeService = inject(AXMChatRealtimeService);
|
|
1121
1118
|
}
|
|
1122
1119
|
getCurrentUser() {
|
|
1123
1120
|
const user = this.sessionService.user;
|
|
@@ -1127,774 +1124,675 @@ class AXMCommentManagementService {
|
|
|
1127
1124
|
return {
|
|
1128
1125
|
id: user.id,
|
|
1129
1126
|
type: 'user',
|
|
1127
|
+
fullName: user.title?.trim(),
|
|
1128
|
+
username: user.name?.trim(),
|
|
1130
1129
|
};
|
|
1131
1130
|
}
|
|
1132
1131
|
async getUserInfo(userId) {
|
|
1133
1132
|
try {
|
|
1134
|
-
await this.usersService.getOne(userId);
|
|
1135
|
-
return {
|
|
1133
|
+
const user = await this.usersService.getOne(userId);
|
|
1134
|
+
return {
|
|
1135
|
+
id: user.id,
|
|
1136
|
+
type: 'user',
|
|
1137
|
+
fullName: `${user.firstName} ${user.lastName}`.trim(),
|
|
1138
|
+
username: user.username?.trim(),
|
|
1139
|
+
};
|
|
1136
1140
|
}
|
|
1137
|
-
catch {
|
|
1138
|
-
|
|
1141
|
+
catch (error) {
|
|
1142
|
+
console.error(`Failed to get user info for ID: ${userId}`, error);
|
|
1143
|
+
return {
|
|
1144
|
+
id: userId,
|
|
1145
|
+
type: 'user',
|
|
1146
|
+
fullName: 'Unknown User',
|
|
1147
|
+
username: 'Unknown User',
|
|
1148
|
+
};
|
|
1139
1149
|
}
|
|
1140
1150
|
}
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1151
|
+
async formatMessage(message) {
|
|
1152
|
+
if (message.author && !message.author.fullName) {
|
|
1153
|
+
const authorInfo = await this.getUserInfo(message.author.id);
|
|
1154
|
+
return {
|
|
1155
|
+
...message,
|
|
1156
|
+
author: authorInfo,
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1159
|
+
return message;
|
|
1148
1160
|
}
|
|
1149
|
-
|
|
1150
|
-
const
|
|
1151
|
-
const
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
comment.depth = (parent.depth ?? 0) + 1;
|
|
1157
|
-
}
|
|
1158
|
-
else {
|
|
1159
|
-
tree.push(comment);
|
|
1160
|
-
}
|
|
1161
|
-
});
|
|
1162
|
-
commentMap.forEach((comment) => {
|
|
1163
|
-
comment.replyCount = comment.replies.length;
|
|
1161
|
+
async getUnreadCount(roomId) {
|
|
1162
|
+
const { items } = await this.chatImplService.getMessages(roomId, 0, 99);
|
|
1163
|
+
const currentUserId = this.getCurrentUser().id;
|
|
1164
|
+
const unreadMessages = items.filter((message) => {
|
|
1165
|
+
const isFromCurrentUser = message.author.id === currentUserId;
|
|
1166
|
+
const isReadByCurrentUser = (message.seen || []).some((seen) => seen.author.id === currentUserId);
|
|
1167
|
+
return !isFromCurrentUser && !isReadByCurrentUser;
|
|
1164
1168
|
});
|
|
1165
|
-
return
|
|
1169
|
+
return unreadMessages.length;
|
|
1166
1170
|
}
|
|
1167
|
-
async
|
|
1168
|
-
const
|
|
1171
|
+
async formatRoom(room) {
|
|
1172
|
+
const messages = await this.getMessages(room.id, 0, 1);
|
|
1173
|
+
const lastMessage = messages.items.length > 0 ? messages.items[0] : undefined;
|
|
1174
|
+
const unreadCount = await this.getUnreadCount(room.id);
|
|
1175
|
+
const currentUserId = this.getCurrentUser().id;
|
|
1176
|
+
const members = await Promise.all(room.members.map(async (member) => {
|
|
1177
|
+
if (member.fullName) {
|
|
1178
|
+
return member;
|
|
1179
|
+
}
|
|
1180
|
+
return this.getUserInfo(member.id);
|
|
1181
|
+
}));
|
|
1169
1182
|
return {
|
|
1170
1183
|
...room,
|
|
1171
|
-
|
|
1172
|
-
|
|
1184
|
+
lastMessage,
|
|
1185
|
+
unreadCount,
|
|
1186
|
+
members: members.filter((m) => m.id !== currentUserId),
|
|
1173
1187
|
};
|
|
1174
1188
|
}
|
|
1175
|
-
async
|
|
1189
|
+
async createRoom(memberIds, title) {
|
|
1190
|
+
if (memberIds.length === 0) {
|
|
1191
|
+
throw new Error('At least one member is required to create a room');
|
|
1192
|
+
}
|
|
1176
1193
|
const currentUser = this.getCurrentUser();
|
|
1177
|
-
const
|
|
1178
|
-
const
|
|
1179
|
-
this.
|
|
1180
|
-
|
|
1194
|
+
const allMemberIds = [...new Set([...memberIds, currentUser.id])];
|
|
1195
|
+
const memberReferences = await Promise.all(allMemberIds.map((id) => this.getUserInfo(id)));
|
|
1196
|
+
const newRoom = await this.chatImplService.createRoom(memberReferences, title, currentUser);
|
|
1197
|
+
const newChatRoom = await this.formatRoom(newRoom);
|
|
1198
|
+
this.realtimeService.notifyRoom({ type: 'add', payload: newChatRoom });
|
|
1199
|
+
return newChatRoom;
|
|
1181
1200
|
}
|
|
1182
|
-
async
|
|
1183
|
-
const room = await this.
|
|
1201
|
+
async getRoom(roomId) {
|
|
1202
|
+
const room = await this.chatImplService.getRoom(roomId);
|
|
1184
1203
|
if (!room) {
|
|
1185
|
-
|
|
1204
|
+
throw new Error(`Chat room with ID ${roomId} not found.`);
|
|
1186
1205
|
}
|
|
1187
|
-
return this.
|
|
1206
|
+
return this.formatRoom(room);
|
|
1188
1207
|
}
|
|
1189
|
-
async
|
|
1190
|
-
const
|
|
1191
|
-
|
|
1208
|
+
async listRooms(skip = 0, take = 100) {
|
|
1209
|
+
const { items } = await this.chatImplService.listRooms(skip, take);
|
|
1210
|
+
const settledRooms = await Promise.allSettled(items.map((room) => this.formatRoom(room)));
|
|
1211
|
+
const chatRooms = settledRooms
|
|
1212
|
+
.filter((result) => {
|
|
1213
|
+
if (result.status === 'rejected') {
|
|
1214
|
+
console.error('Failed to fetch room details:', result.reason);
|
|
1215
|
+
return false;
|
|
1216
|
+
}
|
|
1217
|
+
return true;
|
|
1218
|
+
})
|
|
1219
|
+
.map((result) => result.value);
|
|
1220
|
+
return { items: chatRooms, total: chatRooms.length };
|
|
1192
1221
|
}
|
|
1193
|
-
async
|
|
1194
|
-
const
|
|
1195
|
-
|
|
1196
|
-
|
|
1222
|
+
async updateRoom(roomId, data) {
|
|
1223
|
+
const currentUser = this.getCurrentUser();
|
|
1224
|
+
return this.chatImplService.updateRoom(roomId, data, currentUser);
|
|
1225
|
+
}
|
|
1226
|
+
async deleteRoom(roomId) {
|
|
1227
|
+
const result = await this.chatImplService.deleteRoom(roomId);
|
|
1228
|
+
if (result) {
|
|
1229
|
+
this.realtimeService.notifyRoom({ type: 'remove', payload: roomId });
|
|
1197
1230
|
}
|
|
1198
|
-
|
|
1199
|
-
const updatedThread = await this.formatThread(updatedRoom);
|
|
1200
|
-
this.realtimeService.notifyThread({ type: 'update', payload: updatedThread });
|
|
1201
|
-
return updatedThread;
|
|
1231
|
+
return result;
|
|
1202
1232
|
}
|
|
1203
|
-
async
|
|
1204
|
-
const
|
|
1205
|
-
if (
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1233
|
+
async addParticipant(roomId, userId) {
|
|
1234
|
+
const room = await this.chatImplService.getRoom(roomId);
|
|
1235
|
+
if (room.members.some((m) => m.id === userId))
|
|
1236
|
+
return room;
|
|
1237
|
+
const userRef = await this.getUserInfo(userId);
|
|
1238
|
+
const updatedMembers = [...room.members, userRef];
|
|
1239
|
+
const currentUser = this.getCurrentUser();
|
|
1240
|
+
return this.chatImplService.updateRoom(roomId, { members: updatedMembers }, currentUser);
|
|
1241
|
+
}
|
|
1242
|
+
async removeParticipant(roomId, userId) {
|
|
1243
|
+
const room = await this.chatImplService.getRoom(roomId);
|
|
1244
|
+
const updatedMembers = room.members.filter((member) => member.id !== userId);
|
|
1245
|
+
const currentUser = this.getCurrentUser();
|
|
1246
|
+
return this.chatImplService.updateRoom(roomId, { members: updatedMembers }, currentUser);
|
|
1247
|
+
}
|
|
1248
|
+
async createTab(data) {
|
|
1249
|
+
const newTab = await this.chatImplService.createTab(data);
|
|
1250
|
+
this.realtimeService.notifyTab({ type: 'add', payload: newTab });
|
|
1251
|
+
return newTab;
|
|
1252
|
+
}
|
|
1253
|
+
getTab(tabId) {
|
|
1254
|
+
return this.chatImplService.getTab(tabId);
|
|
1255
|
+
}
|
|
1256
|
+
listTabs(skip, take) {
|
|
1257
|
+
return this.chatImplService.listTabs(skip, take);
|
|
1258
|
+
}
|
|
1259
|
+
updateTab(tabId, data) {
|
|
1260
|
+
return this.chatImplService.updateTab(tabId, data);
|
|
1261
|
+
}
|
|
1262
|
+
async deleteTab(tabId) {
|
|
1263
|
+
const result = await this.chatImplService.deleteTab(tabId);
|
|
1264
|
+
if (result) {
|
|
1265
|
+
this.realtimeService.notifyTab({ type: 'remove', payload: tabId });
|
|
1209
1266
|
}
|
|
1210
|
-
return
|
|
1267
|
+
return result;
|
|
1211
1268
|
}
|
|
1212
|
-
async
|
|
1213
|
-
const
|
|
1214
|
-
const
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1269
|
+
async addIncludeRoomToTab(tabId, roomId) {
|
|
1270
|
+
const tab = await this.getTab(tabId);
|
|
1271
|
+
const room = await this.getRoom(roomId);
|
|
1272
|
+
if (tab && room) {
|
|
1273
|
+
const updatedRooms = [...tab.includeRooms, room];
|
|
1274
|
+
return this.updateTab(tabId, { includeRooms: updatedRooms });
|
|
1275
|
+
}
|
|
1276
|
+
else {
|
|
1277
|
+
throw new Error(`Tab with ID ${tabId} or room with ID ${roomId} not found.`);
|
|
1278
|
+
}
|
|
1218
1279
|
}
|
|
1219
|
-
async
|
|
1220
|
-
const
|
|
1221
|
-
const
|
|
1222
|
-
if (
|
|
1223
|
-
|
|
1280
|
+
async removeIncludeRoomFromTab(tabId, roomId) {
|
|
1281
|
+
const tab = await this.getTab(tabId);
|
|
1282
|
+
const room = await this.getRoom(roomId);
|
|
1283
|
+
if (tab && room) {
|
|
1284
|
+
if (tab.includeRooms.some((r) => r.id === roomId)) {
|
|
1285
|
+
const updatedRooms = tab.includeRooms.filter((r) => r.id !== roomId);
|
|
1286
|
+
return this.updateTab(tabId, { includeRooms: updatedRooms });
|
|
1287
|
+
}
|
|
1288
|
+
else {
|
|
1289
|
+
throw new Error(`${tabId} tab does not include room with ID ${roomId}.`);
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
else {
|
|
1293
|
+
throw new Error(`Tab with ID ${tabId} or room with ID ${roomId} not found.`);
|
|
1224
1294
|
}
|
|
1225
|
-
return formattedComments;
|
|
1226
1295
|
}
|
|
1227
|
-
async
|
|
1228
|
-
const
|
|
1229
|
-
|
|
1296
|
+
async addExcludeRoomToTab(tabId, roomId) {
|
|
1297
|
+
const tab = await this.getTab(tabId);
|
|
1298
|
+
const room = await this.getRoom(roomId);
|
|
1299
|
+
if (tab && room) {
|
|
1300
|
+
const updatedRooms = [...tab.excludeRooms, room];
|
|
1301
|
+
return this.updateTab(tabId, { excludeRooms: updatedRooms });
|
|
1302
|
+
}
|
|
1303
|
+
else {
|
|
1304
|
+
throw new Error(`Tab with ID ${tabId} or room with ID ${roomId} not found.`);
|
|
1305
|
+
}
|
|
1230
1306
|
}
|
|
1231
|
-
async
|
|
1232
|
-
const
|
|
1233
|
-
const
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1307
|
+
async removeExcludeRoomFromTab(tabId, roomId) {
|
|
1308
|
+
const tab = await this.getTab(tabId);
|
|
1309
|
+
const room = await this.getRoom(roomId);
|
|
1310
|
+
if (tab && room) {
|
|
1311
|
+
if (tab.excludeRooms.some((r) => r.id === roomId)) {
|
|
1312
|
+
const updatedRooms = tab.excludeRooms.filter((r) => r.id !== roomId);
|
|
1313
|
+
return this.updateTab(tabId, { excludeRooms: updatedRooms });
|
|
1314
|
+
}
|
|
1315
|
+
else {
|
|
1316
|
+
throw new Error(`${tabId} tab does not exclude room with ID ${roomId}.`);
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
else {
|
|
1320
|
+
throw new Error(`Tab with ID ${tabId} or room with ID ${roomId} not found.`);
|
|
1321
|
+
}
|
|
1237
1322
|
}
|
|
1238
|
-
async
|
|
1239
|
-
const
|
|
1323
|
+
async sendMessage(roomId, content, contentType = 'text', replyId, userId) {
|
|
1324
|
+
const author = userId ? await this.getUserInfo(userId) : this.getCurrentUser();
|
|
1325
|
+
const newMessage = await this.chatImplService.sendMessage(roomId, content, author, contentType, replyId);
|
|
1326
|
+
const formattedMessage = await this.formatMessage(newMessage);
|
|
1327
|
+
this.realtimeService.notifyMessage({ type: 'add', payload: formattedMessage });
|
|
1328
|
+
return formattedMessage;
|
|
1329
|
+
}
|
|
1330
|
+
async getMessages(roomId, skip, take) {
|
|
1331
|
+
const result = await this.chatImplService.getMessages(roomId, skip, take);
|
|
1332
|
+
const formattedMessages = await Promise.all(result.items.map((m) => this.formatMessage(m)));
|
|
1333
|
+
return { items: formattedMessages, total: result.total };
|
|
1334
|
+
}
|
|
1335
|
+
async getMessage(messageId) {
|
|
1336
|
+
const message = await this.chatImplService.getMessage(messageId);
|
|
1337
|
+
return this.formatMessage(message);
|
|
1338
|
+
}
|
|
1339
|
+
async editMessage(messageId, content, contentType = 'text') {
|
|
1340
|
+
const currentUser = this.getCurrentUser();
|
|
1341
|
+
const updatedMessage = await this.chatImplService.editMessage(messageId, content, currentUser, contentType);
|
|
1342
|
+
this.realtimeService.notifyMessage({ type: 'update', payload: await this.formatMessage(updatedMessage) });
|
|
1343
|
+
return updatedMessage;
|
|
1344
|
+
}
|
|
1345
|
+
async deleteMessage(messageId) {
|
|
1346
|
+
const result = await this.chatImplService.deleteMessage(messageId);
|
|
1240
1347
|
if (result) {
|
|
1241
|
-
this.realtimeService.
|
|
1348
|
+
this.realtimeService.notifyMessage({ type: 'remove', payload: messageId });
|
|
1242
1349
|
}
|
|
1243
1350
|
return result;
|
|
1244
1351
|
}
|
|
1245
|
-
async
|
|
1352
|
+
async replyMessage(replyToMessageId, content, contentType = 'text') {
|
|
1353
|
+
const originalMessage = await this.chatImplService.getMessage(replyToMessageId);
|
|
1354
|
+
return this.sendMessage(originalMessage.roomId, content, contentType, replyToMessageId);
|
|
1355
|
+
}
|
|
1356
|
+
async pinMessage(messageId) {
|
|
1357
|
+
const currentUser = this.getCurrentUser();
|
|
1358
|
+
return this.chatImplService.pinMessage(messageId, true, currentUser);
|
|
1359
|
+
}
|
|
1360
|
+
async unpinMessage(messageId) {
|
|
1361
|
+
const currentUser = this.getCurrentUser();
|
|
1362
|
+
return this.chatImplService.pinMessage(messageId, false, currentUser);
|
|
1363
|
+
}
|
|
1364
|
+
async addReaction(messageId, type) {
|
|
1246
1365
|
const author = this.getCurrentUser();
|
|
1247
|
-
const
|
|
1248
|
-
const reactions =
|
|
1366
|
+
const message = await this.chatImplService.getMessage(messageId);
|
|
1367
|
+
const reactions = message.reactions || [];
|
|
1249
1368
|
if (reactions.some((r) => r.author.id === author.id && r.type === type)) {
|
|
1250
|
-
return
|
|
1369
|
+
return message;
|
|
1251
1370
|
}
|
|
1252
1371
|
const updatedReactions = [...reactions, { author, type }];
|
|
1253
|
-
const
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
return formattedComment;
|
|
1372
|
+
const res = await this.chatImplService.updateReactions(messageId, updatedReactions, author);
|
|
1373
|
+
this.realtimeService.notifyMessage({ type: 'update', payload: await this.formatMessage(res) });
|
|
1374
|
+
return res;
|
|
1257
1375
|
}
|
|
1258
|
-
async removeReaction(
|
|
1376
|
+
async removeReaction(messageId, type) {
|
|
1259
1377
|
const author = this.getCurrentUser();
|
|
1260
|
-
const
|
|
1261
|
-
const updatedReactions = (
|
|
1262
|
-
const
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
return formattedComment;
|
|
1378
|
+
const message = await this.chatImplService.getMessage(messageId);
|
|
1379
|
+
const updatedReactions = (message.reactions || []).filter((r) => !(r.author.id === author.id && r.type === type));
|
|
1380
|
+
const res = await this.chatImplService.updateReactions(messageId, updatedReactions, author);
|
|
1381
|
+
this.realtimeService.notifyMessage({ type: 'update', payload: await this.formatMessage(res) });
|
|
1382
|
+
return res;
|
|
1266
1383
|
}
|
|
1267
|
-
getReactions(
|
|
1268
|
-
return this.
|
|
1384
|
+
async getReactions(messageId) {
|
|
1385
|
+
return this.chatImplService.getReactions(messageId);
|
|
1269
1386
|
}
|
|
1270
|
-
|
|
1271
|
-
|
|
1387
|
+
async markSeen(messageId) {
|
|
1388
|
+
const author = this.getCurrentUser();
|
|
1389
|
+
const message = await this.chatImplService.getMessage(messageId);
|
|
1390
|
+
const seen = message.seen || [];
|
|
1391
|
+
if (seen.some((s) => s.author.id === author.id)) {
|
|
1392
|
+
return message;
|
|
1393
|
+
}
|
|
1394
|
+
const updatedSeen = [...seen, { author, type: 'read' }];
|
|
1395
|
+
const updatedMessage = await this.chatImplService.updateSeen(messageId, updatedSeen, author);
|
|
1396
|
+
this.realtimeService.notifyRoom({ type: 'seen', payload: updatedMessage.roomId });
|
|
1397
|
+
return updatedMessage;
|
|
1272
1398
|
}
|
|
1273
|
-
|
|
1274
|
-
return this.
|
|
1399
|
+
async getSeenBy(messageId) {
|
|
1400
|
+
return this.chatImplService.getSeenBy(messageId);
|
|
1275
1401
|
}
|
|
1276
|
-
async
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1402
|
+
async markRoomSeen(roomId) {
|
|
1403
|
+
try {
|
|
1404
|
+
if (!roomId) {
|
|
1405
|
+
return true;
|
|
1406
|
+
}
|
|
1407
|
+
const { items } = await this.getMessages(roomId, 0, 99);
|
|
1408
|
+
const currentUserId = this.getCurrentUser().id;
|
|
1409
|
+
const unreadMessages = items.filter((message) => message.author.id !== currentUserId && !message.seen?.some((s) => s.author.id === currentUserId));
|
|
1410
|
+
if (unreadMessages.length > 0) {
|
|
1411
|
+
await Promise.all(unreadMessages.map((message) => this.markSeen(message.id)));
|
|
1412
|
+
}
|
|
1413
|
+
this.realtimeService.notifyRoom({ type: 'seen', payload: roomId });
|
|
1414
|
+
return true;
|
|
1415
|
+
}
|
|
1416
|
+
catch (error) {
|
|
1417
|
+
console.error(`Error marking room ${roomId} as seen:`, error);
|
|
1418
|
+
return false;
|
|
1419
|
+
}
|
|
1281
1420
|
}
|
|
1282
|
-
async
|
|
1283
|
-
const
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1421
|
+
async startTyping(roomId, userId) {
|
|
1422
|
+
const user = userId ? await this.getUserInfo(userId) : this.getCurrentUser();
|
|
1423
|
+
this.realtimeService.startTyping(user, roomId);
|
|
1424
|
+
}
|
|
1425
|
+
async stopTyping(roomId, userId) {
|
|
1426
|
+
const user = userId ? await this.getUserInfo(userId) : this.getCurrentUser();
|
|
1427
|
+
this.realtimeService.stopTyping(user, roomId);
|
|
1287
1428
|
}
|
|
1288
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
1289
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.
|
|
1429
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMChatManagementService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1430
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMChatManagementService, providedIn: 'root' }); }
|
|
1290
1431
|
}
|
|
1291
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
1432
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMChatManagementService, decorators: [{
|
|
1292
1433
|
type: Injectable,
|
|
1293
1434
|
args: [{
|
|
1294
1435
|
providedIn: 'root',
|
|
1295
1436
|
}]
|
|
1296
1437
|
}] });
|
|
1297
1438
|
|
|
1298
|
-
class
|
|
1439
|
+
class AXMCommentRealtimeService {
|
|
1440
|
+
}
|
|
1441
|
+
class AXMCommentRealtimeServiceImpl extends AXMCommentRealtimeService {
|
|
1299
1442
|
constructor() {
|
|
1300
|
-
|
|
1301
|
-
this.
|
|
1302
|
-
this.
|
|
1303
|
-
this.
|
|
1304
|
-
this.
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
this.
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
this.
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
};
|
|
1443
|
+
super(...arguments);
|
|
1444
|
+
this._comment$ = new Subject();
|
|
1445
|
+
this.comment$ = this._comment$.asObservable();
|
|
1446
|
+
this._thread$ = new Subject();
|
|
1447
|
+
this.thread$ = this._thread$.asObservable();
|
|
1448
|
+
}
|
|
1449
|
+
notifyComment(event) {
|
|
1450
|
+
this._comment$.next(event);
|
|
1451
|
+
}
|
|
1452
|
+
notifyThread(event) {
|
|
1453
|
+
this._thread$.next(event);
|
|
1454
|
+
}
|
|
1455
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentRealtimeServiceImpl, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1456
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentRealtimeServiceImpl, providedIn: 'root' }); }
|
|
1457
|
+
}
|
|
1458
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentRealtimeServiceImpl, decorators: [{
|
|
1459
|
+
type: Injectable,
|
|
1460
|
+
args: [{
|
|
1461
|
+
providedIn: 'root',
|
|
1462
|
+
}]
|
|
1463
|
+
}] });
|
|
1464
|
+
|
|
1465
|
+
//#region ---- Abstract Comment Service ----
|
|
1466
|
+
class AXMCommentService {
|
|
1467
|
+
}
|
|
1468
|
+
//#endregion
|
|
1469
|
+
class AXMCommentServiceImpl {
|
|
1470
|
+
constructor() {
|
|
1471
|
+
this.roomService = inject(AXMRoomService);
|
|
1472
|
+
this.messageService = inject(AXMMessageService);
|
|
1473
|
+
this.filterService = inject(AXPFilterOperatorMiddlewareService);
|
|
1474
|
+
}
|
|
1475
|
+
async createThread(creatorUser, entityRef, topic, title) {
|
|
1476
|
+
const room = {
|
|
1477
|
+
type: 'comment',
|
|
1478
|
+
topic: topic,
|
|
1479
|
+
title: title || `Comments for ${entityRef.type}#${entityRef.id}`,
|
|
1480
|
+
members: [creatorUser],
|
|
1481
|
+
entityRef: entityRef,
|
|
1482
|
+
createdBy: creatorUser.id,
|
|
1483
|
+
createdAt: new Date(),
|
|
1342
1484
|
};
|
|
1485
|
+
const newRoomId = await this.roomService.insertOne(room);
|
|
1486
|
+
return this.roomService.getOne(newRoomId);
|
|
1343
1487
|
}
|
|
1344
|
-
|
|
1345
|
-
this.
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1488
|
+
async getThread(entityRef, topic) {
|
|
1489
|
+
const { items } = await this.roomService.query({
|
|
1490
|
+
skip: 0,
|
|
1491
|
+
take: 1,
|
|
1492
|
+
filter: {
|
|
1493
|
+
logic: 'and',
|
|
1494
|
+
filters: [
|
|
1495
|
+
{
|
|
1496
|
+
field: 'entityRef.id',
|
|
1497
|
+
value: entityRef.id,
|
|
1498
|
+
operator: this.filterService.getOperator('equal'),
|
|
1499
|
+
},
|
|
1500
|
+
{
|
|
1501
|
+
field: 'entityRef.type',
|
|
1502
|
+
value: entityRef.type,
|
|
1503
|
+
operator: this.filterService.getOperator('equal'),
|
|
1504
|
+
},
|
|
1505
|
+
{
|
|
1506
|
+
field: 'topic',
|
|
1507
|
+
value: topic,
|
|
1508
|
+
operator: this.filterService.getOperator('equal'),
|
|
1509
|
+
},
|
|
1510
|
+
],
|
|
1511
|
+
},
|
|
1350
1512
|
});
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1513
|
+
return items[0] || null;
|
|
1514
|
+
}
|
|
1515
|
+
async listThreads(entityRef, topic) {
|
|
1516
|
+
const { items } = await this.roomService.query({
|
|
1517
|
+
skip: 0,
|
|
1518
|
+
take: 100,
|
|
1519
|
+
filter: {
|
|
1520
|
+
logic: 'and',
|
|
1521
|
+
filters: [
|
|
1522
|
+
{
|
|
1523
|
+
field: 'entityRef.id',
|
|
1524
|
+
value: entityRef.id,
|
|
1525
|
+
operator: this.filterService.getOperator('equal'),
|
|
1526
|
+
},
|
|
1527
|
+
{
|
|
1528
|
+
field: 'entityRef.type',
|
|
1529
|
+
value: entityRef.type,
|
|
1530
|
+
operator: this.filterService.getOperator('equal'),
|
|
1531
|
+
},
|
|
1532
|
+
{
|
|
1533
|
+
field: 'topic',
|
|
1534
|
+
value: topic,
|
|
1535
|
+
operator: this.filterService.getOperator('equal'),
|
|
1536
|
+
},
|
|
1537
|
+
],
|
|
1538
|
+
},
|
|
1365
1539
|
});
|
|
1540
|
+
return items;
|
|
1366
1541
|
}
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
return comments.map((c) => {
|
|
1371
|
-
if (c.id === comment.replyId) {
|
|
1372
|
-
const newReplies = c.replies ? [...c.replies, comment] : [comment];
|
|
1373
|
-
return { ...c, replies: newReplies, replyCount: newReplies.length };
|
|
1374
|
-
}
|
|
1375
|
-
return c;
|
|
1376
|
-
});
|
|
1377
|
-
});
|
|
1378
|
-
}
|
|
1379
|
-
else {
|
|
1380
|
-
this.comments.update((comments) => [...comments, comment]);
|
|
1381
|
-
}
|
|
1542
|
+
async updateThread(threadId, data) {
|
|
1543
|
+
await this.roomService.updateOne(threadId, data);
|
|
1544
|
+
return this.roomService.getOne(threadId);
|
|
1382
1545
|
}
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
if (c.id === updatedComment.id) {
|
|
1387
|
-
return { ...c, ...updatedComment, replies: updatedComment.replies || c.replies };
|
|
1388
|
-
}
|
|
1389
|
-
if (c.replies && c.replies.length > 0) {
|
|
1390
|
-
return { ...c, replies: update(c.replies) };
|
|
1391
|
-
}
|
|
1392
|
-
return c;
|
|
1393
|
-
});
|
|
1394
|
-
};
|
|
1395
|
-
this.comments.update((comments) => update(comments));
|
|
1546
|
+
async deleteThread(threadId) {
|
|
1547
|
+
await this.roomService.deleteOne(threadId);
|
|
1548
|
+
return true;
|
|
1396
1549
|
}
|
|
1397
|
-
|
|
1398
|
-
const
|
|
1399
|
-
|
|
1550
|
+
async addComment(threadId, content, author, parentCommentId, contentType = 'text') {
|
|
1551
|
+
const messageContent = { content, contentType };
|
|
1552
|
+
const message = {
|
|
1553
|
+
roomId: threadId,
|
|
1554
|
+
message: messageContent,
|
|
1555
|
+
author,
|
|
1556
|
+
replyId: parentCommentId,
|
|
1557
|
+
reactions: [],
|
|
1558
|
+
seen: [],
|
|
1559
|
+
createdBy: author.id,
|
|
1560
|
+
createdAt: new Date(),
|
|
1561
|
+
};
|
|
1562
|
+
const messageId = await this.messageService.insertOne(message);
|
|
1563
|
+
return this.messageService.getOne(messageId);
|
|
1400
1564
|
}
|
|
1401
|
-
|
|
1402
|
-
const
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1565
|
+
async getComments(threadId) {
|
|
1566
|
+
const { items } = await this.messageService.query({
|
|
1567
|
+
skip: 0,
|
|
1568
|
+
filter: { field: 'roomId', value: threadId, operator: this.filterService.getOperator('equal') },
|
|
1569
|
+
sort: [{ field: 'createdAt', dir: 'asc' }],
|
|
1570
|
+
take: 500,
|
|
1571
|
+
});
|
|
1572
|
+
return items;
|
|
1406
1573
|
}
|
|
1407
|
-
|
|
1408
|
-
return
|
|
1574
|
+
async getComment(commentId) {
|
|
1575
|
+
return this.messageService.getOne(commentId);
|
|
1409
1576
|
}
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1577
|
+
async editComment(commentId, content, editor, contentType = 'text') {
|
|
1578
|
+
const messageContent = { content, contentType };
|
|
1579
|
+
await this.messageService.updateOne(commentId, {
|
|
1580
|
+
message: messageContent,
|
|
1581
|
+
updatedAt: new Date(),
|
|
1582
|
+
updatedBy: editor.id,
|
|
1583
|
+
});
|
|
1584
|
+
return this.messageService.getOne(commentId);
|
|
1414
1585
|
}
|
|
1415
|
-
|
|
1416
|
-
this.
|
|
1586
|
+
async deleteComment(commentId) {
|
|
1587
|
+
await this.messageService.deleteOne(commentId);
|
|
1588
|
+
return true;
|
|
1417
1589
|
}
|
|
1418
|
-
|
|
1419
|
-
|
|
1590
|
+
async updateReactions(commentId, reactions) {
|
|
1591
|
+
await this.messageService.updateOne(commentId, { reactions });
|
|
1592
|
+
return this.messageService.getOne(commentId);
|
|
1420
1593
|
}
|
|
1421
|
-
async
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
if (thread) {
|
|
1425
|
-
this.thread.set(thread);
|
|
1426
|
-
this.comments.set(thread.comments || []);
|
|
1427
|
-
}
|
|
1428
|
-
else {
|
|
1429
|
-
this.comments.set([]);
|
|
1430
|
-
this.thread.set(undefined);
|
|
1431
|
-
}
|
|
1432
|
-
}
|
|
1433
|
-
catch (error) {
|
|
1434
|
-
console.error('Failed to load comments:', error);
|
|
1435
|
-
this.toastService.show({
|
|
1436
|
-
content: 'Failed to load comments. Please try again.',
|
|
1437
|
-
color: 'danger',
|
|
1438
|
-
location: 'bottom-center',
|
|
1439
|
-
closeButton: true,
|
|
1440
|
-
timeOut: 3000,
|
|
1441
|
-
timeOutProgress: true,
|
|
1442
|
-
});
|
|
1443
|
-
this.comments.set([]);
|
|
1444
|
-
}
|
|
1594
|
+
async getReactions(commentId) {
|
|
1595
|
+
const comment = await this.messageService.getOne(commentId);
|
|
1596
|
+
return comment.reactions || [];
|
|
1445
1597
|
}
|
|
1446
|
-
|
|
1447
|
-
this.
|
|
1448
|
-
this.
|
|
1449
|
-
this.isEditingMode.set(true);
|
|
1450
|
-
this.activeEditComment.set({ ...comment, userName: userName || '' });
|
|
1451
|
-
const contentToEdit = reply ? reply.message?.content : comment.message?.content;
|
|
1452
|
-
this.commentContent.set(contentToEdit || '');
|
|
1453
|
-
this.wysiwygEditor().getHostElement().scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
1598
|
+
async pinComment(commentId, isPinned) {
|
|
1599
|
+
await this.messageService.updateOne(commentId, { isPinned });
|
|
1600
|
+
return this.messageService.getOne(commentId);
|
|
1454
1601
|
}
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
this.
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
icon: 'fa-regular fa-warning',
|
|
1472
|
-
content: 'Are you sure you want to delete this comment?',
|
|
1473
|
-
title: 'Delete Comment',
|
|
1474
|
-
type: 'danger',
|
|
1475
|
-
orientation: 'horizontal',
|
|
1476
|
-
buttons: [
|
|
1477
|
-
{
|
|
1478
|
-
text: 'Delete',
|
|
1479
|
-
color: 'danger',
|
|
1480
|
-
onClick: async (e) => {
|
|
1481
|
-
e.handled = true;
|
|
1482
|
-
e.source.text = 'Deleting...';
|
|
1483
|
-
e.source.disabled = true;
|
|
1484
|
-
e.source.loading = true;
|
|
1485
|
-
try {
|
|
1486
|
-
await this.commentService.deleteComment(commentId);
|
|
1487
|
-
this.removeMessageById(commentId);
|
|
1488
|
-
this.toastService.show({
|
|
1489
|
-
content: 'Comment deleted successfully.',
|
|
1490
|
-
color: 'success',
|
|
1491
|
-
location: 'bottom-center',
|
|
1492
|
-
closeButton: true,
|
|
1493
|
-
timeOut: 3000,
|
|
1494
|
-
timeOutProgress: true,
|
|
1495
|
-
});
|
|
1496
|
-
if (this.isEditingMode() && this.activeEditComment()?.id === commentId) {
|
|
1497
|
-
this.resetReplyEditState();
|
|
1498
|
-
}
|
|
1499
|
-
dialog.close();
|
|
1500
|
-
}
|
|
1501
|
-
catch (error) {
|
|
1502
|
-
this.toastService.show({
|
|
1503
|
-
content: typeof error === 'string' ? error : 'Failed to delete comment!',
|
|
1504
|
-
color: 'danger',
|
|
1505
|
-
location: 'bottom-center',
|
|
1506
|
-
closeButton: true,
|
|
1507
|
-
timeOut: 3000,
|
|
1508
|
-
timeOutProgress: true,
|
|
1509
|
-
});
|
|
1510
|
-
}
|
|
1511
|
-
},
|
|
1512
|
-
},
|
|
1513
|
-
{
|
|
1514
|
-
text: 'Cancel',
|
|
1515
|
-
color: 'default',
|
|
1516
|
-
autofocus: true,
|
|
1517
|
-
onClick: (e) => {
|
|
1518
|
-
dialog.close();
|
|
1519
|
-
},
|
|
1520
|
-
},
|
|
1521
|
-
],
|
|
1522
|
-
closeButton: false,
|
|
1523
|
-
});
|
|
1602
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentServiceImpl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1603
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentServiceImpl, providedIn: 'root' }); }
|
|
1604
|
+
}
|
|
1605
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentServiceImpl, decorators: [{
|
|
1606
|
+
type: Injectable,
|
|
1607
|
+
args: [{
|
|
1608
|
+
providedIn: 'root',
|
|
1609
|
+
}]
|
|
1610
|
+
}] });
|
|
1611
|
+
|
|
1612
|
+
class AXMCommentManagementService {
|
|
1613
|
+
constructor() {
|
|
1614
|
+
this.commentImplService = inject(AXMCommentServiceImpl);
|
|
1615
|
+
this.sessionService = inject(AXPSessionService);
|
|
1616
|
+
this.usersService = inject(AXMUsersEntityService);
|
|
1617
|
+
this.realtimeService = inject(AXMCommentRealtimeService);
|
|
1524
1618
|
}
|
|
1525
|
-
|
|
1526
|
-
this.
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1619
|
+
getCurrentUser() {
|
|
1620
|
+
const user = this.sessionService.user;
|
|
1621
|
+
if (!user) {
|
|
1622
|
+
throw new Error('No authenticated user found.');
|
|
1623
|
+
}
|
|
1624
|
+
return {
|
|
1625
|
+
id: user.id,
|
|
1626
|
+
type: 'user',
|
|
1627
|
+
};
|
|
1532
1628
|
}
|
|
1533
|
-
async
|
|
1534
|
-
const isLiked = this.isLikedByUser(comment);
|
|
1535
|
-
this.updateLikeStatus(comment.id, !isLiked);
|
|
1629
|
+
async getUserInfo(userId) {
|
|
1536
1630
|
try {
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
}
|
|
1540
|
-
else {
|
|
1541
|
-
await this.commentService.likeComment(comment.id);
|
|
1542
|
-
}
|
|
1631
|
+
await this.usersService.getOne(userId);
|
|
1632
|
+
return { id: userId, type: 'user' };
|
|
1543
1633
|
}
|
|
1544
|
-
catch
|
|
1545
|
-
|
|
1546
|
-
this.updateLikeStatus(comment.id, isLiked); // Revert optimistic update
|
|
1634
|
+
catch {
|
|
1635
|
+
throw new Error(`User with ID ${userId} not found`);
|
|
1547
1636
|
}
|
|
1548
1637
|
}
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
return c;
|
|
1556
|
-
let reactions = c.reactions || [];
|
|
1557
|
-
if (willBeLiked) {
|
|
1558
|
-
reactions.push({ author: user, type: 'like' });
|
|
1559
|
-
}
|
|
1560
|
-
else {
|
|
1561
|
-
reactions = reactions.filter((r) => r.author.id !== user.id || r.type !== 'like');
|
|
1562
|
-
}
|
|
1563
|
-
return { ...c, reactions };
|
|
1564
|
-
}
|
|
1565
|
-
if (c.replies && c.replies.length > 0) {
|
|
1566
|
-
c.replies = findAndToggle(c.replies);
|
|
1567
|
-
}
|
|
1568
|
-
return c;
|
|
1569
|
-
});
|
|
1570
|
-
};
|
|
1571
|
-
this.comments.update((comments) => findAndToggle(comments));
|
|
1572
|
-
}
|
|
1573
|
-
removeMessageById(commentId) {
|
|
1574
|
-
const filterOut = (comments) => {
|
|
1575
|
-
return comments
|
|
1576
|
-
.filter((c) => c.id !== commentId)
|
|
1577
|
-
.map((c) => {
|
|
1578
|
-
if (c.replies && c.replies.length > 0) {
|
|
1579
|
-
c.replies = filterOut(c.replies);
|
|
1580
|
-
}
|
|
1581
|
-
return c;
|
|
1582
|
-
});
|
|
1638
|
+
formatComment(message, depth = 0) {
|
|
1639
|
+
return {
|
|
1640
|
+
...message,
|
|
1641
|
+
depth,
|
|
1642
|
+
replies: [],
|
|
1643
|
+
replyCount: 0,
|
|
1583
1644
|
};
|
|
1584
|
-
this.comments.update((comments) => filterOut(comments));
|
|
1585
1645
|
}
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
if (!currentThread) {
|
|
1595
|
-
currentThread = await this.commentService.createThread({ type: this.refrenceType(), id: this.refrenceId() }, this.subject());
|
|
1596
|
-
this.thread.set(currentThread);
|
|
1597
|
-
}
|
|
1598
|
-
if (this.isEditingMode() && this.activeEditComment()?.id) {
|
|
1599
|
-
await this.commentService.editComment(this.activeEditComment().id, this.commentContent());
|
|
1600
|
-
this.hasCooldown.set(true);
|
|
1601
|
-
this.isEditingMode.set(false);
|
|
1602
|
-
this.activeEditComment.set(undefined);
|
|
1646
|
+
buildCommentTree(comments) {
|
|
1647
|
+
const commentMap = new Map(comments.map((c) => [c.id, c]));
|
|
1648
|
+
const tree = [];
|
|
1649
|
+
comments.forEach((comment) => {
|
|
1650
|
+
if (comment.replyId && commentMap.has(comment.replyId)) {
|
|
1651
|
+
const parent = commentMap.get(comment.replyId);
|
|
1652
|
+
parent.replies.push(comment);
|
|
1653
|
+
comment.depth = (parent.depth ?? 0) + 1;
|
|
1603
1654
|
}
|
|
1604
1655
|
else {
|
|
1605
|
-
|
|
1606
|
-
this.hasCooldown.set(true);
|
|
1607
|
-
this.isReplyingMode.set(false);
|
|
1608
|
-
this.activeReplyComment.set(undefined);
|
|
1656
|
+
tree.push(comment);
|
|
1609
1657
|
}
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1658
|
+
});
|
|
1659
|
+
commentMap.forEach((comment) => {
|
|
1660
|
+
comment.replyCount = comment.replies.length;
|
|
1661
|
+
});
|
|
1662
|
+
return tree;
|
|
1663
|
+
}
|
|
1664
|
+
async formatThread(room) {
|
|
1665
|
+
const comments = await this.getComments(room.id, true);
|
|
1666
|
+
return {
|
|
1667
|
+
...room,
|
|
1668
|
+
comments,
|
|
1669
|
+
commentCount: comments.length,
|
|
1670
|
+
};
|
|
1671
|
+
}
|
|
1672
|
+
async createThread(entityRef, topic, title) {
|
|
1673
|
+
const currentUser = this.getCurrentUser();
|
|
1674
|
+
const newRoom = await this.commentImplService.createThread(currentUser, entityRef, topic, title);
|
|
1675
|
+
const newThread = await this.formatThread(newRoom);
|
|
1676
|
+
this.realtimeService.notifyThread({ type: 'add', payload: newThread });
|
|
1677
|
+
return newThread;
|
|
1678
|
+
}
|
|
1679
|
+
async getThread(entityRef, topic) {
|
|
1680
|
+
const room = await this.commentImplService.getThread(entityRef, topic);
|
|
1681
|
+
if (!room) {
|
|
1682
|
+
return null;
|
|
1629
1683
|
}
|
|
1684
|
+
return this.formatThread(room);
|
|
1630
1685
|
}
|
|
1631
|
-
|
|
1632
|
-
const
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
this.highlightedCommentId.set(null);
|
|
1640
|
-
}, 1000);
|
|
1641
|
-
}
|
|
1686
|
+
async listThreads(entityRef, topic) {
|
|
1687
|
+
const rooms = await this.commentImplService.listThreads(entityRef, topic);
|
|
1688
|
+
return Promise.all(rooms.map((room) => this.formatThread(room)));
|
|
1689
|
+
}
|
|
1690
|
+
async updateThread(entityRef, topic, data) {
|
|
1691
|
+
const thread = await this.getThread(entityRef, topic);
|
|
1692
|
+
if (!thread) {
|
|
1693
|
+
throw new Error(`Thread for entity ${entityRef.type}#${entityRef.id} not found.`);
|
|
1642
1694
|
}
|
|
1695
|
+
const updatedRoom = await this.commentImplService.updateThread(thread.id, data);
|
|
1696
|
+
const updatedThread = await this.formatThread(updatedRoom);
|
|
1697
|
+
this.realtimeService.notifyThread({ type: 'update', payload: updatedThread });
|
|
1698
|
+
return updatedThread;
|
|
1643
1699
|
}
|
|
1644
|
-
|
|
1645
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.3", type: AXMCommentComponent, isStandalone: true, selector: "axm-comment", inputs: { refrenceType: { classPropertyName: "refrenceType", publicName: "refrenceType", isSignal: true, isRequired: true, transformFunction: null }, refrenceId: { classPropertyName: "refrenceId", publicName: "refrenceId", isSignal: true, isRequired: true, transformFunction: null }, subject: { classPropertyName: "subject", publicName: "subject", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "wysiwygEditor", first: true, predicate: ["w"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"ax-size-full ax-flex ax-flex-col ax-justify-between ax-p-4 ax-overflow-hidden\">\n <ax-comment-container class=\"ax-overflow-auto\">\n @if (isLoading()) {\n <div class=\"ax-flex ax-items-center ax-py-12 ax-bg-lightest ax-px-5\">\n <ax-skeleton class=\"ax-min-w-16 ax-h-16 ax-rounded-full ax-me-4\"></ax-skeleton>\n <div class=\"ax-flex ax-flex-col ax-gap-2 ax-w-full\">\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-2 ax-rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-2 ax-rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-8/12 ax-h-2 ax-rounded-full\"></ax-skeleton>\n </div>\n </div>\n } @else if (!isLoading() && comments().length > 0) {\n <ax-comment-view class=\"ax-bg-lightest\">\n @for (comment of comments(); track comment.id) {\n <ax-comment-item\n [id]=\"comment.id!\"\n [replyCount]=\"comment.replyCount\"\n [class.highlighted]=\"highlightedCommentId() === comment.id\"\n [@fadeIn]\n >\n <axp-user-avatar #user [size]=\"48\" [userId]=\"comment.author.id\" ngProjectAs=\"'ax-avatar'\"></axp-user-avatar>\n <ax-title>{{ user.firstName() + ' ' + user.lastName() }}</ax-title>\n <ax-comment-date>{{ comment.createdAt | format: 'timeleft' | async }} </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button class=\"ax-sm\" look=\"blank\" color=\"neutral\">\n <ax-icon icon=\"ax-icon ax-icon-solid ax-icon-more-horizontal\"></ax-icon>\n </ax-button>\n\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n text=\"Edit\"\n color=\"neutral\"\n (click)=\"editMessage(comment, undefined, user.firstName() + ' ' + user.lastName())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-edit\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n\n <ax-button-item text=\"Delete\" color=\"danger\" (click)=\"deleteComment(comment.id!)\">\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content [innerHTML]=\"sanitizeHtml(comment.message.content)\"></ax-content>\n <ax-comment-like (click)=\"toggleLike(comment)\" [liked]=\"isLikedByUser(comment)\">\n {{ getReactionsCount(comment) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, undefined, user.firstName() + ' ' + user.lastName())\"\n ></ax-comment-reply-text>\n @for (reply of comment.replies; track reply.id) {\n <ax-comment-item [id]=\"reply.id\" [class.highlighted]=\"highlightedCommentId() === reply.id\" [@fadeIn]>\n <axp-user-avatar\n #user2\n [size]=\"48\"\n [userId]=\"reply.author.id\"\n ngProjectAs=\"'ax-avatar'\"\n ></axp-user-avatar>\n <ax-title>{{ user2.firstName() + ' ' + user2.lastName() }}</ax-title>\n <ax-comment-date>{{ reply.createdAt | format: 'timeleft' | async }} </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button class=\"ax-sm\" look=\"blank\" color=\"neutral\">\n <ax-icon icon=\"ax-icon ax-icon-solid ax-icon-more-horizontal\"></ax-icon>\n </ax-button>\n\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n text=\"Edit\"\n color=\"neutral\"\n (click)=\"editMessage(comment, reply, user2.firstName() + ' ' + user2.lastName())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-edit\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item text=\"Delete\" color=\"danger\" (click)=\"deleteComment(reply.id!)\">\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content [innerHTML]=\"sanitizeHtml(reply.message.content)\"></ax-content>\n <ax-comment-like (click)=\"toggleLike(reply)\" [liked]=\"isLikedByUser(reply)\">\n {{ getReactionsCount(reply) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, reply, user2.firstName() + ' ' + user2.lastName())\"\n ></ax-comment-reply-text>\n </ax-comment-item>\n }\n </ax-comment-item>\n }\n </ax-comment-view>\n } @else {\n <div>\n <div class=\"ax-flex ax-flex-col ax-gap-4 ax-justify-center ax-items-center ax-p-10\">\n <svg\n class=\"ax-mx-auto\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"154\"\n height=\"161\"\n viewBox=\"0 0 154 161\"\n fill=\"none\"\n >\n <path\n d=\"M0.0616455 84.4268C0.0616455 42.0213 34.435 7.83765 76.6507 7.83765C118.803 7.83765 153.224 42.0055 153.224 84.4268C153.224 102.42 147.026 118.974 136.622 132.034C122.282 150.138 100.367 161 76.6507 161C52.7759 161 30.9882 150.059 16.6633 132.034C6.25961 118.974 0.0616455 102.42 0.0616455 84.4268Z\"\n fill=\"#EEF2FF\"\n />\n <path\n d=\"M96.8189 0.632498L96.8189 0.632384L96.8083 0.630954C96.2034 0.549581 95.5931 0.5 94.9787 0.5H29.338C22.7112 0.5 17.3394 5.84455 17.3394 12.4473V142.715C17.3394 149.318 22.7112 154.662 29.338 154.662H123.948C130.591 154.662 135.946 149.317 135.946 142.715V38.9309C135.946 38.0244 135.847 37.1334 135.648 36.2586L135.648 36.2584C135.117 33.9309 133.874 31.7686 132.066 30.1333C132.066 30.1331 132.065 30.1329 132.065 30.1327L103.068 3.65203C103.068 3.6519 103.067 3.65177 103.067 3.65164C101.311 2.03526 99.1396 0.995552 96.8189 0.632498Z\"\n fill=\"white\"\n stroke=\"#E5E7EB\"\n />\n <ellipse cx=\"80.0618\" cy=\"81\" rx=\"28.0342\" ry=\"28.0342\" fill=\"#EEF2FF\" />\n <path\n d=\"M99.2393 61.3061L99.2391 61.3058C88.498 50.5808 71.1092 50.5804 60.3835 61.3061C49.6423 72.0316 49.6422 89.4361 60.3832 100.162C71.109 110.903 88.4982 110.903 99.2393 100.162C109.965 89.4363 109.965 72.0317 99.2393 61.3061ZM105.863 54.6832C120.249 69.0695 120.249 92.3985 105.863 106.785C91.4605 121.171 68.1468 121.171 53.7446 106.785C39.3582 92.3987 39.3582 69.0693 53.7446 54.683C68.1468 40.2965 91.4605 40.2966 105.863 54.6832Z\"\n stroke=\"#E5E7EB\"\n />\n <path\n d=\"M110.782 119.267L102.016 110.492C104.888 108.267 107.476 105.651 109.564 102.955L118.329 111.729L110.782 119.267Z\"\n stroke=\"#E5E7EB\"\n />\n <path\n d=\"M139.122 125.781L139.122 125.78L123.313 109.988C123.313 109.987 123.313 109.987 123.312 109.986C121.996 108.653 119.849 108.657 118.521 109.985L118.871 110.335L118.521 109.985L109.047 119.459C107.731 120.775 107.735 122.918 109.044 124.247L109.047 124.249L124.858 140.06C128.789 143.992 135.191 143.992 139.122 140.06C143.069 136.113 143.069 129.728 139.122 125.781Z\"\n fill=\"#A5B4FC\"\n stroke=\"#818CF8\"\n />\n <path\n d=\"M83.185 87.2285C82.5387 87.2285 82.0027 86.6926 82.0027 86.0305C82.0027 83.3821 77.9987 83.3821 77.9987 86.0305C77.9987 86.6926 77.4627 87.2285 76.8006 87.2285C76.1543 87.2285 75.6183 86.6926 75.6183 86.0305C75.6183 80.2294 84.3831 80.2451 84.3831 86.0305C84.3831 86.6926 83.8471 87.2285 83.185 87.2285Z\"\n fill=\"#4F46E5\"\n />\n <path\n d=\"M93.3528 77.0926H88.403C87.7409 77.0926 87.2049 76.5567 87.2049 75.8946C87.2049 75.2483 87.7409 74.7123 88.403 74.7123H93.3528C94.0149 74.7123 94.5509 75.2483 94.5509 75.8946C94.5509 76.5567 94.0149 77.0926 93.3528 77.0926Z\"\n fill=\"#4F46E5\"\n />\n <path\n d=\"M71.5987 77.0925H66.6488C65.9867 77.0925 65.4507 76.5565 65.4507 75.8945C65.4507 75.2481 65.9867 74.7122 66.6488 74.7122H71.5987C72.245 74.7122 72.781 75.2481 72.781 75.8945C72.781 76.5565 72.245 77.0925 71.5987 77.0925Z\"\n fill=\"#4F46E5\"\n />\n <rect x=\"38.3522\" y=\"21.5128\" width=\"41.0256\" height=\"2.73504\" rx=\"1.36752\" fill=\"#4F46E5\" />\n <rect x=\"38.3522\" y=\"133.65\" width=\"54.7009\" height=\"5.47009\" rx=\"2.73504\" fill=\"#A5B4FC\" />\n <rect x=\"38.3522\" y=\"29.7179\" width=\"13.6752\" height=\"2.73504\" rx=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"56.13\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"61.6001\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"67.0702\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n </svg>\n <div>\n <h2 class=\"ax-text-center ax-text-neutral-600 ax-font-semibold ax-leading-loose ax-pb-2\">\n There is no Comment!\n </h2>\n </div>\n </div>\n </div>\n }\n </ax-comment-container>\n <ax-form>\n <ax-form-field>\n <div>\n @if (isReplyingMode() || isEditingMode()) {\n <div\n class=\"ax-flex ax-justify-between ax-rounded-b-none ax-border ax-border-b-0 ax-rounded-lg ax-px-6 ax-py-3 ax-w-full ax-items-center ax-overflow-hidden ax-text-sm ax-leading-none\"\n >\n <div (click)=\"scrollMain()\" class=\"ax-flex ax-justify-start ax-items-center ax-cursor-pointer\">\n <i\n [class]=\"isReplyingMode() ? 'fa-reply' : 'fa-pen'\"\n class=\"fa-solid ax-text-primary-500 dark:ax-text-primary-300 ax-text-2xl ax-me-4\"\n ></i>\n <div\n class=\"ax-flex ax-flex-col ax-gap-2 ax-justify-between ax-align-middle ax-leading-4 ax-overflow-hidden\"\n >\n <p class=\"ax-text-primary-500 dark:ax-text-primary-300\">\n {{ isReplyingMode() ? 'Reply to ' : 'Edit Message' }}\n <span class=\"ax-font-bold\">\n {{ isReplyingMode() ? activeReplyComment()?.userName : '' }}\n </span>\n </p>\n <div\n class=\"ax-truncate\"\n [innerHTML]=\"\n isReplyingMode()\n ? sanitizeHtml(activeReplyComment()?.message?.content ?? '')\n : sanitizeHtml(activeEditComment()?.message?.content ?? '')\n \"\n ></div>\n </div>\n </div>\n <div><i (click)=\"resetReplyEditState()\" class=\"fa-solid ax-text-2xl fa-xmark ax-cursor-pointer\"></i></div>\n </div>\n }\n <ax-wysiwyg-container #w [look]=\"wysiwygOptions().look\" [(ngModel)]=\"commentContent\">\n <ax-wysiwyg-view class=\"ax-min-h-28\"></ax-wysiwyg-view>\n <ax-toolbar>\n <ax-content>\n <ax-wysiwyg-history></ax-wysiwyg-history>\n <ax-wysiwyg-font-style></ax-wysiwyg-font-style>\n <ax-wysiwyg-colors></ax-wysiwyg-colors>\n <ax-wysiwyg-list></ax-wysiwyg-list>\n <ax-wysiwyg-alignment></ax-wysiwyg-alignment>\n </ax-content>\n <ax-suffix>\n <ax-dropdown-button\n [disabled]=\"hasCooldown()\"\n type=\"submit\"\n color=\"primary\"\n mode=\"split\"\n text=\"Send\"\n (onClick)=\"submitComment()\"\n >\n @if (isSubmitting()) {\n <ax-loading></ax-loading>\n }\n <ax-button-item-list>\n <ax-button-item (click)=\"submitComment()\" text=\"Send Private ...\" name=\"private\" data=\"private\">\n <ax-prefix>\n <ax-icon icon=\"fa-regular fa-user-secret\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-button>\n </ax-suffix>\n </ax-toolbar>\n <ax-validation-rule rule=\"callback\" [options]=\"{ validate: validateContent }\"></ax-validation-rule>\n </ax-wysiwyg-container>\n </div>\n </ax-form-field>\n </ax-form>\n</div>\n", styles: [":host{display:block;width:100%;height:100%}ax-wysiwyg-container .ax-editor-container{border-top-left-radius:0!important;border-top-right-radius:0!important}ax-wysiwyg-container .ax-error-message{padding-left:.5rem}ax-wysiwyg-container .highlighted{background:var(--ax-color-primary-050)!important;border-radius:.25rem;transition:background 1s ease-in-out}\n"], dependencies: [{ kind: "ngmodule", type: AXWysiwygModule }, { kind: "component", type: i1.AXWysiwygContainerComponent, selector: "ax-wysiwyg-container", inputs: ["look", "placeHolder"], outputs: ["onValueChanged"] }, { kind: "component", type: i1.AXWysiwygViewComponent, selector: "ax-wysiwyg-view", inputs: ["class"] }, { kind: "component", type: i1.AXWysiwygAlignmentComponent, selector: "ax-wysiwyg-alignment" }, { kind: "component", type: i1.AXWysiwygColorsComponent, selector: "ax-wysiwyg-colors" }, { kind: "component", type: i1.AXWysiwygFontStyleComponent, selector: "ax-wysiwyg-font-style" }, { kind: "component", type: i1.AXWysiwygHistoryComponent, selector: "ax-wysiwyg-history" }, { kind: "component", type: i1.AXWysiwygListComponent, selector: "ax-wysiwyg-list" }, { kind: "ngmodule", type: AXConversationModule }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i2.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i1$1.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: AXCommentModule }, { kind: "component", type: i4.AXCommentViewComponent, selector: "ax-comment-view" }, { kind: "component", type: i4.AXCommentContainerComponent, selector: "ax-comment-container" }, { kind: "component", type: i4.AxCommentItemComponent, selector: "ax-comment-item", inputs: ["replyCount"] }, { kind: "component", type: i4.AXCommentLikeComponent, selector: "ax-comment-like", inputs: ["liked"], outputs: ["likedChange", "onLiked"] }, { kind: "component", type: i4.AXMenuOptionsComponent, selector: "ax-comment-menu-options" }, { kind: "component", type: i4.AXCommentReplyTextComponent, selector: "ax-comment-reply-text" }, { kind: "component", type: i4.AXCommentDateComponent, selector: "ax-comment-date" }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i5.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: i5.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i5.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXAvatarModule }, { kind: "ngmodule", type: AXImageModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i6.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i7.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "component", type: i8.AXFormFieldComponent, selector: "ax-form-field", inputs: ["labelMode"] }, { kind: "component", type: i8.AXFormComponent, selector: "ax-form", inputs: ["labelMode", "look", "messageStyle", "updateOn"], outputs: ["onValidate", "updateOnChange"] }, { kind: "directive", type: i8.AXValidationRuleDirective, selector: "ax-validation-rule", inputs: ["rule", "options", "message", "disabled"] }, { kind: "ngmodule", type: AXToolBarModule }, { kind: "component", type: i9.AXToolBarComponent, selector: "ax-toolbar" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i10.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i10.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "component", type: i11.AXDropdownButtonComponent, selector: "ax-dropdown-button", inputs: ["disabled", "size", "color", "look", "text", "type", "mode"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "lookChange", "colorChange", "disabledChange"] }, { kind: "component", type: AXPUserAvatarComponent, selector: "axp-user-avatar", inputs: ["size", "userId"] }, { kind: "pipe", type: i12.AXFormatPipe, name: "format" }, { kind: "pipe", type: AsyncPipe, name: "async" }], animations: [
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1653
|
-
}
|
|
1654
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMCommentComponent, decorators: [{
|
|
1655
|
-
type: Component,
|
|
1656
|
-
args: [{ selector: 'axm-comment', animations: [
|
|
1657
|
-
trigger('fadeIn', [
|
|
1658
|
-
transition(':enter', [
|
|
1659
|
-
style({ opacity: 0, transform: 'translateY(10px)' }),
|
|
1660
|
-
animate('300ms ease-out', style({ opacity: 1, transform: 'translateY(0)' })),
|
|
1661
|
-
]),
|
|
1662
|
-
]),
|
|
1663
|
-
], imports: [
|
|
1664
|
-
AXWysiwygModule,
|
|
1665
|
-
AXConversationModule,
|
|
1666
|
-
AXSkeletonModule,
|
|
1667
|
-
AXDecoratorModule,
|
|
1668
|
-
AXCommentModule,
|
|
1669
|
-
AXButtonModule,
|
|
1670
|
-
AXAvatarModule,
|
|
1671
|
-
AXImageModule,
|
|
1672
|
-
AXLoadingModule,
|
|
1673
|
-
AXDropdownModule,
|
|
1674
|
-
AXFormatModule,
|
|
1675
|
-
AsyncPipe,
|
|
1676
|
-
AXFormModule,
|
|
1677
|
-
AXToolBarModule,
|
|
1678
|
-
FormsModule,
|
|
1679
|
-
AXDropdownButtonModule,
|
|
1680
|
-
AXPUserAvatarComponent,
|
|
1681
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ax-size-full ax-flex ax-flex-col ax-justify-between ax-p-4 ax-overflow-hidden\">\n <ax-comment-container class=\"ax-overflow-auto\">\n @if (isLoading()) {\n <div class=\"ax-flex ax-items-center ax-py-12 ax-bg-lightest ax-px-5\">\n <ax-skeleton class=\"ax-min-w-16 ax-h-16 ax-rounded-full ax-me-4\"></ax-skeleton>\n <div class=\"ax-flex ax-flex-col ax-gap-2 ax-w-full\">\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-2 ax-rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-2 ax-rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-8/12 ax-h-2 ax-rounded-full\"></ax-skeleton>\n </div>\n </div>\n } @else if (!isLoading() && comments().length > 0) {\n <ax-comment-view class=\"ax-bg-lightest\">\n @for (comment of comments(); track comment.id) {\n <ax-comment-item\n [id]=\"comment.id!\"\n [replyCount]=\"comment.replyCount\"\n [class.highlighted]=\"highlightedCommentId() === comment.id\"\n [@fadeIn]\n >\n <axp-user-avatar #user [size]=\"48\" [userId]=\"comment.author.id\" ngProjectAs=\"'ax-avatar'\"></axp-user-avatar>\n <ax-title>{{ user.firstName() + ' ' + user.lastName() }}</ax-title>\n <ax-comment-date>{{ comment.createdAt | format: 'timeleft' | async }} </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button class=\"ax-sm\" look=\"blank\" color=\"neutral\">\n <ax-icon icon=\"ax-icon ax-icon-solid ax-icon-more-horizontal\"></ax-icon>\n </ax-button>\n\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n text=\"Edit\"\n color=\"neutral\"\n (click)=\"editMessage(comment, undefined, user.firstName() + ' ' + user.lastName())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-edit\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n\n <ax-button-item text=\"Delete\" color=\"danger\" (click)=\"deleteComment(comment.id!)\">\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content [innerHTML]=\"sanitizeHtml(comment.message.content)\"></ax-content>\n <ax-comment-like (click)=\"toggleLike(comment)\" [liked]=\"isLikedByUser(comment)\">\n {{ getReactionsCount(comment) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, undefined, user.firstName() + ' ' + user.lastName())\"\n ></ax-comment-reply-text>\n @for (reply of comment.replies; track reply.id) {\n <ax-comment-item [id]=\"reply.id\" [class.highlighted]=\"highlightedCommentId() === reply.id\" [@fadeIn]>\n <axp-user-avatar\n #user2\n [size]=\"48\"\n [userId]=\"reply.author.id\"\n ngProjectAs=\"'ax-avatar'\"\n ></axp-user-avatar>\n <ax-title>{{ user2.firstName() + ' ' + user2.lastName() }}</ax-title>\n <ax-comment-date>{{ reply.createdAt | format: 'timeleft' | async }} </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button class=\"ax-sm\" look=\"blank\" color=\"neutral\">\n <ax-icon icon=\"ax-icon ax-icon-solid ax-icon-more-horizontal\"></ax-icon>\n </ax-button>\n\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n text=\"Edit\"\n color=\"neutral\"\n (click)=\"editMessage(comment, reply, user2.firstName() + ' ' + user2.lastName())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-edit\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item text=\"Delete\" color=\"danger\" (click)=\"deleteComment(reply.id!)\">\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content [innerHTML]=\"sanitizeHtml(reply.message.content)\"></ax-content>\n <ax-comment-like (click)=\"toggleLike(reply)\" [liked]=\"isLikedByUser(reply)\">\n {{ getReactionsCount(reply) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, reply, user2.firstName() + ' ' + user2.lastName())\"\n ></ax-comment-reply-text>\n </ax-comment-item>\n }\n </ax-comment-item>\n }\n </ax-comment-view>\n } @else {\n <div>\n <div class=\"ax-flex ax-flex-col ax-gap-4 ax-justify-center ax-items-center ax-p-10\">\n <svg\n class=\"ax-mx-auto\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"154\"\n height=\"161\"\n viewBox=\"0 0 154 161\"\n fill=\"none\"\n >\n <path\n d=\"M0.0616455 84.4268C0.0616455 42.0213 34.435 7.83765 76.6507 7.83765C118.803 7.83765 153.224 42.0055 153.224 84.4268C153.224 102.42 147.026 118.974 136.622 132.034C122.282 150.138 100.367 161 76.6507 161C52.7759 161 30.9882 150.059 16.6633 132.034C6.25961 118.974 0.0616455 102.42 0.0616455 84.4268Z\"\n fill=\"#EEF2FF\"\n />\n <path\n d=\"M96.8189 0.632498L96.8189 0.632384L96.8083 0.630954C96.2034 0.549581 95.5931 0.5 94.9787 0.5H29.338C22.7112 0.5 17.3394 5.84455 17.3394 12.4473V142.715C17.3394 149.318 22.7112 154.662 29.338 154.662H123.948C130.591 154.662 135.946 149.317 135.946 142.715V38.9309C135.946 38.0244 135.847 37.1334 135.648 36.2586L135.648 36.2584C135.117 33.9309 133.874 31.7686 132.066 30.1333C132.066 30.1331 132.065 30.1329 132.065 30.1327L103.068 3.65203C103.068 3.6519 103.067 3.65177 103.067 3.65164C101.311 2.03526 99.1396 0.995552 96.8189 0.632498Z\"\n fill=\"white\"\n stroke=\"#E5E7EB\"\n />\n <ellipse cx=\"80.0618\" cy=\"81\" rx=\"28.0342\" ry=\"28.0342\" fill=\"#EEF2FF\" />\n <path\n d=\"M99.2393 61.3061L99.2391 61.3058C88.498 50.5808 71.1092 50.5804 60.3835 61.3061C49.6423 72.0316 49.6422 89.4361 60.3832 100.162C71.109 110.903 88.4982 110.903 99.2393 100.162C109.965 89.4363 109.965 72.0317 99.2393 61.3061ZM105.863 54.6832C120.249 69.0695 120.249 92.3985 105.863 106.785C91.4605 121.171 68.1468 121.171 53.7446 106.785C39.3582 92.3987 39.3582 69.0693 53.7446 54.683C68.1468 40.2965 91.4605 40.2966 105.863 54.6832Z\"\n stroke=\"#E5E7EB\"\n />\n <path\n d=\"M110.782 119.267L102.016 110.492C104.888 108.267 107.476 105.651 109.564 102.955L118.329 111.729L110.782 119.267Z\"\n stroke=\"#E5E7EB\"\n />\n <path\n d=\"M139.122 125.781L139.122 125.78L123.313 109.988C123.313 109.987 123.313 109.987 123.312 109.986C121.996 108.653 119.849 108.657 118.521 109.985L118.871 110.335L118.521 109.985L109.047 119.459C107.731 120.775 107.735 122.918 109.044 124.247L109.047 124.249L124.858 140.06C128.789 143.992 135.191 143.992 139.122 140.06C143.069 136.113 143.069 129.728 139.122 125.781Z\"\n fill=\"#A5B4FC\"\n stroke=\"#818CF8\"\n />\n <path\n d=\"M83.185 87.2285C82.5387 87.2285 82.0027 86.6926 82.0027 86.0305C82.0027 83.3821 77.9987 83.3821 77.9987 86.0305C77.9987 86.6926 77.4627 87.2285 76.8006 87.2285C76.1543 87.2285 75.6183 86.6926 75.6183 86.0305C75.6183 80.2294 84.3831 80.2451 84.3831 86.0305C84.3831 86.6926 83.8471 87.2285 83.185 87.2285Z\"\n fill=\"#4F46E5\"\n />\n <path\n d=\"M93.3528 77.0926H88.403C87.7409 77.0926 87.2049 76.5567 87.2049 75.8946C87.2049 75.2483 87.7409 74.7123 88.403 74.7123H93.3528C94.0149 74.7123 94.5509 75.2483 94.5509 75.8946C94.5509 76.5567 94.0149 77.0926 93.3528 77.0926Z\"\n fill=\"#4F46E5\"\n />\n <path\n d=\"M71.5987 77.0925H66.6488C65.9867 77.0925 65.4507 76.5565 65.4507 75.8945C65.4507 75.2481 65.9867 74.7122 66.6488 74.7122H71.5987C72.245 74.7122 72.781 75.2481 72.781 75.8945C72.781 76.5565 72.245 77.0925 71.5987 77.0925Z\"\n fill=\"#4F46E5\"\n />\n <rect x=\"38.3522\" y=\"21.5128\" width=\"41.0256\" height=\"2.73504\" rx=\"1.36752\" fill=\"#4F46E5\" />\n <rect x=\"38.3522\" y=\"133.65\" width=\"54.7009\" height=\"5.47009\" rx=\"2.73504\" fill=\"#A5B4FC\" />\n <rect x=\"38.3522\" y=\"29.7179\" width=\"13.6752\" height=\"2.73504\" rx=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"56.13\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"61.6001\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"67.0702\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n </svg>\n <div>\n <h2 class=\"ax-text-center ax-text-neutral-600 ax-font-semibold ax-leading-loose ax-pb-2\">\n There is no Comment!\n </h2>\n </div>\n </div>\n </div>\n }\n </ax-comment-container>\n <ax-form>\n <ax-form-field>\n <div>\n @if (isReplyingMode() || isEditingMode()) {\n <div\n class=\"ax-flex ax-justify-between ax-rounded-b-none ax-border ax-border-b-0 ax-rounded-lg ax-px-6 ax-py-3 ax-w-full ax-items-center ax-overflow-hidden ax-text-sm ax-leading-none\"\n >\n <div (click)=\"scrollMain()\" class=\"ax-flex ax-justify-start ax-items-center ax-cursor-pointer\">\n <i\n [class]=\"isReplyingMode() ? 'fa-reply' : 'fa-pen'\"\n class=\"fa-solid ax-text-primary-500 dark:ax-text-primary-300 ax-text-2xl ax-me-4\"\n ></i>\n <div\n class=\"ax-flex ax-flex-col ax-gap-2 ax-justify-between ax-align-middle ax-leading-4 ax-overflow-hidden\"\n >\n <p class=\"ax-text-primary-500 dark:ax-text-primary-300\">\n {{ isReplyingMode() ? 'Reply to ' : 'Edit Message' }}\n <span class=\"ax-font-bold\">\n {{ isReplyingMode() ? activeReplyComment()?.userName : '' }}\n </span>\n </p>\n <div\n class=\"ax-truncate\"\n [innerHTML]=\"\n isReplyingMode()\n ? sanitizeHtml(activeReplyComment()?.message?.content ?? '')\n : sanitizeHtml(activeEditComment()?.message?.content ?? '')\n \"\n ></div>\n </div>\n </div>\n <div><i (click)=\"resetReplyEditState()\" class=\"fa-solid ax-text-2xl fa-xmark ax-cursor-pointer\"></i></div>\n </div>\n }\n <ax-wysiwyg-container #w [look]=\"wysiwygOptions().look\" [(ngModel)]=\"commentContent\">\n <ax-wysiwyg-view class=\"ax-min-h-28\"></ax-wysiwyg-view>\n <ax-toolbar>\n <ax-content>\n <ax-wysiwyg-history></ax-wysiwyg-history>\n <ax-wysiwyg-font-style></ax-wysiwyg-font-style>\n <ax-wysiwyg-colors></ax-wysiwyg-colors>\n <ax-wysiwyg-list></ax-wysiwyg-list>\n <ax-wysiwyg-alignment></ax-wysiwyg-alignment>\n </ax-content>\n <ax-suffix>\n <ax-dropdown-button\n [disabled]=\"hasCooldown()\"\n type=\"submit\"\n color=\"primary\"\n mode=\"split\"\n text=\"Send\"\n (onClick)=\"submitComment()\"\n >\n @if (isSubmitting()) {\n <ax-loading></ax-loading>\n }\n <ax-button-item-list>\n <ax-button-item (click)=\"submitComment()\" text=\"Send Private ...\" name=\"private\" data=\"private\">\n <ax-prefix>\n <ax-icon icon=\"fa-regular fa-user-secret\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-button>\n </ax-suffix>\n </ax-toolbar>\n <ax-validation-rule rule=\"callback\" [options]=\"{ validate: validateContent }\"></ax-validation-rule>\n </ax-wysiwyg-container>\n </div>\n </ax-form-field>\n </ax-form>\n</div>\n", styles: [":host{display:block;width:100%;height:100%}ax-wysiwyg-container .ax-editor-container{border-top-left-radius:0!important;border-top-right-radius:0!important}ax-wysiwyg-container .ax-error-message{padding-left:.5rem}ax-wysiwyg-container .highlighted{background:var(--ax-color-primary-050)!important;border-radius:.25rem;transition:background 1s ease-in-out}\n"] }]
|
|
1682
|
-
}] });
|
|
1683
|
-
|
|
1684
|
-
var comment_component = /*#__PURE__*/Object.freeze({
|
|
1685
|
-
__proto__: null,
|
|
1686
|
-
AXMCommentComponent: AXMCommentComponent
|
|
1687
|
-
});
|
|
1688
|
-
|
|
1689
|
-
class AXMCommentPopupComponent extends AXBasePageComponent {
|
|
1690
|
-
constructor() {
|
|
1691
|
-
super(...arguments);
|
|
1692
|
-
this.refrenceType = input.required(...(ngDevMode ? [{ debugName: "refrenceType" }] : []));
|
|
1693
|
-
this.refrenceId = input.required(...(ngDevMode ? [{ debugName: "refrenceId" }] : []));
|
|
1694
|
-
this.subject = input.required(...(ngDevMode ? [{ debugName: "subject" }] : []));
|
|
1700
|
+
async deleteThread(entityRef, topic) {
|
|
1701
|
+
const thread = await this.getThread(entityRef, topic);
|
|
1702
|
+
if (thread) {
|
|
1703
|
+
await this.commentImplService.deleteThread(thread.id);
|
|
1704
|
+
this.realtimeService.notifyThread({ type: 'remove', payload: thread.id });
|
|
1705
|
+
return true;
|
|
1706
|
+
}
|
|
1707
|
+
return false;
|
|
1695
1708
|
}
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
// Comment
|
|
1703
|
-
AXMCommentComponent, selector: "axm-comment", inputs: ["refrenceType", "refrenceId", "subject"] }, { kind: "pipe", type: i1$2.AsyncPipe, name: "async" }, { kind: "pipe", type: i4$1.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
1704
|
-
}
|
|
1705
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMCommentPopupComponent, decorators: [{
|
|
1706
|
-
type: Component,
|
|
1707
|
-
args: [{ selector: 'axm-comment-popup', standalone: true, imports: [
|
|
1708
|
-
// Angular
|
|
1709
|
-
CommonModule,
|
|
1710
|
-
// ACoreX
|
|
1711
|
-
AXDecoratorModule,
|
|
1712
|
-
AXButtonModule,
|
|
1713
|
-
AXTranslationModule,
|
|
1714
|
-
// Comment
|
|
1715
|
-
AXMCommentComponent,
|
|
1716
|
-
], encapsulation: ViewEncapsulation.None, providers: [], template: "<ax-content>\n <div class=\"ax-p-6 ax-min-h-[30vh] ax-overflow-y-auto\">\n <axm-comment [refrenceType]=\"refrenceType()\" [refrenceId]=\"refrenceId()\" [subject]=\"subject()\"></axm-comment>\n </div>\n</ax-content>\n<ax-footer>\n <ax-prefix></ax-prefix>\n <ax-suffix>\n <ax-button [text]=\"'close' | translate | async\" look=\"solid\" color=\"primary\" (onClick)=\"close()\"> </ax-button>\n </ax-suffix>\n</ax-footer>\n" }]
|
|
1717
|
-
}] });
|
|
1718
|
-
|
|
1719
|
-
var commentPopup_component = /*#__PURE__*/Object.freeze({
|
|
1720
|
-
__proto__: null,
|
|
1721
|
-
AXMCommentPopupComponent: AXMCommentPopupComponent
|
|
1722
|
-
});
|
|
1723
|
-
|
|
1724
|
-
class AXMUserLookupPopup extends AXBasePageComponent {
|
|
1725
|
-
constructor() {
|
|
1726
|
-
super(...arguments);
|
|
1727
|
-
this.lookupNode = {
|
|
1728
|
-
name: 'form-field',
|
|
1729
|
-
path: 'form-field',
|
|
1730
|
-
type: 'form-field',
|
|
1731
|
-
children: [
|
|
1732
|
-
{
|
|
1733
|
-
name: 'lookup',
|
|
1734
|
-
path: 'lookup',
|
|
1735
|
-
type: 'lookup-editor',
|
|
1736
|
-
options: {
|
|
1737
|
-
entity: 'SecurityManagement.users',
|
|
1738
|
-
multiple: true,
|
|
1739
|
-
},
|
|
1740
|
-
},
|
|
1741
|
-
],
|
|
1742
|
-
options: {
|
|
1743
|
-
label: 'Select users:',
|
|
1744
|
-
},
|
|
1745
|
-
};
|
|
1746
|
-
this.titleNode = {
|
|
1747
|
-
name: 'form-field',
|
|
1748
|
-
path: 'form-field',
|
|
1749
|
-
type: 'form-field',
|
|
1750
|
-
children: [
|
|
1751
|
-
{
|
|
1752
|
-
name: 'title',
|
|
1753
|
-
path: 'title',
|
|
1754
|
-
type: 'text-editor',
|
|
1755
|
-
options: {
|
|
1756
|
-
placeholder: 'Enter title',
|
|
1757
|
-
required: true,
|
|
1758
|
-
},
|
|
1759
|
-
},
|
|
1760
|
-
],
|
|
1761
|
-
options: {
|
|
1762
|
-
label: 'Title:',
|
|
1763
|
-
},
|
|
1764
|
-
};
|
|
1765
|
-
this.context = signal({}, ...(ngDevMode ? [{ debugName: "context" }] : []));
|
|
1709
|
+
async addComment(threadId, content, parentCommentId, contentType = 'text', userId) {
|
|
1710
|
+
const author = userId ? await this.getUserInfo(userId) : this.getCurrentUser();
|
|
1711
|
+
const rawComment = await this.commentImplService.addComment(threadId, content, author, parentCommentId, contentType);
|
|
1712
|
+
const formattedComment = this.formatComment(rawComment);
|
|
1713
|
+
this.realtimeService.notifyComment({ type: 'add', payload: formattedComment });
|
|
1714
|
+
return formattedComment;
|
|
1766
1715
|
}
|
|
1767
|
-
|
|
1768
|
-
this.
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1716
|
+
async getComments(threadId, nested) {
|
|
1717
|
+
const rawComments = await this.commentImplService.getComments(threadId);
|
|
1718
|
+
const formattedComments = rawComments.map((c) => this.formatComment(c));
|
|
1719
|
+
if (nested) {
|
|
1720
|
+
return this.buildCommentTree(formattedComments);
|
|
1721
|
+
}
|
|
1722
|
+
return formattedComments;
|
|
1772
1723
|
}
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1724
|
+
async getComment(commentId) {
|
|
1725
|
+
const rawComment = await this.commentImplService.getComment(commentId);
|
|
1726
|
+
return this.formatComment(rawComment);
|
|
1727
|
+
}
|
|
1728
|
+
async editComment(commentId, content, contentType = 'text') {
|
|
1729
|
+
const editor = this.getCurrentUser();
|
|
1730
|
+
const rawComment = await this.commentImplService.editComment(commentId, content, editor, contentType);
|
|
1731
|
+
const formattedComment = this.formatComment(rawComment);
|
|
1732
|
+
this.realtimeService.notifyComment({ type: 'update', payload: formattedComment });
|
|
1733
|
+
return formattedComment;
|
|
1734
|
+
}
|
|
1735
|
+
async deleteComment(commentId) {
|
|
1736
|
+
const result = await this.commentImplService.deleteComment(commentId);
|
|
1737
|
+
if (result) {
|
|
1738
|
+
this.realtimeService.notifyComment({ type: 'remove', payload: commentId });
|
|
1779
1739
|
}
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
[disabled]="(context()?.lookup?.length > 1 && !context()?.title) || !context()?.lookup?.length"
|
|
1789
|
-
(onClick)="handleClose()"
|
|
1790
|
-
></ax-button>
|
|
1791
|
-
</ax-suffix>
|
|
1792
|
-
</ax-footer>`, isInline: true, dependencies: [{ kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.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: AXPLayoutBuilderModule }, { kind: "component", type: i2$1.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i2$1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i5.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"] }] }); }
|
|
1793
|
-
}
|
|
1794
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMUserLookupPopup, decorators: [{
|
|
1795
|
-
type: Component,
|
|
1796
|
-
args: [{
|
|
1797
|
-
template: `<axp-widgets-container [context]="context()" (onContextChanged)="context.set($event.data)">
|
|
1798
|
-
<div class="ax-p-4 ax-flex ax-flex-col ax-gap-4">
|
|
1799
|
-
<ng-container axp-widget-renderer [node]="lookupNode" [mode]="'edit'"> </ng-container>
|
|
1800
|
-
@if (context()?.lookup?.length > 1) {
|
|
1801
|
-
<ng-container axp-widget-renderer [node]="titleNode" [mode]="'edit'"> </ng-container>
|
|
1740
|
+
return result;
|
|
1741
|
+
}
|
|
1742
|
+
async addReaction(commentId, type) {
|
|
1743
|
+
const author = this.getCurrentUser();
|
|
1744
|
+
const comment = await this.commentImplService.getComment(commentId);
|
|
1745
|
+
const reactions = comment.reactions || [];
|
|
1746
|
+
if (reactions.some((r) => r.author.id === author.id && r.type === type)) {
|
|
1747
|
+
return this.formatComment(comment);
|
|
1802
1748
|
}
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
<ax-button
|
|
1809
|
-
text="Accept & Send"
|
|
1810
|
-
color="primary"
|
|
1811
|
-
[disabled]="(context()?.lookup?.length > 1 && !context()?.title) || !context()?.lookup?.length"
|
|
1812
|
-
(onClick)="handleClose()"
|
|
1813
|
-
></ax-button>
|
|
1814
|
-
</ax-suffix>
|
|
1815
|
-
</ax-footer>`,
|
|
1816
|
-
imports: [AXDecoratorModule, AXPLayoutBuilderModule, AXButtonModule],
|
|
1817
|
-
}]
|
|
1818
|
-
}] });
|
|
1819
|
-
|
|
1820
|
-
class AXMCommentWidgetViewComponent extends AXPValueWidgetComponent {
|
|
1821
|
-
constructor() {
|
|
1822
|
-
super(...arguments);
|
|
1823
|
-
this.refrenceType = computed(() => this.options().refrenceType, ...(ngDevMode ? [{ debugName: "refrenceType" }] : []));
|
|
1824
|
-
this.refrenceId = computed(() => this.options().refrenceId, ...(ngDevMode ? [{ debugName: "refrenceId" }] : []));
|
|
1825
|
-
this.subject = computed(() => this.options().subject, ...(ngDevMode ? [{ debugName: "subject" }] : []));
|
|
1749
|
+
const updatedReactions = [...reactions, { author, type }];
|
|
1750
|
+
const rawComment = await this.commentImplService.updateReactions(commentId, updatedReactions);
|
|
1751
|
+
const formattedComment = this.formatComment(rawComment);
|
|
1752
|
+
this.realtimeService.notifyComment({ type: 'update', payload: formattedComment });
|
|
1753
|
+
return formattedComment;
|
|
1826
1754
|
}
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
template: `
|
|
1836
|
-
<axm-comment [refrenceId]="refrenceId()" [refrenceType]="refrenceType()" [subject]="subject()"></axm-comment>
|
|
1837
|
-
`,
|
|
1838
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1839
|
-
imports: [AXMCommentComponent],
|
|
1840
|
-
}]
|
|
1841
|
-
}] });
|
|
1842
|
-
|
|
1843
|
-
var commentWidgetView_component = /*#__PURE__*/Object.freeze({
|
|
1844
|
-
__proto__: null,
|
|
1845
|
-
AXMCommentWidgetViewComponent: AXMCommentWidgetViewComponent
|
|
1846
|
-
});
|
|
1847
|
-
|
|
1848
|
-
const AXPCommentWidget = {
|
|
1849
|
-
name: 'comment',
|
|
1850
|
-
title: 'Comments',
|
|
1851
|
-
description: 'Display and manage comments for entities',
|
|
1852
|
-
type: 'view',
|
|
1853
|
-
categories: [],
|
|
1854
|
-
groups: [AXPWidgetGroupEnum.FormElement],
|
|
1855
|
-
icon: 'fa-solid fa-comments',
|
|
1856
|
-
properties: [],
|
|
1857
|
-
components: {
|
|
1858
|
-
view: {
|
|
1859
|
-
component: () => Promise.resolve().then(function () { return commentWidgetView_component; }).then((c) => c.AXMCommentWidgetViewComponent),
|
|
1860
|
-
},
|
|
1861
|
-
},
|
|
1862
|
-
};
|
|
1863
|
-
|
|
1864
|
-
class AXMCommentPopupStartAction extends AXPWorkflowAction {
|
|
1865
|
-
constructor() {
|
|
1866
|
-
super(...arguments);
|
|
1867
|
-
this.popupService = inject(AXPopupService);
|
|
1868
|
-
this.translate = inject(AXTranslationService);
|
|
1755
|
+
async removeReaction(commentId, type) {
|
|
1756
|
+
const author = this.getCurrentUser();
|
|
1757
|
+
const comment = await this.commentImplService.getComment(commentId);
|
|
1758
|
+
const updatedReactions = (comment.reactions || []).filter((r) => !(r.author.id === author.id && r.type === type));
|
|
1759
|
+
const rawComment = await this.commentImplService.updateReactions(commentId, updatedReactions);
|
|
1760
|
+
const formattedComment = this.formatComment(rawComment);
|
|
1761
|
+
this.realtimeService.notifyComment({ type: 'update', payload: formattedComment });
|
|
1762
|
+
return formattedComment;
|
|
1869
1763
|
}
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1764
|
+
getReactions(commentId) {
|
|
1765
|
+
return this.commentImplService.getReactions(commentId);
|
|
1766
|
+
}
|
|
1767
|
+
likeComment(commentId) {
|
|
1768
|
+
return this.addReaction(commentId, 'like');
|
|
1769
|
+
}
|
|
1770
|
+
unlikeComment(commentId) {
|
|
1771
|
+
return this.removeReaction(commentId, 'like');
|
|
1772
|
+
}
|
|
1773
|
+
async pinComment(commentId) {
|
|
1774
|
+
const rawComment = await this.commentImplService.pinComment(commentId, true);
|
|
1775
|
+
const formattedComment = this.formatComment(rawComment);
|
|
1776
|
+
this.realtimeService.notifyComment({ type: 'update', payload: formattedComment });
|
|
1777
|
+
return formattedComment;
|
|
1778
|
+
}
|
|
1779
|
+
async unpinComment(commentId) {
|
|
1780
|
+
const rawComment = await this.commentImplService.pinComment(commentId, false);
|
|
1781
|
+
const formattedComment = this.formatComment(rawComment);
|
|
1782
|
+
this.realtimeService.notifyComment({ type: 'update', payload: formattedComment });
|
|
1783
|
+
return formattedComment;
|
|
1881
1784
|
}
|
|
1882
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
1883
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.
|
|
1785
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentManagementService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1786
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentManagementService, providedIn: 'root' }); }
|
|
1884
1787
|
}
|
|
1885
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
1886
|
-
type: Injectable
|
|
1788
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentManagementService, decorators: [{
|
|
1789
|
+
type: Injectable,
|
|
1790
|
+
args: [{
|
|
1791
|
+
providedIn: 'root',
|
|
1792
|
+
}]
|
|
1887
1793
|
}] });
|
|
1888
|
-
const AXMCommentPopupWorkflow = {
|
|
1889
|
-
startStepId: 'start',
|
|
1890
|
-
steps: {
|
|
1891
|
-
start: {
|
|
1892
|
-
action: 'show-comment-popup-action',
|
|
1893
|
-
},
|
|
1894
|
-
},
|
|
1895
|
-
};
|
|
1896
1794
|
|
|
1897
|
-
function
|
|
1795
|
+
function convertCommentToNotification(thread, comment, currentUser) {
|
|
1898
1796
|
return {
|
|
1899
1797
|
channel: 'InApp',
|
|
1900
1798
|
template: {
|
|
@@ -1903,451 +1801,658 @@ function convertChatMessageToNotification(room, message, currentUser) {
|
|
|
1903
1801
|
icon: 'fa-light fa-comment',
|
|
1904
1802
|
isPinned: false,
|
|
1905
1803
|
},
|
|
1906
|
-
title:
|
|
1907
|
-
body:
|
|
1908
|
-
sender:
|
|
1804
|
+
title: thread.title || 'New Comment',
|
|
1805
|
+
body: comment.message.content,
|
|
1806
|
+
sender: comment.author,
|
|
1909
1807
|
receiver: currentUser,
|
|
1910
|
-
content:
|
|
1808
|
+
content: comment.message,
|
|
1911
1809
|
readAt: null,
|
|
1912
|
-
type: '
|
|
1810
|
+
type: 'Comment',
|
|
1811
|
+
data: {
|
|
1812
|
+
threadId: thread.id,
|
|
1813
|
+
refrenceType: thread.entityRef?.type,
|
|
1814
|
+
refrenceId: thread.entityRef?.id,
|
|
1815
|
+
},
|
|
1913
1816
|
};
|
|
1914
1817
|
}
|
|
1915
1818
|
|
|
1916
|
-
|
|
1917
|
-
class AXMChatService {
|
|
1918
|
-
}
|
|
1919
|
-
//#endregion
|
|
1920
|
-
class AXMChatServiceImpl {
|
|
1819
|
+
class AXMCommentComponent {
|
|
1921
1820
|
constructor() {
|
|
1922
|
-
this.
|
|
1923
|
-
this.
|
|
1924
|
-
this.
|
|
1821
|
+
this.refrenceType = input.required(...(ngDevMode ? [{ debugName: "refrenceType" }] : []));
|
|
1822
|
+
this.refrenceId = input.required(...(ngDevMode ? [{ debugName: "refrenceId" }] : []));
|
|
1823
|
+
this.subject = input.required(...(ngDevMode ? [{ debugName: "subject" }] : []));
|
|
1824
|
+
this.hasCooldown = signal(false, ...(ngDevMode ? [{ debugName: "hasCooldown" }] : []));
|
|
1825
|
+
this.commentContent = signal('', ...(ngDevMode ? [{ debugName: "commentContent" }] : []));
|
|
1826
|
+
this.isSubmitting = signal(false, ...(ngDevMode ? [{ debugName: "isSubmitting" }] : []));
|
|
1827
|
+
this.isReplyingMode = signal(false, ...(ngDevMode ? [{ debugName: "isReplyingMode" }] : []));
|
|
1828
|
+
this.isEditingMode = signal(false, ...(ngDevMode ? [{ debugName: "isEditingMode" }] : []));
|
|
1829
|
+
this.isLoading = signal(true, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
1830
|
+
this.failedImageIds = signal([], ...(ngDevMode ? [{ debugName: "failedImageIds" }] : []));
|
|
1831
|
+
this.activeReplyComment = signal(undefined, ...(ngDevMode ? [{ debugName: "activeReplyComment" }] : []));
|
|
1832
|
+
this.activeEditComment = signal(undefined, ...(ngDevMode ? [{ debugName: "activeEditComment" }] : []));
|
|
1833
|
+
this.highlightedCommentId = signal(null, ...(ngDevMode ? [{ debugName: "highlightedCommentId" }] : []));
|
|
1834
|
+
this.wysiwygEditor = viewChild.required('w');
|
|
1835
|
+
this.commentService = inject(AXMCommentManagementService);
|
|
1836
|
+
this.realtimeService = inject(AXMCommentRealtimeService);
|
|
1925
1837
|
this.sessionService = inject(AXPSessionService);
|
|
1926
|
-
this.
|
|
1927
|
-
this.
|
|
1928
|
-
this.
|
|
1929
|
-
this.
|
|
1930
|
-
this.
|
|
1931
|
-
this.
|
|
1932
|
-
this.
|
|
1933
|
-
this.
|
|
1934
|
-
this.
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
this.
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
this.
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
}
|
|
1948
|
-
//#region ---- Helper Methods ----
|
|
1949
|
-
getCurrentUser() {
|
|
1950
|
-
const user = this.sessionService.user;
|
|
1951
|
-
return {
|
|
1952
|
-
id: user?.id || 'guest-user',
|
|
1953
|
-
type: 'user',
|
|
1954
|
-
fullName: user?.title?.trim() || 'Guest User',
|
|
1955
|
-
username: user?.name?.trim() || 'guest-user',
|
|
1956
|
-
};
|
|
1957
|
-
}
|
|
1958
|
-
async getUserInfo(userId) {
|
|
1959
|
-
try {
|
|
1960
|
-
const user = await this.usersService.getOne(userId);
|
|
1961
|
-
return {
|
|
1962
|
-
id: user.id,
|
|
1963
|
-
type: 'user',
|
|
1964
|
-
fullName: `${user.firstName} ${user.lastName}`.trim(),
|
|
1965
|
-
username: user.username?.trim(),
|
|
1966
|
-
};
|
|
1967
|
-
}
|
|
1968
|
-
catch (error) {
|
|
1969
|
-
console.error(`Failed to get user info for ID: ${userId}`, error);
|
|
1970
|
-
return {
|
|
1971
|
-
id: userId,
|
|
1972
|
-
type: 'user',
|
|
1973
|
-
fullName: 'Unknown User',
|
|
1974
|
-
username: 'Unknown User',
|
|
1975
|
-
};
|
|
1976
|
-
}
|
|
1977
|
-
}
|
|
1978
|
-
async formatMessage(message) {
|
|
1979
|
-
if (message.author && !message.author.fullName) {
|
|
1980
|
-
const authorInfo = await this.getUserInfo(message.author.id);
|
|
1838
|
+
this.toastService = inject(AXToastService);
|
|
1839
|
+
this.dialogService = inject(AXDialogService);
|
|
1840
|
+
this.notificationConnectorService = inject(AXMNotificationConnectorService);
|
|
1841
|
+
this.router = inject(Router);
|
|
1842
|
+
this.sanitize = inject(DomSanitizer);
|
|
1843
|
+
this.destroyRef = inject(DestroyRef);
|
|
1844
|
+
this.comments = signal([], ...(ngDevMode ? [{ debugName: "comments" }] : []));
|
|
1845
|
+
this.thread = signal(undefined, ...(ngDevMode ? [{ debugName: "thread" }] : []));
|
|
1846
|
+
this.wysiwygOptions = signal({
|
|
1847
|
+
look: 'solid',
|
|
1848
|
+
}, ...(ngDevMode ? [{ debugName: "wysiwygOptions" }] : []));
|
|
1849
|
+
this.avatarConfig = signal({
|
|
1850
|
+
color: 'primary',
|
|
1851
|
+
look: 'rounded',
|
|
1852
|
+
type: 'solid',
|
|
1853
|
+
}, ...(ngDevMode ? [{ debugName: "avatarConfig" }] : []));
|
|
1854
|
+
this.validateContent = (content) => {
|
|
1855
|
+
let isValid = true;
|
|
1856
|
+
if (!content || content === '<p><br></p>') {
|
|
1857
|
+
isValid = false;
|
|
1858
|
+
}
|
|
1981
1859
|
return {
|
|
1982
|
-
|
|
1983
|
-
|
|
1860
|
+
rule: 'callback',
|
|
1861
|
+
result: isValid,
|
|
1862
|
+
message: isValid ? '' : 'Please fill the content',
|
|
1863
|
+
value: content,
|
|
1984
1864
|
};
|
|
1985
|
-
}
|
|
1986
|
-
return message;
|
|
1987
|
-
}
|
|
1988
|
-
async getUnreadCount(roomId) {
|
|
1989
|
-
const { items } = await this.messageService.query({
|
|
1990
|
-
skip: 0,
|
|
1991
|
-
take: 99,
|
|
1992
|
-
filter: { field: 'roomId', value: roomId, operator: { type: 'equal' } },
|
|
1993
|
-
});
|
|
1994
|
-
const currentUserId = this.getCurrentUser().id;
|
|
1995
|
-
const unreadMessages = items.filter((message) => {
|
|
1996
|
-
const isFromCurrentUser = message.author.id === currentUserId;
|
|
1997
|
-
const isReadByCurrentUser = (message.seen || []).some((seen) => seen.author.id === currentUserId);
|
|
1998
|
-
return !isFromCurrentUser && !isReadByCurrentUser;
|
|
1999
|
-
});
|
|
2000
|
-
return unreadMessages.length;
|
|
2001
|
-
}
|
|
2002
|
-
//#endregion
|
|
2003
|
-
//#region ---- ChatRoomService Implementations ----
|
|
2004
|
-
async createRoom(memberIds, title) {
|
|
2005
|
-
if (memberIds.length === 0) {
|
|
2006
|
-
throw new Error('At least one member is required to create a room');
|
|
2007
|
-
}
|
|
2008
|
-
const currentUser = this.getCurrentUser();
|
|
2009
|
-
const allMemberIds = [...new Set([...memberIds, currentUser.id])];
|
|
2010
|
-
const memberReferences = await Promise.all(allMemberIds.map((id) => this.getUserInfo(id)));
|
|
2011
|
-
const room = {
|
|
2012
|
-
members: memberReferences,
|
|
2013
|
-
title: title,
|
|
2014
|
-
topic: memberIds.length > 1 ? 'group' : 'personal',
|
|
2015
|
-
createdAt: new Date(),
|
|
2016
|
-
updatedAt: new Date(),
|
|
2017
|
-
type: 'chat',
|
|
2018
|
-
createdBy: this.getCurrentUser().id,
|
|
2019
|
-
updatedBy: this.getCurrentUser().id,
|
|
2020
|
-
};
|
|
2021
|
-
const roomId = await this.roomService.insertOne(room);
|
|
2022
|
-
const newRoom = await this.getRoom(roomId);
|
|
2023
|
-
this._roomAdded$.next(newRoom);
|
|
2024
|
-
return newRoom;
|
|
2025
|
-
}
|
|
2026
|
-
async getRoom(roomId) {
|
|
2027
|
-
const room = await this.roomService.getOne(roomId);
|
|
2028
|
-
if (!room || room.type !== 'chat') {
|
|
2029
|
-
throw new Error(`Chat room with ID ${roomId} not found.`);
|
|
2030
|
-
}
|
|
2031
|
-
const messages = await this.getMessages(roomId, 0, 1);
|
|
2032
|
-
const lastMessage = messages.items.length > 0 ? messages.items[0] : undefined;
|
|
2033
|
-
const unreadCount = await this.getUnreadCount(roomId);
|
|
2034
|
-
const currentUserId = this.getCurrentUser().id;
|
|
2035
|
-
const members = await Promise.all(room.members.map(async (member) => {
|
|
2036
|
-
if (member.fullName) {
|
|
2037
|
-
return member;
|
|
2038
|
-
}
|
|
2039
|
-
return this.getUserInfo(member.id);
|
|
2040
|
-
}));
|
|
2041
|
-
return {
|
|
2042
|
-
...room,
|
|
2043
|
-
lastMessage,
|
|
2044
|
-
unreadCount,
|
|
2045
|
-
members: members.filter((m) => m.id !== currentUserId),
|
|
2046
1865
|
};
|
|
2047
1866
|
}
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
1867
|
+
ngOnInit() {
|
|
1868
|
+
this.isLoading.set(true);
|
|
1869
|
+
this.loadComments().finally(() => {
|
|
1870
|
+
setTimeout(() => {
|
|
1871
|
+
this.isLoading.set(false);
|
|
1872
|
+
}, 250);
|
|
1873
|
+
});
|
|
1874
|
+
this.realtimeService.comment$
|
|
1875
|
+
.pipe(takeUntilDestroyed(this.destroyRef), filter((event) => !!event))
|
|
1876
|
+
.subscribe((event) => {
|
|
1877
|
+
switch (event.type) {
|
|
1878
|
+
case 'add':
|
|
1879
|
+
this.handleAddComment(event.payload);
|
|
1880
|
+
break;
|
|
1881
|
+
case 'update':
|
|
1882
|
+
this.handleUpdateComment(event.payload);
|
|
1883
|
+
break;
|
|
1884
|
+
case 'remove':
|
|
1885
|
+
this.removeMessageById(event.payload);
|
|
1886
|
+
break;
|
|
1887
|
+
}
|
|
2053
1888
|
});
|
|
2054
|
-
const settledRooms = await Promise.allSettled(items.map((room) => this.getRoom(room.id)));
|
|
2055
|
-
const chatRooms = settledRooms
|
|
2056
|
-
.filter((result) => {
|
|
2057
|
-
if (result.status === 'rejected') {
|
|
2058
|
-
console.error('Failed to fetch room details:', result.reason);
|
|
2059
|
-
return false;
|
|
2060
|
-
}
|
|
2061
|
-
return true;
|
|
2062
|
-
})
|
|
2063
|
-
.map((result) => result.value);
|
|
2064
|
-
return { items: chatRooms, total: chatRooms.length };
|
|
2065
|
-
}
|
|
2066
|
-
async updateRoom(roomId, data) {
|
|
2067
|
-
const update = { ...data, updatedAt: new Date(), updatedBy: this.getCurrentUser().id };
|
|
2068
|
-
return this.roomService.updateOne(roomId, update);
|
|
2069
1889
|
}
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
this.
|
|
2074
|
-
|
|
1890
|
+
handleAddComment(comment) {
|
|
1891
|
+
if (comment.author.id !== this.getCurrentUser()?.id) {
|
|
1892
|
+
const notification = convertCommentToNotification(this.thread(), comment, this.sessionService.user);
|
|
1893
|
+
this.notificationConnectorService.create({
|
|
1894
|
+
...notification,
|
|
1895
|
+
id: comment.id,
|
|
1896
|
+
entityName: 'notifications',
|
|
1897
|
+
createAt: new Date(),
|
|
1898
|
+
}, {
|
|
1899
|
+
onClick: () => {
|
|
1900
|
+
this.router.navigate([this.refrenceType(), 't', this.refrenceType(), 'i', this.refrenceId()]);
|
|
1901
|
+
},
|
|
1902
|
+
activeWindow: true,
|
|
1903
|
+
});
|
|
2075
1904
|
}
|
|
2076
|
-
|
|
2077
|
-
|
|
1905
|
+
if (comment.replyId) {
|
|
1906
|
+
this.comments.update((comments) => {
|
|
1907
|
+
return comments.map((c) => {
|
|
1908
|
+
if (c.id === comment.replyId) {
|
|
1909
|
+
const newReplies = c.replies ? [...c.replies, comment] : [comment];
|
|
1910
|
+
return { ...c, replies: newReplies, replyCount: newReplies.length };
|
|
1911
|
+
}
|
|
1912
|
+
return c;
|
|
1913
|
+
});
|
|
1914
|
+
});
|
|
1915
|
+
}
|
|
1916
|
+
else {
|
|
1917
|
+
this.comments.update((comments) => [...comments, comment]);
|
|
2078
1918
|
}
|
|
2079
1919
|
}
|
|
2080
|
-
|
|
2081
|
-
const
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
const room = await this.roomService.getOne(roomId);
|
|
2094
|
-
const updatedMembers = room.members.filter((member) => member.id !== userId);
|
|
2095
|
-
return this.roomService.updateOne(roomId, {
|
|
2096
|
-
members: updatedMembers,
|
|
2097
|
-
updatedAt: new Date(),
|
|
2098
|
-
updatedBy: this.getCurrentUser().id,
|
|
2099
|
-
});
|
|
1920
|
+
handleUpdateComment(updatedComment) {
|
|
1921
|
+
const update = (list) => {
|
|
1922
|
+
return list.map((c) => {
|
|
1923
|
+
if (c.id === updatedComment.id) {
|
|
1924
|
+
return { ...c, ...updatedComment, replies: updatedComment.replies || c.replies };
|
|
1925
|
+
}
|
|
1926
|
+
if (c.replies && c.replies.length > 0) {
|
|
1927
|
+
return { ...c, replies: update(c.replies) };
|
|
1928
|
+
}
|
|
1929
|
+
return c;
|
|
1930
|
+
});
|
|
1931
|
+
};
|
|
1932
|
+
this.comments.update((comments) => update(comments));
|
|
2100
1933
|
}
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
const tabId = await this.tabService.insertOne(data);
|
|
2105
|
-
const newTab = await this.getTab(tabId);
|
|
2106
|
-
this._tabAdded$.next(newTab);
|
|
2107
|
-
return newTab;
|
|
1934
|
+
getCurrentUser() {
|
|
1935
|
+
const user = this.sessionService.user;
|
|
1936
|
+
return user ? { id: user.id, type: 'user' } : null;
|
|
2108
1937
|
}
|
|
2109
|
-
|
|
2110
|
-
|
|
1938
|
+
isLikedByUser(comment) {
|
|
1939
|
+
const user = this.getCurrentUser();
|
|
1940
|
+
if (!user)
|
|
1941
|
+
return false;
|
|
1942
|
+
return (comment.reactions || []).some((r) => r.author.id === user.id && r.type === 'like');
|
|
2111
1943
|
}
|
|
2112
|
-
|
|
2113
|
-
return
|
|
1944
|
+
getReactionsCount(comment) {
|
|
1945
|
+
return (comment.reactions || []).filter((r) => r.type === 'like').length;
|
|
2114
1946
|
}
|
|
2115
|
-
|
|
2116
|
-
|
|
1947
|
+
sanitizeHtml(htmlContent) {
|
|
1948
|
+
if (!htmlContent)
|
|
1949
|
+
return this.sanitize.bypassSecurityTrustHtml('');
|
|
1950
|
+
return this.sanitize.bypassSecurityTrustHtml(htmlContent);
|
|
2117
1951
|
}
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
await this.tabService.deleteOne(tabId);
|
|
2121
|
-
this._tabRemoved$.next(tabId);
|
|
2122
|
-
return true;
|
|
2123
|
-
}
|
|
2124
|
-
catch (error) {
|
|
2125
|
-
console.error(`Error deleting tab ${tabId}:`, error);
|
|
2126
|
-
return false;
|
|
2127
|
-
}
|
|
1952
|
+
handleImageError(imageId) {
|
|
1953
|
+
this.failedImageIds.update((ids) => [...ids, imageId]);
|
|
2128
1954
|
}
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
const room = await this.getRoom(roomId);
|
|
2132
|
-
if (tab && room) {
|
|
2133
|
-
const updatedRooms = [...tab.includeRooms, room];
|
|
2134
|
-
return this.updateTab(tabId, { includeRooms: updatedRooms });
|
|
2135
|
-
}
|
|
2136
|
-
else {
|
|
2137
|
-
throw new Error(`Tab with ID ${tabId} or room with ID ${roomId} not found.`);
|
|
2138
|
-
}
|
|
1955
|
+
checkImageExists(imageId) {
|
|
1956
|
+
return !this.failedImageIds().includes(imageId);
|
|
2139
1957
|
}
|
|
2140
|
-
async
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
return this.updateTab(tabId, { includeRooms: updatedRooms });
|
|
1958
|
+
async loadComments() {
|
|
1959
|
+
try {
|
|
1960
|
+
const thread = await this.commentService.getThread({ type: this.refrenceType(), id: this.refrenceId() }, this.subject());
|
|
1961
|
+
if (thread) {
|
|
1962
|
+
this.thread.set(thread);
|
|
1963
|
+
this.comments.set(thread.comments || []);
|
|
2147
1964
|
}
|
|
2148
1965
|
else {
|
|
2149
|
-
|
|
1966
|
+
this.comments.set([]);
|
|
1967
|
+
this.thread.set(undefined);
|
|
2150
1968
|
}
|
|
2151
1969
|
}
|
|
2152
|
-
|
|
2153
|
-
|
|
1970
|
+
catch (error) {
|
|
1971
|
+
console.error('Failed to load comments:', error);
|
|
1972
|
+
this.toastService.show({
|
|
1973
|
+
content: 'Failed to load comments. Please try again.',
|
|
1974
|
+
color: 'danger',
|
|
1975
|
+
location: 'bottom-center',
|
|
1976
|
+
closeButton: true,
|
|
1977
|
+
timeOut: 3000,
|
|
1978
|
+
timeOutProgress: true,
|
|
1979
|
+
});
|
|
1980
|
+
this.comments.set([]);
|
|
2154
1981
|
}
|
|
2155
1982
|
}
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
1983
|
+
editMessage(comment, reply, userName) {
|
|
1984
|
+
this.isReplyingMode.set(false);
|
|
1985
|
+
this.activeReplyComment.set(undefined);
|
|
1986
|
+
this.isEditingMode.set(true);
|
|
1987
|
+
this.activeEditComment.set({ ...comment, userName: userName || '' });
|
|
1988
|
+
const contentToEdit = reply ? reply.message?.content : comment.message?.content;
|
|
1989
|
+
this.commentContent.set(contentToEdit || '');
|
|
1990
|
+
this.wysiwygEditor().getHostElement().scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
1991
|
+
}
|
|
1992
|
+
replyMessage(comment, reply, userName) {
|
|
1993
|
+
this.isEditingMode.set(false);
|
|
1994
|
+
this.activeEditComment.set(undefined);
|
|
1995
|
+
this.isReplyingMode.set(true);
|
|
1996
|
+
this.activeReplyComment.set({ ...comment, userName: userName || '' });
|
|
1997
|
+
if (reply) {
|
|
1998
|
+
const author = reply.author.fullName || reply.author.id;
|
|
1999
|
+
const mention = `<strong><a data-id="${reply.author.username}">@${userName || author}</a></strong> `;
|
|
2000
|
+
this.commentContent.set(mention);
|
|
2001
|
+
document.getElementsByClassName('ql-editor')[0].innerHTML = mention;
|
|
2002
|
+
this.wysiwygEditor()?.focus();
|
|
2165
2003
|
}
|
|
2004
|
+
this.wysiwygEditor().getHostElement().scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
2166
2005
|
}
|
|
2167
|
-
async
|
|
2168
|
-
const
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2006
|
+
async deleteComment(commentId) {
|
|
2007
|
+
const dialog = this.dialogService.open({
|
|
2008
|
+
icon: 'fa-regular fa-warning',
|
|
2009
|
+
content: 'Are you sure you want to delete this comment?',
|
|
2010
|
+
title: 'Delete Comment',
|
|
2011
|
+
type: 'danger',
|
|
2012
|
+
orientation: 'horizontal',
|
|
2013
|
+
buttons: [
|
|
2014
|
+
{
|
|
2015
|
+
text: 'Delete',
|
|
2016
|
+
color: 'danger',
|
|
2017
|
+
onClick: async (e) => {
|
|
2018
|
+
e.handled = true;
|
|
2019
|
+
e.source.text = 'Deleting...';
|
|
2020
|
+
e.source.disabled = true;
|
|
2021
|
+
e.source.loading = true;
|
|
2022
|
+
try {
|
|
2023
|
+
await this.commentService.deleteComment(commentId);
|
|
2024
|
+
this.removeMessageById(commentId);
|
|
2025
|
+
this.toastService.show({
|
|
2026
|
+
content: 'Comment deleted successfully.',
|
|
2027
|
+
color: 'success',
|
|
2028
|
+
location: 'bottom-center',
|
|
2029
|
+
closeButton: true,
|
|
2030
|
+
timeOut: 3000,
|
|
2031
|
+
timeOutProgress: true,
|
|
2032
|
+
});
|
|
2033
|
+
if (this.isEditingMode() && this.activeEditComment()?.id === commentId) {
|
|
2034
|
+
this.resetReplyEditState();
|
|
2035
|
+
}
|
|
2036
|
+
dialog.close();
|
|
2037
|
+
}
|
|
2038
|
+
catch (error) {
|
|
2039
|
+
this.toastService.show({
|
|
2040
|
+
content: typeof error === 'string' ? error : 'Failed to delete comment!',
|
|
2041
|
+
color: 'danger',
|
|
2042
|
+
location: 'bottom-center',
|
|
2043
|
+
closeButton: true,
|
|
2044
|
+
timeOut: 3000,
|
|
2045
|
+
timeOutProgress: true,
|
|
2046
|
+
});
|
|
2047
|
+
}
|
|
2048
|
+
},
|
|
2049
|
+
},
|
|
2050
|
+
{
|
|
2051
|
+
text: 'Cancel',
|
|
2052
|
+
color: 'default',
|
|
2053
|
+
autofocus: true,
|
|
2054
|
+
onClick: (e) => {
|
|
2055
|
+
dialog.close();
|
|
2056
|
+
},
|
|
2057
|
+
},
|
|
2058
|
+
],
|
|
2059
|
+
closeButton: false,
|
|
2060
|
+
});
|
|
2061
|
+
}
|
|
2062
|
+
resetReplyEditState() {
|
|
2063
|
+
this.isEditingMode.set(false);
|
|
2064
|
+
this.activeEditComment.set(undefined);
|
|
2065
|
+
this.isReplyingMode.set(false);
|
|
2066
|
+
this.activeReplyComment.set(undefined);
|
|
2067
|
+
this.commentContent.set('');
|
|
2068
|
+
document.getElementsByClassName('ql-editor')[0].innerHTML = '';
|
|
2069
|
+
}
|
|
2070
|
+
async toggleLike(comment) {
|
|
2071
|
+
const isLiked = this.isLikedByUser(comment);
|
|
2072
|
+
this.updateLikeStatus(comment.id, !isLiked);
|
|
2073
|
+
try {
|
|
2074
|
+
if (isLiked) {
|
|
2075
|
+
await this.commentService.unlikeComment(comment.id);
|
|
2174
2076
|
}
|
|
2175
2077
|
else {
|
|
2176
|
-
|
|
2078
|
+
await this.commentService.likeComment(comment.id);
|
|
2177
2079
|
}
|
|
2178
2080
|
}
|
|
2179
|
-
|
|
2180
|
-
|
|
2081
|
+
catch (error) {
|
|
2082
|
+
console.error('Failed to toggle like:', error);
|
|
2083
|
+
this.updateLikeStatus(comment.id, isLiked); // Revert optimistic update
|
|
2181
2084
|
}
|
|
2182
2085
|
}
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2086
|
+
updateLikeStatus(commentId, willBeLiked) {
|
|
2087
|
+
const findAndToggle = (comments) => {
|
|
2088
|
+
return comments.map((c) => {
|
|
2089
|
+
if (c.id === commentId) {
|
|
2090
|
+
const user = this.getCurrentUser();
|
|
2091
|
+
if (!user)
|
|
2092
|
+
return c;
|
|
2093
|
+
let reactions = c.reactions || [];
|
|
2094
|
+
if (willBeLiked) {
|
|
2095
|
+
reactions.push({ author: user, type: 'like' });
|
|
2096
|
+
}
|
|
2097
|
+
else {
|
|
2098
|
+
reactions = reactions.filter((r) => r.author.id !== user.id || r.type !== 'like');
|
|
2099
|
+
}
|
|
2100
|
+
return { ...c, reactions };
|
|
2101
|
+
}
|
|
2102
|
+
if (c.replies && c.replies.length > 0) {
|
|
2103
|
+
c.replies = findAndToggle(c.replies);
|
|
2104
|
+
}
|
|
2105
|
+
return c;
|
|
2106
|
+
});
|
|
2199
2107
|
};
|
|
2200
|
-
|
|
2201
|
-
const newMessage = await this.messageService.getOne(messageId);
|
|
2202
|
-
const formattedMessage = await this.formatMessage(newMessage);
|
|
2203
|
-
this._messageSent$.next(formattedMessage);
|
|
2204
|
-
return formattedMessage;
|
|
2205
|
-
}
|
|
2206
|
-
async getMessages(roomId, skip = 0, take = 99) {
|
|
2207
|
-
const result = await this.messageService.query({
|
|
2208
|
-
skip,
|
|
2209
|
-
take,
|
|
2210
|
-
filter: { field: 'roomId', value: roomId, operator: { type: 'equal' } },
|
|
2211
|
-
sort: [{ field: 'createdAt', dir: 'desc' }],
|
|
2212
|
-
});
|
|
2213
|
-
const formattedMessages = await Promise.all(result.items.map((m) => this.formatMessage(m)));
|
|
2214
|
-
return { items: formattedMessages, total: result.total };
|
|
2215
|
-
}
|
|
2216
|
-
async getMessage(messageId) {
|
|
2217
|
-
const message = await this.messageService.getOne(messageId);
|
|
2218
|
-
return this.formatMessage(message);
|
|
2108
|
+
this.comments.update((comments) => findAndToggle(comments));
|
|
2219
2109
|
}
|
|
2220
|
-
|
|
2221
|
-
const
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2110
|
+
removeMessageById(commentId) {
|
|
2111
|
+
const filterOut = (comments) => {
|
|
2112
|
+
return comments
|
|
2113
|
+
.filter((c) => c.id !== commentId)
|
|
2114
|
+
.map((c) => {
|
|
2115
|
+
if (c.replies && c.replies.length > 0) {
|
|
2116
|
+
c.replies = filterOut(c.replies);
|
|
2117
|
+
}
|
|
2118
|
+
return c;
|
|
2119
|
+
});
|
|
2120
|
+
};
|
|
2121
|
+
this.comments.update((comments) => filterOut(comments));
|
|
2227
2122
|
}
|
|
2228
|
-
async
|
|
2123
|
+
async submitComment() {
|
|
2124
|
+
if (!this.validateContent(this.commentContent()).result) {
|
|
2125
|
+
return;
|
|
2126
|
+
}
|
|
2127
|
+
this.isSubmitting.set(true);
|
|
2128
|
+
console.log(this.commentContent());
|
|
2229
2129
|
try {
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2130
|
+
let currentThread = this.thread();
|
|
2131
|
+
if (!currentThread) {
|
|
2132
|
+
currentThread = await this.commentService.createThread({ type: this.refrenceType(), id: this.refrenceId() }, this.subject());
|
|
2133
|
+
this.thread.set(currentThread);
|
|
2134
|
+
}
|
|
2135
|
+
if (this.isEditingMode() && this.activeEditComment()?.id) {
|
|
2136
|
+
await this.commentService.editComment(this.activeEditComment().id, this.commentContent());
|
|
2137
|
+
this.hasCooldown.set(true);
|
|
2138
|
+
this.isEditingMode.set(false);
|
|
2139
|
+
this.activeEditComment.set(undefined);
|
|
2140
|
+
}
|
|
2141
|
+
else {
|
|
2142
|
+
await this.commentService.addComment(currentThread.id, this.commentContent(), this.activeReplyComment()?.id);
|
|
2143
|
+
this.hasCooldown.set(true);
|
|
2144
|
+
this.isReplyingMode.set(false);
|
|
2145
|
+
this.activeReplyComment.set(undefined);
|
|
2146
|
+
}
|
|
2147
|
+
this.commentContent.set('');
|
|
2148
|
+
document.getElementsByClassName('ql-editor')[0].innerHTML = '';
|
|
2149
|
+
setTimeout(() => {
|
|
2150
|
+
this.hasCooldown.set(false);
|
|
2151
|
+
}, 1000);
|
|
2233
2152
|
}
|
|
2234
2153
|
catch (error) {
|
|
2235
|
-
|
|
2154
|
+
console.error('Error submitting comment:', error);
|
|
2155
|
+
this.toastService.show({
|
|
2156
|
+
content: typeof error === 'string' ? error : 'Failed to submit comment. Please try again.',
|
|
2157
|
+
color: 'danger',
|
|
2158
|
+
location: 'bottom-center',
|
|
2159
|
+
closeButton: true,
|
|
2160
|
+
timeOut: 3000,
|
|
2161
|
+
timeOutProgress: true,
|
|
2162
|
+
});
|
|
2163
|
+
}
|
|
2164
|
+
finally {
|
|
2165
|
+
this.isSubmitting.set(false);
|
|
2236
2166
|
}
|
|
2237
2167
|
}
|
|
2238
|
-
|
|
2239
|
-
const
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
async unpinMessage(messageId) {
|
|
2250
|
-
return this.messageService.updateOne(messageId, {
|
|
2251
|
-
isPinned: false,
|
|
2252
|
-
updatedAt: new Date(),
|
|
2253
|
-
updatedBy: this.getCurrentUser().id,
|
|
2254
|
-
});
|
|
2255
|
-
}
|
|
2256
|
-
//#endregion
|
|
2257
|
-
//#region ---- ChatReactionService Implementations ----
|
|
2258
|
-
async addReaction(messageId, type) {
|
|
2259
|
-
const author = this.getCurrentUser();
|
|
2260
|
-
const message = await this.messageService.getOne(messageId);
|
|
2261
|
-
const reactions = message.reactions || [];
|
|
2262
|
-
if (reactions.some((r) => r.author.id === author.id && r.type === type)) {
|
|
2263
|
-
return message;
|
|
2168
|
+
scrollMain() {
|
|
2169
|
+
const comment = this.isReplyingMode() ? this.activeReplyComment() : this.activeEditComment();
|
|
2170
|
+
if (comment && comment.id) {
|
|
2171
|
+
const el = document.getElementById(comment.id);
|
|
2172
|
+
if (el) {
|
|
2173
|
+
el.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
2174
|
+
this.highlightedCommentId.set(comment.id);
|
|
2175
|
+
setTimeout(() => {
|
|
2176
|
+
this.highlightedCommentId.set(null);
|
|
2177
|
+
}, 1000);
|
|
2178
|
+
}
|
|
2264
2179
|
}
|
|
2265
|
-
const updatedReactions = [...reactions, { author, type }];
|
|
2266
|
-
const res = await this.messageService.updateOne(messageId, {
|
|
2267
|
-
reactions: updatedReactions,
|
|
2268
|
-
updatedAt: new Date(),
|
|
2269
|
-
updatedBy: this.getCurrentUser().id,
|
|
2270
|
-
});
|
|
2271
|
-
this._messageReacted$.next(res);
|
|
2272
|
-
return res;
|
|
2273
2180
|
}
|
|
2274
|
-
|
|
2275
|
-
const author = this.getCurrentUser();
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
});
|
|
2283
|
-
|
|
2284
|
-
|
|
2181
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2182
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: AXMCommentComponent, isStandalone: true, selector: "axm-comment", inputs: { refrenceType: { classPropertyName: "refrenceType", publicName: "refrenceType", isSignal: true, isRequired: true, transformFunction: null }, refrenceId: { classPropertyName: "refrenceId", publicName: "refrenceId", isSignal: true, isRequired: true, transformFunction: null }, subject: { classPropertyName: "subject", publicName: "subject", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "wysiwygEditor", first: true, predicate: ["w"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"ax-size-full ax-flex ax-flex-col ax-justify-between ax-p-4 ax-overflow-hidden\">\n <ax-comment-container class=\"ax-overflow-auto\">\n @if (isLoading()) {\n <div class=\"ax-flex ax-items-center ax-py-12 ax-bg-lightest ax-px-5\">\n <ax-skeleton class=\"ax-min-w-16 ax-h-16 ax-rounded-full ax-me-4\"></ax-skeleton>\n <div class=\"ax-flex ax-flex-col ax-gap-2 ax-w-full\">\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-2 ax-rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-2 ax-rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-8/12 ax-h-2 ax-rounded-full\"></ax-skeleton>\n </div>\n </div>\n } @else if (!isLoading() && comments().length > 0) {\n <ax-comment-view class=\"ax-bg-lightest\">\n @for (comment of comments(); track comment.id) {\n <ax-comment-item\n [id]=\"comment.id!\"\n [replyCount]=\"comment.replyCount\"\n [class.highlighted]=\"highlightedCommentId() === comment.id\"\n [@fadeIn]\n >\n <axp-user-avatar #user [size]=\"48\" [userId]=\"comment.author.id\" ngProjectAs=\"'ax-avatar'\"></axp-user-avatar>\n <ax-title>{{ user.firstName() + ' ' + user.lastName() }}</ax-title>\n <ax-comment-date>{{ comment.createdAt | format: 'timeleft' | async }} </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button class=\"ax-sm\" look=\"blank\" color=\"neutral\">\n <ax-icon icon=\"ax-icon ax-icon-solid ax-icon-more-horizontal\"></ax-icon>\n </ax-button>\n\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n text=\"Edit\"\n color=\"neutral\"\n (click)=\"editMessage(comment, undefined, user.firstName() + ' ' + user.lastName())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-edit\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n\n <ax-button-item text=\"Delete\" color=\"danger\" (click)=\"deleteComment(comment.id!)\">\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content [innerHTML]=\"sanitizeHtml(comment.message.content)\"></ax-content>\n <ax-comment-like (click)=\"toggleLike(comment)\" [liked]=\"isLikedByUser(comment)\">\n {{ getReactionsCount(comment) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, undefined, user.firstName() + ' ' + user.lastName())\"\n ></ax-comment-reply-text>\n @for (reply of comment.replies; track reply.id) {\n <ax-comment-item [id]=\"reply.id\" [class.highlighted]=\"highlightedCommentId() === reply.id\" [@fadeIn]>\n <axp-user-avatar\n #user2\n [size]=\"48\"\n [userId]=\"reply.author.id\"\n ngProjectAs=\"'ax-avatar'\"\n ></axp-user-avatar>\n <ax-title>{{ user2.firstName() + ' ' + user2.lastName() }}</ax-title>\n <ax-comment-date>{{ reply.createdAt | format: 'timeleft' | async }} </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button class=\"ax-sm\" look=\"blank\" color=\"neutral\">\n <ax-icon icon=\"ax-icon ax-icon-solid ax-icon-more-horizontal\"></ax-icon>\n </ax-button>\n\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n text=\"Edit\"\n color=\"neutral\"\n (click)=\"editMessage(comment, reply, user2.firstName() + ' ' + user2.lastName())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-edit\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item text=\"Delete\" color=\"danger\" (click)=\"deleteComment(reply.id!)\">\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content [innerHTML]=\"sanitizeHtml(reply.message.content)\"></ax-content>\n <ax-comment-like (click)=\"toggleLike(reply)\" [liked]=\"isLikedByUser(reply)\">\n {{ getReactionsCount(reply) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, reply, user2.firstName() + ' ' + user2.lastName())\"\n ></ax-comment-reply-text>\n </ax-comment-item>\n }\n </ax-comment-item>\n }\n </ax-comment-view>\n } @else {\n <div>\n <div class=\"ax-flex ax-flex-col ax-gap-4 ax-justify-center ax-items-center ax-p-10\">\n <svg\n class=\"ax-mx-auto\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"154\"\n height=\"161\"\n viewBox=\"0 0 154 161\"\n fill=\"none\"\n >\n <path\n d=\"M0.0616455 84.4268C0.0616455 42.0213 34.435 7.83765 76.6507 7.83765C118.803 7.83765 153.224 42.0055 153.224 84.4268C153.224 102.42 147.026 118.974 136.622 132.034C122.282 150.138 100.367 161 76.6507 161C52.7759 161 30.9882 150.059 16.6633 132.034C6.25961 118.974 0.0616455 102.42 0.0616455 84.4268Z\"\n fill=\"#EEF2FF\"\n />\n <path\n d=\"M96.8189 0.632498L96.8189 0.632384L96.8083 0.630954C96.2034 0.549581 95.5931 0.5 94.9787 0.5H29.338C22.7112 0.5 17.3394 5.84455 17.3394 12.4473V142.715C17.3394 149.318 22.7112 154.662 29.338 154.662H123.948C130.591 154.662 135.946 149.317 135.946 142.715V38.9309C135.946 38.0244 135.847 37.1334 135.648 36.2586L135.648 36.2584C135.117 33.9309 133.874 31.7686 132.066 30.1333C132.066 30.1331 132.065 30.1329 132.065 30.1327L103.068 3.65203C103.068 3.6519 103.067 3.65177 103.067 3.65164C101.311 2.03526 99.1396 0.995552 96.8189 0.632498Z\"\n fill=\"white\"\n stroke=\"#E5E7EB\"\n />\n <ellipse cx=\"80.0618\" cy=\"81\" rx=\"28.0342\" ry=\"28.0342\" fill=\"#EEF2FF\" />\n <path\n d=\"M99.2393 61.3061L99.2391 61.3058C88.498 50.5808 71.1092 50.5804 60.3835 61.3061C49.6423 72.0316 49.6422 89.4361 60.3832 100.162C71.109 110.903 88.4982 110.903 99.2393 100.162C109.965 89.4363 109.965 72.0317 99.2393 61.3061ZM105.863 54.6832C120.249 69.0695 120.249 92.3985 105.863 106.785C91.4605 121.171 68.1468 121.171 53.7446 106.785C39.3582 92.3987 39.3582 69.0693 53.7446 54.683C68.1468 40.2965 91.4605 40.2966 105.863 54.6832Z\"\n stroke=\"#E5E7EB\"\n />\n <path\n d=\"M110.782 119.267L102.016 110.492C104.888 108.267 107.476 105.651 109.564 102.955L118.329 111.729L110.782 119.267Z\"\n stroke=\"#E5E7EB\"\n />\n <path\n d=\"M139.122 125.781L139.122 125.78L123.313 109.988C123.313 109.987 123.313 109.987 123.312 109.986C121.996 108.653 119.849 108.657 118.521 109.985L118.871 110.335L118.521 109.985L109.047 119.459C107.731 120.775 107.735 122.918 109.044 124.247L109.047 124.249L124.858 140.06C128.789 143.992 135.191 143.992 139.122 140.06C143.069 136.113 143.069 129.728 139.122 125.781Z\"\n fill=\"#A5B4FC\"\n stroke=\"#818CF8\"\n />\n <path\n d=\"M83.185 87.2285C82.5387 87.2285 82.0027 86.6926 82.0027 86.0305C82.0027 83.3821 77.9987 83.3821 77.9987 86.0305C77.9987 86.6926 77.4627 87.2285 76.8006 87.2285C76.1543 87.2285 75.6183 86.6926 75.6183 86.0305C75.6183 80.2294 84.3831 80.2451 84.3831 86.0305C84.3831 86.6926 83.8471 87.2285 83.185 87.2285Z\"\n fill=\"#4F46E5\"\n />\n <path\n d=\"M93.3528 77.0926H88.403C87.7409 77.0926 87.2049 76.5567 87.2049 75.8946C87.2049 75.2483 87.7409 74.7123 88.403 74.7123H93.3528C94.0149 74.7123 94.5509 75.2483 94.5509 75.8946C94.5509 76.5567 94.0149 77.0926 93.3528 77.0926Z\"\n fill=\"#4F46E5\"\n />\n <path\n d=\"M71.5987 77.0925H66.6488C65.9867 77.0925 65.4507 76.5565 65.4507 75.8945C65.4507 75.2481 65.9867 74.7122 66.6488 74.7122H71.5987C72.245 74.7122 72.781 75.2481 72.781 75.8945C72.781 76.5565 72.245 77.0925 71.5987 77.0925Z\"\n fill=\"#4F46E5\"\n />\n <rect x=\"38.3522\" y=\"21.5128\" width=\"41.0256\" height=\"2.73504\" rx=\"1.36752\" fill=\"#4F46E5\" />\n <rect x=\"38.3522\" y=\"133.65\" width=\"54.7009\" height=\"5.47009\" rx=\"2.73504\" fill=\"#A5B4FC\" />\n <rect x=\"38.3522\" y=\"29.7179\" width=\"13.6752\" height=\"2.73504\" rx=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"56.13\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"61.6001\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"67.0702\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n </svg>\n <div>\n <h2 class=\"ax-text-center ax-text-neutral-600 ax-font-semibold ax-leading-loose ax-pb-2\">\n There is no Comment!\n </h2>\n </div>\n </div>\n </div>\n }\n </ax-comment-container>\n <ax-form>\n <ax-form-field>\n <div>\n @if (isReplyingMode() || isEditingMode()) {\n <div\n class=\"ax-flex ax-justify-between ax-rounded-b-none ax-border ax-border-b-0 ax-rounded-lg ax-px-6 ax-py-3 ax-w-full ax-items-center ax-overflow-hidden ax-text-sm ax-leading-none\"\n >\n <div (click)=\"scrollMain()\" class=\"ax-flex ax-justify-start ax-items-center ax-cursor-pointer\">\n <i\n [class]=\"isReplyingMode() ? 'fa-reply' : 'fa-pen'\"\n class=\"fa-solid ax-text-primary-500 dark:ax-text-primary-300 ax-text-2xl ax-me-4\"\n ></i>\n <div\n class=\"ax-flex ax-flex-col ax-gap-2 ax-justify-between ax-align-middle ax-leading-4 ax-overflow-hidden\"\n >\n <p class=\"ax-text-primary-500 dark:ax-text-primary-300\">\n {{ isReplyingMode() ? 'Reply to ' : 'Edit Message' }}\n <span class=\"ax-font-bold\">\n {{ isReplyingMode() ? activeReplyComment()?.userName : '' }}\n </span>\n </p>\n <div\n class=\"ax-truncate\"\n [innerHTML]=\"\n isReplyingMode()\n ? sanitizeHtml(activeReplyComment()?.message?.content ?? '')\n : sanitizeHtml(activeEditComment()?.message?.content ?? '')\n \"\n ></div>\n </div>\n </div>\n <div><i (click)=\"resetReplyEditState()\" class=\"fa-solid ax-text-2xl fa-xmark ax-cursor-pointer\"></i></div>\n </div>\n }\n <ax-wysiwyg-container #w [look]=\"wysiwygOptions().look\" [(ngModel)]=\"commentContent\">\n <ax-wysiwyg-view class=\"ax-min-h-28\"></ax-wysiwyg-view>\n <ax-toolbar>\n <ax-content>\n <ax-wysiwyg-history></ax-wysiwyg-history>\n <ax-wysiwyg-font-style></ax-wysiwyg-font-style>\n <ax-wysiwyg-colors></ax-wysiwyg-colors>\n <ax-wysiwyg-list></ax-wysiwyg-list>\n <ax-wysiwyg-alignment></ax-wysiwyg-alignment>\n </ax-content>\n <ax-suffix>\n <ax-dropdown-button\n [disabled]=\"hasCooldown()\"\n type=\"submit\"\n color=\"primary\"\n mode=\"split\"\n text=\"Send\"\n (onClick)=\"submitComment()\"\n >\n @if (isSubmitting()) {\n <ax-loading></ax-loading>\n }\n <ax-button-item-list>\n <ax-button-item (click)=\"submitComment()\" text=\"Send Private ...\" name=\"private\" data=\"private\">\n <ax-prefix>\n <ax-icon icon=\"fa-regular fa-user-secret\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-button>\n </ax-suffix>\n </ax-toolbar>\n <ax-validation-rule rule=\"callback\" [options]=\"{ validate: validateContent }\"></ax-validation-rule>\n </ax-wysiwyg-container>\n </div>\n </ax-form-field>\n </ax-form>\n</div>\n", styles: [":host{display:block;width:100%;height:100%}ax-wysiwyg-container .ax-editor-container{border-top-left-radius:0!important;border-top-right-radius:0!important}ax-wysiwyg-container .ax-error-message{padding-left:.5rem}ax-wysiwyg-container .highlighted{background:var(--ax-color-primary-050)!important;border-radius:.25rem;transition:background 1s ease-in-out}\n"], dependencies: [{ kind: "ngmodule", type: AXWysiwygModule }, { kind: "component", type: i1.AXWysiwygContainerComponent, selector: "ax-wysiwyg-container", inputs: ["look", "placeHolder"], outputs: ["onValueChanged"] }, { kind: "component", type: i1.AXWysiwygViewComponent, selector: "ax-wysiwyg-view", inputs: ["class"] }, { kind: "component", type: i1.AXWysiwygAlignmentComponent, selector: "ax-wysiwyg-alignment" }, { kind: "component", type: i1.AXWysiwygColorsComponent, selector: "ax-wysiwyg-colors" }, { kind: "component", type: i1.AXWysiwygFontStyleComponent, selector: "ax-wysiwyg-font-style" }, { kind: "component", type: i1.AXWysiwygHistoryComponent, selector: "ax-wysiwyg-history" }, { kind: "component", type: i1.AXWysiwygListComponent, selector: "ax-wysiwyg-list" }, { kind: "ngmodule", type: AXConversationModule }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i2.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i1$1.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: AXCommentModule }, { kind: "component", type: i4.AXCommentViewComponent, selector: "ax-comment-view" }, { kind: "component", type: i4.AXCommentContainerComponent, selector: "ax-comment-container" }, { kind: "component", type: i4.AxCommentItemComponent, selector: "ax-comment-item", inputs: ["replyCount"] }, { kind: "component", type: i4.AXCommentLikeComponent, selector: "ax-comment-like", inputs: ["liked"], outputs: ["likedChange", "onLiked"] }, { kind: "component", type: i4.AXMenuOptionsComponent, selector: "ax-comment-menu-options" }, { kind: "component", type: i4.AXCommentReplyTextComponent, selector: "ax-comment-reply-text" }, { kind: "component", type: i4.AXCommentDateComponent, selector: "ax-comment-date" }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i5.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: i5.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i5.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXAvatarModule }, { kind: "ngmodule", type: AXImageModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i6.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i7.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXFormModule }, { kind: "component", type: i8.AXFormFieldComponent, selector: "ax-form-field", inputs: ["labelMode"] }, { kind: "component", type: i8.AXFormComponent, selector: "ax-form", inputs: ["labelMode", "look", "messageStyle", "updateOn"], outputs: ["onValidate", "updateOnChange"] }, { kind: "directive", type: i8.AXValidationRuleDirective, selector: "ax-validation-rule", inputs: ["rule", "options", "message", "disabled"] }, { kind: "ngmodule", type: AXToolBarModule }, { kind: "component", type: i9.AXToolBarComponent, selector: "ax-toolbar" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i10.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i10.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "component", type: i11.AXDropdownButtonComponent, selector: "ax-dropdown-button", inputs: ["disabled", "size", "color", "look", "text", "type", "mode"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "lookChange", "colorChange", "disabledChange"] }, { kind: "component", type: AXPUserAvatarComponent, selector: "axp-user-avatar", inputs: ["size", "userId"] }, { kind: "pipe", type: i12.AXFormatPipe, name: "format" }, { kind: "pipe", type: AsyncPipe, name: "async" }], animations: [
|
|
2183
|
+
trigger('fadeIn', [
|
|
2184
|
+
transition(':enter', [
|
|
2185
|
+
style({ opacity: 0, transform: 'translateY(10px)' }),
|
|
2186
|
+
animate('300ms ease-out', style({ opacity: 1, transform: 'translateY(0)' })),
|
|
2187
|
+
]),
|
|
2188
|
+
]),
|
|
2189
|
+
], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2190
|
+
}
|
|
2191
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentComponent, decorators: [{
|
|
2192
|
+
type: Component,
|
|
2193
|
+
args: [{ selector: 'axm-comment', animations: [
|
|
2194
|
+
trigger('fadeIn', [
|
|
2195
|
+
transition(':enter', [
|
|
2196
|
+
style({ opacity: 0, transform: 'translateY(10px)' }),
|
|
2197
|
+
animate('300ms ease-out', style({ opacity: 1, transform: 'translateY(0)' })),
|
|
2198
|
+
]),
|
|
2199
|
+
]),
|
|
2200
|
+
], imports: [
|
|
2201
|
+
AXWysiwygModule,
|
|
2202
|
+
AXConversationModule,
|
|
2203
|
+
AXSkeletonModule,
|
|
2204
|
+
AXDecoratorModule,
|
|
2205
|
+
AXCommentModule,
|
|
2206
|
+
AXButtonModule,
|
|
2207
|
+
AXAvatarModule,
|
|
2208
|
+
AXImageModule,
|
|
2209
|
+
AXLoadingModule,
|
|
2210
|
+
AXDropdownModule,
|
|
2211
|
+
AXFormatModule,
|
|
2212
|
+
AsyncPipe,
|
|
2213
|
+
AXFormModule,
|
|
2214
|
+
AXToolBarModule,
|
|
2215
|
+
FormsModule,
|
|
2216
|
+
AXDropdownButtonModule,
|
|
2217
|
+
AXPUserAvatarComponent,
|
|
2218
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ax-size-full ax-flex ax-flex-col ax-justify-between ax-p-4 ax-overflow-hidden\">\n <ax-comment-container class=\"ax-overflow-auto\">\n @if (isLoading()) {\n <div class=\"ax-flex ax-items-center ax-py-12 ax-bg-lightest ax-px-5\">\n <ax-skeleton class=\"ax-min-w-16 ax-h-16 ax-rounded-full ax-me-4\"></ax-skeleton>\n <div class=\"ax-flex ax-flex-col ax-gap-2 ax-w-full\">\n <ax-skeleton class=\"ax-w-full ax-h-6 ax-rounded\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-2 ax-rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-full ax-h-2 ax-rounded-full\"></ax-skeleton>\n <ax-skeleton class=\"ax-w-8/12 ax-h-2 ax-rounded-full\"></ax-skeleton>\n </div>\n </div>\n } @else if (!isLoading() && comments().length > 0) {\n <ax-comment-view class=\"ax-bg-lightest\">\n @for (comment of comments(); track comment.id) {\n <ax-comment-item\n [id]=\"comment.id!\"\n [replyCount]=\"comment.replyCount\"\n [class.highlighted]=\"highlightedCommentId() === comment.id\"\n [@fadeIn]\n >\n <axp-user-avatar #user [size]=\"48\" [userId]=\"comment.author.id\" ngProjectAs=\"'ax-avatar'\"></axp-user-avatar>\n <ax-title>{{ user.firstName() + ' ' + user.lastName() }}</ax-title>\n <ax-comment-date>{{ comment.createdAt | format: 'timeleft' | async }} </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button class=\"ax-sm\" look=\"blank\" color=\"neutral\">\n <ax-icon icon=\"ax-icon ax-icon-solid ax-icon-more-horizontal\"></ax-icon>\n </ax-button>\n\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n text=\"Edit\"\n color=\"neutral\"\n (click)=\"editMessage(comment, undefined, user.firstName() + ' ' + user.lastName())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-edit\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n\n <ax-button-item text=\"Delete\" color=\"danger\" (click)=\"deleteComment(comment.id!)\">\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content [innerHTML]=\"sanitizeHtml(comment.message.content)\"></ax-content>\n <ax-comment-like (click)=\"toggleLike(comment)\" [liked]=\"isLikedByUser(comment)\">\n {{ getReactionsCount(comment) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, undefined, user.firstName() + ' ' + user.lastName())\"\n ></ax-comment-reply-text>\n @for (reply of comment.replies; track reply.id) {\n <ax-comment-item [id]=\"reply.id\" [class.highlighted]=\"highlightedCommentId() === reply.id\" [@fadeIn]>\n <axp-user-avatar\n #user2\n [size]=\"48\"\n [userId]=\"reply.author.id\"\n ngProjectAs=\"'ax-avatar'\"\n ></axp-user-avatar>\n <ax-title>{{ user2.firstName() + ' ' + user2.lastName() }}</ax-title>\n <ax-comment-date>{{ reply.createdAt | format: 'timeleft' | async }} </ax-comment-date>\n <ax-comment-menu-options>\n <ax-button class=\"ax-sm\" look=\"blank\" color=\"neutral\">\n <ax-icon icon=\"ax-icon ax-icon-solid ax-icon-more-horizontal\"></ax-icon>\n </ax-button>\n\n <ax-dropdown-panel>\n <ax-button-item-list>\n <ax-button-item\n text=\"Edit\"\n color=\"neutral\"\n (click)=\"editMessage(comment, reply, user2.firstName() + ' ' + user2.lastName())\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-edit\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item text=\"Delete\" color=\"danger\" (click)=\"deleteComment(reply.id!)\">\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-comment-menu-options>\n <ax-content [innerHTML]=\"sanitizeHtml(reply.message.content)\"></ax-content>\n <ax-comment-like (click)=\"toggleLike(reply)\" [liked]=\"isLikedByUser(reply)\">\n {{ getReactionsCount(reply) }}\n </ax-comment-like>\n <ax-comment-reply-text\n (click)=\"replyMessage(comment, reply, user2.firstName() + ' ' + user2.lastName())\"\n ></ax-comment-reply-text>\n </ax-comment-item>\n }\n </ax-comment-item>\n }\n </ax-comment-view>\n } @else {\n <div>\n <div class=\"ax-flex ax-flex-col ax-gap-4 ax-justify-center ax-items-center ax-p-10\">\n <svg\n class=\"ax-mx-auto\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"154\"\n height=\"161\"\n viewBox=\"0 0 154 161\"\n fill=\"none\"\n >\n <path\n d=\"M0.0616455 84.4268C0.0616455 42.0213 34.435 7.83765 76.6507 7.83765C118.803 7.83765 153.224 42.0055 153.224 84.4268C153.224 102.42 147.026 118.974 136.622 132.034C122.282 150.138 100.367 161 76.6507 161C52.7759 161 30.9882 150.059 16.6633 132.034C6.25961 118.974 0.0616455 102.42 0.0616455 84.4268Z\"\n fill=\"#EEF2FF\"\n />\n <path\n d=\"M96.8189 0.632498L96.8189 0.632384L96.8083 0.630954C96.2034 0.549581 95.5931 0.5 94.9787 0.5H29.338C22.7112 0.5 17.3394 5.84455 17.3394 12.4473V142.715C17.3394 149.318 22.7112 154.662 29.338 154.662H123.948C130.591 154.662 135.946 149.317 135.946 142.715V38.9309C135.946 38.0244 135.847 37.1334 135.648 36.2586L135.648 36.2584C135.117 33.9309 133.874 31.7686 132.066 30.1333C132.066 30.1331 132.065 30.1329 132.065 30.1327L103.068 3.65203C103.068 3.6519 103.067 3.65177 103.067 3.65164C101.311 2.03526 99.1396 0.995552 96.8189 0.632498Z\"\n fill=\"white\"\n stroke=\"#E5E7EB\"\n />\n <ellipse cx=\"80.0618\" cy=\"81\" rx=\"28.0342\" ry=\"28.0342\" fill=\"#EEF2FF\" />\n <path\n d=\"M99.2393 61.3061L99.2391 61.3058C88.498 50.5808 71.1092 50.5804 60.3835 61.3061C49.6423 72.0316 49.6422 89.4361 60.3832 100.162C71.109 110.903 88.4982 110.903 99.2393 100.162C109.965 89.4363 109.965 72.0317 99.2393 61.3061ZM105.863 54.6832C120.249 69.0695 120.249 92.3985 105.863 106.785C91.4605 121.171 68.1468 121.171 53.7446 106.785C39.3582 92.3987 39.3582 69.0693 53.7446 54.683C68.1468 40.2965 91.4605 40.2966 105.863 54.6832Z\"\n stroke=\"#E5E7EB\"\n />\n <path\n d=\"M110.782 119.267L102.016 110.492C104.888 108.267 107.476 105.651 109.564 102.955L118.329 111.729L110.782 119.267Z\"\n stroke=\"#E5E7EB\"\n />\n <path\n d=\"M139.122 125.781L139.122 125.78L123.313 109.988C123.313 109.987 123.313 109.987 123.312 109.986C121.996 108.653 119.849 108.657 118.521 109.985L118.871 110.335L118.521 109.985L109.047 119.459C107.731 120.775 107.735 122.918 109.044 124.247L109.047 124.249L124.858 140.06C128.789 143.992 135.191 143.992 139.122 140.06C143.069 136.113 143.069 129.728 139.122 125.781Z\"\n fill=\"#A5B4FC\"\n stroke=\"#818CF8\"\n />\n <path\n d=\"M83.185 87.2285C82.5387 87.2285 82.0027 86.6926 82.0027 86.0305C82.0027 83.3821 77.9987 83.3821 77.9987 86.0305C77.9987 86.6926 77.4627 87.2285 76.8006 87.2285C76.1543 87.2285 75.6183 86.6926 75.6183 86.0305C75.6183 80.2294 84.3831 80.2451 84.3831 86.0305C84.3831 86.6926 83.8471 87.2285 83.185 87.2285Z\"\n fill=\"#4F46E5\"\n />\n <path\n d=\"M93.3528 77.0926H88.403C87.7409 77.0926 87.2049 76.5567 87.2049 75.8946C87.2049 75.2483 87.7409 74.7123 88.403 74.7123H93.3528C94.0149 74.7123 94.5509 75.2483 94.5509 75.8946C94.5509 76.5567 94.0149 77.0926 93.3528 77.0926Z\"\n fill=\"#4F46E5\"\n />\n <path\n d=\"M71.5987 77.0925H66.6488C65.9867 77.0925 65.4507 76.5565 65.4507 75.8945C65.4507 75.2481 65.9867 74.7122 66.6488 74.7122H71.5987C72.245 74.7122 72.781 75.2481 72.781 75.8945C72.781 76.5565 72.245 77.0925 71.5987 77.0925Z\"\n fill=\"#4F46E5\"\n />\n <rect x=\"38.3522\" y=\"21.5128\" width=\"41.0256\" height=\"2.73504\" rx=\"1.36752\" fill=\"#4F46E5\" />\n <rect x=\"38.3522\" y=\"133.65\" width=\"54.7009\" height=\"5.47009\" rx=\"2.73504\" fill=\"#A5B4FC\" />\n <rect x=\"38.3522\" y=\"29.7179\" width=\"13.6752\" height=\"2.73504\" rx=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"56.13\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"61.6001\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n <circle cx=\"67.0702\" cy=\"31.0854\" r=\"1.36752\" fill=\"#4F46E5\" />\n </svg>\n <div>\n <h2 class=\"ax-text-center ax-text-neutral-600 ax-font-semibold ax-leading-loose ax-pb-2\">\n There is no Comment!\n </h2>\n </div>\n </div>\n </div>\n }\n </ax-comment-container>\n <ax-form>\n <ax-form-field>\n <div>\n @if (isReplyingMode() || isEditingMode()) {\n <div\n class=\"ax-flex ax-justify-between ax-rounded-b-none ax-border ax-border-b-0 ax-rounded-lg ax-px-6 ax-py-3 ax-w-full ax-items-center ax-overflow-hidden ax-text-sm ax-leading-none\"\n >\n <div (click)=\"scrollMain()\" class=\"ax-flex ax-justify-start ax-items-center ax-cursor-pointer\">\n <i\n [class]=\"isReplyingMode() ? 'fa-reply' : 'fa-pen'\"\n class=\"fa-solid ax-text-primary-500 dark:ax-text-primary-300 ax-text-2xl ax-me-4\"\n ></i>\n <div\n class=\"ax-flex ax-flex-col ax-gap-2 ax-justify-between ax-align-middle ax-leading-4 ax-overflow-hidden\"\n >\n <p class=\"ax-text-primary-500 dark:ax-text-primary-300\">\n {{ isReplyingMode() ? 'Reply to ' : 'Edit Message' }}\n <span class=\"ax-font-bold\">\n {{ isReplyingMode() ? activeReplyComment()?.userName : '' }}\n </span>\n </p>\n <div\n class=\"ax-truncate\"\n [innerHTML]=\"\n isReplyingMode()\n ? sanitizeHtml(activeReplyComment()?.message?.content ?? '')\n : sanitizeHtml(activeEditComment()?.message?.content ?? '')\n \"\n ></div>\n </div>\n </div>\n <div><i (click)=\"resetReplyEditState()\" class=\"fa-solid ax-text-2xl fa-xmark ax-cursor-pointer\"></i></div>\n </div>\n }\n <ax-wysiwyg-container #w [look]=\"wysiwygOptions().look\" [(ngModel)]=\"commentContent\">\n <ax-wysiwyg-view class=\"ax-min-h-28\"></ax-wysiwyg-view>\n <ax-toolbar>\n <ax-content>\n <ax-wysiwyg-history></ax-wysiwyg-history>\n <ax-wysiwyg-font-style></ax-wysiwyg-font-style>\n <ax-wysiwyg-colors></ax-wysiwyg-colors>\n <ax-wysiwyg-list></ax-wysiwyg-list>\n <ax-wysiwyg-alignment></ax-wysiwyg-alignment>\n </ax-content>\n <ax-suffix>\n <ax-dropdown-button\n [disabled]=\"hasCooldown()\"\n type=\"submit\"\n color=\"primary\"\n mode=\"split\"\n text=\"Send\"\n (onClick)=\"submitComment()\"\n >\n @if (isSubmitting()) {\n <ax-loading></ax-loading>\n }\n <ax-button-item-list>\n <ax-button-item (click)=\"submitComment()\" text=\"Send Private ...\" name=\"private\" data=\"private\">\n <ax-prefix>\n <ax-icon icon=\"fa-regular fa-user-secret\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-button>\n </ax-suffix>\n </ax-toolbar>\n <ax-validation-rule rule=\"callback\" [options]=\"{ validate: validateContent }\"></ax-validation-rule>\n </ax-wysiwyg-container>\n </div>\n </ax-form-field>\n </ax-form>\n</div>\n", styles: [":host{display:block;width:100%;height:100%}ax-wysiwyg-container .ax-editor-container{border-top-left-radius:0!important;border-top-right-radius:0!important}ax-wysiwyg-container .ax-error-message{padding-left:.5rem}ax-wysiwyg-container .highlighted{background:var(--ax-color-primary-050)!important;border-radius:.25rem;transition:background 1s ease-in-out}\n"] }]
|
|
2219
|
+
}] });
|
|
2220
|
+
|
|
2221
|
+
var comment_component = /*#__PURE__*/Object.freeze({
|
|
2222
|
+
__proto__: null,
|
|
2223
|
+
AXMCommentComponent: AXMCommentComponent
|
|
2224
|
+
});
|
|
2225
|
+
|
|
2226
|
+
class AXMCommentPopupComponent extends AXBasePageComponent {
|
|
2227
|
+
constructor() {
|
|
2228
|
+
super(...arguments);
|
|
2229
|
+
this.refrenceType = input.required(...(ngDevMode ? [{ debugName: "refrenceType" }] : []));
|
|
2230
|
+
this.refrenceId = input.required(...(ngDevMode ? [{ debugName: "refrenceId" }] : []));
|
|
2231
|
+
this.subject = input.required(...(ngDevMode ? [{ debugName: "subject" }] : []));
|
|
2285
2232
|
}
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2233
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentPopupComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
2234
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.1.4", type: AXMCommentPopupComponent, isStandalone: true, selector: "axm-comment-popup", inputs: { refrenceType: { classPropertyName: "refrenceType", publicName: "refrenceType", isSignal: true, isRequired: true, transformFunction: null }, refrenceId: { classPropertyName: "refrenceId", publicName: "refrenceId", isSignal: true, isRequired: true, transformFunction: null }, subject: { classPropertyName: "subject", publicName: "subject", isSignal: true, isRequired: true, transformFunction: null } }, providers: [], usesInheritance: true, ngImport: i0, template: "<ax-content>\n <div class=\"ax-p-6 ax-min-h-[30vh] ax-overflow-y-auto\">\n <axm-comment [refrenceType]=\"refrenceType()\" [refrenceId]=\"refrenceId()\" [subject]=\"subject()\"></axm-comment>\n </div>\n</ax-content>\n<ax-footer>\n <ax-prefix></ax-prefix>\n <ax-suffix>\n <ax-button [text]=\"'close' | translate | async\" look=\"solid\" color=\"primary\" (onClick)=\"close()\"> </ax-button>\n </ax-suffix>\n</ax-footer>\n", dependencies: [{ kind: "ngmodule", type:
|
|
2235
|
+
// Angular
|
|
2236
|
+
CommonModule }, { kind: "ngmodule", type:
|
|
2237
|
+
// ACoreX
|
|
2238
|
+
AXDecoratorModule }, { kind: "component", type: i1$1.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: AXButtonModule }, { kind: "component", type: i5.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: AXTranslationModule }, { kind: "component", type:
|
|
2239
|
+
// Comment
|
|
2240
|
+
AXMCommentComponent, selector: "axm-comment", inputs: ["refrenceType", "refrenceId", "subject"] }, { kind: "pipe", type: i1$2.AsyncPipe, name: "async" }, { kind: "pipe", type: i4$1.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
2241
|
+
}
|
|
2242
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentPopupComponent, decorators: [{
|
|
2243
|
+
type: Component,
|
|
2244
|
+
args: [{ selector: 'axm-comment-popup', standalone: true, imports: [
|
|
2245
|
+
// Angular
|
|
2246
|
+
CommonModule,
|
|
2247
|
+
// ACoreX
|
|
2248
|
+
AXDecoratorModule,
|
|
2249
|
+
AXButtonModule,
|
|
2250
|
+
AXTranslationModule,
|
|
2251
|
+
// Comment
|
|
2252
|
+
AXMCommentComponent,
|
|
2253
|
+
], encapsulation: ViewEncapsulation.None, providers: [], template: "<ax-content>\n <div class=\"ax-p-6 ax-min-h-[30vh] ax-overflow-y-auto\">\n <axm-comment [refrenceType]=\"refrenceType()\" [refrenceId]=\"refrenceId()\" [subject]=\"subject()\"></axm-comment>\n </div>\n</ax-content>\n<ax-footer>\n <ax-prefix></ax-prefix>\n <ax-suffix>\n <ax-button [text]=\"'close' | translate | async\" look=\"solid\" color=\"primary\" (onClick)=\"close()\"> </ax-button>\n </ax-suffix>\n</ax-footer>\n" }]
|
|
2254
|
+
}] });
|
|
2255
|
+
|
|
2256
|
+
var commentPopup_component = /*#__PURE__*/Object.freeze({
|
|
2257
|
+
__proto__: null,
|
|
2258
|
+
AXMCommentPopupComponent: AXMCommentPopupComponent
|
|
2259
|
+
});
|
|
2260
|
+
|
|
2261
|
+
class AXMUserLookupPopup extends AXBasePageComponent {
|
|
2262
|
+
constructor() {
|
|
2263
|
+
super(...arguments);
|
|
2264
|
+
this.lookupNode = {
|
|
2265
|
+
name: 'form-field',
|
|
2266
|
+
path: 'form-field',
|
|
2267
|
+
type: 'form-field',
|
|
2268
|
+
children: [
|
|
2269
|
+
{
|
|
2270
|
+
name: 'lookup',
|
|
2271
|
+
path: 'lookup',
|
|
2272
|
+
type: 'lookup-editor',
|
|
2273
|
+
options: {
|
|
2274
|
+
entity: 'SecurityManagement.users',
|
|
2275
|
+
multiple: true,
|
|
2276
|
+
},
|
|
2277
|
+
},
|
|
2278
|
+
],
|
|
2279
|
+
options: {
|
|
2280
|
+
label: 'Select users:',
|
|
2281
|
+
},
|
|
2282
|
+
};
|
|
2283
|
+
this.titleNode = {
|
|
2284
|
+
name: 'form-field',
|
|
2285
|
+
path: 'form-field',
|
|
2286
|
+
type: 'form-field',
|
|
2287
|
+
children: [
|
|
2288
|
+
{
|
|
2289
|
+
name: 'title',
|
|
2290
|
+
path: 'title',
|
|
2291
|
+
type: 'text-editor',
|
|
2292
|
+
options: {
|
|
2293
|
+
placeholder: 'Enter title',
|
|
2294
|
+
required: true,
|
|
2295
|
+
},
|
|
2296
|
+
},
|
|
2297
|
+
],
|
|
2298
|
+
options: {
|
|
2299
|
+
label: 'Title:',
|
|
2300
|
+
},
|
|
2301
|
+
};
|
|
2302
|
+
this.context = signal({}, ...(ngDevMode ? [{ debugName: "context" }] : []));
|
|
2289
2303
|
}
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
const message = await this.messageService.getOne(messageId);
|
|
2295
|
-
const seen = message.seen || [];
|
|
2296
|
-
if (seen.some((s) => s.author.id === author.id)) {
|
|
2297
|
-
return message;
|
|
2298
|
-
}
|
|
2299
|
-
const updatedSeen = [...seen, { author, type: 'read' }];
|
|
2300
|
-
const updatedMessage = await this.messageService.updateOne(messageId, {
|
|
2301
|
-
seen: updatedSeen,
|
|
2302
|
-
updatedAt: new Date(),
|
|
2303
|
-
updatedBy: this.getCurrentUser().id,
|
|
2304
|
+
handleClose() {
|
|
2305
|
+
this.close({
|
|
2306
|
+
lookup: this.context()?.lookup,
|
|
2307
|
+
title: this.context()?.title,
|
|
2304
2308
|
});
|
|
2305
|
-
this._messageSeen$.next(await this.formatMessage(updatedMessage));
|
|
2306
|
-
return updatedMessage;
|
|
2307
|
-
}
|
|
2308
|
-
async getSeenBy(messageId) {
|
|
2309
|
-
const message = await this.messageService.getOne(messageId);
|
|
2310
|
-
return message.seen || [];
|
|
2311
2309
|
}
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
const currentUserId = this.getCurrentUser().id;
|
|
2319
|
-
const unreadMessages = items.filter((message) => message.author.id !== currentUserId && !message.seen?.some((s) => s.author.id === currentUserId));
|
|
2320
|
-
if (unreadMessages.length > 0) {
|
|
2321
|
-
await Promise.all(unreadMessages.map((message) => this.markSeen(message.id)));
|
|
2322
|
-
}
|
|
2323
|
-
this._roomSeen$.next(roomId);
|
|
2324
|
-
return true;
|
|
2310
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMUserLookupPopup, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
2311
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: AXMUserLookupPopup, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: `<axp-widgets-container [context]="context()" (onContextChanged)="context.set($event.data)">
|
|
2312
|
+
<div class="ax-p-4 ax-flex ax-flex-col ax-gap-4">
|
|
2313
|
+
<ng-container axp-widget-renderer [node]="lookupNode" [mode]="'edit'"> </ng-container>
|
|
2314
|
+
@if (context()?.lookup?.length > 1) {
|
|
2315
|
+
<ng-container axp-widget-renderer [node]="titleNode" [mode]="'edit'"> </ng-container>
|
|
2325
2316
|
}
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2317
|
+
</div>
|
|
2318
|
+
</axp-widgets-container>
|
|
2319
|
+
|
|
2320
|
+
<ax-footer>
|
|
2321
|
+
<ax-suffix>
|
|
2322
|
+
<ax-button
|
|
2323
|
+
text="Accept & Send"
|
|
2324
|
+
color="primary"
|
|
2325
|
+
[disabled]="(context()?.lookup?.length > 1 && !context()?.title) || !context()?.lookup?.length"
|
|
2326
|
+
(onClick)="handleClose()"
|
|
2327
|
+
></ax-button>
|
|
2328
|
+
</ax-suffix>
|
|
2329
|
+
</ax-footer>`, isInline: true, dependencies: [{ kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.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: AXPLayoutBuilderModule }, { kind: "component", type: i2$1.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i2$1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i5.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"] }] }); }
|
|
2330
|
+
}
|
|
2331
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMUserLookupPopup, decorators: [{
|
|
2332
|
+
type: Component,
|
|
2333
|
+
args: [{
|
|
2334
|
+
template: `<axp-widgets-container [context]="context()" (onContextChanged)="context.set($event.data)">
|
|
2335
|
+
<div class="ax-p-4 ax-flex ax-flex-col ax-gap-4">
|
|
2336
|
+
<ng-container axp-widget-renderer [node]="lookupNode" [mode]="'edit'"> </ng-container>
|
|
2337
|
+
@if (context()?.lookup?.length > 1) {
|
|
2338
|
+
<ng-container axp-widget-renderer [node]="titleNode" [mode]="'edit'"> </ng-container>
|
|
2329
2339
|
}
|
|
2340
|
+
</div>
|
|
2341
|
+
</axp-widgets-container>
|
|
2342
|
+
|
|
2343
|
+
<ax-footer>
|
|
2344
|
+
<ax-suffix>
|
|
2345
|
+
<ax-button
|
|
2346
|
+
text="Accept & Send"
|
|
2347
|
+
color="primary"
|
|
2348
|
+
[disabled]="(context()?.lookup?.length > 1 && !context()?.title) || !context()?.lookup?.length"
|
|
2349
|
+
(onClick)="handleClose()"
|
|
2350
|
+
></ax-button>
|
|
2351
|
+
</ax-suffix>
|
|
2352
|
+
</ax-footer>`,
|
|
2353
|
+
imports: [AXDecoratorModule, AXPLayoutBuilderModule, AXButtonModule],
|
|
2354
|
+
}]
|
|
2355
|
+
}] });
|
|
2356
|
+
|
|
2357
|
+
class AXMCommentWidgetViewComponent extends AXPValueWidgetComponent {
|
|
2358
|
+
constructor() {
|
|
2359
|
+
super(...arguments);
|
|
2360
|
+
this.refrenceType = computed(() => this.options().refrenceType, ...(ngDevMode ? [{ debugName: "refrenceType" }] : []));
|
|
2361
|
+
this.refrenceId = computed(() => this.options().refrenceId, ...(ngDevMode ? [{ debugName: "refrenceId" }] : []));
|
|
2362
|
+
this.subject = computed(() => this.options().subject, ...(ngDevMode ? [{ debugName: "subject" }] : []));
|
|
2330
2363
|
}
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
this._typingStatus$.next({ roomId, user, isTyping: true });
|
|
2336
|
-
}
|
|
2337
|
-
async stopTyping(roomId, userId) {
|
|
2338
|
-
const user = userId ? await this.getUserInfo(userId) : this.getCurrentUser();
|
|
2339
|
-
this._typingStatus$.next({ roomId, user, isTyping: false });
|
|
2340
|
-
}
|
|
2341
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMChatServiceImpl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2342
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMChatServiceImpl, providedIn: 'root' }); }
|
|
2364
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
2365
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: AXMCommentWidgetViewComponent, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: `
|
|
2366
|
+
<axm-comment [refrenceId]="refrenceId()" [refrenceType]="refrenceType()" [subject]="subject()"></axm-comment>
|
|
2367
|
+
`, isInline: true, dependencies: [{ kind: "component", type: AXMCommentComponent, selector: "axm-comment", inputs: ["refrenceType", "refrenceId", "subject"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2343
2368
|
}
|
|
2344
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
2345
|
-
type:
|
|
2369
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentWidgetViewComponent, decorators: [{
|
|
2370
|
+
type: Component,
|
|
2346
2371
|
args: [{
|
|
2347
|
-
|
|
2372
|
+
template: `
|
|
2373
|
+
<axm-comment [refrenceId]="refrenceId()" [refrenceType]="refrenceType()" [subject]="subject()"></axm-comment>
|
|
2374
|
+
`,
|
|
2375
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2376
|
+
imports: [AXMCommentComponent],
|
|
2348
2377
|
}]
|
|
2349
2378
|
}] });
|
|
2350
2379
|
|
|
2380
|
+
var commentWidgetView_component = /*#__PURE__*/Object.freeze({
|
|
2381
|
+
__proto__: null,
|
|
2382
|
+
AXMCommentWidgetViewComponent: AXMCommentWidgetViewComponent
|
|
2383
|
+
});
|
|
2384
|
+
|
|
2385
|
+
const AXPCommentWidget = {
|
|
2386
|
+
name: 'comment',
|
|
2387
|
+
title: 'Comments',
|
|
2388
|
+
description: 'Display and manage comments for entities',
|
|
2389
|
+
type: 'view',
|
|
2390
|
+
categories: [],
|
|
2391
|
+
groups: [AXPWidgetGroupEnum.FormElement],
|
|
2392
|
+
icon: 'fa-solid fa-comments',
|
|
2393
|
+
properties: [],
|
|
2394
|
+
components: {
|
|
2395
|
+
view: {
|
|
2396
|
+
component: () => Promise.resolve().then(function () { return commentWidgetView_component; }).then((c) => c.AXMCommentWidgetViewComponent),
|
|
2397
|
+
},
|
|
2398
|
+
},
|
|
2399
|
+
};
|
|
2400
|
+
|
|
2401
|
+
class AXMCommentPopupStartAction extends AXPWorkflowAction {
|
|
2402
|
+
constructor() {
|
|
2403
|
+
super(...arguments);
|
|
2404
|
+
this.popupService = inject(AXPopupService);
|
|
2405
|
+
this.translate = inject(AXTranslationService);
|
|
2406
|
+
}
|
|
2407
|
+
async execute(context) {
|
|
2408
|
+
const comp = (await Promise.resolve().then(function () { return commentPopup_component; })).AXMCommentPopupComponent;
|
|
2409
|
+
this.popupService.open(comp, {
|
|
2410
|
+
title: await this.translate.translateAsync('Comments'),
|
|
2411
|
+
size: 'lg',
|
|
2412
|
+
data: {
|
|
2413
|
+
refrenceType: signal(context.getVariable('options.refType')),
|
|
2414
|
+
refrenceId: signal(context.getVariable('options.refId')),
|
|
2415
|
+
subject: signal(context.getVariable('options.subject')),
|
|
2416
|
+
},
|
|
2417
|
+
});
|
|
2418
|
+
}
|
|
2419
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentPopupStartAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2420
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentPopupStartAction }); }
|
|
2421
|
+
}
|
|
2422
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentPopupStartAction, decorators: [{
|
|
2423
|
+
type: Injectable
|
|
2424
|
+
}] });
|
|
2425
|
+
const AXMCommentPopupWorkflow = {
|
|
2426
|
+
startStepId: 'start',
|
|
2427
|
+
steps: {
|
|
2428
|
+
start: {
|
|
2429
|
+
action: 'show-comment-popup-action',
|
|
2430
|
+
},
|
|
2431
|
+
},
|
|
2432
|
+
};
|
|
2433
|
+
|
|
2434
|
+
function convertChatMessageToNotification(room, message, currentUser) {
|
|
2435
|
+
return {
|
|
2436
|
+
channel: 'InApp',
|
|
2437
|
+
template: {
|
|
2438
|
+
category: 'Inbox',
|
|
2439
|
+
prority: 'Notice',
|
|
2440
|
+
icon: 'fa-light fa-comment',
|
|
2441
|
+
isPinned: false,
|
|
2442
|
+
},
|
|
2443
|
+
title: room.title || 'New Message',
|
|
2444
|
+
body: message.message.content,
|
|
2445
|
+
sender: message.author,
|
|
2446
|
+
receiver: currentUser,
|
|
2447
|
+
content: message.message,
|
|
2448
|
+
readAt: null,
|
|
2449
|
+
type: 'Chat',
|
|
2450
|
+
data: {
|
|
2451
|
+
roomId: room.id,
|
|
2452
|
+
},
|
|
2453
|
+
};
|
|
2454
|
+
}
|
|
2455
|
+
|
|
2351
2456
|
class AXMChatItemComponent {
|
|
2352
2457
|
constructor() {
|
|
2353
2458
|
// Input
|
|
@@ -2435,10 +2540,10 @@ class AXMChatItemComponent {
|
|
|
2435
2540
|
}
|
|
2436
2541
|
return '';
|
|
2437
2542
|
}
|
|
2438
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
2439
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.
|
|
2543
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMChatItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2544
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: AXMChatItemComponent, isStandalone: true, selector: "axm-chat-item", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, typing: { classPropertyName: "typing", publicName: "typing", isSignal: true, isRequired: false, transformFunction: null }, lastMessageReaction: { classPropertyName: "lastMessageReaction", publicName: "lastMessageReaction", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pressChatItem: "pressChatItem" }, ngImport: i0, template: "<div\n [id]=\"data().id\"\n class=\"ax-cursor-pointer ax-p-4 ax-flex ax-items-center ax-justify-between ax-gap-4 ax-border-b ax-border-divider\"\n (click)=\"onPressChatItem(data().id)\"\n>\n <!-- Avatar and User Info Section -->\n <div class=\"ax-flex ax-min-w-0 ax-gap-4 ax-flex-1\">\n <!-- Avatar with Online Status -->\n <div class=\"ax-flex-shrink-0\">\n @if (chatName().isPrivate) {\n <axp-user-avatar [size]=\"48\" [userId]=\"chatName().id\"></axp-user-avatar>\n } @else {\n <ax-avatar [size]=\"48\">\n <ax-text class=\"ax-primary-lightest\">\n <small class=\"ax-text-xs ax-font-semibold fas fa-users\"></small>\n </ax-text>\n </ax-avatar>\n }\n <!--Temp-->\n </div>\n\n <!-- User Details and Last Message -->\n <div class=\"ax-flex ax-flex-col ax-min-w-0 ax-flex-1 ax-gap-1\">\n <div class=\"ax-flex ax-items-center ax-justify-between ax-gap-2\">\n <p class=\"ax-font-semibold ax-text-on-surface ax-truncate ax-py-1\" [title]=\"chatName().fullName\">\n {{ chatName().fullName }}\n </p>\n <div class=\"ax-flex ax-items-center ax-gap-1\">\n @if (messageSeenStatus()) {\n <ax-icon class=\"ax-icon ax-text-success ax-size-5\" [class]=\"messageSeenStatus()\"></ax-icon>\n }\n @if (this.data().lastMessage) {\n <span class=\"ax-text-xs ax-whitespace-nowrap\">\n {{ formattedLastMessageDate() }}\n </span>\n }\n </div>\n </div>\n <div class=\"ax-flex ax-items-center ax-justify-between ax-gap-2 ax-mt-1 ax-overflow-hidden\">\n @if (typing()?.isTyping) {\n <div class=\"ax-pb-1 ax-flex ax-justify-center ax-items-end ax-gap-1\">\n <span class=\"ax-text-on-surface-light ax-font-semibold ax-capitalize ax-whitespace-nowrap ax-text-sm\">\n @if (!chatName().isPrivate) {\n {{ typing()?.user }}\n }\n {{ 'is-typing' | translate: { scope: 'conversation' } | async }}\n </span>\n <div class=\"typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n </div>\n } @else {\n <div class=\"ax-flex ax-items-center ax-gap-2 ax-text-sm ax-shrink ax-min-w-0\">\n @if ((lastMessage().author?.fullName || lastMessage().author?.username) && !chatName().isPrivate) {\n <span class=\"ax-text-on-surface-light ax-font-semibold ax-capitalize ax-whitespace-nowrap\">\n {{ (lastMessage().author?.fullName || lastMessage().author?.username) + ': ' }}\n </span>\n }\n @switch (lastMessage().contentType) {\n @case ('image') {\n <i class=\"fa-regular fa-image\"></i>\n }\n @case ('video') {\n <i class=\"fa-regular fa-video\"></i>\n }\n @case ('file') {\n <i class=\"fa-regular fa-file\"></i>\n }\n @case ('audio') {\n <i class=\"fa-regular fa-microphone\"></i>\n }\n @case ('link') {\n <i class=\"fa-regular fa-link\"></i>\n }\n }\n\n <span class=\"ax-truncate ax-capitalize\">\n {{ lastMessage().content }}\n </span>\n </div>\n }\n <div class=\"ax-flex ax-items-center ax-gap-2\">\n @if (hasUnread()) {\n <ax-badge color=\"primary\" [text]=\"unreadCount()\" class=\"ax-flex-shrink-0 ax-ml-auto\"></ax-badge>\n }\n <!-- @if (lastMessageReaction()) {\n <div class=\"ax-flex ax-items-center ax-gap-1 ax-bg-surface ax-rounded-full ax-p-1 ax-px-2\">\n <span class=\"ax-text-sm\">{{ lastMessageReaction() }}</span>\n <span class=\"ax-text-xs\">{{ lastMessage().reactions.length }}</span>\n </div>\n } -->\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [":host{display:block;width:100%}.typing-indicator{display:flex;align-items:center;padding-bottom:.4rem}.typing-indicator span{height:4px;width:4px;margin:0 1px;background-color:#9e9ea1;border-radius:50%;display:inline-block;animation:bounce 1.4s infinite ease-in-out both}.typing-indicator span:nth-child(1){animation-delay:-.32s}.typing-indicator span:nth-child(2){animation-delay:-.16s}@keyframes bounce{0%,80%,to{transform:scale(0)}40%{transform:scale(1)}}\n"], dependencies: [{ kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i1$1.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: AXBadgeModule }, { kind: "component", type: i2$2.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "component", type: AXPUserAvatarComponent, selector: "axp-user-avatar", inputs: ["size", "userId"] }, { kind: "ngmodule", type: AXAvatarModule }, { kind: "component", type: i3.AXAvatarComponent, selector: "ax-avatar", inputs: ["color", "size", "shape", "look"], outputs: ["sizeChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i4$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2440
2545
|
}
|
|
2441
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
2546
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMChatItemComponent, decorators: [{
|
|
2442
2547
|
type: Component,
|
|
2443
2548
|
args: [{ selector: 'axm-chat-item', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
2444
2549
|
AXDecoratorModule,
|
|
@@ -2448,19 +2553,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
|
|
|
2448
2553
|
AXDecoratorModule,
|
|
2449
2554
|
AXTranslationModule,
|
|
2450
2555
|
AsyncPipe,
|
|
2451
|
-
], template: "<div\n [id]=\"data().id\"\n class=\"ax-cursor-pointer ax-p-4 ax-flex ax-items-center ax-justify-between ax-gap-4 ax-border-b ax-border-divider\"\n (click)=\"onPressChatItem(data().id)\"\n>\n <!-- Avatar and User Info Section -->\n <div class=\"ax-flex ax-min-w-0 ax-gap-4 ax-flex-1\">\n <!-- Avatar with Online Status -->\n <div class=\"ax-flex-shrink-0\">\n @if (chatName().isPrivate) {\n <axp-user-avatar [size]=\"48\" [userId]=\"chatName().id\"></axp-user-avatar>\n } @else {\n <ax-avatar [size]=\"48\">\n <ax-text class=\"ax-primary-lightest\">\n <small class=\"ax-text-xs ax-font-semibold fas fa-users\"></small>\n </ax-text>\n </ax-avatar>\n }\n <!--Temp-->\n </div>\n\n <!-- User Details and Last Message -->\n <div class=\"ax-flex ax-flex-col ax-min-w-0 ax-flex-1 ax-gap-1\">\n <div class=\"ax-flex ax-items-center ax-justify-between ax-gap-2\">\n <p class=\"ax-font-semibold ax-text-on-surface ax-truncate ax-py-1\" [title]=\"chatName().fullName\">\n {{ chatName().fullName }}\n </p>\n <div class=\"ax-flex ax-items-center ax-gap-1\">\n @if (messageSeenStatus()) {\n <ax-icon class=\"ax-icon ax-text-success ax-size-5\" [class]=\"messageSeenStatus()\"></ax-icon>\n }\n @if (this.data().lastMessage) {\n <span class=\"ax-text-xs ax-whitespace-nowrap\">\n {{ formattedLastMessageDate() }}\n </span>\n }\n </div>\n </div>\n <div class=\"ax-flex ax-items-center ax-justify-between ax-gap-2 ax-mt-1 ax-overflow-hidden\">\n @if (typing()?.isTyping) {\n <div class=\"ax-pb-1 ax-flex ax-justify-center ax-items-end ax-gap-1\">\n <span class=\"ax-text-on-surface-light ax-font-semibold ax-capitalize ax-whitespace-nowrap ax-text-sm\">\n @if (!chatName().isPrivate) {\n {{ typing()?.user }}\n }\n {{ 'is-typing' | translate: { scope: 'conversation' } | async }}\n </span>\n <div class=\"typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n </div>\n } @else {\n <div class=\"ax-flex ax-items-center ax-gap-2 ax-text-sm ax-shrink ax-min-w-0\">\n @if ((lastMessage().author?.fullName || lastMessage().author?.username) && !chatName().isPrivate) {\n <span class=\"ax-text-on-surface-light ax-font-semibold ax-capitalize ax-whitespace-nowrap\">\n {{ (lastMessage().author?.fullName || lastMessage().author?.username) + ': ' }}\n </span>\n }\n @switch (lastMessage().contentType) {\n @case ('image') {\n <i class=\"fa-regular fa-image\"></i>\n }\n @case ('video') {\n <i class=\"fa-regular fa-video\"></i>\n }\n @case ('file') {\n <i class=\"fa-regular fa-file\"></i>\n }\n @case ('audio') {\n <i class=\"fa-regular fa-microphone\"></i>\n }\n @case ('link') {\n <i class=\"fa-regular fa-link\"></i>\n }\n }\n\n <span class=\"ax-truncate ax-capitalize\">\n {{ lastMessage().content }}\n </span>\n </div>\n }\n <div class=\"ax-flex ax-items-center ax-gap-2\">\n @if (hasUnread()) {\n <ax-badge color=\"primary\" [text]=\"unreadCount()\" class=\"ax-flex-shrink-0 ax-ml-auto\"></ax-badge>\n }\n <!-- @if (lastMessageReaction()) {\n <div class=\"ax-flex ax-items-center ax-gap-1 ax-bg-surface ax-rounded-full ax-p-1 ax-px-2\">\n <span class=\"ax-text-sm\">{{ lastMessageReaction() }}</span>\n <span class=\"ax-text-xs\">{{ lastMessage().reactions.length }}</span>\n </div>\n } -->\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [":host{display:block;width:100%}.typing-indicator{display:flex;align-items:center;padding-bottom:.
|
|
2556
|
+
], template: "<div\n [id]=\"data().id\"\n class=\"ax-cursor-pointer ax-p-4 ax-flex ax-items-center ax-justify-between ax-gap-4 ax-border-b ax-border-divider\"\n (click)=\"onPressChatItem(data().id)\"\n>\n <!-- Avatar and User Info Section -->\n <div class=\"ax-flex ax-min-w-0 ax-gap-4 ax-flex-1\">\n <!-- Avatar with Online Status -->\n <div class=\"ax-flex-shrink-0\">\n @if (chatName().isPrivate) {\n <axp-user-avatar [size]=\"48\" [userId]=\"chatName().id\"></axp-user-avatar>\n } @else {\n <ax-avatar [size]=\"48\">\n <ax-text class=\"ax-primary-lightest\">\n <small class=\"ax-text-xs ax-font-semibold fas fa-users\"></small>\n </ax-text>\n </ax-avatar>\n }\n <!--Temp-->\n </div>\n\n <!-- User Details and Last Message -->\n <div class=\"ax-flex ax-flex-col ax-min-w-0 ax-flex-1 ax-gap-1\">\n <div class=\"ax-flex ax-items-center ax-justify-between ax-gap-2\">\n <p class=\"ax-font-semibold ax-text-on-surface ax-truncate ax-py-1\" [title]=\"chatName().fullName\">\n {{ chatName().fullName }}\n </p>\n <div class=\"ax-flex ax-items-center ax-gap-1\">\n @if (messageSeenStatus()) {\n <ax-icon class=\"ax-icon ax-text-success ax-size-5\" [class]=\"messageSeenStatus()\"></ax-icon>\n }\n @if (this.data().lastMessage) {\n <span class=\"ax-text-xs ax-whitespace-nowrap\">\n {{ formattedLastMessageDate() }}\n </span>\n }\n </div>\n </div>\n <div class=\"ax-flex ax-items-center ax-justify-between ax-gap-2 ax-mt-1 ax-overflow-hidden\">\n @if (typing()?.isTyping) {\n <div class=\"ax-pb-1 ax-flex ax-justify-center ax-items-end ax-gap-1\">\n <span class=\"ax-text-on-surface-light ax-font-semibold ax-capitalize ax-whitespace-nowrap ax-text-sm\">\n @if (!chatName().isPrivate) {\n {{ typing()?.user }}\n }\n {{ 'is-typing' | translate: { scope: 'conversation' } | async }}\n </span>\n <div class=\"typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n </div>\n } @else {\n <div class=\"ax-flex ax-items-center ax-gap-2 ax-text-sm ax-shrink ax-min-w-0\">\n @if ((lastMessage().author?.fullName || lastMessage().author?.username) && !chatName().isPrivate) {\n <span class=\"ax-text-on-surface-light ax-font-semibold ax-capitalize ax-whitespace-nowrap\">\n {{ (lastMessage().author?.fullName || lastMessage().author?.username) + ': ' }}\n </span>\n }\n @switch (lastMessage().contentType) {\n @case ('image') {\n <i class=\"fa-regular fa-image\"></i>\n }\n @case ('video') {\n <i class=\"fa-regular fa-video\"></i>\n }\n @case ('file') {\n <i class=\"fa-regular fa-file\"></i>\n }\n @case ('audio') {\n <i class=\"fa-regular fa-microphone\"></i>\n }\n @case ('link') {\n <i class=\"fa-regular fa-link\"></i>\n }\n }\n\n <span class=\"ax-truncate ax-capitalize\">\n {{ lastMessage().content }}\n </span>\n </div>\n }\n <div class=\"ax-flex ax-items-center ax-gap-2\">\n @if (hasUnread()) {\n <ax-badge color=\"primary\" [text]=\"unreadCount()\" class=\"ax-flex-shrink-0 ax-ml-auto\"></ax-badge>\n }\n <!-- @if (lastMessageReaction()) {\n <div class=\"ax-flex ax-items-center ax-gap-1 ax-bg-surface ax-rounded-full ax-p-1 ax-px-2\">\n <span class=\"ax-text-sm\">{{ lastMessageReaction() }}</span>\n <span class=\"ax-text-xs\">{{ lastMessage().reactions.length }}</span>\n </div>\n } -->\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [":host{display:block;width:100%}.typing-indicator{display:flex;align-items:center;padding-bottom:.4rem}.typing-indicator span{height:4px;width:4px;margin:0 1px;background-color:#9e9ea1;border-radius:50%;display:inline-block;animation:bounce 1.4s infinite ease-in-out both}.typing-indicator span:nth-child(1){animation-delay:-.32s}.typing-indicator span:nth-child(2){animation-delay:-.16s}@keyframes bounce{0%,80%,to{transform:scale(0)}40%{transform:scale(1)}}\n"] }]
|
|
2452
2557
|
}] });
|
|
2453
2558
|
|
|
2454
2559
|
class AXMChatComponent extends AXPPageLayoutBaseComponent {
|
|
2455
2560
|
constructor() {
|
|
2456
2561
|
super(...arguments);
|
|
2457
2562
|
this.activatedRoute = inject(ActivatedRoute);
|
|
2458
|
-
this.chatService = inject(
|
|
2563
|
+
this.chatService = inject(AXMChatManagementService);
|
|
2564
|
+
this.realtimeService = inject(AXMChatRealtimeService);
|
|
2459
2565
|
this.popupService = inject(AXPopupService);
|
|
2460
2566
|
this.dialogService = inject(AXDialogService);
|
|
2461
2567
|
this.router = inject(Router);
|
|
2462
2568
|
this.unsubscribe = inject(AXUnsubscriber);
|
|
2463
|
-
this.osNotificationService = inject(AXMOsNotificationService);
|
|
2464
2569
|
this.notificationConnectorService = inject(AXMNotificationConnectorService);
|
|
2465
2570
|
// View Children
|
|
2466
2571
|
this.tab = viewChild('tab', ...(ngDevMode ? [{ debugName: "tab" }] : []));
|
|
@@ -2554,7 +2659,7 @@ class AXMChatComponent extends AXPPageLayoutBaseComponent {
|
|
|
2554
2659
|
super.ngOnInit();
|
|
2555
2660
|
this.isLoading.set(true);
|
|
2556
2661
|
this.error.set(null);
|
|
2557
|
-
await Promise.all([this.loadChats(), this.loadTabs()
|
|
2662
|
+
await Promise.all([this.loadChats(), this.loadTabs()]);
|
|
2558
2663
|
this.isLoading.set(false);
|
|
2559
2664
|
//
|
|
2560
2665
|
this.router.events
|
|
@@ -2563,34 +2668,85 @@ class AXMChatComponent extends AXPPageLayoutBaseComponent {
|
|
|
2563
2668
|
await this.loadFromRoute();
|
|
2564
2669
|
});
|
|
2565
2670
|
//
|
|
2566
|
-
this.
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2671
|
+
this.realtimeService.room$.pipe(this.unsubscribe.takeUntilDestroy).subscribe((event) => {
|
|
2672
|
+
switch (event.type) {
|
|
2673
|
+
case 'add':
|
|
2674
|
+
this.allRooms.update((rooms) => [event.payload, ...rooms.filter((r) => r.id !== event.payload.id)]);
|
|
2675
|
+
break;
|
|
2676
|
+
case 'remove':
|
|
2677
|
+
this.allRooms.update((rooms) => rooms.filter((r) => r.id !== event.payload));
|
|
2678
|
+
if (event.payload === this.selectedRoom()?.id) {
|
|
2679
|
+
this.selectedRoom.set(null);
|
|
2680
|
+
this.router.navigate(['./'], { relativeTo: this.activatedRoute });
|
|
2681
|
+
}
|
|
2682
|
+
break;
|
|
2683
|
+
case 'update':
|
|
2684
|
+
this.allRooms.update((rooms) => rooms.map((r) => (r.id === event.payload.id ? event.payload : r)));
|
|
2685
|
+
break;
|
|
2686
|
+
case 'seen':
|
|
2687
|
+
this.allRooms.update((rooms) => rooms.map((room) => (room.id === event.payload ? { ...room, unreadCount: 0 } : room)));
|
|
2688
|
+
break;
|
|
2571
2689
|
}
|
|
2572
2690
|
});
|
|
2573
|
-
this.
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2691
|
+
this.realtimeService.message$.pipe(this.unsubscribe.takeUntilDestroy).subscribe((event) => {
|
|
2692
|
+
switch (event.type) {
|
|
2693
|
+
case 'add': {
|
|
2694
|
+
const message = event.payload;
|
|
2695
|
+
const rooms = this.allRooms();
|
|
2696
|
+
const roomIndex = rooms.findIndex((r) => r.id === message.roomId);
|
|
2697
|
+
if (roomIndex > -1) {
|
|
2698
|
+
const roomToUpdate = rooms[roomIndex];
|
|
2699
|
+
const isCurrentUser = message.author.id === this.sessionService.user?.id;
|
|
2700
|
+
const updatedRoom = {
|
|
2701
|
+
...roomToUpdate,
|
|
2702
|
+
lastMessage: message,
|
|
2703
|
+
unreadCount: !isCurrentUser ? (roomToUpdate.unreadCount || 0) + 1 : roomToUpdate.unreadCount,
|
|
2704
|
+
};
|
|
2705
|
+
const newRooms = [updatedRoom, ...rooms.filter((r) => r.id !== message.roomId)];
|
|
2706
|
+
this.allRooms.set(newRooms);
|
|
2707
|
+
if (!isCurrentUser && (this.selectedRoom()?.id !== message.roomId || document.hidden)) {
|
|
2708
|
+
const notification = convertChatMessageToNotification(roomToUpdate, message, this.sessionService.user);
|
|
2709
|
+
this.notificationConnectorService.create({
|
|
2710
|
+
...notification,
|
|
2711
|
+
id: message.id,
|
|
2712
|
+
entityName: 'notifications',
|
|
2713
|
+
createAt: new Date(),
|
|
2714
|
+
}, {
|
|
2715
|
+
onClick: () => {
|
|
2716
|
+
this.router.navigate([roomToUpdate.id], { relativeTo: this.activatedRoute });
|
|
2717
|
+
},
|
|
2718
|
+
activeWindow: true,
|
|
2719
|
+
});
|
|
2720
|
+
}
|
|
2721
|
+
}
|
|
2722
|
+
else {
|
|
2723
|
+
this.chatService.getRoom(message.roomId).then((newRoom) => {
|
|
2724
|
+
this.allRooms.update((currentRooms) => [newRoom, ...currentRooms]);
|
|
2725
|
+
});
|
|
2726
|
+
}
|
|
2727
|
+
break;
|
|
2578
2728
|
}
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2729
|
+
case 'update': {
|
|
2730
|
+
const message = event.payload;
|
|
2731
|
+
this.allRooms.update((rooms) => {
|
|
2732
|
+
return rooms.map((room) => {
|
|
2733
|
+
if (room.lastMessage?.id === message.id) {
|
|
2734
|
+
return {
|
|
2735
|
+
...room,
|
|
2736
|
+
lastMessage: {
|
|
2737
|
+
...room.lastMessage,
|
|
2738
|
+
...message,
|
|
2739
|
+
},
|
|
2740
|
+
};
|
|
2741
|
+
}
|
|
2742
|
+
return room;
|
|
2743
|
+
});
|
|
2744
|
+
});
|
|
2745
|
+
break;
|
|
2588
2746
|
}
|
|
2589
|
-
|
|
2590
|
-
});
|
|
2591
|
-
this.allRooms.set(updatedRooms);
|
|
2747
|
+
}
|
|
2592
2748
|
});
|
|
2593
|
-
this.
|
|
2749
|
+
this.realtimeService.typingStatus$.pipe(this.unsubscribe.takeUntilDestroy).subscribe(async (status) => {
|
|
2594
2750
|
const currentUserId = this.sessionService.user?.id;
|
|
2595
2751
|
if (status.user.id !== currentUserId) {
|
|
2596
2752
|
if (status.isTyping) {
|
|
@@ -2607,70 +2763,6 @@ class AXMChatComponent extends AXPPageLayoutBaseComponent {
|
|
|
2607
2763
|
}
|
|
2608
2764
|
}
|
|
2609
2765
|
});
|
|
2610
|
-
this.chatService.messageSent$.pipe(this.unsubscribe.takeUntilDestroy).subscribe((message) => {
|
|
2611
|
-
const rooms = this.allRooms();
|
|
2612
|
-
const roomIndex = rooms.findIndex((r) => r.id === message.roomId);
|
|
2613
|
-
if (roomIndex > -1) {
|
|
2614
|
-
const roomToUpdate = rooms[roomIndex];
|
|
2615
|
-
const isCurrentUser = message.author.id === this.sessionService.user?.id;
|
|
2616
|
-
const updatedRoom = {
|
|
2617
|
-
...roomToUpdate,
|
|
2618
|
-
lastMessage: message,
|
|
2619
|
-
unreadCount: !isCurrentUser ? (roomToUpdate.unreadCount || 0) + 1 : roomToUpdate.unreadCount,
|
|
2620
|
-
};
|
|
2621
|
-
const newRooms = [updatedRoom, ...rooms.filter((r) => r.id !== message.roomId)];
|
|
2622
|
-
this.allRooms.set(newRooms);
|
|
2623
|
-
//
|
|
2624
|
-
if (!isCurrentUser && this.selectedRoom()?.id !== message.roomId) {
|
|
2625
|
-
const notification = convertChatMessageToNotification(roomToUpdate, message, this.sessionService.user);
|
|
2626
|
-
this.notificationConnectorService.create({
|
|
2627
|
-
...notification,
|
|
2628
|
-
id: message.id,
|
|
2629
|
-
entityName: 'notifications',
|
|
2630
|
-
createAt: new Date(),
|
|
2631
|
-
}, {
|
|
2632
|
-
onClick: () => {
|
|
2633
|
-
this.router.navigate([roomToUpdate.id], { relativeTo: this.activatedRoute });
|
|
2634
|
-
},
|
|
2635
|
-
activeWindow: true,
|
|
2636
|
-
});
|
|
2637
|
-
// this.osNotificationService.show(notification.title || 'Notification', {
|
|
2638
|
-
// body: notification.body || 'No body',
|
|
2639
|
-
// icon: notification.user.image || '',
|
|
2640
|
-
// onClick: () => {
|
|
2641
|
-
// this.router.navigate([roomToUpdate.id], { relativeTo: this.activatedRoute });
|
|
2642
|
-
// },
|
|
2643
|
-
// activeWindow: true,
|
|
2644
|
-
// });
|
|
2645
|
-
}
|
|
2646
|
-
//
|
|
2647
|
-
}
|
|
2648
|
-
else {
|
|
2649
|
-
// New room, fetch it and add it to the top.
|
|
2650
|
-
this.chatService.getRoom(message.roomId).then((newRoom) => {
|
|
2651
|
-
this.allRooms.update((currentRooms) => {
|
|
2652
|
-
// Prepending the new room
|
|
2653
|
-
return [newRoom, ...currentRooms];
|
|
2654
|
-
});
|
|
2655
|
-
});
|
|
2656
|
-
}
|
|
2657
|
-
});
|
|
2658
|
-
this.chatService.messageReacted$.pipe(this.unsubscribe.takeUntilDestroy).subscribe((message) => {
|
|
2659
|
-
this.allRooms.update((rooms) => {
|
|
2660
|
-
return rooms.map((room) => {
|
|
2661
|
-
if (room.lastMessage?.id === message.id) {
|
|
2662
|
-
return {
|
|
2663
|
-
...room,
|
|
2664
|
-
lastMessage: {
|
|
2665
|
-
...room.lastMessage,
|
|
2666
|
-
reactions: message.reactions,
|
|
2667
|
-
},
|
|
2668
|
-
};
|
|
2669
|
-
}
|
|
2670
|
-
return room;
|
|
2671
|
-
});
|
|
2672
|
-
});
|
|
2673
|
-
});
|
|
2674
2766
|
}
|
|
2675
2767
|
async loadFromRoute() {
|
|
2676
2768
|
const chatId = this.activatedRoute.snapshot.firstChild?.paramMap.get('id');
|
|
@@ -2881,14 +2973,14 @@ class AXMChatComponent extends AXPPageLayoutBaseComponent {
|
|
|
2881
2973
|
this.toastService.danger('Failed to create room');
|
|
2882
2974
|
}
|
|
2883
2975
|
}
|
|
2884
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
2885
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.
|
|
2976
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMChatComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
2977
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: AXMChatComponent, isStandalone: true, selector: "axm-chat", host: { listeners: { "document:keydown.escape": "onKeydownHandler($event)" } }, providers: [
|
|
2886
2978
|
{
|
|
2887
2979
|
provide: AXPPageLayoutBase,
|
|
2888
2980
|
useExisting: AXMChatComponent,
|
|
2889
2981
|
},
|
|
2890
2982
|
AXUnsubscriber,
|
|
2891
|
-
], viewQueries: [{ propertyName: "tab", first: true, predicate: ["tab"], descendants: true, isSignal: true }, { propertyName: "container", first: true, predicate: ["container"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<axp-page-layout #container>\n <axp-layout-start-side class=\"ax-border-e ax-lightest-surface ax-h-full\">\n <axp-layout-header>\n <axp-layout-title>{{ 'module-name' | translate: { scope: 'conversation' } | async }}</axp-layout-title>\n <axp-layout-toolbar>\n <ax-search-box\n #searchInput\n look=\"solid\"\n [placeholder]=\"placeholder()\"\n [value]=\"searchQuery()\"\n (onValueChanged)=\"onSearch($event.value)\"\n class=\"ax-w-full\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-search-box>\n </axp-layout-toolbar>\n </axp-layout-header>\n <axp-layout-content class=\"ax-flex ax-flex-col ax-min-h-0 ax-max-w-80\">\n @if (!layoutService.isMobileDevice()) {\n <ng-container [ngTemplateOutlet]=\"template\"></ng-container>\n }\n </axp-layout-content>\n </axp-layout-start-side>\n\n <axp-page-content style=\"height: calc(100vh - 22rem)\">\n @if (selectedRoom()) {\n <router-outlet></router-outlet>\n } @else if (layoutService.isMobileDevice()) {\n <ax-search-box\n #searchInput\n look=\"solid\"\n [placeholder]=\"placeholder()\"\n [value]=\"searchQuery()\"\n (onValueChanged)=\"onSearch($event.value)\"\n class=\"ax-w-full ax-mb-2\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-search-box>\n <ng-container [ngTemplateOutlet]=\"template\"></ng-container>\n }\n </axp-page-content>\n</axp-page-layout>\n<ng-template #template>\n <!-- Tabs -->\n <div [class]=\"!layoutService.isMobileDevice() ? 'ax-px-4': ''\">\n <ax-tabs\n #tab\n class=\"ax-text-neutral-400\"\n [look]=\"'with-line'\"\n [location]=\"'bottom'\"\n [fitParent]=\"true\"\n (onActiveTabChanged)=\"activeTabIndex.set($event.index)\"\n >\n @for (tab of tabs(); track tab.id; let i = $index) {\n <ax-tab-item [text]=\"tab.title\" [active]=\"activeTabIndex() === i\">\n <ax-suffix>\n <ax-badge\n [text]=\"getRoomCountForTab(tab).toString()\"\n [color]=\"activeTabIndex() === i ? 'primary' : 'secondary'\"\n class=\"ax-min-w-[1.5rem] ax-justify-center\"\n ></ax-badge>\n </ax-suffix>\n </ax-tab-item>\n }\n </ax-tabs>\n </div>\n\n <!-- Chat List Content -->\n <div\n class=\"ax-flex-1 ax-overflow-hidden ax-flex ax-flex-col ax-justify-between ax-min-w-80\"\n [class.ax-border-t]=\"tabs().length > 0\"\n >\n <!-- Loading State -->\n @if (isLoading()) {\n <div class=\"ax-p-4 ax-space-y-4\">\n @for (_ of [1, 2, 3, 4, 5, 6]; track $index) {\n <div class=\"ax-flex ax-items-center ax-space-x-3\">\n <ax-skeleton [animated]=\"true\" class=\"ax-w-12 ax-h-12 ax-rounded-full\"></ax-skeleton>\n <div class=\"ax-flex-1 ax-space-y-2\">\n <ax-skeleton [animated]=\"true\" class=\"ax-w-3/4 ax-h-4 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton [animated]=\"true\" class=\"ax-w-1/2 ax-h-3 ax-rounded-md\"></ax-skeleton>\n </div>\n </div>\n }\n </div>\n } @else if (error()) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4 ax-text-center\">\n <ax-icon class=\"ax-text-danger ax-text-5xl ax-mb-3\">\n <i class=\"fa-light fa-circle-exclamation\"></i>\n </ax-icon>\n <p class=\"ax-font-semibold ax-text-lg\">\n {{ 'chat-error' | translate: { scope: 'conversation' } | async }}\n </p>\n <p class=\"ax-font-semibold ax-text-lg\">\n {{ 'chat-try-again' | translate: { scope: 'conversation' } | async }}\n </p>\n <p class=\"ax-text-secondary ax-mb-4\">{{ error() }}</p>\n <ax-button\n [text]=\"'try-again' | translate: { scope: 'conversation' } | async\"\n color=\"primary\"\n (onClick)=\"refreshChat()\"\n ></ax-button>\n </div>\n } @else {\n <div class=\"ax-flex-1 ax-overflow-y-auto\">\n @for (i of filteredRooms(); track i.id) {\n <axm-chat-item\n [data]=\"i\"\n [typing]=\"$any(typingStatus()[i.id])\"\n [lastMessageReaction]=\"i.lastMessage?.reactions?.[0]?.type ?? null\"\n [attr.data-id]=\"i.id\"\n (click)=\"openChat(i.id)\"\n [class.ax-bg-dark]=\"selectedRoom()?.id === i.id\"\n class=\"ax-transition-all ax-duration-100 hover:ax-bg-surface\"\n [@fadeIn]\n tabindex=\"0\"\n (keydown.enter)=\"openChat(i.id)\"\n role=\"button\"\n ></axm-chat-item>\n } @empty {\n <div class=\"ax-p-4 ax-font-medium ax-text-center ax-text-secondary\">\n @if (isSearching()) {\n No chats found matching your search.\n } @else {\n There are no conversations in this tab.\n }\n </div>\n }\n </div>\n }\n\n <!-- Footer Content -->\n @if (!layoutService.isMobileDevice()) {\n <div class=\"ax-border-t ax-border-divider ax-bg-lightest ax-p-4\">\n <ax-button class=\"ax-w-full\" color=\"primary\" text=\"New Conversation\" (onClick)=\"onNewConversation()\">\n <ax-prefix>\n <ax-icon>\n <i class=\"fa-solid fa-plus\"></i>\n </ax-icon>\n </ax-prefix>\n </ax-button>\n </div>\n } @else {\n <ax-button\n class=\"ax-fixed ax-bottom-16 ax-right-8 !ax-rounded-full !ax-w-14 !ax-h-14 ax-shadow-lg\"\n color=\"primary\"\n (onClick)=\"onNewConversation()\"\n >\n <ax-icon class=\"ax-text-2xl\">\n <i class=\"fa-solid fa-plus\"></i>\n </ax-icon>\n </ax-button>\n }\n </div>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "component", type: AXMChatItemComponent, selector: "axm-chat-item", inputs: ["data", "typing", "lastMessageReaction"], outputs: ["pressChatItem"] }, { kind: "ngmodule", type:
|
|
2983
|
+
], viewQueries: [{ propertyName: "tab", first: true, predicate: ["tab"], descendants: true, isSignal: true }, { propertyName: "container", first: true, predicate: ["container"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<axp-page-layout #container>\n <axp-layout-start-side class=\"ax-border-e ax-lightest-surface ax-h-full\">\n <axp-layout-header>\n <axp-layout-title>{{ 'module-name' | translate: { scope: 'conversation' } | async }}</axp-layout-title>\n <axp-layout-toolbar>\n <ax-search-box\n #searchInput\n look=\"solid\"\n [placeholder]=\"placeholder()\"\n [value]=\"searchQuery()\"\n (onValueChanged)=\"onSearch($event.value)\"\n class=\"ax-w-full\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-search-box>\n </axp-layout-toolbar>\n </axp-layout-header>\n <axp-layout-content class=\"ax-flex ax-flex-col ax-min-h-0 ax-max-w-80\">\n @if (!layoutService.isMobileDevice()) {\n <ng-container [ngTemplateOutlet]=\"template\"></ng-container>\n }\n </axp-layout-content>\n </axp-layout-start-side>\n\n <axp-page-content style=\"height: calc(100vh - 22rem)\">\n @if (selectedRoom()) {\n <router-outlet></router-outlet>\n } @else if (layoutService.isMobileDevice()) {\n <ax-search-box\n #searchInput\n look=\"solid\"\n [placeholder]=\"placeholder()\"\n [value]=\"searchQuery()\"\n (onValueChanged)=\"onSearch($event.value)\"\n class=\"ax-w-full ax-mb-2\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-search-box>\n <ng-container [ngTemplateOutlet]=\"template\"></ng-container>\n }\n </axp-page-content>\n</axp-page-layout>\n<ng-template #template>\n <!-- Tabs -->\n <div [class]=\"!layoutService.isMobileDevice() ? 'ax-px-4' : ''\">\n <ax-tabs\n #tab\n class=\"ax-text-neutral-400 !ax-overflow-x-hidden\"\n [look]=\"'with-line'\"\n [location]=\"'bottom'\"\n [fitParent]=\"true\"\n (onActiveTabChanged)=\"activeTabIndex.set($event.index)\"\n >\n @for (tab of tabs(); track tab.id; let i = $index) {\n <ax-tab-item [text]=\"tab.title\" [active]=\"activeTabIndex() === i\">\n <ax-suffix>\n <ax-badge\n [text]=\"getRoomCountForTab(tab).toString()\"\n [color]=\"activeTabIndex() === i ? 'primary' : 'secondary'\"\n class=\"ax-min-w-[1.5rem] ax-justify-center\"\n ></ax-badge>\n </ax-suffix>\n </ax-tab-item>\n }\n </ax-tabs>\n </div>\n\n <!-- Chat List Content -->\n <div\n class=\"ax-flex-1 ax-overflow-hidden ax-flex ax-flex-col ax-justify-between ax-min-w-80\"\n [class.ax-border-t]=\"tabs().length > 0\"\n >\n <!-- Loading State -->\n @if (isLoading()) {\n <div class=\"ax-p-4 ax-space-y-4\">\n @for (_ of [1, 2, 3, 4, 5, 6]; track $index) {\n <div class=\"ax-flex ax-items-center ax-space-x-3\">\n <ax-skeleton [animated]=\"true\" class=\"ax-w-12 ax-h-12 ax-rounded-full\"></ax-skeleton>\n <div class=\"ax-flex-1 ax-space-y-2\">\n <ax-skeleton [animated]=\"true\" class=\"ax-w-3/4 ax-h-4 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton [animated]=\"true\" class=\"ax-w-1/2 ax-h-3 ax-rounded-md\"></ax-skeleton>\n </div>\n </div>\n }\n </div>\n } @else if (error()) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4 ax-text-center\">\n <ax-icon class=\"ax-text-danger ax-text-5xl ax-mb-3\">\n <i class=\"fa-light fa-circle-exclamation\"></i>\n </ax-icon>\n <p class=\"ax-font-semibold ax-text-lg\">\n {{ 'chat-error' | translate: { scope: 'conversation' } | async }}\n </p>\n <p class=\"ax-font-semibold ax-text-lg\">\n {{ 'chat-try-again' | translate: { scope: 'conversation' } | async }}\n </p>\n <p class=\"ax-text-secondary ax-mb-4\">{{ error() }}</p>\n <ax-button\n [text]=\"'try-again' | translate: { scope: 'conversation' } | async\"\n color=\"primary\"\n (onClick)=\"refreshChat()\"\n ></ax-button>\n </div>\n } @else {\n <div class=\"ax-flex-1 ax-overflow-y-auto\">\n @for (i of filteredRooms(); track i.id) {\n <axm-chat-item\n [data]=\"i\"\n [typing]=\"$any(typingStatus()[i.id])\"\n [lastMessageReaction]=\"i.lastMessage?.reactions?.[0]?.type ?? null\"\n [attr.data-id]=\"i.id\"\n (click)=\"openChat(i.id)\"\n [class.ax-bg-dark]=\"selectedRoom()?.id === i.id\"\n class=\"ax-transition-all ax-duration-100 hover:ax-bg-surface\"\n [@fadeIn]\n tabindex=\"0\"\n (keydown.enter)=\"openChat(i.id)\"\n role=\"button\"\n ></axm-chat-item>\n } @empty {\n <div class=\"ax-p-4 ax-font-medium ax-text-center ax-text-secondary\">\n @if (isSearching()) {\n No chats found matching your search.\n } @else {\n There are no conversations in this tab.\n }\n </div>\n }\n </div>\n }\n\n <!-- Footer Content -->\n @if (!layoutService.isMobileDevice()) {\n <div class=\"ax-border-t ax-border-divider ax-bg-lightest ax-p-4\">\n <ax-button class=\"ax-w-full\" color=\"primary\" text=\"New Conversation\" (onClick)=\"onNewConversation()\">\n <ax-prefix>\n <ax-icon>\n <i class=\"fa-solid fa-plus\"></i>\n </ax-icon>\n </ax-prefix>\n </ax-button>\n </div>\n } @else {\n <ax-button\n class=\"ax-fixed ax-bottom-16 ax-right-8 !ax-rounded-full !ax-w-14 !ax-h-14 ax-shadow-lg\"\n color=\"primary\"\n (onClick)=\"onNewConversation()\"\n >\n <ax-icon class=\"ax-text-2xl\">\n <i class=\"fa-solid fa-plus\"></i>\n </ax-icon>\n </ax-button>\n }\n </div>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "component", type: AXMChatItemComponent, selector: "axm-chat-item", inputs: ["data", "typing", "lastMessageReaction"], outputs: ["pressChatItem"] }, { kind: "ngmodule", type:
|
|
2892
2984
|
// Common Modules
|
|
2893
2985
|
CommonModule }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2$3.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "ngmodule", type:
|
|
2894
2986
|
// Acorex Core Modules
|
|
@@ -2904,7 +2996,7 @@ class AXMChatComponent extends AXPPageLayoutBaseComponent {
|
|
|
2904
2996
|
]),
|
|
2905
2997
|
], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2906
2998
|
}
|
|
2907
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
2999
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMChatComponent, decorators: [{
|
|
2908
3000
|
type: Component,
|
|
2909
3001
|
args: [{ selector: 'axm-chat', changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
2910
3002
|
{
|
|
@@ -2954,7 +3046,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
|
|
|
2954
3046
|
animate('300ms ease-out', style({ opacity: 1, transform: 'translateY(0)' })),
|
|
2955
3047
|
]),
|
|
2956
3048
|
]),
|
|
2957
|
-
], template: "<axp-page-layout #container>\n <axp-layout-start-side class=\"ax-border-e ax-lightest-surface ax-h-full\">\n <axp-layout-header>\n <axp-layout-title>{{ 'module-name' | translate: { scope: 'conversation' } | async }}</axp-layout-title>\n <axp-layout-toolbar>\n <ax-search-box\n #searchInput\n look=\"solid\"\n [placeholder]=\"placeholder()\"\n [value]=\"searchQuery()\"\n (onValueChanged)=\"onSearch($event.value)\"\n class=\"ax-w-full\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-search-box>\n </axp-layout-toolbar>\n </axp-layout-header>\n <axp-layout-content class=\"ax-flex ax-flex-col ax-min-h-0 ax-max-w-80\">\n @if (!layoutService.isMobileDevice()) {\n <ng-container [ngTemplateOutlet]=\"template\"></ng-container>\n }\n </axp-layout-content>\n </axp-layout-start-side>\n\n <axp-page-content style=\"height: calc(100vh - 22rem)\">\n @if (selectedRoom()) {\n <router-outlet></router-outlet>\n } @else if (layoutService.isMobileDevice()) {\n <ax-search-box\n #searchInput\n look=\"solid\"\n [placeholder]=\"placeholder()\"\n [value]=\"searchQuery()\"\n (onValueChanged)=\"onSearch($event.value)\"\n class=\"ax-w-full ax-mb-2\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-search-box>\n <ng-container [ngTemplateOutlet]=\"template\"></ng-container>\n }\n </axp-page-content>\n</axp-page-layout>\n<ng-template #template>\n <!-- Tabs -->\n <div [class]=\"!layoutService.isMobileDevice() ? 'ax-px-4': ''\">\n <ax-tabs\n #tab\n class=\"ax-text-neutral-400\"\n [look]=\"'with-line'\"\n [location]=\"'bottom'\"\n [fitParent]=\"true\"\n (onActiveTabChanged)=\"activeTabIndex.set($event.index)\"\n >\n @for (tab of tabs(); track tab.id; let i = $index) {\n <ax-tab-item [text]=\"tab.title\" [active]=\"activeTabIndex() === i\">\n <ax-suffix>\n <ax-badge\n [text]=\"getRoomCountForTab(tab).toString()\"\n [color]=\"activeTabIndex() === i ? 'primary' : 'secondary'\"\n class=\"ax-min-w-[1.5rem] ax-justify-center\"\n ></ax-badge>\n </ax-suffix>\n </ax-tab-item>\n }\n </ax-tabs>\n </div>\n\n <!-- Chat List Content -->\n <div\n class=\"ax-flex-1 ax-overflow-hidden ax-flex ax-flex-col ax-justify-between ax-min-w-80\"\n [class.ax-border-t]=\"tabs().length > 0\"\n >\n <!-- Loading State -->\n @if (isLoading()) {\n <div class=\"ax-p-4 ax-space-y-4\">\n @for (_ of [1, 2, 3, 4, 5, 6]; track $index) {\n <div class=\"ax-flex ax-items-center ax-space-x-3\">\n <ax-skeleton [animated]=\"true\" class=\"ax-w-12 ax-h-12 ax-rounded-full\"></ax-skeleton>\n <div class=\"ax-flex-1 ax-space-y-2\">\n <ax-skeleton [animated]=\"true\" class=\"ax-w-3/4 ax-h-4 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton [animated]=\"true\" class=\"ax-w-1/2 ax-h-3 ax-rounded-md\"></ax-skeleton>\n </div>\n </div>\n }\n </div>\n } @else if (error()) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4 ax-text-center\">\n <ax-icon class=\"ax-text-danger ax-text-5xl ax-mb-3\">\n <i class=\"fa-light fa-circle-exclamation\"></i>\n </ax-icon>\n <p class=\"ax-font-semibold ax-text-lg\">\n {{ 'chat-error' | translate: { scope: 'conversation' } | async }}\n </p>\n <p class=\"ax-font-semibold ax-text-lg\">\n {{ 'chat-try-again' | translate: { scope: 'conversation' } | async }}\n </p>\n <p class=\"ax-text-secondary ax-mb-4\">{{ error() }}</p>\n <ax-button\n [text]=\"'try-again' | translate: { scope: 'conversation' } | async\"\n color=\"primary\"\n (onClick)=\"refreshChat()\"\n ></ax-button>\n </div>\n } @else {\n <div class=\"ax-flex-1 ax-overflow-y-auto\">\n @for (i of filteredRooms(); track i.id) {\n <axm-chat-item\n [data]=\"i\"\n [typing]=\"$any(typingStatus()[i.id])\"\n [lastMessageReaction]=\"i.lastMessage?.reactions?.[0]?.type ?? null\"\n [attr.data-id]=\"i.id\"\n (click)=\"openChat(i.id)\"\n [class.ax-bg-dark]=\"selectedRoom()?.id === i.id\"\n class=\"ax-transition-all ax-duration-100 hover:ax-bg-surface\"\n [@fadeIn]\n tabindex=\"0\"\n (keydown.enter)=\"openChat(i.id)\"\n role=\"button\"\n ></axm-chat-item>\n } @empty {\n <div class=\"ax-p-4 ax-font-medium ax-text-center ax-text-secondary\">\n @if (isSearching()) {\n No chats found matching your search.\n } @else {\n There are no conversations in this tab.\n }\n </div>\n }\n </div>\n }\n\n <!-- Footer Content -->\n @if (!layoutService.isMobileDevice()) {\n <div class=\"ax-border-t ax-border-divider ax-bg-lightest ax-p-4\">\n <ax-button class=\"ax-w-full\" color=\"primary\" text=\"New Conversation\" (onClick)=\"onNewConversation()\">\n <ax-prefix>\n <ax-icon>\n <i class=\"fa-solid fa-plus\"></i>\n </ax-icon>\n </ax-prefix>\n </ax-button>\n </div>\n } @else {\n <ax-button\n class=\"ax-fixed ax-bottom-16 ax-right-8 !ax-rounded-full !ax-w-14 !ax-h-14 ax-shadow-lg\"\n color=\"primary\"\n (onClick)=\"onNewConversation()\"\n >\n <ax-icon class=\"ax-text-2xl\">\n <i class=\"fa-solid fa-plus\"></i>\n </ax-icon>\n </ax-button>\n }\n </div>\n</ng-template>\n" }]
|
|
3049
|
+
], template: "<axp-page-layout #container>\n <axp-layout-start-side class=\"ax-border-e ax-lightest-surface ax-h-full\">\n <axp-layout-header>\n <axp-layout-title>{{ 'module-name' | translate: { scope: 'conversation' } | async }}</axp-layout-title>\n <axp-layout-toolbar>\n <ax-search-box\n #searchInput\n look=\"solid\"\n [placeholder]=\"placeholder()\"\n [value]=\"searchQuery()\"\n (onValueChanged)=\"onSearch($event.value)\"\n class=\"ax-w-full\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-search-box>\n </axp-layout-toolbar>\n </axp-layout-header>\n <axp-layout-content class=\"ax-flex ax-flex-col ax-min-h-0 ax-max-w-80\">\n @if (!layoutService.isMobileDevice()) {\n <ng-container [ngTemplateOutlet]=\"template\"></ng-container>\n }\n </axp-layout-content>\n </axp-layout-start-side>\n\n <axp-page-content style=\"height: calc(100vh - 22rem)\">\n @if (selectedRoom()) {\n <router-outlet></router-outlet>\n } @else if (layoutService.isMobileDevice()) {\n <ax-search-box\n #searchInput\n look=\"solid\"\n [placeholder]=\"placeholder()\"\n [value]=\"searchQuery()\"\n (onValueChanged)=\"onSearch($event.value)\"\n class=\"ax-w-full ax-mb-2\"\n >\n <ax-clear-button></ax-clear-button>\n </ax-search-box>\n <ng-container [ngTemplateOutlet]=\"template\"></ng-container>\n }\n </axp-page-content>\n</axp-page-layout>\n<ng-template #template>\n <!-- Tabs -->\n <div [class]=\"!layoutService.isMobileDevice() ? 'ax-px-4' : ''\">\n <ax-tabs\n #tab\n class=\"ax-text-neutral-400 !ax-overflow-x-hidden\"\n [look]=\"'with-line'\"\n [location]=\"'bottom'\"\n [fitParent]=\"true\"\n (onActiveTabChanged)=\"activeTabIndex.set($event.index)\"\n >\n @for (tab of tabs(); track tab.id; let i = $index) {\n <ax-tab-item [text]=\"tab.title\" [active]=\"activeTabIndex() === i\">\n <ax-suffix>\n <ax-badge\n [text]=\"getRoomCountForTab(tab).toString()\"\n [color]=\"activeTabIndex() === i ? 'primary' : 'secondary'\"\n class=\"ax-min-w-[1.5rem] ax-justify-center\"\n ></ax-badge>\n </ax-suffix>\n </ax-tab-item>\n }\n </ax-tabs>\n </div>\n\n <!-- Chat List Content -->\n <div\n class=\"ax-flex-1 ax-overflow-hidden ax-flex ax-flex-col ax-justify-between ax-min-w-80\"\n [class.ax-border-t]=\"tabs().length > 0\"\n >\n <!-- Loading State -->\n @if (isLoading()) {\n <div class=\"ax-p-4 ax-space-y-4\">\n @for (_ of [1, 2, 3, 4, 5, 6]; track $index) {\n <div class=\"ax-flex ax-items-center ax-space-x-3\">\n <ax-skeleton [animated]=\"true\" class=\"ax-w-12 ax-h-12 ax-rounded-full\"></ax-skeleton>\n <div class=\"ax-flex-1 ax-space-y-2\">\n <ax-skeleton [animated]=\"true\" class=\"ax-w-3/4 ax-h-4 ax-rounded-md\"></ax-skeleton>\n <ax-skeleton [animated]=\"true\" class=\"ax-w-1/2 ax-h-3 ax-rounded-md\"></ax-skeleton>\n </div>\n </div>\n }\n </div>\n } @else if (error()) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4 ax-text-center\">\n <ax-icon class=\"ax-text-danger ax-text-5xl ax-mb-3\">\n <i class=\"fa-light fa-circle-exclamation\"></i>\n </ax-icon>\n <p class=\"ax-font-semibold ax-text-lg\">\n {{ 'chat-error' | translate: { scope: 'conversation' } | async }}\n </p>\n <p class=\"ax-font-semibold ax-text-lg\">\n {{ 'chat-try-again' | translate: { scope: 'conversation' } | async }}\n </p>\n <p class=\"ax-text-secondary ax-mb-4\">{{ error() }}</p>\n <ax-button\n [text]=\"'try-again' | translate: { scope: 'conversation' } | async\"\n color=\"primary\"\n (onClick)=\"refreshChat()\"\n ></ax-button>\n </div>\n } @else {\n <div class=\"ax-flex-1 ax-overflow-y-auto\">\n @for (i of filteredRooms(); track i.id) {\n <axm-chat-item\n [data]=\"i\"\n [typing]=\"$any(typingStatus()[i.id])\"\n [lastMessageReaction]=\"i.lastMessage?.reactions?.[0]?.type ?? null\"\n [attr.data-id]=\"i.id\"\n (click)=\"openChat(i.id)\"\n [class.ax-bg-dark]=\"selectedRoom()?.id === i.id\"\n class=\"ax-transition-all ax-duration-100 hover:ax-bg-surface\"\n [@fadeIn]\n tabindex=\"0\"\n (keydown.enter)=\"openChat(i.id)\"\n role=\"button\"\n ></axm-chat-item>\n } @empty {\n <div class=\"ax-p-4 ax-font-medium ax-text-center ax-text-secondary\">\n @if (isSearching()) {\n No chats found matching your search.\n } @else {\n There are no conversations in this tab.\n }\n </div>\n }\n </div>\n }\n\n <!-- Footer Content -->\n @if (!layoutService.isMobileDevice()) {\n <div class=\"ax-border-t ax-border-divider ax-bg-lightest ax-p-4\">\n <ax-button class=\"ax-w-full\" color=\"primary\" text=\"New Conversation\" (onClick)=\"onNewConversation()\">\n <ax-prefix>\n <ax-icon>\n <i class=\"fa-solid fa-plus\"></i>\n </ax-icon>\n </ax-prefix>\n </ax-button>\n </div>\n } @else {\n <ax-button\n class=\"ax-fixed ax-bottom-16 ax-right-8 !ax-rounded-full !ax-w-14 !ax-h-14 ax-shadow-lg\"\n color=\"primary\"\n (onClick)=\"onNewConversation()\"\n >\n <ax-icon class=\"ax-text-2xl\">\n <i class=\"fa-solid fa-plus\"></i>\n </ax-icon>\n </ax-button>\n }\n </div>\n</ng-template>\n" }]
|
|
2958
3050
|
}], propDecorators: { onKeydownHandler: [{
|
|
2959
3051
|
type: HostListener,
|
|
2960
3052
|
args: ['document:keydown.escape', ['$event']]
|
|
@@ -3243,9 +3335,11 @@ class AXMChatPreviewComponent {
|
|
|
3243
3335
|
constructor() {
|
|
3244
3336
|
this.activatedRoute = inject(ActivatedRoute);
|
|
3245
3337
|
this.fileService = inject(AXFileService);
|
|
3246
|
-
this.chatService = inject(
|
|
3338
|
+
this.chatService = inject(AXMChatManagementService);
|
|
3339
|
+
this.realtimeService = inject(AXMChatRealtimeService);
|
|
3247
3340
|
this.sessionService = inject(AXPSessionService);
|
|
3248
3341
|
this.toastService = inject(AXToastService);
|
|
3342
|
+
this.unsubscribe = inject(AXUnsubscriber);
|
|
3249
3343
|
this.inputRef = viewChild(AXConversationInputComponent, ...(ngDevMode ? [{ debugName: "inputRef" }] : []));
|
|
3250
3344
|
this.activeMessage = signal(null, ...(ngDevMode ? [{ debugName: "activeMessage" }] : []));
|
|
3251
3345
|
this.typing$ = new Subject();
|
|
@@ -3284,24 +3378,37 @@ class AXMChatPreviewComponent {
|
|
|
3284
3378
|
this.loadRoomInfo(this.roomId);
|
|
3285
3379
|
}
|
|
3286
3380
|
});
|
|
3287
|
-
this.
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3381
|
+
this.realtimeService.message$.pipe(this.unsubscribe.takeUntilDestroy).subscribe(async (event) => {
|
|
3382
|
+
if (event.type === 'add') {
|
|
3383
|
+
const message = event.payload;
|
|
3384
|
+
if (message.author.id !== this.sessionService.user?.id && message.roomId === this.roomId) {
|
|
3385
|
+
await this.chatService.markSeen(message.id);
|
|
3386
|
+
this.chatData.update((values) => {
|
|
3387
|
+
const newMessage = convertToChatPreview(this.sessionService.user?.id || '', {
|
|
3388
|
+
items: [message],
|
|
3389
|
+
total: 1,
|
|
3390
|
+
})[0];
|
|
3391
|
+
return [...values, newMessage];
|
|
3392
|
+
});
|
|
3393
|
+
}
|
|
3394
|
+
}
|
|
3395
|
+
else if (event.type === 'remove') {
|
|
3396
|
+
this.chatData.update((values) => values.filter((item) => item.id !== event.payload));
|
|
3397
|
+
}
|
|
3398
|
+
else if (event.type === 'update') {
|
|
3399
|
+
const message = event.payload;
|
|
3400
|
+
const convertedNewMessage = convertToChatPreview(this.sessionService.user?.id || '', {
|
|
3401
|
+
items: [message],
|
|
3402
|
+
total: 1,
|
|
3403
|
+
})[0];
|
|
3404
|
+
this.chatData.update((values) => values.map((item) => (item.id === message.id ? { ...convertedNewMessage, ...item } : item)));
|
|
3405
|
+
}
|
|
3406
|
+
});
|
|
3407
|
+
this.typingSubscription = this.typing$.pipe(debounceTime(1000)).subscribe(() => {
|
|
3408
|
+
if (this.roomId) {
|
|
3409
|
+
this.chatService.stopTyping(this.roomId);
|
|
3298
3410
|
}
|
|
3299
3411
|
});
|
|
3300
|
-
// this.typingSubscription = this.typing$.pipe(debounceTime(1000)).subscribe(() => {
|
|
3301
|
-
// if (this.roomId) {
|
|
3302
|
-
// this.chatService.stopTyping(this.roomId);
|
|
3303
|
-
// }
|
|
3304
|
-
// });
|
|
3305
3412
|
}
|
|
3306
3413
|
//GO TO LAST MESSAGE EFFECT.
|
|
3307
3414
|
#af;
|
|
@@ -3473,10 +3580,10 @@ class AXMChatPreviewComponent {
|
|
|
3473
3580
|
input.setActionBoxContainer(icon, message?.content || this.activeMessage()?.content || '');
|
|
3474
3581
|
}
|
|
3475
3582
|
}
|
|
3476
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
3477
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.
|
|
3583
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMChatPreviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3584
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: AXMChatPreviewComponent, isStandalone: true, selector: "axm-chat-preview", viewQueries: [{ propertyName: "inputRef", first: true, predicate: AXConversationInputComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@if (isLoading()) {\n <div class=\"ax-h-full ax-w-full ax-flex ax-items-center ax-justify-center\">\n <ax-loading></ax-loading>\n </div>\n} @else if (error()) {\n <div class=\"ax-h-full ax-w-full ax-flex ax-items-center ax-justify-center\">\n <div class=\"ax-text-center\">\n <p class=\"ax-text-danger\">{{ error() }}</p>\n <button (click)=\"loadMessages(roomId)\" class=\"ax-mt-2 ax-button ax-primary\">Retry</button>\n </div>\n </div>\n} @else {\n <div\n axDomChange\n (axResizeObserver)=\"setHeight($event[0].contentRect.height)\"\n class=\"ax-bg-surface-container ax-h-full\"\n >\n <!-- Messages Container -->\n <ax-conversation-container class=\"ax-overflow-hidden\" [chatData]=\"chatData()\">\n <ax-conversation-view\n (onActionMenuOpening)=\"addItemHandler($event)\"\n (onAction)=\"handleOnAction($event)\"\n (onReplyClick)=\"addInputOverlay('reply', $event.data)\"\n [chatBoxHeight]=\"height() - 60 + 'px'\"\n ></ax-conversation-view>\n @if (!isChannel()) {\n <ax-conversation-input\n class=\"ax-p-1\"\n placeholder=\"Type a message...\"\n [(ngModel)]=\"options().value\"\n (ngModelChange)=\"handleTyping($event)\"\n (onSendClick)=\"handleOnSend($event)\"\n (onFileChange)=\"handleFileChange($event)\"\n (onStopRecording)=\"handleEndRecord($event)\"\n (onCancelRecording)=\"handleCancelRecord($event)\"\n (onEnterPressed)=\"handleEnter()\"\n ></ax-conversation-input>\n }\n </ax-conversation-container>\n </div>\n}\n", styles: [":host{display:block;width:100%;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i10.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i10.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: AXDomChangeDirective, selector: "[axDomChange]", outputs: ["axMutationObserver", "axResizeObserver"] }, { kind: "ngmodule", type: AXConversationModule }, { kind: "component", type: i2$4.AXConversationViewComponent, selector: "ax-conversation-view", inputs: ["chatBoxHeight", "isReplyArrowShown", "avatar"], outputs: ["onScrollEnd", "onActionMenuOpening", "onAction", "onReplyClick"] }, { kind: "component", type: i2$4.AXConversationInputComponent, selector: "ax-conversation-input", inputs: ["look", "placeholder", "maxLength", "hasAttachment", "hasVoice", "hasEmoji", "isLoading", "acceptFileType"], outputs: ["onActionClose", "onSendClick", "onStartRecording", "onCancelRecording", "onEnterPressed"] }, { kind: "component", type: i2$4.AXConversationContainerComponent, selector: "ax-conversation-container", inputs: ["chatData"] }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i6.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3478
3585
|
}
|
|
3479
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
3586
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMChatPreviewComponent, decorators: [{
|
|
3480
3587
|
type: Component,
|
|
3481
3588
|
args: [{ selector: 'axm-chat-preview', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, FormsModule, AXDomChangeDirective, AXConversationModule, AXLoadingModule], template: "@if (isLoading()) {\n <div class=\"ax-h-full ax-w-full ax-flex ax-items-center ax-justify-center\">\n <ax-loading></ax-loading>\n </div>\n} @else if (error()) {\n <div class=\"ax-h-full ax-w-full ax-flex ax-items-center ax-justify-center\">\n <div class=\"ax-text-center\">\n <p class=\"ax-text-danger\">{{ error() }}</p>\n <button (click)=\"loadMessages(roomId)\" class=\"ax-mt-2 ax-button ax-primary\">Retry</button>\n </div>\n </div>\n} @else {\n <div\n axDomChange\n (axResizeObserver)=\"setHeight($event[0].contentRect.height)\"\n class=\"ax-bg-surface-container ax-h-full\"\n >\n <!-- Messages Container -->\n <ax-conversation-container class=\"ax-overflow-hidden\" [chatData]=\"chatData()\">\n <ax-conversation-view\n (onActionMenuOpening)=\"addItemHandler($event)\"\n (onAction)=\"handleOnAction($event)\"\n (onReplyClick)=\"addInputOverlay('reply', $event.data)\"\n [chatBoxHeight]=\"height() - 60 + 'px'\"\n ></ax-conversation-view>\n @if (!isChannel()) {\n <ax-conversation-input\n class=\"ax-p-1\"\n placeholder=\"Type a message...\"\n [(ngModel)]=\"options().value\"\n (ngModelChange)=\"handleTyping($event)\"\n (onSendClick)=\"handleOnSend($event)\"\n (onFileChange)=\"handleFileChange($event)\"\n (onStopRecording)=\"handleEndRecord($event)\"\n (onCancelRecording)=\"handleCancelRecord($event)\"\n (onEnterPressed)=\"handleEnter()\"\n ></ax-conversation-input>\n }\n </ax-conversation-container>\n </div>\n}\n", styles: [":host{display:block;width:100%;height:100%}\n"] }]
|
|
3482
3589
|
}] });
|
|
@@ -3486,6 +3593,114 @@ var chatPreview_component = /*#__PURE__*/Object.freeze({
|
|
|
3486
3593
|
AXMChatPreviewComponent: AXMChatPreviewComponent
|
|
3487
3594
|
});
|
|
3488
3595
|
|
|
3596
|
+
class AXMChatNotificationContentComponent {
|
|
3597
|
+
constructor() {
|
|
3598
|
+
this.item = input(...(ngDevMode ? [undefined, { debugName: "item" }] : []));
|
|
3599
|
+
this.execute = output();
|
|
3600
|
+
}
|
|
3601
|
+
onMarkAsSeen(e) {
|
|
3602
|
+
e.nativeEvent.stopPropagation();
|
|
3603
|
+
this.execute.emit({ name: 'mark-as-seen' });
|
|
3604
|
+
}
|
|
3605
|
+
goToChat(e) {
|
|
3606
|
+
e.nativeEvent.stopPropagation();
|
|
3607
|
+
this.execute.emit({ name: 'go-to-chat' });
|
|
3608
|
+
}
|
|
3609
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMChatNotificationContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3610
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.1.4", type: AXMChatNotificationContentComponent, isStandalone: true, selector: "axm-chat-notification-content", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { execute: "execute" }, ngImport: i0, template: `
|
|
3611
|
+
<div class="ax-text-sm ax-mt-1 ax-line-clamp-2">
|
|
3612
|
+
<p>{{ item()?.body || 'You have a new message.' }}</p>
|
|
3613
|
+
<div class="ax-flex ax-gap-2 ax-pt-2">
|
|
3614
|
+
<!-- <ax-button (onClick)="onMarkAsSeen($event)" [text]="'Mark as Seen'"></ax-button>
|
|
3615
|
+
<ax-button (onClick)="goToChat($event)" [text]="'Go to Chat'"></ax-button> -->
|
|
3616
|
+
</div>
|
|
3617
|
+
</div>
|
|
3618
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }] }); }
|
|
3619
|
+
}
|
|
3620
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMChatNotificationContentComponent, decorators: [{
|
|
3621
|
+
type: Component,
|
|
3622
|
+
args: [{
|
|
3623
|
+
selector: 'axm-chat-notification-content',
|
|
3624
|
+
template: `
|
|
3625
|
+
<div class="ax-text-sm ax-mt-1 ax-line-clamp-2">
|
|
3626
|
+
<p>{{ item()?.body || 'You have a new message.' }}</p>
|
|
3627
|
+
<div class="ax-flex ax-gap-2 ax-pt-2">
|
|
3628
|
+
<!-- <ax-button (onClick)="onMarkAsSeen($event)" [text]="'Mark as Seen'"></ax-button>
|
|
3629
|
+
<ax-button (onClick)="goToChat($event)" [text]="'Go to Chat'"></ax-button> -->
|
|
3630
|
+
</div>
|
|
3631
|
+
</div>
|
|
3632
|
+
`,
|
|
3633
|
+
standalone: true,
|
|
3634
|
+
imports: [CommonModule, AXButtonModule],
|
|
3635
|
+
}]
|
|
3636
|
+
}] });
|
|
3637
|
+
|
|
3638
|
+
class AXMChatNotificationProvider {
|
|
3639
|
+
constructor(injector) {
|
|
3640
|
+
this.injector = injector;
|
|
3641
|
+
this.name = 'Chat';
|
|
3642
|
+
this.title = 'Chat';
|
|
3643
|
+
this.icon = 'fa-solid fa-comment-sms';
|
|
3644
|
+
}
|
|
3645
|
+
content() {
|
|
3646
|
+
return Promise.resolve(AXMChatNotificationContentComponent);
|
|
3647
|
+
}
|
|
3648
|
+
async execute(command, item) {
|
|
3649
|
+
const router = this.injector.get(Router);
|
|
3650
|
+
const chatService = this.injector.get(AXMChatManagementService);
|
|
3651
|
+
const activatedRoute = this.injector.get(ActivatedRoute);
|
|
3652
|
+
const roomId = item.data?.['roomId'];
|
|
3653
|
+
if (!roomId) {
|
|
3654
|
+
console.error('Room ID is missing from notification item.');
|
|
3655
|
+
return;
|
|
3656
|
+
}
|
|
3657
|
+
const app = activatedRoute.snapshot.firstChild?.paramMap.get('app') || 'platform';
|
|
3658
|
+
switch (command.name) {
|
|
3659
|
+
case 'mark-as-seen':
|
|
3660
|
+
await chatService.markRoomSeen(roomId);
|
|
3661
|
+
break;
|
|
3662
|
+
case 'go-to-chat':
|
|
3663
|
+
router.navigate([app, 'chat', roomId]);
|
|
3664
|
+
break;
|
|
3665
|
+
case 'click':
|
|
3666
|
+
router.navigate([app, 'chat', roomId]);
|
|
3667
|
+
break;
|
|
3668
|
+
default:
|
|
3669
|
+
break;
|
|
3670
|
+
}
|
|
3671
|
+
}
|
|
3672
|
+
}
|
|
3673
|
+
class AXMCommentNotificationProvider {
|
|
3674
|
+
constructor(injector) {
|
|
3675
|
+
this.injector = injector;
|
|
3676
|
+
this.name = 'Comment';
|
|
3677
|
+
this.title = 'Comment';
|
|
3678
|
+
this.icon = 'fa-solid fa-comment';
|
|
3679
|
+
}
|
|
3680
|
+
async execute(command, item) {
|
|
3681
|
+
console.log('Comment notification clicked', item);
|
|
3682
|
+
// Placeholder for comment execution logic
|
|
3683
|
+
}
|
|
3684
|
+
}
|
|
3685
|
+
const AXM_CONVERSATION_NOTIFICATION_PROVIDERS = [
|
|
3686
|
+
{
|
|
3687
|
+
provide: AXP_NOTIFICATION_DEFINITION_PROVIDER,
|
|
3688
|
+
useFactory: (injector) => {
|
|
3689
|
+
return new AXMChatNotificationProvider(injector);
|
|
3690
|
+
},
|
|
3691
|
+
deps: [Injector],
|
|
3692
|
+
multi: true,
|
|
3693
|
+
},
|
|
3694
|
+
{
|
|
3695
|
+
provide: AXP_NOTIFICATION_DEFINITION_PROVIDER,
|
|
3696
|
+
useFactory: (injector) => {
|
|
3697
|
+
return new AXMCommentNotificationProvider(injector);
|
|
3698
|
+
},
|
|
3699
|
+
deps: [Injector],
|
|
3700
|
+
multi: true,
|
|
3701
|
+
},
|
|
3702
|
+
];
|
|
3703
|
+
|
|
3489
3704
|
function routesFactory() {
|
|
3490
3705
|
const routes = [
|
|
3491
3706
|
{
|
|
@@ -3548,11 +3763,11 @@ function routesFactory() {
|
|
|
3548
3763
|
return routes;
|
|
3549
3764
|
}
|
|
3550
3765
|
class AXMConversationModule {
|
|
3551
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
3552
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.1.
|
|
3766
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMConversationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
3767
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.1.4", ngImport: i0, type: AXMConversationModule, imports: [i2$1.AXPLayoutBuilderModule, i2$5.AXPWorkflowModule], exports: [
|
|
3553
3768
|
// Modules
|
|
3554
3769
|
RouterModule] }); }
|
|
3555
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.1.
|
|
3770
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMConversationModule, providers: [
|
|
3556
3771
|
// Services
|
|
3557
3772
|
{
|
|
3558
3773
|
provide: AXMMessageService,
|
|
@@ -3571,6 +3786,10 @@ class AXMConversationModule {
|
|
|
3571
3786
|
provide: AXMChatService,
|
|
3572
3787
|
useClass: AXMChatServiceImpl,
|
|
3573
3788
|
},
|
|
3789
|
+
{
|
|
3790
|
+
provide: AXMChatRealtimeService,
|
|
3791
|
+
useClass: AXMChatRealtimeServiceImpl,
|
|
3792
|
+
},
|
|
3574
3793
|
{
|
|
3575
3794
|
provide: AXMCommentService,
|
|
3576
3795
|
useClass: AXMCommentServiceImpl,
|
|
@@ -3604,6 +3823,7 @@ class AXMConversationModule {
|
|
|
3604
3823
|
// Conversation Module
|
|
3605
3824
|
importProvidersFrom(AXConversationModule.forRoot()),
|
|
3606
3825
|
DatePipe,
|
|
3826
|
+
...AXM_CONVERSATION_NOTIFICATION_PROVIDERS,
|
|
3607
3827
|
], imports: [AXPLayoutBuilderModule.forChild({
|
|
3608
3828
|
widgets: [AXPCommentWidget],
|
|
3609
3829
|
}),
|
|
@@ -3618,7 +3838,7 @@ class AXMConversationModule {
|
|
|
3618
3838
|
// Modules
|
|
3619
3839
|
RouterModule] }); }
|
|
3620
3840
|
}
|
|
3621
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
3841
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMConversationModule, decorators: [{
|
|
3622
3842
|
type: NgModule,
|
|
3623
3843
|
args: [{
|
|
3624
3844
|
declarations: [],
|
|
@@ -3658,6 +3878,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
|
|
|
3658
3878
|
provide: AXMChatService,
|
|
3659
3879
|
useClass: AXMChatServiceImpl,
|
|
3660
3880
|
},
|
|
3881
|
+
{
|
|
3882
|
+
provide: AXMChatRealtimeService,
|
|
3883
|
+
useClass: AXMChatRealtimeServiceImpl,
|
|
3884
|
+
},
|
|
3661
3885
|
{
|
|
3662
3886
|
provide: AXMCommentService,
|
|
3663
3887
|
useClass: AXMCommentServiceImpl,
|
|
@@ -3691,6 +3915,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
|
|
|
3691
3915
|
// Conversation Module
|
|
3692
3916
|
importProvidersFrom(AXConversationModule.forRoot()),
|
|
3693
3917
|
DatePipe,
|
|
3918
|
+
...AXM_CONVERSATION_NOTIFICATION_PROVIDERS,
|
|
3694
3919
|
],
|
|
3695
3920
|
}]
|
|
3696
3921
|
}] });
|
|
@@ -3699,5 +3924,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
|
|
|
3699
3924
|
* Generated bundle index. Do not edit.
|
|
3700
3925
|
*/
|
|
3701
3926
|
|
|
3702
|
-
export { AXMChatComponent, AXMChatItemComponent, AXMChatPreviewComponent, AXMChatService, AXMChatServiceImpl, AXMCommentComponent, AXMCommentManagementService, AXMCommentPopupComponent, AXMCommentPopupStartAction, AXMCommentPopupWorkflow, AXMCommentRealtimeService, AXMCommentRealtimeServiceImpl, AXMCommentService, AXMCommentServiceImpl, AXMCommentWidgetViewComponent, AXMConversationModule, AXMConversationTabService, AXMConversationTabServiceImpl, AXMMessageService, AXMMessageServiceImpl, AXMRoomService, AXMRoomServiceImpl, AXMUserLookupPopup, AXPCommentWidget, RootConfig, messageFactory, roomFactory, tabFactory };
|
|
3927
|
+
export { AXMChatComponent, AXMChatItemComponent, AXMChatManagementService, AXMChatPreviewComponent, AXMChatRealtimeService, AXMChatRealtimeServiceImpl, AXMChatService, AXMChatServiceImpl, AXMCommentComponent, AXMCommentManagementService, AXMCommentPopupComponent, AXMCommentPopupStartAction, AXMCommentPopupWorkflow, AXMCommentRealtimeService, AXMCommentRealtimeServiceImpl, AXMCommentService, AXMCommentServiceImpl, AXMCommentWidgetViewComponent, AXMConversationModule, AXMConversationTabService, AXMConversationTabServiceImpl, AXMMessageService, AXMMessageServiceImpl, AXMRoomService, AXMRoomServiceImpl, AXMUserLookupPopup, AXPCommentWidget, RootConfig, messageFactory, roomFactory, tabFactory };
|
|
3703
3928
|
//# sourceMappingURL=acorex-modules-conversation.mjs.map
|