@acorex/modules 20.2.0-next.1 → 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 +59 -4
- package/common/index.d.ts +1 -8
- package/contact-management/index.d.ts +69 -2
- package/conversation/README.md +2 -2
- package/conversation/index.d.ts +219 -114
- 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-y6rICHrT.mjs → acorex-modules-auth-acorex-modules-auth-tDyQQDnk.mjs} +254 -105
- package/fesm2022/acorex-modules-auth-acorex-modules-auth-tDyQQDnk.mjs.map +1 -0
- package/fesm2022/{acorex-modules-auth-app-chooser.component-Cpy0VN6n.mjs → acorex-modules-auth-app-chooser.component-yu1DJZKN.mjs} +8 -6
- package/fesm2022/acorex-modules-auth-app-chooser.component-yu1DJZKN.mjs.map +1 -0
- 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-ZEX4NMuJ.mjs → acorex-modules-auth-login.module-D1aa1F6G.mjs} +8 -8
- package/fesm2022/{acorex-modules-auth-login.module-ZEX4NMuJ.mjs.map → acorex-modules-auth-login.module-D1aa1F6G.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-master.layout-D-lIn4Pl.mjs → acorex-modules-auth-master.layout-CGQmSlGQ.mjs} +5 -5
- package/fesm2022/{acorex-modules-auth-master.layout-D-lIn4Pl.mjs.map → acorex-modules-auth-master.layout-CGQmSlGQ.mjs.map} +1 -1
- package/fesm2022/acorex-modules-auth-oauth-callback.component-m9YiJ4e9.mjs +97 -0
- package/fesm2022/acorex-modules-auth-oauth-callback.component-m9YiJ4e9.mjs.map +1 -0
- package/fesm2022/{acorex-modules-auth-password.component-CafZfqKe.mjs → acorex-modules-auth-password.component-Cb3FJ1DZ.mjs} +9 -9
- package/fesm2022/{acorex-modules-auth-password.component-CafZfqKe.mjs.map → acorex-modules-auth-password.component-Cb3FJ1DZ.mjs.map} +1 -1
- package/fesm2022/acorex-modules-auth-password.component-CiWdX7f_.mjs +226 -0
- package/fesm2022/acorex-modules-auth-password.component-CiWdX7f_.mjs.map +1 -0
- package/fesm2022/{acorex-modules-auth-routes-D9-qfC3V.mjs → acorex-modules-auth-routes-pae8qpX9.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-routes-D9-qfC3V.mjs.map → acorex-modules-auth-routes-pae8qpX9.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-tenant-chooser.component-B1aE-TOD.mjs → acorex-modules-auth-tenant-chooser.component-Bk0l3XoV.mjs} +21 -12
- package/fesm2022/acorex-modules-auth-tenant-chooser.component-Bk0l3XoV.mjs.map +1 -0
- package/fesm2022/{acorex-modules-auth-two-factor-code.component-BglerlU-.mjs → acorex-modules-auth-two-factor-code.component-DDEIajiI.mjs} +8 -8
- package/fesm2022/{acorex-modules-auth-two-factor-code.component-BglerlU-.mjs.map → acorex-modules-auth-two-factor-code.component-DDEIajiI.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-two-factor.module-D3N2XyOH.mjs → acorex-modules-auth-two-factor.module-DtcoHPH4.mjs} +7 -7
- package/fesm2022/{acorex-modules-auth-two-factor.module-D3N2XyOH.mjs.map → acorex-modules-auth-two-factor.module-DtcoHPH4.mjs.map} +1 -1
- package/fesm2022/acorex-modules-auth-user-sessions.component-sI6P2joA.mjs +135 -0
- package/fesm2022/acorex-modules-auth-user-sessions.component-sI6P2joA.mjs.map +1 -0
- 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 +1611 -1308
- 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 +180 -73
- 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-branch.entity-CHp5WtIF.mjs.map +1 -1
- package/fesm2022/acorex-modules-organization-management-department.entity-BxCyXNtv.mjs.map +1 -1
- package/fesm2022/acorex-modules-organization-management-division.entity-DzQT2jpz.mjs.map +1 -1
- package/fesm2022/acorex-modules-organization-management-employee.entity-CSY_U9Bl.mjs.map +1 -1
- package/fesm2022/acorex-modules-organization-management-employment-type.entity-h9Hua7Xe.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-position-category.entity-CIir9UMg.mjs.map +1 -1
- package/fesm2022/acorex-modules-organization-management-position.entity-BpkjUsoZ.mjs.map +1 -1
- package/fesm2022/acorex-modules-organization-management-responsibility-category.entity-tJFpEylO.mjs.map +1 -1
- package/fesm2022/acorex-modules-organization-management-responsibility.entity-DmKSoxpL.mjs.map +1 -1
- package/fesm2022/acorex-modules-organization-management-role-category.entity-CAljzQcH.mjs.map +1 -1
- 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-skill-category.entity-iIbc-pjJ.mjs.map +1 -1
- package/fesm2022/acorex-modules-organization-management-skill.entity-DoAsCzm9.mjs.map +1 -1
- package/fesm2022/acorex-modules-organization-management-team.entity-DMCfAZsr.mjs.map +1 -1
- 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 +830 -258
- 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-enYapFRb.mjs → acorex-modules-workflow-management-acorex-modules-workflow-management-DC7jdoqZ.mjs} +64 -33
- package/fesm2022/acorex-modules-workflow-management-acorex-modules-workflow-management-DC7jdoqZ.mjs.map +1 -0
- package/fesm2022/{acorex-modules-workflow-management-task-board.page-CPL7HwN4.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 +79 -60
- package/package.json +20 -8
- package/security-management/index.d.ts +13 -4
- package/task-management/README.md +189 -0
- package/task-management/index.d.ts +320 -0
- package/workflow-management/index.d.ts +10 -5
- package/fesm2022/acorex-modules-auth-acorex-modules-auth-y6rICHrT.mjs.map +0 -1
- package/fesm2022/acorex-modules-auth-app-chooser.component-Cpy0VN6n.mjs.map +0 -1
- package/fesm2022/acorex-modules-auth-password.component-DLCb0_6e.mjs +0 -134
- package/fesm2022/acorex-modules-auth-password.component-DLCb0_6e.mjs.map +0 -1
- package/fesm2022/acorex-modules-auth-tenant-chooser.component-B1aE-TOD.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-enYapFRb.mjs.map +0 -1
- package/fesm2022/acorex-modules-workflow-management-task-board.page-CPL7HwN4.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,16 +55,14 @@ 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
64
|
import { AXToastService } from '@acorex/components/toast';
|
|
64
65
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
65
|
-
import { AXMUsersEntityService } from '@acorex/modules/security-management';
|
|
66
66
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
67
67
|
import { AXBasePageComponent } from '@acorex/components/page';
|
|
68
68
|
import { AXDomChangeDirective } from '@acorex/cdk/dom';
|
|
@@ -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,1352 +932,1527 @@ 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
|
-
|
|
943
|
-
class AXMCommentService {
|
|
942
|
+
class AXMChatRealtimeService {
|
|
944
943
|
}
|
|
945
|
-
|
|
946
|
-
class AXMCommentServiceImpl {
|
|
944
|
+
class AXMChatRealtimeServiceImpl extends AXMChatRealtimeService {
|
|
947
945
|
constructor() {
|
|
948
|
-
|
|
949
|
-
this.
|
|
950
|
-
this.
|
|
951
|
-
this.
|
|
952
|
-
this.
|
|
953
|
-
this.
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
this.
|
|
957
|
-
this.commentAdded$ = this._commentAdded$.asObservable();
|
|
958
|
-
this._commentRemoved$ = new Subject();
|
|
959
|
-
this.commentRemoved$ = this._commentRemoved$.asObservable();
|
|
960
|
-
this._commentUpdated$ = new Subject();
|
|
961
|
-
this.commentUpdated$ = this._commentUpdated$.asObservable();
|
|
962
|
-
this._threadAdded$ = new Subject();
|
|
963
|
-
this.threadAdded$ = this._threadAdded$.asObservable();
|
|
964
|
-
this._threadRemoved$ = new Subject();
|
|
965
|
-
this.threadRemoved$ = this._threadRemoved$.asObservable();
|
|
966
|
-
}
|
|
967
|
-
//#endregion
|
|
968
|
-
//#region ---- Helper Methods ----
|
|
969
|
-
getCurrentUser() {
|
|
970
|
-
const user = this.sessionService.user;
|
|
971
|
-
if (!user) {
|
|
972
|
-
throw new Error('No authenticated user found.');
|
|
973
|
-
}
|
|
974
|
-
return {
|
|
975
|
-
id: user.id,
|
|
976
|
-
type: 'user',
|
|
977
|
-
};
|
|
946
|
+
super(...arguments);
|
|
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();
|
|
978
955
|
}
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
await this.usersService.getOne(userId); // check if user exists
|
|
982
|
-
return { id: userId, type: 'user' };
|
|
983
|
-
}
|
|
984
|
-
catch {
|
|
985
|
-
throw new Error(`User with ID ${userId} not found`);
|
|
986
|
-
}
|
|
956
|
+
notifyRoom(event) {
|
|
957
|
+
this._room$.next(event);
|
|
987
958
|
}
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
...message,
|
|
991
|
-
depth,
|
|
992
|
-
replies: [],
|
|
993
|
-
replyCount: 0,
|
|
994
|
-
};
|
|
959
|
+
notifyMessage(event) {
|
|
960
|
+
this._message$.next(event);
|
|
995
961
|
}
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
const tree = [];
|
|
999
|
-
comments.forEach((comment) => {
|
|
1000
|
-
if (comment.replyId && commentMap.has(comment.replyId)) {
|
|
1001
|
-
const parent = commentMap.get(comment.replyId);
|
|
1002
|
-
parent.replies.push(comment);
|
|
1003
|
-
comment.depth = parent.depth + 1;
|
|
1004
|
-
}
|
|
1005
|
-
else {
|
|
1006
|
-
tree.push(comment);
|
|
1007
|
-
}
|
|
1008
|
-
});
|
|
1009
|
-
commentMap.forEach((comment) => {
|
|
1010
|
-
comment.replyCount = comment.replies.length;
|
|
1011
|
-
});
|
|
1012
|
-
return tree;
|
|
962
|
+
notifyTab(event) {
|
|
963
|
+
this._tab$.next(event);
|
|
1013
964
|
}
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
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 });
|
|
970
|
+
}
|
|
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' }); }
|
|
973
|
+
}
|
|
974
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMChatRealtimeServiceImpl, decorators: [{
|
|
975
|
+
type: Injectable,
|
|
976
|
+
args: [{
|
|
977
|
+
providedIn: 'root',
|
|
978
|
+
}]
|
|
979
|
+
}] });
|
|
980
|
+
|
|
981
|
+
class AXMChatService {
|
|
982
|
+
}
|
|
983
|
+
class AXMChatServiceImpl {
|
|
984
|
+
constructor() {
|
|
985
|
+
this.roomService = inject(AXMRoomService);
|
|
986
|
+
this.messageService = inject(AXMMessageService);
|
|
987
|
+
this.tabService = inject(AXMConversationTabService);
|
|
988
|
+
}
|
|
989
|
+
createRoom(members, title, currentUser) {
|
|
1018
990
|
const room = {
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
members: [currentUser],
|
|
1023
|
-
entityRef: entityRef,
|
|
1024
|
-
createdBy: currentUser.id,
|
|
991
|
+
members,
|
|
992
|
+
title: title,
|
|
993
|
+
topic: members.length > 2 ? 'group' : 'personal',
|
|
1025
994
|
createdAt: new Date(),
|
|
995
|
+
updatedAt: new Date(),
|
|
996
|
+
type: 'chat',
|
|
997
|
+
createdBy: currentUser.id,
|
|
998
|
+
updatedBy: currentUser.id,
|
|
1026
999
|
};
|
|
1027
|
-
|
|
1028
|
-
const newThread = await this.getThread(entityRef, topic);
|
|
1029
|
-
if (!newThread) {
|
|
1030
|
-
throw new Error('Failed to create or retrieve thread after creation.');
|
|
1031
|
-
}
|
|
1032
|
-
this._threadAdded$.next(newThread);
|
|
1033
|
-
return newThread;
|
|
1000
|
+
return this.roomService.insertOne(room).then((id) => this.roomService.getOne(id));
|
|
1034
1001
|
}
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
skip: 0,
|
|
1038
|
-
take: 1,
|
|
1039
|
-
filter: {
|
|
1040
|
-
logic: 'and',
|
|
1041
|
-
filters: [
|
|
1042
|
-
{
|
|
1043
|
-
field: 'entityRef.id',
|
|
1044
|
-
value: entityRef.id,
|
|
1045
|
-
operator: this.filterService.getOperator('equal'),
|
|
1046
|
-
},
|
|
1047
|
-
{
|
|
1048
|
-
field: 'entityRef.type',
|
|
1049
|
-
value: entityRef.type,
|
|
1050
|
-
operator: this.filterService.getOperator('equal'),
|
|
1051
|
-
},
|
|
1052
|
-
{
|
|
1053
|
-
field: 'topic',
|
|
1054
|
-
value: topic,
|
|
1055
|
-
operator: this.filterService.getOperator('equal'),
|
|
1056
|
-
},
|
|
1057
|
-
],
|
|
1058
|
-
},
|
|
1059
|
-
});
|
|
1060
|
-
const room = items[0];
|
|
1061
|
-
if (!room) {
|
|
1062
|
-
return null;
|
|
1063
|
-
}
|
|
1064
|
-
const comments = await this.getComments(room.id, true);
|
|
1065
|
-
return {
|
|
1066
|
-
...room,
|
|
1067
|
-
comments,
|
|
1068
|
-
commentCount: comments.length,
|
|
1069
|
-
};
|
|
1002
|
+
getRoom(roomId) {
|
|
1003
|
+
return this.roomService.getOne(roomId);
|
|
1070
1004
|
}
|
|
1071
|
-
async
|
|
1072
|
-
|
|
1073
|
-
skip
|
|
1074
|
-
take
|
|
1075
|
-
filter: {
|
|
1076
|
-
logic: 'and',
|
|
1077
|
-
filters: [
|
|
1078
|
-
{
|
|
1079
|
-
field: 'entityRef.id',
|
|
1080
|
-
value: entityRef.id,
|
|
1081
|
-
operator: this.filterService.getOperator('equal'),
|
|
1082
|
-
},
|
|
1083
|
-
{
|
|
1084
|
-
field: 'entityRef.type',
|
|
1085
|
-
value: entityRef.type,
|
|
1086
|
-
operator: this.filterService.getOperator('equal'),
|
|
1087
|
-
},
|
|
1088
|
-
{
|
|
1089
|
-
field: 'topic',
|
|
1090
|
-
value: topic,
|
|
1091
|
-
operator: this.filterService.getOperator('equal'),
|
|
1092
|
-
},
|
|
1093
|
-
],
|
|
1094
|
-
},
|
|
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' } },
|
|
1095
1010
|
});
|
|
1096
|
-
const threads = await Promise.all(items.map((room) => this.getThread(room.entityRef, room.topic)));
|
|
1097
|
-
return threads.filter((t) => t !== null);
|
|
1098
1011
|
}
|
|
1099
|
-
|
|
1100
|
-
const
|
|
1101
|
-
|
|
1102
|
-
throw new Error(`Thread for entity ${entityRef.type}#${entityRef.id} not found.`);
|
|
1103
|
-
}
|
|
1104
|
-
await this.roomService.updateOne(thread.id, data);
|
|
1105
|
-
const updatedThread = await this.getThread(entityRef, topic);
|
|
1106
|
-
if (!updatedThread) {
|
|
1107
|
-
throw new Error('Failed to retrieve thread after update.');
|
|
1108
|
-
}
|
|
1109
|
-
return updatedThread;
|
|
1012
|
+
updateRoom(roomId, data, currentUser) {
|
|
1013
|
+
const update = { ...data, updatedAt: new Date(), updatedBy: currentUser.id };
|
|
1014
|
+
return this.roomService.updateOne(roomId, update);
|
|
1110
1015
|
}
|
|
1111
|
-
async
|
|
1112
|
-
|
|
1113
|
-
if (thread) {
|
|
1114
|
-
await this.roomService.deleteOne(thread.id);
|
|
1115
|
-
this._threadRemoved$.next(thread.id);
|
|
1116
|
-
}
|
|
1016
|
+
async deleteRoom(roomId) {
|
|
1017
|
+
await this.roomService.deleteOne(roomId);
|
|
1117
1018
|
return true;
|
|
1118
1019
|
}
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
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) {
|
|
1123
1037
|
const messageContent = { content, contentType };
|
|
1124
1038
|
const message = {
|
|
1125
|
-
roomId
|
|
1039
|
+
roomId,
|
|
1126
1040
|
message: messageContent,
|
|
1127
1041
|
author,
|
|
1128
|
-
replyId
|
|
1042
|
+
replyId,
|
|
1043
|
+
createdAt: new Date(),
|
|
1044
|
+
updatedAt: new Date(),
|
|
1045
|
+
createdBy: author.id,
|
|
1046
|
+
updatedBy: author.id,
|
|
1129
1047
|
reactions: [],
|
|
1130
1048
|
seen: [],
|
|
1131
|
-
createdBy: author.id,
|
|
1132
|
-
createdAt: new Date(),
|
|
1133
1049
|
};
|
|
1134
|
-
|
|
1135
|
-
const newComment = await this.getComment(messageId);
|
|
1136
|
-
this._commentAdded$.next(newComment);
|
|
1137
|
-
return newComment;
|
|
1050
|
+
return this.messageService.insertOne({ ...message }).then((id) => this.messageService.getOne(id));
|
|
1138
1051
|
}
|
|
1139
|
-
async
|
|
1140
|
-
|
|
1141
|
-
skip
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
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' }],
|
|
1145
1058
|
});
|
|
1146
|
-
const formattedComments = items.map((c) => this.formatComment(c));
|
|
1147
|
-
if (nested) {
|
|
1148
|
-
return this.buildCommentTree(formattedComments);
|
|
1149
|
-
}
|
|
1150
|
-
return formattedComments;
|
|
1151
1059
|
}
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
return this.formatComment(message);
|
|
1060
|
+
getMessage(messageId) {
|
|
1061
|
+
return this.messageService.getOne(messageId);
|
|
1155
1062
|
}
|
|
1156
|
-
|
|
1063
|
+
editMessage(messageId, content, currentUser, contentType = 'text') {
|
|
1157
1064
|
const messageContent = { content, contentType };
|
|
1158
|
-
|
|
1065
|
+
return this.messageService.updateOne(messageId, {
|
|
1159
1066
|
message: messageContent,
|
|
1160
1067
|
updatedAt: new Date(),
|
|
1161
|
-
updatedBy:
|
|
1068
|
+
updatedBy: currentUser.id,
|
|
1162
1069
|
});
|
|
1163
|
-
const updatedComment = await this.getComment(commentId);
|
|
1164
|
-
this._commentUpdated$.next(updatedComment);
|
|
1165
|
-
return updatedComment;
|
|
1166
1070
|
}
|
|
1167
|
-
async
|
|
1168
|
-
|
|
1169
|
-
await this.messageService.deleteOne(commentId);
|
|
1170
|
-
this._commentRemoved$.next(commentId);
|
|
1071
|
+
async deleteMessage(messageId) {
|
|
1072
|
+
await this.messageService.deleteOne(messageId);
|
|
1171
1073
|
return true;
|
|
1172
1074
|
}
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
if (reactions.some((r) => r.author.id === author.id && r.type === type)) {
|
|
1180
|
-
return this.formatComment(comment);
|
|
1181
|
-
}
|
|
1182
|
-
const updatedReactions = [...reactions, { author, type }];
|
|
1183
|
-
await this.messageService.updateOne(commentId, { reactions: updatedReactions });
|
|
1184
|
-
const updatedComment = await this.getComment(commentId);
|
|
1185
|
-
this._commentUpdated$.next(updatedComment);
|
|
1186
|
-
return updatedComment;
|
|
1187
|
-
}
|
|
1188
|
-
async removeReaction(commentId, type) {
|
|
1189
|
-
const author = this.getCurrentUser();
|
|
1190
|
-
const comment = await this.messageService.getOne(commentId);
|
|
1191
|
-
const updatedReactions = (comment.reactions || []).filter((r) => !(r.author.id === author.id && r.type === type));
|
|
1192
|
-
await this.messageService.updateOne(commentId, { reactions: updatedReactions });
|
|
1193
|
-
const updatedComment = await this.getComment(commentId);
|
|
1194
|
-
this._commentUpdated$.next(updatedComment);
|
|
1195
|
-
return updatedComment;
|
|
1196
|
-
}
|
|
1197
|
-
async getReactions(commentId) {
|
|
1198
|
-
const comment = await this.messageService.getOne(commentId);
|
|
1199
|
-
return comment.reactions || [];
|
|
1075
|
+
pinMessage(messageId, isPinned, currentUser) {
|
|
1076
|
+
return this.messageService.updateOne(messageId, {
|
|
1077
|
+
isPinned,
|
|
1078
|
+
updatedAt: new Date(),
|
|
1079
|
+
updatedBy: currentUser.id,
|
|
1080
|
+
});
|
|
1200
1081
|
}
|
|
1201
|
-
|
|
1202
|
-
return this.
|
|
1082
|
+
updateReactions(messageId, reactions, currentUser) {
|
|
1083
|
+
return this.messageService.updateOne(messageId, {
|
|
1084
|
+
reactions,
|
|
1085
|
+
updatedAt: new Date(),
|
|
1086
|
+
updatedBy: currentUser.id,
|
|
1087
|
+
});
|
|
1203
1088
|
}
|
|
1204
|
-
|
|
1205
|
-
return this.
|
|
1089
|
+
getReactions(messageId) {
|
|
1090
|
+
return this.messageService.getOne(messageId).then((m) => m.reactions || []);
|
|
1206
1091
|
}
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
return updatedComment;
|
|
1092
|
+
updateSeen(messageId, seen, currentUser) {
|
|
1093
|
+
return this.messageService.updateOne(messageId, {
|
|
1094
|
+
seen,
|
|
1095
|
+
updatedAt: new Date(),
|
|
1096
|
+
updatedBy: currentUser.id,
|
|
1097
|
+
});
|
|
1214
1098
|
}
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
const updatedComment = await this.getComment(commentId);
|
|
1218
|
-
this._commentUpdated$.next(updatedComment);
|
|
1219
|
-
return updatedComment;
|
|
1099
|
+
getSeenBy(messageId) {
|
|
1100
|
+
return this.messageService.getOne(messageId).then((m) => m.seen || []);
|
|
1220
1101
|
}
|
|
1221
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
1222
|
-
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' }); }
|
|
1223
1104
|
}
|
|
1224
|
-
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: [{
|
|
1225
1106
|
type: Injectable,
|
|
1226
1107
|
args: [{
|
|
1227
1108
|
providedIn: 'root',
|
|
1228
1109
|
}]
|
|
1229
1110
|
}] });
|
|
1230
1111
|
|
|
1231
|
-
class
|
|
1112
|
+
class AXMChatManagementService {
|
|
1232
1113
|
constructor() {
|
|
1233
|
-
this.
|
|
1234
|
-
this.refrenceId = input.required(...(ngDevMode ? [{ debugName: "refrenceId" }] : []));
|
|
1235
|
-
this.subject = input.required(...(ngDevMode ? [{ debugName: "subject" }] : []));
|
|
1236
|
-
this.hasCooldown = signal(false, ...(ngDevMode ? [{ debugName: "hasCooldown" }] : []));
|
|
1237
|
-
this.commentContent = signal('', ...(ngDevMode ? [{ debugName: "commentContent" }] : []));
|
|
1238
|
-
this.isSubmitting = signal(false, ...(ngDevMode ? [{ debugName: "isSubmitting" }] : []));
|
|
1239
|
-
this.isReplyingMode = signal(false, ...(ngDevMode ? [{ debugName: "isReplyingMode" }] : []));
|
|
1240
|
-
this.isEditingMode = signal(false, ...(ngDevMode ? [{ debugName: "isEditingMode" }] : []));
|
|
1241
|
-
this.isLoading = signal(true, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
1242
|
-
this.failedImageIds = signal([], ...(ngDevMode ? [{ debugName: "failedImageIds" }] : []));
|
|
1243
|
-
this.activeReplyComment = signal(undefined, ...(ngDevMode ? [{ debugName: "activeReplyComment" }] : []));
|
|
1244
|
-
this.activeEditComment = signal(undefined, ...(ngDevMode ? [{ debugName: "activeEditComment" }] : []));
|
|
1245
|
-
this.highlightedCommentId = signal(null, ...(ngDevMode ? [{ debugName: "highlightedCommentId" }] : []));
|
|
1246
|
-
this.wysiwygEditor = viewChild.required('w');
|
|
1247
|
-
this.commentService = inject(AXMCommentService);
|
|
1114
|
+
this.chatImplService = inject(AXMChatServiceImpl);
|
|
1248
1115
|
this.sessionService = inject(AXPSessionService);
|
|
1249
|
-
this.
|
|
1250
|
-
this.
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
}
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
}
|
|
1116
|
+
this.usersService = inject(AXMUsersEntityService);
|
|
1117
|
+
this.realtimeService = inject(AXMChatRealtimeService);
|
|
1118
|
+
}
|
|
1119
|
+
getCurrentUser() {
|
|
1120
|
+
const user = this.sessionService.user;
|
|
1121
|
+
if (!user) {
|
|
1122
|
+
throw new Error('No authenticated user found.');
|
|
1123
|
+
}
|
|
1124
|
+
return {
|
|
1125
|
+
id: user.id,
|
|
1126
|
+
type: 'user',
|
|
1127
|
+
fullName: user.title?.trim(),
|
|
1128
|
+
username: user.name?.trim(),
|
|
1129
|
+
};
|
|
1130
|
+
}
|
|
1131
|
+
async getUserInfo(userId) {
|
|
1132
|
+
try {
|
|
1133
|
+
const user = await this.usersService.getOne(userId);
|
|
1268
1134
|
return {
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1135
|
+
id: user.id,
|
|
1136
|
+
type: 'user',
|
|
1137
|
+
fullName: `${user.firstName} ${user.lastName}`.trim(),
|
|
1138
|
+
username: user.username?.trim(),
|
|
1273
1139
|
};
|
|
1274
|
-
}
|
|
1140
|
+
}
|
|
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
|
+
};
|
|
1149
|
+
}
|
|
1275
1150
|
}
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
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;
|
|
1160
|
+
}
|
|
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;
|
|
1282
1168
|
});
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
});
|
|
1169
|
+
return unreadMessages.length;
|
|
1170
|
+
}
|
|
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;
|
|
1294
1179
|
}
|
|
1295
|
-
|
|
1296
|
-
|
|
1180
|
+
return this.getUserInfo(member.id);
|
|
1181
|
+
}));
|
|
1182
|
+
return {
|
|
1183
|
+
...room,
|
|
1184
|
+
lastMessage,
|
|
1185
|
+
unreadCount,
|
|
1186
|
+
members: members.filter((m) => m.id !== currentUserId),
|
|
1187
|
+
};
|
|
1188
|
+
}
|
|
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
|
+
}
|
|
1193
|
+
const currentUser = this.getCurrentUser();
|
|
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;
|
|
1200
|
+
}
|
|
1201
|
+
async getRoom(roomId) {
|
|
1202
|
+
const room = await this.chatImplService.getRoom(roomId);
|
|
1203
|
+
if (!room) {
|
|
1204
|
+
throw new Error(`Chat room with ID ${roomId} not found.`);
|
|
1205
|
+
}
|
|
1206
|
+
return this.formatRoom(room);
|
|
1207
|
+
}
|
|
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;
|
|
1297
1216
|
}
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
if (c.id === updatedComment.id) {
|
|
1303
|
-
return { ...c, ...updatedComment, replies: updatedComment.replies || c.replies };
|
|
1304
|
-
}
|
|
1305
|
-
if (c.replies && c.replies.length > 0) {
|
|
1306
|
-
return { ...c, replies: update(c.replies) };
|
|
1307
|
-
}
|
|
1308
|
-
return c;
|
|
1309
|
-
});
|
|
1310
|
-
};
|
|
1311
|
-
this.comments.update((comments) => update(comments));
|
|
1312
|
-
});
|
|
1217
|
+
return true;
|
|
1218
|
+
})
|
|
1219
|
+
.map((result) => result.value);
|
|
1220
|
+
return { items: chatRooms, total: chatRooms.length };
|
|
1313
1221
|
}
|
|
1314
|
-
|
|
1315
|
-
const
|
|
1316
|
-
return
|
|
1222
|
+
async updateRoom(roomId, data) {
|
|
1223
|
+
const currentUser = this.getCurrentUser();
|
|
1224
|
+
return this.chatImplService.updateRoom(roomId, data, currentUser);
|
|
1317
1225
|
}
|
|
1318
|
-
|
|
1319
|
-
const
|
|
1320
|
-
if (
|
|
1321
|
-
|
|
1322
|
-
|
|
1226
|
+
async deleteRoom(roomId) {
|
|
1227
|
+
const result = await this.chatImplService.deleteRoom(roomId);
|
|
1228
|
+
if (result) {
|
|
1229
|
+
this.realtimeService.notifyRoom({ type: 'remove', payload: roomId });
|
|
1230
|
+
}
|
|
1231
|
+
return result;
|
|
1323
1232
|
}
|
|
1324
|
-
|
|
1325
|
-
|
|
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);
|
|
1326
1241
|
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
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);
|
|
1331
1247
|
}
|
|
1332
|
-
|
|
1333
|
-
this.
|
|
1248
|
+
async createTab(data) {
|
|
1249
|
+
const newTab = await this.chatImplService.createTab(data);
|
|
1250
|
+
this.realtimeService.notifyTab({ type: 'add', payload: newTab });
|
|
1251
|
+
return newTab;
|
|
1334
1252
|
}
|
|
1335
|
-
|
|
1336
|
-
return
|
|
1253
|
+
getTab(tabId) {
|
|
1254
|
+
return this.chatImplService.getTab(tabId);
|
|
1337
1255
|
}
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
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 });
|
|
1266
|
+
}
|
|
1267
|
+
return result;
|
|
1268
|
+
}
|
|
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
|
+
}
|
|
1279
|
+
}
|
|
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 });
|
|
1344
1287
|
}
|
|
1345
1288
|
else {
|
|
1346
|
-
|
|
1347
|
-
this.thread.set(undefined);
|
|
1289
|
+
throw new Error(`${tabId} tab does not include room with ID ${roomId}.`);
|
|
1348
1290
|
}
|
|
1349
1291
|
}
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
this.toastService.show({
|
|
1353
|
-
content: 'Failed to load comments. Please try again.',
|
|
1354
|
-
color: 'danger',
|
|
1355
|
-
location: 'bottom-center',
|
|
1356
|
-
closeButton: true,
|
|
1357
|
-
timeOut: 3000,
|
|
1358
|
-
timeOutProgress: true,
|
|
1359
|
-
});
|
|
1360
|
-
this.comments.set([]);
|
|
1292
|
+
else {
|
|
1293
|
+
throw new Error(`Tab with ID ${tabId} or room with ID ${roomId} not found.`);
|
|
1361
1294
|
}
|
|
1362
1295
|
}
|
|
1363
|
-
|
|
1364
|
-
this.
|
|
1365
|
-
this.
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
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
|
+
}
|
|
1371
1306
|
}
|
|
1372
|
-
|
|
1373
|
-
this.
|
|
1374
|
-
this.
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
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.`);
|
|
1383
1321
|
}
|
|
1384
|
-
this.wysiwygEditor().getHostElement().scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
1385
1322
|
}
|
|
1386
|
-
async
|
|
1387
|
-
const
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
orientation: 'horizontal',
|
|
1393
|
-
buttons: [
|
|
1394
|
-
{
|
|
1395
|
-
text: 'Delete',
|
|
1396
|
-
color: 'danger',
|
|
1397
|
-
onClick: async (e) => {
|
|
1398
|
-
e.handled = true;
|
|
1399
|
-
e.source.text = 'Deleting...';
|
|
1400
|
-
e.source.disabled = true;
|
|
1401
|
-
e.source.loading = true;
|
|
1402
|
-
try {
|
|
1403
|
-
await this.commentService.deleteComment(commentId);
|
|
1404
|
-
this.removeMessageById(commentId);
|
|
1405
|
-
this.toastService.show({
|
|
1406
|
-
content: 'Comment deleted successfully.',
|
|
1407
|
-
color: 'success',
|
|
1408
|
-
location: 'bottom-center',
|
|
1409
|
-
closeButton: true,
|
|
1410
|
-
timeOut: 3000,
|
|
1411
|
-
timeOutProgress: true,
|
|
1412
|
-
});
|
|
1413
|
-
if (this.isEditingMode() && this.activeEditComment()?.id === commentId) {
|
|
1414
|
-
this.resetReplyEditState();
|
|
1415
|
-
}
|
|
1416
|
-
dialog.close();
|
|
1417
|
-
}
|
|
1418
|
-
catch (error) {
|
|
1419
|
-
this.toastService.show({
|
|
1420
|
-
content: typeof error === 'string' ? error : 'Failed to delete comment!',
|
|
1421
|
-
color: 'danger',
|
|
1422
|
-
location: 'bottom-center',
|
|
1423
|
-
closeButton: true,
|
|
1424
|
-
timeOut: 3000,
|
|
1425
|
-
timeOutProgress: true,
|
|
1426
|
-
});
|
|
1427
|
-
}
|
|
1428
|
-
},
|
|
1429
|
-
},
|
|
1430
|
-
{
|
|
1431
|
-
text: 'Cancel',
|
|
1432
|
-
color: 'default',
|
|
1433
|
-
autofocus: true,
|
|
1434
|
-
onClick: (e) => {
|
|
1435
|
-
dialog.close();
|
|
1436
|
-
},
|
|
1437
|
-
},
|
|
1438
|
-
],
|
|
1439
|
-
closeButton: false,
|
|
1440
|
-
});
|
|
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;
|
|
1441
1329
|
}
|
|
1442
|
-
|
|
1443
|
-
this.
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
this.activeReplyComment.set(undefined);
|
|
1447
|
-
this.commentContent.set('');
|
|
1448
|
-
document.getElementsByClassName('ql-editor')[0].innerHTML = '';
|
|
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 };
|
|
1449
1334
|
}
|
|
1450
|
-
async
|
|
1451
|
-
const
|
|
1452
|
-
this.
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
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);
|
|
1347
|
+
if (result) {
|
|
1348
|
+
this.realtimeService.notifyMessage({ type: 'remove', payload: messageId });
|
|
1460
1349
|
}
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1350
|
+
return result;
|
|
1351
|
+
}
|
|
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) {
|
|
1365
|
+
const author = this.getCurrentUser();
|
|
1366
|
+
const message = await this.chatImplService.getMessage(messageId);
|
|
1367
|
+
const reactions = message.reactions || [];
|
|
1368
|
+
if (reactions.some((r) => r.author.id === author.id && r.type === type)) {
|
|
1369
|
+
return message;
|
|
1464
1370
|
}
|
|
1371
|
+
const updatedReactions = [...reactions, { author, type }];
|
|
1372
|
+
const res = await this.chatImplService.updateReactions(messageId, updatedReactions, author);
|
|
1373
|
+
this.realtimeService.notifyMessage({ type: 'update', payload: await this.formatMessage(res) });
|
|
1374
|
+
return res;
|
|
1465
1375
|
}
|
|
1466
|
-
|
|
1467
|
-
const
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
let reactions = c.reactions || [];
|
|
1474
|
-
if (willBeLiked) {
|
|
1475
|
-
reactions.push({ author: user, type: 'like' });
|
|
1476
|
-
}
|
|
1477
|
-
else {
|
|
1478
|
-
reactions = reactions.filter((r) => r.author.id !== user.id || r.type !== 'like');
|
|
1479
|
-
}
|
|
1480
|
-
return { ...c, reactions };
|
|
1481
|
-
}
|
|
1482
|
-
if (c.replies && c.replies.length > 0) {
|
|
1483
|
-
c.replies = findAndToggle(c.replies);
|
|
1484
|
-
}
|
|
1485
|
-
return c;
|
|
1486
|
-
});
|
|
1487
|
-
};
|
|
1488
|
-
this.comments.update((comments) => findAndToggle(comments));
|
|
1376
|
+
async removeReaction(messageId, type) {
|
|
1377
|
+
const author = this.getCurrentUser();
|
|
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;
|
|
1489
1383
|
}
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
return comments
|
|
1493
|
-
.filter((c) => c.id !== commentId)
|
|
1494
|
-
.map((c) => {
|
|
1495
|
-
if (c.replies && c.replies.length > 0) {
|
|
1496
|
-
c.replies = filterOut(c.replies);
|
|
1497
|
-
}
|
|
1498
|
-
return c;
|
|
1499
|
-
});
|
|
1500
|
-
};
|
|
1501
|
-
this.comments.update((comments) => filterOut(comments));
|
|
1384
|
+
async getReactions(messageId) {
|
|
1385
|
+
return this.chatImplService.getReactions(messageId);
|
|
1502
1386
|
}
|
|
1503
|
-
async
|
|
1504
|
-
|
|
1505
|
-
|
|
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;
|
|
1506
1393
|
}
|
|
1507
|
-
|
|
1508
|
-
|
|
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;
|
|
1398
|
+
}
|
|
1399
|
+
async getSeenBy(messageId) {
|
|
1400
|
+
return this.chatImplService.getSeenBy(messageId);
|
|
1401
|
+
}
|
|
1402
|
+
async markRoomSeen(roomId) {
|
|
1509
1403
|
try {
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
currentThread = await this.commentService.createThread({ type: this.refrenceType(), id: this.refrenceId() }, this.subject());
|
|
1513
|
-
this.thread.set(currentThread);
|
|
1514
|
-
}
|
|
1515
|
-
if (this.isEditingMode() && this.activeEditComment()?.id) {
|
|
1516
|
-
await this.commentService.editComment(this.activeEditComment().id, this.commentContent());
|
|
1517
|
-
this.hasCooldown.set(true);
|
|
1518
|
-
this.isEditingMode.set(false);
|
|
1519
|
-
this.activeEditComment.set(undefined);
|
|
1404
|
+
if (!roomId) {
|
|
1405
|
+
return true;
|
|
1520
1406
|
}
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
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)));
|
|
1526
1412
|
}
|
|
1527
|
-
this.
|
|
1528
|
-
|
|
1529
|
-
setTimeout(() => {
|
|
1530
|
-
this.hasCooldown.set(false);
|
|
1531
|
-
}, 1000);
|
|
1413
|
+
this.realtimeService.notifyRoom({ type: 'seen', payload: roomId });
|
|
1414
|
+
return true;
|
|
1532
1415
|
}
|
|
1533
1416
|
catch (error) {
|
|
1534
|
-
console.error(
|
|
1535
|
-
|
|
1536
|
-
content: typeof error === 'string' ? error : 'Failed to submit comment. Please try again.',
|
|
1537
|
-
color: 'danger',
|
|
1538
|
-
location: 'bottom-center',
|
|
1539
|
-
closeButton: true,
|
|
1540
|
-
timeOut: 3000,
|
|
1541
|
-
timeOutProgress: true,
|
|
1542
|
-
});
|
|
1543
|
-
}
|
|
1544
|
-
finally {
|
|
1545
|
-
this.isSubmitting.set(false);
|
|
1417
|
+
console.error(`Error marking room ${roomId} as seen:`, error);
|
|
1418
|
+
return false;
|
|
1546
1419
|
}
|
|
1547
1420
|
}
|
|
1548
|
-
|
|
1549
|
-
const
|
|
1550
|
-
|
|
1551
|
-
const el = document.getElementById(comment.id);
|
|
1552
|
-
if (el) {
|
|
1553
|
-
el.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
1554
|
-
this.highlightedCommentId.set(comment.id);
|
|
1555
|
-
setTimeout(() => {
|
|
1556
|
-
this.highlightedCommentId.set(null);
|
|
1557
|
-
}, 1000);
|
|
1558
|
-
}
|
|
1559
|
-
}
|
|
1421
|
+
async startTyping(roomId, userId) {
|
|
1422
|
+
const user = userId ? await this.getUserInfo(userId) : this.getCurrentUser();
|
|
1423
|
+
this.realtimeService.startTyping(user, roomId);
|
|
1560
1424
|
}
|
|
1561
|
-
|
|
1562
|
-
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: [
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
]),
|
|
1568
|
-
]),
|
|
1569
|
-
], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1425
|
+
async stopTyping(roomId, userId) {
|
|
1426
|
+
const user = userId ? await this.getUserInfo(userId) : this.getCurrentUser();
|
|
1427
|
+
this.realtimeService.stopTyping(user, roomId);
|
|
1428
|
+
}
|
|
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' }); }
|
|
1570
1431
|
}
|
|
1571
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
1572
|
-
type:
|
|
1573
|
-
args: [{
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
style({ opacity: 0, transform: 'translateY(10px)' }),
|
|
1577
|
-
animate('300ms ease-out', style({ opacity: 1, transform: 'translateY(0)' })),
|
|
1578
|
-
]),
|
|
1579
|
-
]),
|
|
1580
|
-
], imports: [
|
|
1581
|
-
AXWysiwygModule,
|
|
1582
|
-
AXConversationModule,
|
|
1583
|
-
AXSkeletonModule,
|
|
1584
|
-
AXDecoratorModule,
|
|
1585
|
-
AXCommentModule,
|
|
1586
|
-
AXButtonModule,
|
|
1587
|
-
AXAvatarModule,
|
|
1588
|
-
AXImageModule,
|
|
1589
|
-
AXLoadingModule,
|
|
1590
|
-
AXDropdownModule,
|
|
1591
|
-
AXFormatModule,
|
|
1592
|
-
AsyncPipe,
|
|
1593
|
-
AXFormModule,
|
|
1594
|
-
AXToolBarModule,
|
|
1595
|
-
FormsModule,
|
|
1596
|
-
AXDropdownButtonModule,
|
|
1597
|
-
AXPUserAvatarComponent,
|
|
1598
|
-
], 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"] }]
|
|
1432
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMChatManagementService, decorators: [{
|
|
1433
|
+
type: Injectable,
|
|
1434
|
+
args: [{
|
|
1435
|
+
providedIn: 'root',
|
|
1436
|
+
}]
|
|
1599
1437
|
}] });
|
|
1600
1438
|
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
});
|
|
1605
|
-
|
|
1606
|
-
class AXMCommentPopupComponent extends AXBasePageComponent {
|
|
1439
|
+
class AXMCommentRealtimeService {
|
|
1440
|
+
}
|
|
1441
|
+
class AXMCommentRealtimeServiceImpl extends AXMCommentRealtimeService {
|
|
1607
1442
|
constructor() {
|
|
1608
1443
|
super(...arguments);
|
|
1609
|
-
this.
|
|
1610
|
-
this.
|
|
1611
|
-
this.
|
|
1444
|
+
this._comment$ = new Subject();
|
|
1445
|
+
this.comment$ = this._comment$.asObservable();
|
|
1446
|
+
this._thread$ = new Subject();
|
|
1447
|
+
this.thread$ = this._thread$.asObservable();
|
|
1612
1448
|
}
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
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' }); }
|
|
1621
1457
|
}
|
|
1622
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
1623
|
-
type:
|
|
1624
|
-
args: [{
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
// ACoreX
|
|
1628
|
-
AXDecoratorModule,
|
|
1629
|
-
AXButtonModule,
|
|
1630
|
-
AXTranslationModule,
|
|
1631
|
-
// Comment
|
|
1632
|
-
AXMCommentComponent,
|
|
1633
|
-
], 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" }]
|
|
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
|
+
}]
|
|
1634
1463
|
}] });
|
|
1635
1464
|
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
class AXMUserLookupPopup extends AXBasePageComponent {
|
|
1465
|
+
//#region ---- Abstract Comment Service ----
|
|
1466
|
+
class AXMCommentService {
|
|
1467
|
+
}
|
|
1468
|
+
//#endregion
|
|
1469
|
+
class AXMCommentServiceImpl {
|
|
1642
1470
|
constructor() {
|
|
1643
|
-
|
|
1644
|
-
this.
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
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(),
|
|
1484
|
+
};
|
|
1485
|
+
const newRoomId = await this.roomService.insertOne(room);
|
|
1486
|
+
return this.roomService.getOne(newRoomId);
|
|
1487
|
+
}
|
|
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'),
|
|
1656
1499
|
},
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
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
|
+
],
|
|
1661
1511
|
},
|
|
1662
|
-
};
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1512
|
+
});
|
|
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'),
|
|
1675
1526
|
},
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
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
|
+
],
|
|
1680
1538
|
},
|
|
1539
|
+
});
|
|
1540
|
+
return items;
|
|
1541
|
+
}
|
|
1542
|
+
async updateThread(threadId, data) {
|
|
1543
|
+
await this.roomService.updateOne(threadId, data);
|
|
1544
|
+
return this.roomService.getOne(threadId);
|
|
1545
|
+
}
|
|
1546
|
+
async deleteThread(threadId) {
|
|
1547
|
+
await this.roomService.deleteOne(threadId);
|
|
1548
|
+
return true;
|
|
1549
|
+
}
|
|
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(),
|
|
1681
1561
|
};
|
|
1682
|
-
|
|
1562
|
+
const messageId = await this.messageService.insertOne(message);
|
|
1563
|
+
return this.messageService.getOne(messageId);
|
|
1683
1564
|
}
|
|
1684
|
-
|
|
1685
|
-
this.
|
|
1686
|
-
|
|
1687
|
-
|
|
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,
|
|
1688
1571
|
});
|
|
1572
|
+
return items;
|
|
1689
1573
|
}
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
<div class="ax-p-4 ax-flex ax-flex-col ax-gap-4">
|
|
1693
|
-
<ng-container axp-widget-renderer [node]="lookupNode" [mode]="'edit'"> </ng-container>
|
|
1694
|
-
@if (context()?.lookup?.length > 1) {
|
|
1695
|
-
<ng-container axp-widget-renderer [node]="titleNode" [mode]="'edit'"> </ng-container>
|
|
1696
|
-
}
|
|
1697
|
-
</div>
|
|
1698
|
-
</axp-widgets-container>
|
|
1699
|
-
|
|
1700
|
-
<ax-footer>
|
|
1701
|
-
<ax-suffix>
|
|
1702
|
-
<ax-button
|
|
1703
|
-
text="Accept & Send"
|
|
1704
|
-
color="primary"
|
|
1705
|
-
[disabled]="(context()?.lookup?.length > 1 && !context()?.title) || !context()?.lookup?.length"
|
|
1706
|
-
(onClick)="handleClose()"
|
|
1707
|
-
></ax-button>
|
|
1708
|
-
</ax-suffix>
|
|
1709
|
-
</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"] }] }); }
|
|
1710
|
-
}
|
|
1711
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMUserLookupPopup, decorators: [{
|
|
1712
|
-
type: Component,
|
|
1713
|
-
args: [{
|
|
1714
|
-
template: `<axp-widgets-container [context]="context()" (onContextChanged)="context.set($event.data)">
|
|
1715
|
-
<div class="ax-p-4 ax-flex ax-flex-col ax-gap-4">
|
|
1716
|
-
<ng-container axp-widget-renderer [node]="lookupNode" [mode]="'edit'"> </ng-container>
|
|
1717
|
-
@if (context()?.lookup?.length > 1) {
|
|
1718
|
-
<ng-container axp-widget-renderer [node]="titleNode" [mode]="'edit'"> </ng-container>
|
|
1719
|
-
}
|
|
1720
|
-
</div>
|
|
1721
|
-
</axp-widgets-container>
|
|
1722
|
-
|
|
1723
|
-
<ax-footer>
|
|
1724
|
-
<ax-suffix>
|
|
1725
|
-
<ax-button
|
|
1726
|
-
text="Accept & Send"
|
|
1727
|
-
color="primary"
|
|
1728
|
-
[disabled]="(context()?.lookup?.length > 1 && !context()?.title) || !context()?.lookup?.length"
|
|
1729
|
-
(onClick)="handleClose()"
|
|
1730
|
-
></ax-button>
|
|
1731
|
-
</ax-suffix>
|
|
1732
|
-
</ax-footer>`,
|
|
1733
|
-
imports: [AXDecoratorModule, AXPLayoutBuilderModule, AXButtonModule],
|
|
1734
|
-
}]
|
|
1735
|
-
}] });
|
|
1736
|
-
|
|
1737
|
-
class AXMCommentWidgetViewComponent extends AXPValueWidgetComponent {
|
|
1738
|
-
constructor() {
|
|
1739
|
-
super(...arguments);
|
|
1740
|
-
this.refrenceType = computed(() => this.options().refrenceType, ...(ngDevMode ? [{ debugName: "refrenceType" }] : []));
|
|
1741
|
-
this.refrenceId = computed(() => this.options().refrenceId, ...(ngDevMode ? [{ debugName: "refrenceId" }] : []));
|
|
1742
|
-
this.subject = computed(() => this.options().subject, ...(ngDevMode ? [{ debugName: "subject" }] : []));
|
|
1574
|
+
async getComment(commentId) {
|
|
1575
|
+
return this.messageService.getOne(commentId);
|
|
1743
1576
|
}
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
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);
|
|
1585
|
+
}
|
|
1586
|
+
async deleteComment(commentId) {
|
|
1587
|
+
await this.messageService.deleteOne(commentId);
|
|
1588
|
+
return true;
|
|
1589
|
+
}
|
|
1590
|
+
async updateReactions(commentId, reactions) {
|
|
1591
|
+
await this.messageService.updateOne(commentId, { reactions });
|
|
1592
|
+
return this.messageService.getOne(commentId);
|
|
1593
|
+
}
|
|
1594
|
+
async getReactions(commentId) {
|
|
1595
|
+
const comment = await this.messageService.getOne(commentId);
|
|
1596
|
+
return comment.reactions || [];
|
|
1597
|
+
}
|
|
1598
|
+
async pinComment(commentId, isPinned) {
|
|
1599
|
+
await this.messageService.updateOne(commentId, { isPinned });
|
|
1600
|
+
return this.messageService.getOne(commentId);
|
|
1601
|
+
}
|
|
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' }); }
|
|
1748
1604
|
}
|
|
1749
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
1750
|
-
type:
|
|
1605
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentServiceImpl, decorators: [{
|
|
1606
|
+
type: Injectable,
|
|
1751
1607
|
args: [{
|
|
1752
|
-
|
|
1753
|
-
<axm-comment [refrenceId]="refrenceId()" [refrenceType]="refrenceType()" [subject]="subject()"></axm-comment>
|
|
1754
|
-
`,
|
|
1755
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1756
|
-
imports: [AXMCommentComponent],
|
|
1608
|
+
providedIn: 'root',
|
|
1757
1609
|
}]
|
|
1758
1610
|
}] });
|
|
1759
1611
|
|
|
1760
|
-
|
|
1761
|
-
__proto__: null,
|
|
1762
|
-
AXMCommentWidgetViewComponent: AXMCommentWidgetViewComponent
|
|
1763
|
-
});
|
|
1764
|
-
|
|
1765
|
-
const AXPCommentWidget = {
|
|
1766
|
-
name: 'comment',
|
|
1767
|
-
title: 'Comments',
|
|
1768
|
-
description: 'Display and manage comments for entities',
|
|
1769
|
-
type: 'view',
|
|
1770
|
-
categories: [],
|
|
1771
|
-
groups: [AXPWidgetGroupEnum.FormElement],
|
|
1772
|
-
icon: 'fa-solid fa-comments',
|
|
1773
|
-
properties: [],
|
|
1774
|
-
components: {
|
|
1775
|
-
view: {
|
|
1776
|
-
component: () => Promise.resolve().then(function () { return commentWidgetView_component; }).then((c) => c.AXMCommentWidgetViewComponent),
|
|
1777
|
-
},
|
|
1778
|
-
},
|
|
1779
|
-
};
|
|
1780
|
-
|
|
1781
|
-
class AXMCommentPopupStartAction extends AXPWorkflowAction {
|
|
1612
|
+
class AXMCommentManagementService {
|
|
1782
1613
|
constructor() {
|
|
1783
|
-
|
|
1784
|
-
this.
|
|
1785
|
-
this.
|
|
1614
|
+
this.commentImplService = inject(AXMCommentServiceImpl);
|
|
1615
|
+
this.sessionService = inject(AXPSessionService);
|
|
1616
|
+
this.usersService = inject(AXMUsersEntityService);
|
|
1617
|
+
this.realtimeService = inject(AXMCommentRealtimeService);
|
|
1786
1618
|
}
|
|
1787
|
-
async execute(context) {
|
|
1788
|
-
const comp = (await Promise.resolve().then(function () { return commentPopup_component; })).AXMCommentPopupComponent;
|
|
1789
|
-
this.popupService.open(comp, {
|
|
1790
|
-
title: await this.translate.translateAsync('Comments'),
|
|
1791
|
-
size: 'lg',
|
|
1792
|
-
data: {
|
|
1793
|
-
refrenceType: signal(context.getVariable('options.refType')),
|
|
1794
|
-
refrenceId: signal(context.getVariable('options.refId')),
|
|
1795
|
-
subject: signal(context.getVariable('options.subject')),
|
|
1796
|
-
},
|
|
1797
|
-
});
|
|
1798
|
-
}
|
|
1799
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMCommentPopupStartAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1800
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMCommentPopupStartAction }); }
|
|
1801
|
-
}
|
|
1802
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMCommentPopupStartAction, decorators: [{
|
|
1803
|
-
type: Injectable
|
|
1804
|
-
}] });
|
|
1805
|
-
const AXMCommentPopupWorkflow = {
|
|
1806
|
-
startStepId: 'start',
|
|
1807
|
-
steps: {
|
|
1808
|
-
start: {
|
|
1809
|
-
action: 'show-comment-popup-action',
|
|
1810
|
-
},
|
|
1811
|
-
},
|
|
1812
|
-
};
|
|
1813
|
-
|
|
1814
|
-
function convertChatMessageToNotification(room, message, currentUser) {
|
|
1815
|
-
const mapToNotificationUser = (user) => {
|
|
1816
|
-
return {
|
|
1817
|
-
id: user.id,
|
|
1818
|
-
name: user.fullName || '',
|
|
1819
|
-
image: '', // You might want to add an avatar URL here if available
|
|
1820
|
-
username: user.username || '',
|
|
1821
|
-
firstName: user.fullName?.split(' ')[0] || '',
|
|
1822
|
-
lastName: user.fullName?.split(' ')[1] || '',
|
|
1823
|
-
};
|
|
1824
|
-
};
|
|
1825
|
-
return {
|
|
1826
|
-
channel: 'InApp',
|
|
1827
|
-
template: {
|
|
1828
|
-
category: 'Inbox',
|
|
1829
|
-
prority: 'Notice',
|
|
1830
|
-
icon: 'fa-light fa-comment',
|
|
1831
|
-
isPinned: false,
|
|
1832
|
-
},
|
|
1833
|
-
title: room.title || 'New Message',
|
|
1834
|
-
body: message.message.content,
|
|
1835
|
-
user: mapToNotificationUser(message.author),
|
|
1836
|
-
content: {
|
|
1837
|
-
type: 'Notification',
|
|
1838
|
-
data: {
|
|
1839
|
-
roomId: room.id,
|
|
1840
|
-
},
|
|
1841
|
-
},
|
|
1842
|
-
readAt: null,
|
|
1843
|
-
};
|
|
1844
|
-
}
|
|
1845
|
-
|
|
1846
|
-
//#region ---- Abstract Chat Service ----
|
|
1847
|
-
class AXMChatService {
|
|
1848
|
-
}
|
|
1849
|
-
//#endregion
|
|
1850
|
-
class AXMChatServiceImpl {
|
|
1851
|
-
constructor() {
|
|
1852
|
-
this.roomService = inject(AXMRoomService);
|
|
1853
|
-
this.messageService = inject(AXMMessageService);
|
|
1854
|
-
this.tabService = inject(AXMConversationTabService);
|
|
1855
|
-
this.sessionService = inject(AXPSessionService);
|
|
1856
|
-
this.usersService = inject(AXMUsersEntityService);
|
|
1857
|
-
this._messageSent$ = new Subject();
|
|
1858
|
-
this.messageSent$ = this._messageSent$.asObservable();
|
|
1859
|
-
this._messageRemoved$ = new Subject();
|
|
1860
|
-
this.messageRemoved$ = this._messageRemoved$.asObservable();
|
|
1861
|
-
this._messageSeen$ = new Subject();
|
|
1862
|
-
this.messageSeen$ = this._messageSeen$.asObservable();
|
|
1863
|
-
this._roomAdded$ = new Subject();
|
|
1864
|
-
this.roomAdded$ = this._roomAdded$.asObservable();
|
|
1865
|
-
this._roomRemoved$ = new Subject();
|
|
1866
|
-
this.roomRemoved$ = this._roomRemoved$.asObservable();
|
|
1867
|
-
this._roomSeen$ = new Subject();
|
|
1868
|
-
this.roomSeen$ = this._roomSeen$.asObservable();
|
|
1869
|
-
this._messageReacted$ = new Subject();
|
|
1870
|
-
this.messageReacted$ = this._messageReacted$.asObservable();
|
|
1871
|
-
this._tabAdded$ = new Subject();
|
|
1872
|
-
this.tabAdded$ = this._tabAdded$.asObservable();
|
|
1873
|
-
this._tabRemoved$ = new Subject();
|
|
1874
|
-
this.tabRemoved$ = this._tabRemoved$.asObservable();
|
|
1875
|
-
this._typingStatus$ = new Subject();
|
|
1876
|
-
this.typingStatus$ = this._typingStatus$.asObservable();
|
|
1877
|
-
}
|
|
1878
|
-
//#region ---- Helper Methods ----
|
|
1879
1619
|
getCurrentUser() {
|
|
1880
1620
|
const user = this.sessionService.user;
|
|
1621
|
+
if (!user) {
|
|
1622
|
+
throw new Error('No authenticated user found.');
|
|
1623
|
+
}
|
|
1881
1624
|
return {
|
|
1882
|
-
id: user
|
|
1625
|
+
id: user.id,
|
|
1883
1626
|
type: 'user',
|
|
1884
|
-
fullName: user?.title?.trim() || 'Guest User',
|
|
1885
|
-
username: user?.name?.trim() || 'guest-user',
|
|
1886
1627
|
};
|
|
1887
1628
|
}
|
|
1888
1629
|
async getUserInfo(userId) {
|
|
1889
1630
|
try {
|
|
1890
|
-
|
|
1891
|
-
return {
|
|
1892
|
-
id: user.id,
|
|
1893
|
-
type: 'user',
|
|
1894
|
-
fullName: `${user.firstName} ${user.lastName}`.trim(),
|
|
1895
|
-
username: user.username?.trim(),
|
|
1896
|
-
};
|
|
1631
|
+
await this.usersService.getOne(userId);
|
|
1632
|
+
return { id: userId, type: 'user' };
|
|
1897
1633
|
}
|
|
1898
|
-
catch
|
|
1899
|
-
|
|
1900
|
-
return {
|
|
1901
|
-
id: userId,
|
|
1902
|
-
type: 'user',
|
|
1903
|
-
fullName: 'Unknown User',
|
|
1904
|
-
username: 'Unknown User',
|
|
1905
|
-
};
|
|
1634
|
+
catch {
|
|
1635
|
+
throw new Error(`User with ID ${userId} not found`);
|
|
1906
1636
|
}
|
|
1907
1637
|
}
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
}
|
|
1916
|
-
return message;
|
|
1638
|
+
formatComment(message, depth = 0) {
|
|
1639
|
+
return {
|
|
1640
|
+
...message,
|
|
1641
|
+
depth,
|
|
1642
|
+
replies: [],
|
|
1643
|
+
replyCount: 0,
|
|
1644
|
+
};
|
|
1917
1645
|
}
|
|
1918
|
-
|
|
1919
|
-
const
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
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;
|
|
1654
|
+
}
|
|
1655
|
+
else {
|
|
1656
|
+
tree.push(comment);
|
|
1657
|
+
}
|
|
1923
1658
|
});
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
const isFromCurrentUser = message.author.id === currentUserId;
|
|
1927
|
-
const isReadByCurrentUser = (message.seen || []).some((seen) => seen.author.id === currentUserId);
|
|
1928
|
-
return !isFromCurrentUser && !isReadByCurrentUser;
|
|
1659
|
+
commentMap.forEach((comment) => {
|
|
1660
|
+
comment.replyCount = comment.replies.length;
|
|
1929
1661
|
});
|
|
1930
|
-
return
|
|
1931
|
-
}
|
|
1932
|
-
//#endregion
|
|
1933
|
-
//#region ---- ChatRoomService Implementations ----
|
|
1934
|
-
async createRoom(memberIds, title) {
|
|
1935
|
-
if (memberIds.length === 0) {
|
|
1936
|
-
throw new Error('At least one member is required to create a room');
|
|
1937
|
-
}
|
|
1938
|
-
const currentUser = this.getCurrentUser();
|
|
1939
|
-
const allMemberIds = [...new Set([...memberIds, currentUser.id])];
|
|
1940
|
-
const memberReferences = await Promise.all(allMemberIds.map((id) => this.getUserInfo(id)));
|
|
1941
|
-
const room = {
|
|
1942
|
-
members: memberReferences,
|
|
1943
|
-
title: title,
|
|
1944
|
-
topic: memberIds.length > 1 ? 'group' : 'personal',
|
|
1945
|
-
createdAt: new Date(),
|
|
1946
|
-
updatedAt: new Date(),
|
|
1947
|
-
type: 'chat',
|
|
1948
|
-
createdBy: this.getCurrentUser().id,
|
|
1949
|
-
updatedBy: this.getCurrentUser().id,
|
|
1950
|
-
};
|
|
1951
|
-
const roomId = await this.roomService.insertOne(room);
|
|
1952
|
-
const newRoom = await this.getRoom(roomId);
|
|
1953
|
-
this._roomAdded$.next(newRoom);
|
|
1954
|
-
return newRoom;
|
|
1662
|
+
return tree;
|
|
1955
1663
|
}
|
|
1956
|
-
async
|
|
1957
|
-
const
|
|
1958
|
-
if (!room || room.type !== 'chat') {
|
|
1959
|
-
throw new Error(`Chat room with ID ${roomId} not found.`);
|
|
1960
|
-
}
|
|
1961
|
-
const messages = await this.getMessages(roomId, 0, 1);
|
|
1962
|
-
const lastMessage = messages.items.length > 0 ? messages.items[0] : undefined;
|
|
1963
|
-
const unreadCount = await this.getUnreadCount(roomId);
|
|
1964
|
-
const currentUserId = this.getCurrentUser().id;
|
|
1965
|
-
const members = await Promise.all(room.members.map(async (member) => {
|
|
1966
|
-
if (member.fullName) {
|
|
1967
|
-
return member;
|
|
1968
|
-
}
|
|
1969
|
-
return this.getUserInfo(member.id);
|
|
1970
|
-
}));
|
|
1664
|
+
async formatThread(room) {
|
|
1665
|
+
const comments = await this.getComments(room.id, true);
|
|
1971
1666
|
return {
|
|
1972
1667
|
...room,
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
members: members.filter((m) => m.id !== currentUserId),
|
|
1668
|
+
comments,
|
|
1669
|
+
commentCount: comments.length,
|
|
1976
1670
|
};
|
|
1977
1671
|
}
|
|
1978
|
-
async
|
|
1979
|
-
const
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
const settledRooms = await Promise.allSettled(items.map((room) => this.getRoom(room.id)));
|
|
1985
|
-
const chatRooms = settledRooms
|
|
1986
|
-
.filter((result) => {
|
|
1987
|
-
if (result.status === 'rejected') {
|
|
1988
|
-
console.error('Failed to fetch room details:', result.reason);
|
|
1989
|
-
return false;
|
|
1990
|
-
}
|
|
1991
|
-
return true;
|
|
1992
|
-
})
|
|
1993
|
-
.map((result) => result.value);
|
|
1994
|
-
return { items: chatRooms, total: chatRooms.length };
|
|
1995
|
-
}
|
|
1996
|
-
async updateRoom(roomId, data) {
|
|
1997
|
-
const update = { ...data, updatedAt: new Date(), updatedBy: this.getCurrentUser().id };
|
|
1998
|
-
return this.roomService.updateOne(roomId, update);
|
|
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;
|
|
1999
1678
|
}
|
|
2000
|
-
async
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
return true;
|
|
2005
|
-
}
|
|
2006
|
-
catch (error) {
|
|
2007
|
-
return false;
|
|
1679
|
+
async getThread(entityRef, topic) {
|
|
1680
|
+
const room = await this.commentImplService.getThread(entityRef, topic);
|
|
1681
|
+
if (!room) {
|
|
1682
|
+
return null;
|
|
2008
1683
|
}
|
|
1684
|
+
return this.formatThread(room);
|
|
2009
1685
|
}
|
|
2010
|
-
async
|
|
2011
|
-
const
|
|
2012
|
-
|
|
2013
|
-
return room;
|
|
2014
|
-
const userRef = await this.getUserInfo(userId);
|
|
2015
|
-
const updatedMembers = [...room.members, userRef];
|
|
2016
|
-
return this.roomService.updateOne(roomId, {
|
|
2017
|
-
members: updatedMembers,
|
|
2018
|
-
updatedAt: new Date(),
|
|
2019
|
-
updatedBy: this.getCurrentUser().id,
|
|
2020
|
-
});
|
|
1686
|
+
async listThreads(entityRef, topic) {
|
|
1687
|
+
const rooms = await this.commentImplService.listThreads(entityRef, topic);
|
|
1688
|
+
return Promise.all(rooms.map((room) => this.formatThread(room)));
|
|
2021
1689
|
}
|
|
2022
|
-
async
|
|
2023
|
-
const
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
});
|
|
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.`);
|
|
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;
|
|
2030
1699
|
}
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
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;
|
|
2038
1708
|
}
|
|
2039
|
-
async
|
|
2040
|
-
|
|
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;
|
|
1715
|
+
}
|
|
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;
|
|
2041
1723
|
}
|
|
2042
|
-
async
|
|
2043
|
-
|
|
1724
|
+
async getComment(commentId) {
|
|
1725
|
+
const rawComment = await this.commentImplService.getComment(commentId);
|
|
1726
|
+
return this.formatComment(rawComment);
|
|
2044
1727
|
}
|
|
2045
|
-
async
|
|
2046
|
-
|
|
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;
|
|
2047
1734
|
}
|
|
2048
|
-
async
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
this.
|
|
2052
|
-
return true;
|
|
2053
|
-
}
|
|
2054
|
-
catch (error) {
|
|
2055
|
-
console.error(`Error deleting tab ${tabId}:`, error);
|
|
2056
|
-
return false;
|
|
1735
|
+
async deleteComment(commentId) {
|
|
1736
|
+
const result = await this.commentImplService.deleteComment(commentId);
|
|
1737
|
+
if (result) {
|
|
1738
|
+
this.realtimeService.notifyComment({ type: 'remove', payload: commentId });
|
|
2057
1739
|
}
|
|
1740
|
+
return result;
|
|
2058
1741
|
}
|
|
2059
|
-
async
|
|
2060
|
-
const
|
|
2061
|
-
const
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
return this.
|
|
2065
|
-
}
|
|
2066
|
-
else {
|
|
2067
|
-
throw new Error(`Tab with ID ${tabId} or room with ID ${roomId} not found.`);
|
|
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);
|
|
2068
1748
|
}
|
|
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;
|
|
2069
1754
|
}
|
|
2070
|
-
async
|
|
2071
|
-
const
|
|
2072
|
-
const
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
else {
|
|
2079
|
-
throw new Error(`${tabId} tab does not include room with ID ${roomId}.`);
|
|
2080
|
-
}
|
|
2081
|
-
}
|
|
2082
|
-
else {
|
|
2083
|
-
throw new Error(`Tab with ID ${tabId} or room with ID ${roomId} not found.`);
|
|
2084
|
-
}
|
|
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;
|
|
2085
1763
|
}
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
const room = await this.getRoom(roomId);
|
|
2089
|
-
if (tab && room) {
|
|
2090
|
-
const updatedRooms = [...tab.excludeRooms, room];
|
|
2091
|
-
return this.updateTab(tabId, { excludeRooms: updatedRooms });
|
|
2092
|
-
}
|
|
2093
|
-
else {
|
|
2094
|
-
throw new Error(`Tab with ID ${tabId} or room with ID ${roomId} not found.`);
|
|
2095
|
-
}
|
|
1764
|
+
getReactions(commentId) {
|
|
1765
|
+
return this.commentImplService.getReactions(commentId);
|
|
2096
1766
|
}
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
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;
|
|
1784
|
+
}
|
|
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' }); }
|
|
1787
|
+
}
|
|
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
|
+
}]
|
|
1793
|
+
}] });
|
|
1794
|
+
|
|
1795
|
+
function convertCommentToNotification(thread, comment, currentUser) {
|
|
1796
|
+
return {
|
|
1797
|
+
channel: 'InApp',
|
|
1798
|
+
template: {
|
|
1799
|
+
category: 'Inbox',
|
|
1800
|
+
prority: 'Notice',
|
|
1801
|
+
icon: 'fa-light fa-comment',
|
|
1802
|
+
isPinned: false,
|
|
1803
|
+
},
|
|
1804
|
+
title: thread.title || 'New Comment',
|
|
1805
|
+
body: comment.message.content,
|
|
1806
|
+
sender: comment.author,
|
|
1807
|
+
receiver: currentUser,
|
|
1808
|
+
content: comment.message,
|
|
1809
|
+
readAt: null,
|
|
1810
|
+
type: 'Comment',
|
|
1811
|
+
data: {
|
|
1812
|
+
threadId: thread.id,
|
|
1813
|
+
refrenceType: thread.entityRef?.type,
|
|
1814
|
+
refrenceId: thread.entityRef?.id,
|
|
1815
|
+
},
|
|
1816
|
+
};
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1819
|
+
class AXMCommentComponent {
|
|
1820
|
+
constructor() {
|
|
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);
|
|
1837
|
+
this.sessionService = inject(AXPSessionService);
|
|
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;
|
|
2104
1858
|
}
|
|
2105
|
-
|
|
2106
|
-
|
|
1859
|
+
return {
|
|
1860
|
+
rule: 'callback',
|
|
1861
|
+
result: isValid,
|
|
1862
|
+
message: isValid ? '' : 'Please fill the content',
|
|
1863
|
+
value: content,
|
|
1864
|
+
};
|
|
1865
|
+
};
|
|
1866
|
+
}
|
|
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;
|
|
2107
1887
|
}
|
|
1888
|
+
});
|
|
1889
|
+
}
|
|
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
|
+
});
|
|
1904
|
+
}
|
|
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
|
+
});
|
|
2108
1915
|
}
|
|
2109
1916
|
else {
|
|
2110
|
-
|
|
1917
|
+
this.comments.update((comments) => [...comments, comment]);
|
|
2111
1918
|
}
|
|
2112
1919
|
}
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
updatedAt: new Date(),
|
|
2125
|
-
createdBy: this.getCurrentUser().id,
|
|
2126
|
-
updatedBy: this.getCurrentUser().id,
|
|
2127
|
-
reactions: [],
|
|
2128
|
-
seen: [],
|
|
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
|
+
});
|
|
2129
1931
|
};
|
|
2130
|
-
|
|
2131
|
-
const newMessage = await this.messageService.getOne(messageId);
|
|
2132
|
-
const formattedMessage = await this.formatMessage(newMessage);
|
|
2133
|
-
this._messageSent$.next(formattedMessage);
|
|
2134
|
-
return formattedMessage;
|
|
1932
|
+
this.comments.update((comments) => update(comments));
|
|
2135
1933
|
}
|
|
2136
|
-
|
|
2137
|
-
const
|
|
2138
|
-
|
|
2139
|
-
take,
|
|
2140
|
-
filter: { field: 'roomId', value: roomId, operator: { type: 'equal' } },
|
|
2141
|
-
sort: [{ field: 'createdAt', dir: 'desc' }],
|
|
2142
|
-
});
|
|
2143
|
-
const formattedMessages = await Promise.all(result.items.map((m) => this.formatMessage(m)));
|
|
2144
|
-
return { items: formattedMessages, total: result.total };
|
|
1934
|
+
getCurrentUser() {
|
|
1935
|
+
const user = this.sessionService.user;
|
|
1936
|
+
return user ? { id: user.id, type: 'user' } : null;
|
|
2145
1937
|
}
|
|
2146
|
-
|
|
2147
|
-
const
|
|
2148
|
-
|
|
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');
|
|
2149
1943
|
}
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
return this.messageService.updateOne(messageId, {
|
|
2153
|
-
message: messageContent,
|
|
2154
|
-
updatedAt: new Date(),
|
|
2155
|
-
updatedBy: this.getCurrentUser().id,
|
|
2156
|
-
});
|
|
1944
|
+
getReactionsCount(comment) {
|
|
1945
|
+
return (comment.reactions || []).filter((r) => r.type === 'like').length;
|
|
2157
1946
|
}
|
|
2158
|
-
|
|
1947
|
+
sanitizeHtml(htmlContent) {
|
|
1948
|
+
if (!htmlContent)
|
|
1949
|
+
return this.sanitize.bypassSecurityTrustHtml('');
|
|
1950
|
+
return this.sanitize.bypassSecurityTrustHtml(htmlContent);
|
|
1951
|
+
}
|
|
1952
|
+
handleImageError(imageId) {
|
|
1953
|
+
this.failedImageIds.update((ids) => [...ids, imageId]);
|
|
1954
|
+
}
|
|
1955
|
+
checkImageExists(imageId) {
|
|
1956
|
+
return !this.failedImageIds().includes(imageId);
|
|
1957
|
+
}
|
|
1958
|
+
async loadComments() {
|
|
2159
1959
|
try {
|
|
2160
|
-
await this.
|
|
2161
|
-
|
|
2162
|
-
|
|
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 || []);
|
|
1964
|
+
}
|
|
1965
|
+
else {
|
|
1966
|
+
this.comments.set([]);
|
|
1967
|
+
this.thread.set(undefined);
|
|
1968
|
+
}
|
|
2163
1969
|
}
|
|
2164
1970
|
catch (error) {
|
|
2165
|
-
|
|
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([]);
|
|
2166
1981
|
}
|
|
2167
1982
|
}
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
updatedBy: this.getCurrentUser().id,
|
|
2177
|
-
});
|
|
2178
|
-
}
|
|
2179
|
-
async unpinMessage(messageId) {
|
|
2180
|
-
return this.messageService.updateOne(messageId, {
|
|
2181
|
-
isPinned: false,
|
|
2182
|
-
updatedAt: new Date(),
|
|
2183
|
-
updatedBy: this.getCurrentUser().id,
|
|
2184
|
-
});
|
|
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' });
|
|
2185
1991
|
}
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
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();
|
|
2194
2003
|
}
|
|
2195
|
-
|
|
2196
|
-
const res = await this.messageService.updateOne(messageId, {
|
|
2197
|
-
reactions: updatedReactions,
|
|
2198
|
-
updatedAt: new Date(),
|
|
2199
|
-
updatedBy: this.getCurrentUser().id,
|
|
2200
|
-
});
|
|
2201
|
-
this._messageReacted$.next(res);
|
|
2202
|
-
return res;
|
|
2203
|
-
}
|
|
2204
|
-
async removeReaction(messageId, type) {
|
|
2205
|
-
const author = this.getCurrentUser();
|
|
2206
|
-
const message = await this.messageService.getOne(messageId);
|
|
2207
|
-
const updatedReactions = (message.reactions || []).filter((r) => !(r.author.id === author.id && r.type === type));
|
|
2208
|
-
const res = await this.messageService.updateOne(messageId, {
|
|
2209
|
-
reactions: updatedReactions,
|
|
2210
|
-
updatedAt: new Date(),
|
|
2211
|
-
updatedBy: this.getCurrentUser().id,
|
|
2212
|
-
});
|
|
2213
|
-
this._messageReacted$.next(res);
|
|
2214
|
-
return res;
|
|
2215
|
-
}
|
|
2216
|
-
async getReactions(messageId) {
|
|
2217
|
-
const message = await this.messageService.getOne(messageId);
|
|
2218
|
-
return message.reactions || [];
|
|
2004
|
+
this.wysiwygEditor().getHostElement().scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
2219
2005
|
}
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
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);
|
|
2076
|
+
}
|
|
2077
|
+
else {
|
|
2078
|
+
await this.commentService.likeComment(comment.id);
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
catch (error) {
|
|
2082
|
+
console.error('Failed to toggle like:', error);
|
|
2083
|
+
this.updateLikeStatus(comment.id, isLiked); // Revert optimistic update
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
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
|
+
});
|
|
2107
|
+
};
|
|
2108
|
+
this.comments.update((comments) => findAndToggle(comments));
|
|
2109
|
+
}
|
|
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));
|
|
2122
|
+
}
|
|
2123
|
+
async submitComment() {
|
|
2124
|
+
if (!this.validateContent(this.commentContent()).result) {
|
|
2125
|
+
return;
|
|
2126
|
+
}
|
|
2127
|
+
this.isSubmitting.set(true);
|
|
2128
|
+
console.log(this.commentContent());
|
|
2129
|
+
try {
|
|
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);
|
|
2152
|
+
}
|
|
2153
|
+
catch (error) {
|
|
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);
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
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
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
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" }] : []));
|
|
2232
|
+
}
|
|
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" }] : []));
|
|
2303
|
+
}
|
|
2304
|
+
handleClose() {
|
|
2305
|
+
this.close({
|
|
2306
|
+
lookup: this.context()?.lookup,
|
|
2307
|
+
title: this.context()?.title,
|
|
2234
2308
|
});
|
|
2235
|
-
this._messageSeen$.next(await this.formatMessage(updatedMessage));
|
|
2236
|
-
return updatedMessage;
|
|
2237
|
-
}
|
|
2238
|
-
async getSeenBy(messageId) {
|
|
2239
|
-
const message = await this.messageService.getOne(messageId);
|
|
2240
|
-
return message.seen || [];
|
|
2241
2309
|
}
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
const currentUserId = this.getCurrentUser().id;
|
|
2249
|
-
const unreadMessages = items.filter((message) => message.author.id !== currentUserId && !message.seen?.some((s) => s.author.id === currentUserId));
|
|
2250
|
-
if (unreadMessages.length > 0) {
|
|
2251
|
-
await Promise.all(unreadMessages.map((message) => this.markSeen(message.id)));
|
|
2252
|
-
}
|
|
2253
|
-
this._roomSeen$.next(roomId);
|
|
2254
|
-
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>
|
|
2255
2316
|
}
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
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>
|
|
2259
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" }] : []));
|
|
2260
2363
|
}
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
this._typingStatus$.next({ roomId, user, isTyping: true });
|
|
2266
|
-
}
|
|
2267
|
-
async stopTyping(roomId, userId) {
|
|
2268
|
-
const user = userId ? await this.getUserInfo(userId) : this.getCurrentUser();
|
|
2269
|
-
this._typingStatus$.next({ roomId, user, isTyping: false });
|
|
2270
|
-
}
|
|
2271
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMChatServiceImpl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2272
|
-
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 }); }
|
|
2273
2368
|
}
|
|
2274
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
2275
|
-
type:
|
|
2369
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMCommentWidgetViewComponent, decorators: [{
|
|
2370
|
+
type: Component,
|
|
2276
2371
|
args: [{
|
|
2277
|
-
|
|
2372
|
+
template: `
|
|
2373
|
+
<axm-comment [refrenceId]="refrenceId()" [refrenceType]="refrenceType()" [subject]="subject()"></axm-comment>
|
|
2374
|
+
`,
|
|
2375
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2376
|
+
imports: [AXMCommentComponent],
|
|
2278
2377
|
}]
|
|
2279
2378
|
}] });
|
|
2280
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
|
+
|
|
2281
2456
|
class AXMChatItemComponent {
|
|
2282
2457
|
constructor() {
|
|
2283
2458
|
// Input
|
|
@@ -2365,10 +2540,10 @@ class AXMChatItemComponent {
|
|
|
2365
2540
|
}
|
|
2366
2541
|
return '';
|
|
2367
2542
|
}
|
|
2368
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
2369
|
-
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 }); }
|
|
2370
2545
|
}
|
|
2371
|
-
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: [{
|
|
2372
2547
|
type: Component,
|
|
2373
2548
|
args: [{ selector: 'axm-chat-item', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
2374
2549
|
AXDecoratorModule,
|
|
@@ -2378,19 +2553,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
|
|
|
2378
2553
|
AXDecoratorModule,
|
|
2379
2554
|
AXTranslationModule,
|
|
2380
2555
|
AsyncPipe,
|
|
2381
|
-
], 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"] }]
|
|
2382
2557
|
}] });
|
|
2383
2558
|
|
|
2384
2559
|
class AXMChatComponent extends AXPPageLayoutBaseComponent {
|
|
2385
2560
|
constructor() {
|
|
2386
2561
|
super(...arguments);
|
|
2387
2562
|
this.activatedRoute = inject(ActivatedRoute);
|
|
2388
|
-
this.chatService = inject(
|
|
2563
|
+
this.chatService = inject(AXMChatManagementService);
|
|
2564
|
+
this.realtimeService = inject(AXMChatRealtimeService);
|
|
2389
2565
|
this.popupService = inject(AXPopupService);
|
|
2390
2566
|
this.dialogService = inject(AXDialogService);
|
|
2391
2567
|
this.router = inject(Router);
|
|
2392
2568
|
this.unsubscribe = inject(AXUnsubscriber);
|
|
2393
|
-
this.osNotificationService = inject(AXMOsNotificationService);
|
|
2394
2569
|
this.notificationConnectorService = inject(AXMNotificationConnectorService);
|
|
2395
2570
|
// View Children
|
|
2396
2571
|
this.tab = viewChild('tab', ...(ngDevMode ? [{ debugName: "tab" }] : []));
|
|
@@ -2484,7 +2659,7 @@ class AXMChatComponent extends AXPPageLayoutBaseComponent {
|
|
|
2484
2659
|
super.ngOnInit();
|
|
2485
2660
|
this.isLoading.set(true);
|
|
2486
2661
|
this.error.set(null);
|
|
2487
|
-
await Promise.all([this.loadChats(), this.loadTabs()
|
|
2662
|
+
await Promise.all([this.loadChats(), this.loadTabs()]);
|
|
2488
2663
|
this.isLoading.set(false);
|
|
2489
2664
|
//
|
|
2490
2665
|
this.router.events
|
|
@@ -2493,34 +2668,85 @@ class AXMChatComponent extends AXPPageLayoutBaseComponent {
|
|
|
2493
2668
|
await this.loadFromRoute();
|
|
2494
2669
|
});
|
|
2495
2670
|
//
|
|
2496
|
-
this.
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
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;
|
|
2501
2689
|
}
|
|
2502
2690
|
});
|
|
2503
|
-
this.
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
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;
|
|
2508
2728
|
}
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
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;
|
|
2518
2746
|
}
|
|
2519
|
-
|
|
2520
|
-
});
|
|
2521
|
-
this.allRooms.set(updatedRooms);
|
|
2747
|
+
}
|
|
2522
2748
|
});
|
|
2523
|
-
this.
|
|
2749
|
+
this.realtimeService.typingStatus$.pipe(this.unsubscribe.takeUntilDestroy).subscribe(async (status) => {
|
|
2524
2750
|
const currentUserId = this.sessionService.user?.id;
|
|
2525
2751
|
if (status.user.id !== currentUserId) {
|
|
2526
2752
|
if (status.isTyping) {
|
|
@@ -2537,70 +2763,6 @@ class AXMChatComponent extends AXPPageLayoutBaseComponent {
|
|
|
2537
2763
|
}
|
|
2538
2764
|
}
|
|
2539
2765
|
});
|
|
2540
|
-
this.chatService.messageSent$.pipe(this.unsubscribe.takeUntilDestroy).subscribe((message) => {
|
|
2541
|
-
const rooms = this.allRooms();
|
|
2542
|
-
const roomIndex = rooms.findIndex((r) => r.id === message.roomId);
|
|
2543
|
-
if (roomIndex > -1) {
|
|
2544
|
-
const roomToUpdate = rooms[roomIndex];
|
|
2545
|
-
const isCurrentUser = message.author.id === this.sessionService.user?.id;
|
|
2546
|
-
const updatedRoom = {
|
|
2547
|
-
...roomToUpdate,
|
|
2548
|
-
lastMessage: message,
|
|
2549
|
-
unreadCount: !isCurrentUser ? (roomToUpdate.unreadCount || 0) + 1 : roomToUpdate.unreadCount,
|
|
2550
|
-
};
|
|
2551
|
-
const newRooms = [updatedRoom, ...rooms.filter((r) => r.id !== message.roomId)];
|
|
2552
|
-
this.allRooms.set(newRooms);
|
|
2553
|
-
//
|
|
2554
|
-
if (!isCurrentUser && this.selectedRoom()?.id !== message.roomId) {
|
|
2555
|
-
const notification = convertChatMessageToNotification(roomToUpdate, message, this.sessionService.user);
|
|
2556
|
-
this.notificationConnectorService.create({
|
|
2557
|
-
...notification,
|
|
2558
|
-
id: message.id,
|
|
2559
|
-
entityName: 'notifications',
|
|
2560
|
-
createAt: new Date(),
|
|
2561
|
-
}, {
|
|
2562
|
-
onClick: () => {
|
|
2563
|
-
this.router.navigate([roomToUpdate.id], { relativeTo: this.activatedRoute });
|
|
2564
|
-
},
|
|
2565
|
-
activeWindow: true,
|
|
2566
|
-
});
|
|
2567
|
-
// this.osNotificationService.show(notification.title || 'Notification', {
|
|
2568
|
-
// body: notification.body || 'No body',
|
|
2569
|
-
// icon: notification.user.image || '',
|
|
2570
|
-
// onClick: () => {
|
|
2571
|
-
// this.router.navigate([roomToUpdate.id], { relativeTo: this.activatedRoute });
|
|
2572
|
-
// },
|
|
2573
|
-
// activeWindow: true,
|
|
2574
|
-
// });
|
|
2575
|
-
}
|
|
2576
|
-
//
|
|
2577
|
-
}
|
|
2578
|
-
else {
|
|
2579
|
-
// New room, fetch it and add it to the top.
|
|
2580
|
-
this.chatService.getRoom(message.roomId).then((newRoom) => {
|
|
2581
|
-
this.allRooms.update((currentRooms) => {
|
|
2582
|
-
// Prepending the new room
|
|
2583
|
-
return [newRoom, ...currentRooms];
|
|
2584
|
-
});
|
|
2585
|
-
});
|
|
2586
|
-
}
|
|
2587
|
-
});
|
|
2588
|
-
this.chatService.messageReacted$.pipe(this.unsubscribe.takeUntilDestroy).subscribe((message) => {
|
|
2589
|
-
this.allRooms.update((rooms) => {
|
|
2590
|
-
return rooms.map((room) => {
|
|
2591
|
-
if (room.lastMessage?.id === message.id) {
|
|
2592
|
-
return {
|
|
2593
|
-
...room,
|
|
2594
|
-
lastMessage: {
|
|
2595
|
-
...room.lastMessage,
|
|
2596
|
-
reactions: message.reactions,
|
|
2597
|
-
},
|
|
2598
|
-
};
|
|
2599
|
-
}
|
|
2600
|
-
return room;
|
|
2601
|
-
});
|
|
2602
|
-
});
|
|
2603
|
-
});
|
|
2604
2766
|
}
|
|
2605
2767
|
async loadFromRoute() {
|
|
2606
2768
|
const chatId = this.activatedRoute.snapshot.firstChild?.paramMap.get('id');
|
|
@@ -2811,14 +2973,14 @@ class AXMChatComponent extends AXPPageLayoutBaseComponent {
|
|
|
2811
2973
|
this.toastService.danger('Failed to create room');
|
|
2812
2974
|
}
|
|
2813
2975
|
}
|
|
2814
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
2815
|
-
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: [
|
|
2816
2978
|
{
|
|
2817
2979
|
provide: AXPPageLayoutBase,
|
|
2818
2980
|
useExisting: AXMChatComponent,
|
|
2819
2981
|
},
|
|
2820
2982
|
AXUnsubscriber,
|
|
2821
|
-
], 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:
|
|
2822
2984
|
// Common Modules
|
|
2823
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:
|
|
2824
2986
|
// Acorex Core Modules
|
|
@@ -2834,7 +2996,7 @@ class AXMChatComponent extends AXPPageLayoutBaseComponent {
|
|
|
2834
2996
|
]),
|
|
2835
2997
|
], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2836
2998
|
}
|
|
2837
|
-
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: [{
|
|
2838
3000
|
type: Component,
|
|
2839
3001
|
args: [{ selector: 'axm-chat', changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
2840
3002
|
{
|
|
@@ -2884,7 +3046,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
|
|
|
2884
3046
|
animate('300ms ease-out', style({ opacity: 1, transform: 'translateY(0)' })),
|
|
2885
3047
|
]),
|
|
2886
3048
|
]),
|
|
2887
|
-
], 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" }]
|
|
2888
3050
|
}], propDecorators: { onKeydownHandler: [{
|
|
2889
3051
|
type: HostListener,
|
|
2890
3052
|
args: ['document:keydown.escape', ['$event']]
|
|
@@ -3173,9 +3335,11 @@ class AXMChatPreviewComponent {
|
|
|
3173
3335
|
constructor() {
|
|
3174
3336
|
this.activatedRoute = inject(ActivatedRoute);
|
|
3175
3337
|
this.fileService = inject(AXFileService);
|
|
3176
|
-
this.chatService = inject(
|
|
3338
|
+
this.chatService = inject(AXMChatManagementService);
|
|
3339
|
+
this.realtimeService = inject(AXMChatRealtimeService);
|
|
3177
3340
|
this.sessionService = inject(AXPSessionService);
|
|
3178
3341
|
this.toastService = inject(AXToastService);
|
|
3342
|
+
this.unsubscribe = inject(AXUnsubscriber);
|
|
3179
3343
|
this.inputRef = viewChild(AXConversationInputComponent, ...(ngDevMode ? [{ debugName: "inputRef" }] : []));
|
|
3180
3344
|
this.activeMessage = signal(null, ...(ngDevMode ? [{ debugName: "activeMessage" }] : []));
|
|
3181
3345
|
this.typing$ = new Subject();
|
|
@@ -3214,24 +3378,37 @@ class AXMChatPreviewComponent {
|
|
|
3214
3378
|
this.loadRoomInfo(this.roomId);
|
|
3215
3379
|
}
|
|
3216
3380
|
});
|
|
3217
|
-
this.
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
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);
|
|
3228
3410
|
}
|
|
3229
3411
|
});
|
|
3230
|
-
// this.typingSubscription = this.typing$.pipe(debounceTime(1000)).subscribe(() => {
|
|
3231
|
-
// if (this.roomId) {
|
|
3232
|
-
// this.chatService.stopTyping(this.roomId);
|
|
3233
|
-
// }
|
|
3234
|
-
// });
|
|
3235
3412
|
}
|
|
3236
3413
|
//GO TO LAST MESSAGE EFFECT.
|
|
3237
3414
|
#af;
|
|
@@ -3403,10 +3580,10 @@ class AXMChatPreviewComponent {
|
|
|
3403
3580
|
input.setActionBoxContainer(icon, message?.content || this.activeMessage()?.content || '');
|
|
3404
3581
|
}
|
|
3405
3582
|
}
|
|
3406
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
3407
|
-
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 }); }
|
|
3408
3585
|
}
|
|
3409
|
-
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: [{
|
|
3410
3587
|
type: Component,
|
|
3411
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"] }]
|
|
3412
3589
|
}] });
|
|
@@ -3416,6 +3593,114 @@ var chatPreview_component = /*#__PURE__*/Object.freeze({
|
|
|
3416
3593
|
AXMChatPreviewComponent: AXMChatPreviewComponent
|
|
3417
3594
|
});
|
|
3418
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
|
+
|
|
3419
3704
|
function routesFactory() {
|
|
3420
3705
|
const routes = [
|
|
3421
3706
|
{
|
|
@@ -3478,11 +3763,11 @@ function routesFactory() {
|
|
|
3478
3763
|
return routes;
|
|
3479
3764
|
}
|
|
3480
3765
|
class AXMConversationModule {
|
|
3481
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
3482
|
-
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: [
|
|
3483
3768
|
// Modules
|
|
3484
3769
|
RouterModule] }); }
|
|
3485
|
-
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: [
|
|
3486
3771
|
// Services
|
|
3487
3772
|
{
|
|
3488
3773
|
provide: AXMMessageService,
|
|
@@ -3501,10 +3786,18 @@ class AXMConversationModule {
|
|
|
3501
3786
|
provide: AXMChatService,
|
|
3502
3787
|
useClass: AXMChatServiceImpl,
|
|
3503
3788
|
},
|
|
3789
|
+
{
|
|
3790
|
+
provide: AXMChatRealtimeService,
|
|
3791
|
+
useClass: AXMChatRealtimeServiceImpl,
|
|
3792
|
+
},
|
|
3504
3793
|
{
|
|
3505
3794
|
provide: AXMCommentService,
|
|
3506
3795
|
useClass: AXMCommentServiceImpl,
|
|
3507
3796
|
},
|
|
3797
|
+
{
|
|
3798
|
+
provide: AXMCommentRealtimeService,
|
|
3799
|
+
useClass: AXMCommentRealtimeServiceImpl,
|
|
3800
|
+
},
|
|
3508
3801
|
// Entity Provider
|
|
3509
3802
|
{
|
|
3510
3803
|
provide: AXP_ENTITY_DEFINITION_LOADER,
|
|
@@ -3530,6 +3823,7 @@ class AXMConversationModule {
|
|
|
3530
3823
|
// Conversation Module
|
|
3531
3824
|
importProvidersFrom(AXConversationModule.forRoot()),
|
|
3532
3825
|
DatePipe,
|
|
3826
|
+
...AXM_CONVERSATION_NOTIFICATION_PROVIDERS,
|
|
3533
3827
|
], imports: [AXPLayoutBuilderModule.forChild({
|
|
3534
3828
|
widgets: [AXPCommentWidget],
|
|
3535
3829
|
}),
|
|
@@ -3544,7 +3838,7 @@ class AXMConversationModule {
|
|
|
3544
3838
|
// Modules
|
|
3545
3839
|
RouterModule] }); }
|
|
3546
3840
|
}
|
|
3547
|
-
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: [{
|
|
3548
3842
|
type: NgModule,
|
|
3549
3843
|
args: [{
|
|
3550
3844
|
declarations: [],
|
|
@@ -3584,10 +3878,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
|
|
|
3584
3878
|
provide: AXMChatService,
|
|
3585
3879
|
useClass: AXMChatServiceImpl,
|
|
3586
3880
|
},
|
|
3881
|
+
{
|
|
3882
|
+
provide: AXMChatRealtimeService,
|
|
3883
|
+
useClass: AXMChatRealtimeServiceImpl,
|
|
3884
|
+
},
|
|
3587
3885
|
{
|
|
3588
3886
|
provide: AXMCommentService,
|
|
3589
3887
|
useClass: AXMCommentServiceImpl,
|
|
3590
3888
|
},
|
|
3889
|
+
{
|
|
3890
|
+
provide: AXMCommentRealtimeService,
|
|
3891
|
+
useClass: AXMCommentRealtimeServiceImpl,
|
|
3892
|
+
},
|
|
3591
3893
|
// Entity Provider
|
|
3592
3894
|
{
|
|
3593
3895
|
provide: AXP_ENTITY_DEFINITION_LOADER,
|
|
@@ -3613,6 +3915,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
|
|
|
3613
3915
|
// Conversation Module
|
|
3614
3916
|
importProvidersFrom(AXConversationModule.forRoot()),
|
|
3615
3917
|
DatePipe,
|
|
3918
|
+
...AXM_CONVERSATION_NOTIFICATION_PROVIDERS,
|
|
3616
3919
|
],
|
|
3617
3920
|
}]
|
|
3618
3921
|
}] });
|
|
@@ -3621,5 +3924,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
|
|
|
3621
3924
|
* Generated bundle index. Do not edit.
|
|
3622
3925
|
*/
|
|
3623
3926
|
|
|
3624
|
-
export { AXMChatComponent, AXMChatItemComponent, AXMChatPreviewComponent, AXMChatService, AXMChatServiceImpl, AXMCommentComponent, AXMCommentPopupComponent, AXMCommentPopupStartAction, AXMCommentPopupWorkflow, 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 };
|
|
3625
3928
|
//# sourceMappingURL=acorex-modules-conversation.mjs.map
|