fix publication details

This commit is contained in:
peter.maquiran
2025-09-11 11:20:44 +01:00
parent 69e4334ebf
commit 5f7295d41c
74 changed files with 1639 additions and 678 deletions
+267
View File
@@ -99,6 +99,8 @@
"@ngrx/store": "^10.1.2", "@ngrx/store": "^10.1.2",
"@ngx-translate/core": "^13.0.0", "@ngx-translate/core": "^13.0.0",
"@ngxs/store": "^3.8.2", "@ngxs/store": "^3.8.2",
"@openreplay/tracker": "^16.4.8",
"@openreplay/tracker-assist": "^11.0.8",
"@opentelemetry/exporter-metrics-otlp-http": "^0.52.1", "@opentelemetry/exporter-metrics-otlp-http": "^0.52.1",
"@opentelemetry/exporter-trace-otlp-http": "^0.52.1", "@opentelemetry/exporter-trace-otlp-http": "^0.52.1",
"@opentelemetry/exporter-zipkin": "^1.25.1", "@opentelemetry/exporter-zipkin": "^1.25.1",
@@ -7802,6 +7804,123 @@
"read-package-json-fast": "^2.0.1" "read-package-json-fast": "^2.0.1"
} }
}, },
"node_modules/@openreplay/network-proxy": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@openreplay/network-proxy/-/network-proxy-1.2.0.tgz",
"integrity": "sha512-vIOzBWVKn+7/Dk4qFmRxR1fdOEnLt1hXkEYtc3m7eIA2nVwz+BSGW4Hbs/ygFLnNS0HkcBwuRgmXAwRMK5HCrQ=="
},
"node_modules/@openreplay/tracker": {
"version": "16.4.8",
"resolved": "https://registry.npmjs.org/@openreplay/tracker/-/tracker-16.4.8.tgz",
"integrity": "sha512-IB/yIzquRQAYGch55tkwXm0dKN2eKAzLNbxD6I21bKOlcWy+PfOMqb7p4opKR+vE/BReGUG3q7Cl1S6BghDUWQ==",
"dependencies": {
"@openreplay/network-proxy": "^1.2.0",
"error-stack-parser": "^2.1.4",
"error-stack-parser-es": "^0.1.5",
"fflate": "^0.8.2",
"web-vitals": "^4.2.4"
},
"engines": {
"node": ">=14.0"
}
},
"node_modules/@openreplay/tracker-assist": {
"version": "11.0.8",
"resolved": "https://registry.npmjs.org/@openreplay/tracker-assist/-/tracker-assist-11.0.8.tgz",
"integrity": "sha512-Sj1q3MChiiWShGSKDcb10rCdlAVi0VqA+NUnEmdfdSYUlc/lQZWnU4EbpfwSiWd32Ns9pKIohlZPJoulcJ4sdg==",
"dependencies": {
"csstype": "^3.0.10",
"fflate": "^0.8.2",
"socket.io-client": "^4.8.1"
},
"peerDependencies": {
"@openreplay/tracker": ">=14.0.14"
}
},
"node_modules/@openreplay/tracker-assist/node_modules/engine.io-client": {
"version": "6.6.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz",
"integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.2.1",
"ws": "~8.17.1",
"xmlhttprequest-ssl": "~2.1.1"
}
},
"node_modules/@openreplay/tracker-assist/node_modules/engine.io-parser": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
"integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/@openreplay/tracker-assist/node_modules/fflate": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="
},
"node_modules/@openreplay/tracker-assist/node_modules/socket.io-client": {
"version": "4.8.1",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz",
"integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.2",
"engine.io-client": "~6.6.1",
"socket.io-parser": "~4.2.4"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/@openreplay/tracker-assist/node_modules/socket.io-parser": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/@openreplay/tracker-assist/node_modules/ws": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/@openreplay/tracker-assist/node_modules/xmlhttprequest-ssl": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz",
"integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/@openreplay/tracker/node_modules/fflate": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="
},
"node_modules/@opentelemetry/api": { "node_modules/@opentelemetry/api": {
"version": "1.9.0", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz",
@@ -14393,6 +14512,11 @@
"resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz",
"integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg=="
}, },
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
"node_modules/currently-unhandled": { "node_modules/currently-unhandled": {
"version": "0.4.1", "version": "0.4.1",
"resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
@@ -15811,6 +15935,22 @@
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
}, },
"node_modules/error-stack-parser": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
"integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
"dependencies": {
"stackframe": "^1.3.4"
}
},
"node_modules/error-stack-parser-es": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-0.1.5.tgz",
"integrity": "sha512-xHku1X40RO+fO8yJ8Wh2f2rZWVjqyhb1zgq1yZ8aZRQkv6OOKhKWRUaht3eSCUbAOBaKIgM+ykwFLE+QUxgGeg==",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/es-abstract": { "node_modules/es-abstract": {
"version": "1.19.0", "version": "1.19.0",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.0.tgz", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.0.tgz",
@@ -35822,6 +35962,11 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/stackframe": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
"integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="
},
"node_modules/static-extend": { "node_modules/static-extend": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
@@ -43127,6 +43272,11 @@
"defaults": "^1.0.3" "defaults": "^1.0.3"
} }
}, },
"node_modules/web-vitals": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz",
"integrity": "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw=="
},
"node_modules/webdriver-js-extender": { "node_modules/webdriver-js-extender": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz", "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz",
@@ -50488,6 +50638,95 @@
"read-package-json-fast": "^2.0.1" "read-package-json-fast": "^2.0.1"
} }
}, },
"@openreplay/network-proxy": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@openreplay/network-proxy/-/network-proxy-1.2.0.tgz",
"integrity": "sha512-vIOzBWVKn+7/Dk4qFmRxR1fdOEnLt1hXkEYtc3m7eIA2nVwz+BSGW4Hbs/ygFLnNS0HkcBwuRgmXAwRMK5HCrQ=="
},
"@openreplay/tracker": {
"version": "16.4.8",
"resolved": "https://registry.npmjs.org/@openreplay/tracker/-/tracker-16.4.8.tgz",
"integrity": "sha512-IB/yIzquRQAYGch55tkwXm0dKN2eKAzLNbxD6I21bKOlcWy+PfOMqb7p4opKR+vE/BReGUG3q7Cl1S6BghDUWQ==",
"requires": {
"@openreplay/network-proxy": "^1.2.0",
"error-stack-parser": "^2.1.4",
"error-stack-parser-es": "^0.1.5",
"fflate": "^0.8.2",
"web-vitals": "^4.2.4"
},
"dependencies": {
"fflate": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="
}
}
},
"@openreplay/tracker-assist": {
"version": "11.0.8",
"resolved": "https://registry.npmjs.org/@openreplay/tracker-assist/-/tracker-assist-11.0.8.tgz",
"integrity": "sha512-Sj1q3MChiiWShGSKDcb10rCdlAVi0VqA+NUnEmdfdSYUlc/lQZWnU4EbpfwSiWd32Ns9pKIohlZPJoulcJ4sdg==",
"requires": {
"csstype": "^3.0.10",
"fflate": "^0.8.2",
"socket.io-client": "^4.8.1"
},
"dependencies": {
"engine.io-client": {
"version": "6.6.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz",
"integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==",
"requires": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.2.1",
"ws": "~8.17.1",
"xmlhttprequest-ssl": "~2.1.1"
}
},
"engine.io-parser": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
"integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q=="
},
"fflate": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="
},
"socket.io-client": {
"version": "4.8.1",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz",
"integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==",
"requires": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.2",
"engine.io-client": "~6.6.1",
"socket.io-parser": "~4.2.4"
}
},
"socket.io-parser": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
"requires": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"
}
},
"ws": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
"requires": {}
},
"xmlhttprequest-ssl": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz",
"integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ=="
}
}
},
"@opentelemetry/api": { "@opentelemetry/api": {
"version": "1.9.0", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz",
@@ -55568,6 +55807,11 @@
} }
} }
}, },
"csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
"currently-unhandled": { "currently-unhandled": {
"version": "0.4.1", "version": "0.4.1",
"resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
@@ -56658,6 +56902,19 @@
} }
} }
}, },
"error-stack-parser": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
"integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
"requires": {
"stackframe": "^1.3.4"
}
},
"error-stack-parser-es": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-0.1.5.tgz",
"integrity": "sha512-xHku1X40RO+fO8yJ8Wh2f2rZWVjqyhb1zgq1yZ8aZRQkv6OOKhKWRUaht3eSCUbAOBaKIgM+ykwFLE+QUxgGeg=="
},
"es-abstract": { "es-abstract": {
"version": "1.19.0", "version": "1.19.0",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.0.tgz", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.0.tgz",
@@ -72104,6 +72361,11 @@
} }
} }
}, },
"stackframe": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
"integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="
},
"static-extend": { "static-extend": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
@@ -77812,6 +78074,11 @@
"defaults": "^1.0.3" "defaults": "^1.0.3"
} }
}, },
"web-vitals": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz",
"integrity": "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw=="
},
"webdriver-js-extender": { "webdriver-js-extender": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz", "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz",
+2
View File
@@ -118,6 +118,8 @@
"@ngrx/store": "^10.1.2", "@ngrx/store": "^10.1.2",
"@ngx-translate/core": "^13.0.0", "@ngx-translate/core": "^13.0.0",
"@ngxs/store": "^3.8.2", "@ngxs/store": "^3.8.2",
"@openreplay/tracker": "^16.4.8",
"@openreplay/tracker-assist": "^11.0.8",
"@opentelemetry/exporter-metrics-otlp-http": "^0.52.1", "@opentelemetry/exporter-metrics-otlp-http": "^0.52.1",
"@opentelemetry/exporter-trace-otlp-http": "^0.52.1", "@opentelemetry/exporter-trace-otlp-http": "^0.52.1",
"@opentelemetry/exporter-zipkin": "^1.25.1", "@opentelemetry/exporter-zipkin": "^1.25.1",
+215 -33
View File
@@ -103,49 +103,231 @@ import { registerLocaleData } from '@angular/common';
import localePt from '@angular/common/locales/pt'; import localePt from '@angular/common/locales/pt';
import { LogsDatabase } from './infra/database/dexie/instance/logs/service'; import { LogsDatabase } from './infra/database/dexie/instance/logs/service';
import { UserModule } from './module/user/user.module'; import { UserModule } from './module/user/user.module';
import { Logger } from './services/logger/main/service';
// Register the locale data // Register the locale data
registerLocaleData(localePt, 'pt'); registerLocaleData(localePt, 'pt');
Sentry.init( // Sentry.init(
{ // {
dsn: 'https://5b345a3ae70b4e4da463da65881b4aaa@o4504340905525248.ingest.sentry.io/4504345615794176', // dsn: 'https://5b345a3ae70b4e4da463da65881b4aaa@o4504340905525248.ingest.sentry.io/4504345615794176',
// To set your release and dist versions // // To set your release and dist versions
release: 'gabinetedigital@1.0.0', // release: 'gabinetedigital@1.0.0',
dist: '1', // dist: '1',
// Set tracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring. // // Set tracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring.
// We recommend adjusting this value in production. // // We recommend adjusting this value in production.
tracesSampleRate: 1.0, // tracesSampleRate: 1.0,
integrations: [ // integrations: [
new BrowserTracing({ // new BrowserTracing({
tracingOrigins: ['localhost', 'https://gd-api.oapr.gov.ao/api/'], // tracingOrigins: ['localhost', 'https://gd-api.oapr.gov.ao/api/'],
}) as Integration, // }) as Integration,
], // ],
beforeSend(event) { // beforeSend(event) {
console.log('event.exception.values[0].value', event.exception.values[0].value); // console.log('event.exception.values[0].value', event.exception.values[0].value);
if (event.level === 'error') { // if (event.level === 'error') {
LogsDatabase.sentryError.add(event as any).then(() => { // LogsDatabase.sentryError.add(event as any).then(() => {
console.log('event', event) // console.log('event', event)
}) // })
openTelemetryLogging.send({ // openTelemetryLogging.send({
level: 'info', // level: 'info',
message: event.exception.values[0].value, // message: event.exception.values[0].value,
payload: { // payload: {
object: { // object: {
sentry: true, // sentry: true,
error: event // error: event
// }
// },
// })
// }
// console.log('Sentry Event', event);
// // Return event to send it to Sentry
// return event;
// },
// }
// );
import Tracker from '@openreplay/tracker';
import trackerAssist from '@openreplay/tracker-assist'; // 👈 for errors, logs & stack traces
const tracker = new Tracker({
projectKey: "g8HOZiBi5iUWEsK3Ajw5",
__DISABLE_SECURE_MODE: true, // ✅ allow HTTP + localhost
});
tracker.start()
tracker.use(trackerAssist());
tracker.setUserID('john@doe.com');
(function () {
const httpLogs = [];
// --- Patch fetch ---
const originalFetch = window.fetch;
window.fetch = async (input, config = {}) => {
const url = typeof input === "string" ? input : (input as any).url;
const method = config?.method || "GET";
// Capture tracer header
let tracerHeader = null;
if (config?.headers) {
if (config.headers instanceof Headers) {
tracerHeader = config.headers.get("x-tracer");
} else if (typeof config.headers === "object") {
tracerHeader = config.headers["x-tracer"] || config.headers["X-Tracer"];
} }
},
})
} }
// Return event to send it to Sentry
return event; // Capture request body (payload)
}, let requestPayload = null;
if (config?.body) {
try {
requestPayload = typeof config.body === "string"
? config.body
: JSON.stringify(config.body);
} catch {
requestPayload = "[Unserializable body]";
} }
); }
const start = Date.now();
try {
const response = await originalFetch(input, config);
// Clone response so we dont consume it
const clone = response.clone();
let responsePayload = null;
try {
const contentType = clone.headers.get("content-type") || "";
if (contentType.includes("application/json")) {
responsePayload = await clone.json();
} else if (contentType.includes("text")) {
responsePayload = await clone.text();
} else {
responsePayload = "[Non-textual body]";
}
} catch {
responsePayload = "[Unserializable response]";
}
const log = {
type: "fetch",
url,
method,
status: response.status,
xTracer: tracerHeader,
requestPayload,
responsePayload,
duration: Date.now() - start,
timestamp: new Date().toISOString(),
};
if(response.status >= 400 || response.status === 0) {
Logger.error('XHR', log)
}
httpLogs.push(log);
return response;
} catch (error) {
const log = {
type: "fetch",
url,
method,
status: "NETWORK_ERROR",
xTracer: tracerHeader,
requestPayload,
responsePayload: null,
duration: Date.now() - start,
timestamp: new Date().toISOString(),
};
if(!url.includes('petermaquiran.xyz') && url != "") {
Logger.error('XHR', log);
}
httpLogs.push(log);
throw error;
}
};
// --- Patch XMLHttpRequest ---
const OriginalXHR = window.XMLHttpRequest;
function CustomXHR() {
const xhr: any = new OriginalXHR();
const start = Date.now();
xhr._xTracer = null;
xhr._requestPayload = null;
const originalSetRequestHeader = xhr.setRequestHeader;
xhr.setRequestHeader = function (key, value) {
if (key.toLowerCase() === "x-tracer") {
xhr._xTracer = value;
}
return originalSetRequestHeader.call(xhr, key, value);
};
const originalSend = xhr.send;
xhr.send = function (body) {
if (body) {
try {
xhr._requestPayload = typeof body === "string" ? body : JSON.stringify(body);
} catch {
xhr._requestPayload = "[Unserializable body]";
}
}
return originalSend.call(xhr, body);
};
xhr.addEventListener("loadend", function () {
let responsePayload = null;
try {
const contentType = xhr.getResponseHeader("content-type") || "";
if (contentType.includes("application/json")) {
responsePayload = JSON.parse(xhr.responseText);
} else if (contentType.includes("text")) {
responsePayload = xhr.responseText;
} else {
responsePayload = "[Non-textual body]";
}
} catch {
responsePayload = "[Unserializable response]";
}
const log = {
type: "xhr",
url: xhr.responseURL,
method: xhr._method || "GET",
status: xhr.status,
xTracer: xhr._xTracer,
requestPayload: xhr._requestPayload,
responsePayload,
duration: Date.now() - start,
timestamp: new Date().toISOString(),
};
if(xhr.status >= 400 || xhr.status === 0) {
Logger.error('XHR', log)
}
httpLogs.push(log);
});
const originalOpen = xhr.open;
xhr.open = function (method, url, ...rest) {
xhr._method = method;
return originalOpen.call(xhr, method, url, ...rest);
};
return xhr;
}
(window as any).XMLHttpRequest = CustomXHR;
// Expose logs
(window as any).getHttpLogs = () => httpLogs;
})();
@NgModule({ @NgModule({
declarations: [AppComponent, PopupQuestionPipe, InputFilterDirective], declarations: [AppComponent, PopupQuestionPipe, InputFilterDirective],
+47
View File
@@ -0,0 +1,47 @@
import { BaseEntity } from "src/app/utils/entity";
import { z } from "zod"
export const ActionEntitySchema = z.object({
processId: z.number(),
applicationId: z.number(),
organicEntityId: z.number(),
securityId: z.number(),
serieId: z.number(),
userId: z.number(),
dateIndex: z.string().datetime(), // ISO 8601 datetime
description: z.string(),
detail: z.string(),
dateBegin: z.string().datetime(),
dateEnd: z.string().datetime(),
actionType: z.number(),
location: z.string(),
isExported: z.boolean(),
sourceLocation: z.number(),
sourceProcessId: z.number(),
})
export type IAction = z.infer<typeof ActionEntitySchema>
export class ActionEntity extends BaseEntity<ActionEntity>(ActionEntitySchema) implements IAction{
processId: typeof ActionEntitySchema._input.processId
applicationId: typeof ActionEntitySchema._input.processId
organicEntityId: typeof ActionEntitySchema._input.processId
securityId: typeof ActionEntitySchema._input.processId
serieId: typeof ActionEntitySchema._input.processId
userId: typeof ActionEntitySchema._input.processId
dateIndex: typeof ActionEntitySchema._input.dateIndex
description: typeof ActionEntitySchema._input.description
detail: typeof ActionEntitySchema._input.detail
dateBegin: typeof ActionEntitySchema._input.dateBegin
dateEnd: typeof ActionEntitySchema._input.dateEnd
actionType: typeof ActionEntitySchema._input.processId
location: typeof ActionEntitySchema._input.location
isExported: typeof ActionEntitySchema._input.isExported
sourceLocation:typeof ActionEntitySchema._input.processId
sourceProcessId: typeof ActionEntitySchema._input.processId
constructor(data: IAction) {
super();
Object.assign(this, data)
}
}
@@ -0,0 +1,27 @@
import { z } from "zod"
export const PublicationDocumentEntitySchema = z.object({
id: z.number().optional(),
file: z.string(),
extension: z.string(),
name: z.string(),
path: z.string(),
documentId: z.number(),
datePublication: z.string(),
})
export type IPublicationDocument = z.infer<typeof PublicationDocumentEntitySchema>
export class PublicationDocumentEntity implements IPublicationDocument{
file: typeof PublicationDocumentEntitySchema._input.file
extension: typeof PublicationDocumentEntitySchema._input.extension
name: typeof PublicationDocumentEntitySchema._input.name
path: typeof PublicationDocumentEntitySchema._input.path
documentId: typeof PublicationDocumentEntitySchema._input.documentId
datePublication: typeof PublicationDocumentEntitySchema._input.datePublication
id: typeof PublicationDocumentEntitySchema._input.id
constructor(data: IPublicationDocument) {
Object.assign(this, data)
}
}
@@ -0,0 +1,43 @@
import { BaseEntity } from "src/app/utils/entity";
import { z } from "zod"
export const PublicationEntitySchema = z.object({
processId: z.number(),
documentId: z.number(),
applicationId: z.number(),
organicEntityId: z.number(),
securityId: z.number(),
userId: z.number(),
dateIndex: z.string(),
phase: z.number(),
title: z.string(),
message: z.string(),
datePublication: z.string(),
isExported: z.boolean(),
sourceLocation: z.number(),
sourceProcessId: z.number(),
sourceDocumentId: z.number(),
})
export type IPublication = z.infer<typeof PublicationEntitySchema>
export class PublicationEntity extends BaseEntity<PublicationEntity>(PublicationEntitySchema) implements IPublication{
processId: typeof PublicationEntitySchema._input.processId
applicationId: typeof PublicationEntitySchema._input.processId
organicEntityId: typeof PublicationEntitySchema._input.processId
securityId: typeof PublicationEntitySchema._input.processId
serieId: typeof PublicationEntitySchema._input.processId
userId: typeof PublicationEntitySchema._input.processId
dateIndex: typeof PublicationEntitySchema._input.dateIndex
isExported: typeof PublicationEntitySchema._input.isExported
sourceLocation:typeof PublicationEntitySchema._input.processId
sourceProcessId: typeof PublicationEntitySchema._input.processId
sourceDocumentId:typeof PublicationEntitySchema._input.sourceDocumentId
documentId: typeof PublicationEntitySchema._input.documentId
datePublication: typeof PublicationEntitySchema._input.datePublication
constructor(data: IPublication) {
super();
Object.assign(this, data)
}
}
@@ -0,0 +1,36 @@
import { Injectable } from '@angular/core';
import { ActionLocalRepositoryService } from 'src/app/module/actions/data/repository/action-local-repository.service';
import { ActionRemoteRepositoryService } from 'src/app/module/actions/data/repository/action-remote-repository.service';
import { z } from 'zod';
export const ActionsCreateInputDTOSchema = z.object({
userId: z.number(),
description: z.string(),
detail: z.string(),
location: z.string(),
dateBegin: z.string().refine((val) => !isNaN(Date.parse(val)), {
message: "Invalid ISO date string",
}),
dateEnd: z.string().refine((val) => !isNaN(Date.parse(val)), {
message: "Invalid ISO date string",
}),
actionType: z.string(),
});
export type ActionsCreateInput = z.infer<typeof ActionsCreateInputDTOSchema>
@Injectable({
providedIn: 'root'
})
export class ActionsCreateUseCaseService {
constructor(
private remote: ActionRemoteRepositoryService,
private local: ActionLocalRepositoryService
) { }
execute(input: ActionsCreateInput) {
this.remote.create(input);
}
}
@@ -0,0 +1,53 @@
import { Injectable } from '@angular/core';
import { ActionLocalRepositoryService } from 'src/app/module/actions/data/repository/action-local-repository.service';
import { ActionRemoteRepositoryService } from 'src/app/module/actions/data/repository/action-remote-repository.service';
import { z } from "zod";
export const ActionGetAllOutPutSchema = z.array(z.object({
processId: z.number(),
applicationId: z.number(),
organicEntityId: z.number(),
securityId: z.number(),
serieId: z.number(),
userId: z.number(),
dateIndex: z.string().datetime(), // ISO 8601 datetime
description: z.string(),
detail: z.string(),
dateBegin: z.string().datetime(),
dateEnd: z.string().datetime(),
actionType: z.number(),
location: z.string(),
isExported: z.boolean(),
sourceLocation: z.number(),
sourceProcessId: z.number(),
}));
// Example usage:
export type ActionGetAllOutPut = z.infer<typeof ActionGetAllOutPutSchema>;
@Injectable({
providedIn: 'root'
})
export class ActionsGetAllUseCaseService {
constructor(
private remote: ActionRemoteRepositoryService,
private local: ActionLocalRepositoryService
) { }
async execute() {
var result = await this.remote.actionGetAll();
if(result.isOk()) {
const data = result.value.data.data;
this.local.createTransaction( async (table) => {
// Clear the table before inserting new data
await table.clear();
// Insert the new data
await table.bulkAdd(data);
});
}
}
}
@@ -0,0 +1,105 @@
import { Injectable } from '@angular/core';
import { Result } from 'neverthrow';
import { PublicationFileLocalRepositoryService } from 'src/app/module/actions/data/repository/publication-file-local-repository.service';
import { PublicationFileRemoteRepositoryService } from 'src/app/module/actions/data/repository/publication-file-remote-repository.service';
import { z } from 'zod';
import { HttpErrorResponse } from '@angular/common/http';
export const PublicationFileGetByDocumentIdInputDTOSchema = z.object({
datePublication: z.string(),
documentId: z.number(),
processId: z.number(),
});
export type PublicationFileGetByDocumentIdInput = z.infer<typeof PublicationFileGetByDocumentIdInputDTOSchema>
export const PublicationFileGetByDocumentIdOutPutDTOSchema = z.object({
id: z.number().optional(),
file: z.string(),
extension: z.string(),
name: z.string(),
path: z.string(),
documentId: z.number(),
datePublication: z.string(),
}).array();
export type PublicationFileGetByDocumentIdOutPut = z.infer<typeof PublicationFileGetByDocumentIdOutPutDTOSchema>
export interface IPublicationFilesSyncResult {
added: PublicationFileGetByDocumentIdOutPut;
updated: PublicationFileGetByDocumentIdOutPut;
remove: PublicationFileGetByDocumentIdOutPut;
}
@Injectable({
providedIn: 'root'
})
export class PublicationFileGetByDocumentIdService {
constructor(
private local: PublicationFileLocalRepositoryService,
private remote: PublicationFileRemoteRepositoryService
) { }
async execute(input: PublicationFileGetByDocumentIdInput): Promise<Result<IPublicationFilesSyncResult, HttpErrorResponse>> {
var httpResult = await this.remote.FileListByDocumentId(input);
if(httpResult.isOk()) {
var localResult = await this.local.findAll();
if(localResult.isOk()) {
const serverFiles = httpResult.value.data
const added = [];
const updated = [];
const remove = [];
for (const localItem of localResult.value) {
if (localItem.datePublication !== input.datePublication!) {
localItem.datePublication = input.datePublication;
this.local.update(localItem.id, localItem);
}
}
for (const file of serverFiles) {
const findLocally = await this.local.findOne({ name: file.name });
if (findLocally.isOk() && findLocally.value == null) {
added.push({
...file,
documentId: input.documentId!,
datePublication: input.datePublication,
});
const start = performance.now();
this.local.insert({
...file,
documentId: input.documentId!,
datePublication: input.datePublication,
}).then(() => {
const end = performance.now();
console.log(`Insert duration for file "${file.name}": ${(end - start).toFixed(2)} ms`);
});
}
}
for (const localFile of localResult.value) {
const found = httpResult.value.data.filter((e) => e.name === localFile.name);
if (found.length === 0 && localFile.name) {
remove.push(localFile);
this.local.delete(localFile.id);
}
}
return httpResult.map(() =>({
added,
updated,
remove
}))
}
}
return httpResult.map(() =>({
added: [],
updated: [],
remove: []
}));
}
}
@@ -0,0 +1,32 @@
import { Injectable } from '@angular/core';
import { ActionLocalRepositoryService } from 'src/app/module/actions/data/repository/action-local-repository.service';
import { ActionRemoteRepositoryService } from 'src/app/module/actions/data/repository/action-remote-repository.service';
import { z } from 'zod';
const PublicationGetDocumentByProcessIdOutPutSchema = z.object({
file: z.string(),
extension: z.string(),
name: z.string(),
path: z.string(),
documentId: z.number()
}).array();
// Example usage:
export type PublicationGetDocumentByProcessIdOutPut = z.infer<typeof PublicationGetDocumentByProcessIdOutPutSchema>;
@Injectable({
providedIn: 'root'
})
export class PublicationGetDocumentByProcessIdService {
constructor(
private remote: ActionRemoteRepositoryService,
private local: ActionLocalRepositoryService
) {}
execute(processId: string) {
this.remote
}
}
@@ -0,0 +1,134 @@
import { Injectable } from '@angular/core';
import { PublicationLocalRepositoryService } from 'src/app/module/actions/data/repository/publication-local-repository.service';
import { PublicationRemoteRepositoryService } from 'src/app/module/actions/data/repository/publication-remote-repository.service';
import { z } from 'zod';
import { IPublication } from '../entity/publicationEntity';
import { Result } from 'neverthrow';
import { HttpErrorResponse } from '@angular/common/http';
const PublicationListByProcessIdOutPutSchema = z.object({
processId: z.number(),
documentId: z.number(),
applicationId: z.number(),
organicEntityId: z.number(),
securityId: z.number(),
userId: z.number(),
dateIndex: z.string().datetime(),
phase: z.number(),
title: z.string(),
message: z.string(),
datePublication: z.string().datetime(),
isExported: z.boolean(),
sourceLocation: z.number(),
sourceProcessId: z.number(),
sourceDocumentId: z.number(),
}).array();
// Example usage:
export type PublicationListByProcessIdOutPut = z.infer<typeof PublicationListByProcessIdOutPutSchema>;
export interface IPublicationSyncResult {
added: IPublication[];
updated: IPublication[];
remove: IPublication[];
}
@Injectable({
providedIn: 'root'
})
export class PublicationListByProcessIdService {
constructor(
private remote: PublicationRemoteRepositoryService,
private local: PublicationLocalRepositoryService,
) {}
async execute(processId: number): Promise<Result<IPublicationSyncResult, HttpErrorResponse>> {
const result = await this.remote.listByProcessId(processId);
if(result.isOk()) {
const publications = result.value.data.data || [];
var localList = await this.local.findAll();
if(localList.isOk()) {
const localMap = new Map(
localList.value.map(item => [item.documentId.toString(), item])
);
var serverMap = new Map(
publications.map(item => [item.documentId.toString(), item])
);
const added = [];
const updated = [];
const remove = [];
console.log("local::", localList.value.length);
console.log("server::", publications.length);
// detect added & updated
for (const [id, serverItem] of serverMap) {
if (!localMap.has(id)) {
console.log(localList.value.map(item => item.documentId.toString()).join(","), id);
added.push(serverMap.get(id));
} else if (serverItem.datePublication !== localMap.get(id).datePublication) {
updated.push(serverMap.get(id));
console.log('update');
} else {
console.log('else');
console.log(localMap, serverMap);
}
}
// detect removed
for (const [id, localItem] of Object.keys(localMap)) {
if (!serverMap.has(id)) {
remove.push(localMap.get(id));
}
}
console.log("update::", Object.keys(updated).length);
console.log("added::", added.length);
console.log("remove::", remove.length);
// apply updates
if (updated.length > 0) {
await this.local.updateMany(Object.values(updated));
}
// apply removals
for (const deletedItem of remove) {
const findRequest = await this.local.findOne({
documentId: deletedItem.documentId
});
if (findRequest.isOk()) {
await this.local.delete(findRequest.value.documentId!);
}
}
// apply inserts
if (added.length > 0) {
await this.local.insertMany(added);
}
return result.map(()=>({
added,
updated,
remove
}))
}
}
return result.map(()=>({
added: [],
updated: [],
remove: []
}))
}
}
+1 -1
View File
@@ -14,7 +14,7 @@ const UserSchema = z.object({
wxUserId: z.number(), wxUserId: z.number(),
wxFullName: z.string(), wxFullName: z.string(),
wxeMail: z.string(), wxeMail: z.string(),
userPhoto: z.string().nullable(), userPhoto: z.string().nullable().optional(),
}); });
const MemberSchema = z.object({ const MemberSchema = z.object({
@@ -0,0 +1,12 @@
import { DexieRepository } from "src/app/infra/repository/dexie/dexie-repository.service";
import { Observable as DexieObservable, PromiseExtended } from 'Dexie';
import { AttachmentTable } from "src/app/infra/database/dexie/instance/chat/schema/attachment";
import { Result } from "neverthrow";
import { MemberTable, MemberTableSchema } from "src/app/infra/database/dexie/instance/chat/schema/members";
import { RepositoryResult } from "src/app/infra/repository";
import { z } from "zod";
import { MemberListUPdateStatusInputDTO } from "src/app/core/chat/usecase/socket/member-list-update-status-use-case.service";
import { Observable } from "rxjs";
import { ActionTable } from "src/app/infra/database/dexie/instance/action/schema/action";
export abstract class IActionLocalRepository extends DexieRepository<ActionTable, ActionTable> {}
@@ -7,6 +7,7 @@ import { IMemberRemoteRepository } from 'src/app/core/chat/repository/member/mem
export const AddMemberToRoomInputDTOSchema = z.object({ export const AddMemberToRoomInputDTOSchema = z.object({
id: z.string(), id: z.string(),
members: z.array(z.number()), members: z.array(z.number()),
userId: z.number()
}); });
export type AddMemberToRoomInputDTO = z.infer<typeof AddMemberToRoomInputDTOSchema> export type AddMemberToRoomInputDTO = z.infer<typeof AddMemberToRoomInputDTOSchema>
@@ -5,6 +5,7 @@ import { IMemberRemoteRepository } from 'src/app/core/chat/repository/member/mem
// Define the schema for the entire response // Define the schema for the entire response
const MemberSetAdminDTOSchema = z.object({ const MemberSetAdminDTOSchema = z.object({
senderId: z.number(),
roomId: z.string(), roomId: z.string(),
memberId: z.string() memberId: z.string()
}); });
@@ -25,7 +25,7 @@ export class ListenMessageByRoomIdNewUseCase {
return this.MessageSocketRepositoryService.listenToMessages().pipe( return this.MessageSocketRepositoryService.listenToMessages().pipe(
map(message => message.data), map(message => message.data),
filter((message) => message.deviceId != getInstanceId()), filter((message) => message?.deviceId != getInstanceId()),
map(message => { map(message => {
return Object.assign(new MessageEntity(), message) return Object.assign(new MessageEntity(), message)
}) })
@@ -25,7 +25,7 @@ export class ListenSendMessageUseCase {
return this.MessageSocketRepositoryService.listenToMessages().pipe( return this.MessageSocketRepositoryService.listenToMessages().pipe(
map(message => message.data), map(message => message.data),
filter((message) => message.deviceId != getInstanceId()), filter((message) => message?.deviceId != getInstanceId()),
map(message => message) map(message => message)
) )
@@ -138,7 +138,7 @@ export class MessageCreateUseCaseService {
var a = await this.MessageRemoteRepository.messageAttachmentUpload({ var a = await this.MessageRemoteRepository.messageAttachmentUpload({
fileType: att.fileType, fileType: att.fileType,
source: att.source, source: att.source,
file: isWebtrix ? null : att.base64.replace(/^data:[a-zA-Z]+\/[a-zA-Z]+;base64,/, ''), file: isWebtrix ? null : att.base64.split(",")[1],
fileName: att.fileName, fileName: att.fileName,
applicationId: att.applicationId || 0, applicationId: att.applicationId || 0,
docId: att.docId || 0, docId: att.docId || 0,
@@ -83,7 +83,7 @@ export class SendLocalMessagesUseCaseService {
var a = await this.MessageRemoteRepository.messageAttachmentUpload({ var a = await this.MessageRemoteRepository.messageAttachmentUpload({
fileType: att.fileType, fileType: att.fileType,
source: att.source, source: att.source,
file: isWebtrix ? null : att.base64.replace(/^data:[a-zA-Z]+\/[a-zA-Z]+;base64,/, ''), file: isWebtrix ? null : att.base64.split(",")[1],
fileName: att.fileName, fileName: att.fileName,
applicationId: att.applicationId || 0, applicationId: att.applicationId || 0,
docId: att.docId || 0, docId: att.docId || 0,
@@ -37,7 +37,7 @@ export class RoomBoldSyncUseCaseService {
private listenToIncomingMessage() { private listenToIncomingMessage() {
return this.MessageSocketRepositoryService.listenToMessages().pipe( return this.MessageSocketRepositoryService.listenToMessages().pipe(
map(message => message.data), map(message => message.data),
filter((message) => message.deviceId != getInstanceId()), filter((message) => message?.deviceId != getInstanceId()),
map(message => Object.assign(new MessageEntity(), message)), map(message => Object.assign(new MessageEntity(), message)),
filter((message) => !message.meSender()) filter((message) => !message.meSender())
).subscribe(async (message) => { ).subscribe(async (message) => {
@@ -59,7 +59,7 @@ export class RoomBoldSyncUseCaseService {
*/ */
private listenToUpdateMessages() { private listenToUpdateMessages() {
return this.MessageSocketRepositoryService.listenToUpdateMessages().pipe( return this.MessageSocketRepositoryService.listenToUpdateMessages().pipe(
filter((message) => message.deviceId != getInstanceId()), filter((message) => message?.deviceId != getInstanceId()),
map(message => Object.assign(new MessageEntity(), message)) map(message => Object.assign(new MessageEntity(), message))
).subscribe(async (message) => { ).subscribe(async (message) => {
+1 -1
View File
@@ -98,7 +98,7 @@ const UserSessionSchema = z.object({
Inactivity: z.boolean(), Inactivity: z.boolean(),
UrlBeforeInactivity: z.string(), UrlBeforeInactivity: z.string(),
UserPermissions: z.unknown(), // Again, you can define it more explicitly if needed UserPermissions: z.unknown(), // Again, you can define it more explicitly if needed
UserPhoto: z.string().nullable(), UserPhoto: z.string().nullable().optional(),
RefreshToken: z.string(), RefreshToken: z.string(),
}); });
@@ -17,7 +17,7 @@ const UserSchema = z.object({
wxeMail: z.string(), wxeMail: z.string(),
role: z.string(), role: z.string(),
roleId: z.number(), roleId: z.number(),
userPhoto: z.string().nullable(), userPhoto: z.string().nullable().optional(),
adUserSID: z.string(), adUserSID: z.string(),
}); });
@@ -0,0 +1,27 @@
import { EntityTable } from 'Dexie';
import { z } from 'zod';
export enum ActionDetailsStatus {
editedLocal,
deletedLocal,
offline,
pending,
sending,
synced,
}
export const ActionTableSchema = z.object({
processId: z.number().nullable().optional(),
//localProcessId: z.string(), // unique identifier
dateIndex: z.string().transform((val) => new Date(val)), // store as ISO string, transform to Date
description: z.string(),
detail: z.string(),
dateBegin: z.string().transform((val) => new Date(val)),
dateEnd: z.string().transform((val) => new Date(val)),
statusIndex: z.number().int().min(0).max(Object.keys(ActionDetailsStatus).length / 2 - 1),
errorCreating: z.boolean().nullable().optional(),
})
export type ActionTable = z.infer<typeof ActionTableSchema>;
export type DexieActionTable = EntityTable<ActionTable, 'processId'>;
export const ActionTableColumn = 'processId, dateIndex, description, detail, dateBegin, dateEnd, statusIndex, errorCreating';
@@ -0,0 +1,24 @@
import { EntityTable } from 'Dexie';
import { z } from 'zod';
export const PublicationTableSchema = z.object({
processId: z.number(),
documentId: z.number(),
applicationId: z.number(),
organicEntityId: z.number(),
securityId: z.number(),
userId: z.number(),
dateIndex: z.string(),
phase: z.number(),
title: z.string(),
message: z.string(),
datePublication: z.string(),
isExported: z.boolean(),
sourceLocation: z.number(),
sourceProcessId: z.number(),
sourceDocumentId: z.number(),
})
export type PublicationTable = z.infer<typeof PublicationTableSchema>;
export type DexiePublicationTable = EntityTable<PublicationTable, 'documentId'>;
export const PublicationTableColumn = 'documentId, processId, applicationId, organicEntityId, securityId, userId, dateIndex, phase, title, message, datePublication, sourceLocation, sourceProcessId, isExported, sourceDocumentId';
@@ -0,0 +1,16 @@
import { EntityTable } from 'Dexie';
import { z } from 'zod';
export const PublicationFileTableSchema = z.object({
id: z.number().optional(),
file: z.string(),
extension: z.string(),
name: z.string(),
path: z.string(),
documentId: z.number(),
datePublication: z.string(),
})
export type PublicationFileTable = z.infer<typeof PublicationFileTableSchema>;
export type DexiePublicationFilesTable = EntityTable<PublicationFileTable, 'id'>;
export const PublicationFileTableColumn = '++id, file, extension, name, path, documentId, datePublication';
@@ -0,0 +1,22 @@
import { Dexie } from 'Dexie';
import { ActionTableColumn, DexieActionTable } from './schema/action';
import { DexiePublicationTable, PublicationTable, PublicationTableColumn } from './schema/publication';
import { DexiePublicationFilesTable, PublicationFileTable, PublicationFileTableColumn } from './schema/publicationFile';
import FDBFactory from 'fake-indexeddb/lib/FDBFactory';
import FDBKeyRange from 'fake-indexeddb/lib/FDBKeyRange';
export const actionDatabase = new Dexie('action-database-v1', {
indexedDB: new FDBFactory,
IDBKeyRange: FDBKeyRange, // Mocking IDBKeyRange
}) as Dexie & {
action: DexieActionTable,
publication: DexiePublicationTable,
publicationFile: DexiePublicationFilesTable
};
actionDatabase.version(1).stores({
action: ActionTableColumn,
publication: PublicationTableColumn,
publicationFile: PublicationFileTableColumn
});
+18 -78
View File
@@ -3,9 +3,9 @@ import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { ok, err, Result } from 'neverthrow'; import { ok, err, Result } from 'neverthrow';
import { HttpResult } from './type'; import { HttpResult } from './type';
import { BehaviorSubject, Observable } from 'rxjs'; import { BehaviorSubject } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { IHttpOptions } from './adapter'; import { IHttpOptions } from './adapter';
import { TracingType } from 'src/app/services/monitoring/opentelemetry/tracer';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@@ -16,15 +16,15 @@ export class HttpService {
constructor(private http: HttpClient) { } constructor(private http: HttpClient) { }
async post<T>(url: string, body: any): Promise<Result<HttpResult<T>, HttpErrorResponse>> { private async handleRequest<T>(fux: Function, tracing?: TracingType, url?: string, method?: string): Promise<Result<HttpResult<T>, HttpErrorResponse>> {
var response = await fux(tracing) as HttpResponse<T>
try { try {
const response = await this.http.post<T>(url, body, { observe: 'response' }).toPromise();
const data = { const data = {
data: response.body, data: response.body,
status: response.status, status: response.status,
headers: response.headers, headers: response.headers,
url: response.url || url, url: response.url || url,
method: '', method: method || '',
} }
this.responseSubject.next(ok(data)) this.responseSubject.next(ok(data))
return ok(data); return ok(data);
@@ -34,8 +34,12 @@ export class HttpService {
} }
} }
async get<T>(url: string, options?: IHttpOptions): Promise<Result<HttpResult<T>, HttpErrorResponse>> { async post<T>(url: string, body: any, tracing?: TracingType): Promise<Result<HttpResult<T>, HttpErrorResponse>> {
try { return await this.handleRequest<T>(async () => await this.http.post<T>(url, body, { observe: 'response' }).toPromise(), tracing, url, 'POST')
}
async get<T>(url: string, options?: IHttpOptions, tracing?: TracingType): Promise<Result<HttpResult<T>, HttpErrorResponse>> {
let httpParams = new HttpParams(); let httpParams = new HttpParams();
if (options?.params) { if (options?.params) {
Object.keys(options.params).forEach(key => { Object.keys(options.params).forEach(key => {
@@ -51,88 +55,24 @@ export class HttpService {
headers: options?.headers as any || new HttpHeaders(), headers: options?.headers as any || new HttpHeaders(),
responseType: options?.responseType || 'json' as any, responseType: options?.responseType || 'json' as any,
}; };
return await this.handleRequest<T>(async () => await this.http.get<T>(url, { ...httpOptions, observe: 'response', responseType: httpOptions.responseType }).toPromise(), tracing, url, 'GET')
const response = await this.http.get<T>(url, { ...httpOptions, observe: 'response', responseType: httpOptions.responseType }).toPromise();
const data = {
method: 'GET',
data: response.body,
status: response.status,
headers: response.headers,
url: response.url || url
} }
this.responseSubject.next(ok(data)) async put<T>(url: string, body: any, tracing?: TracingType): Promise<Result<HttpResult<T>, HttpErrorResponse>> {
return ok(data); return await this.handleRequest<T>(async () => await this.http.put<T>(url, body, { observe: 'response' }).toPromise(), tracing, url, 'PUT')
} catch (e) {
this.responseSubject.next(err(e))
return err(e as HttpErrorResponse);
}
} }
async put<T>(url: string, body: any): Promise<Result<HttpResult<T>, HttpErrorResponse>> { async patch<T>(url: string, body: any = {}, tracing?: TracingType): Promise<Result<HttpResult<T>, HttpErrorResponse>> {
try { return await this.handleRequest<T>(async () => await this.http.patch<T>(url, body, { observe: 'response' }).toPromise(), tracing,url, 'PATCH');
const response = await this.http.put<T>(url, body, { observe: 'response' }).toPromise();
const data = {
data: response.body,
status: response.status,
headers: response.headers,
url: response.url || url,
method: '',
} }
this.responseSubject.next(ok(data)) async delete<T>(url: string, body = {}, tracing?: TracingType): Promise<Result<HttpResult<T>, HttpErrorResponse>> {
return ok(data);
} catch (e) {
this.responseSubject.next(err(e))
return err(e as HttpErrorResponse);
}
}
async patch<T>(url: string, body: any = {}): Promise<Result<HttpResult<T>, HttpErrorResponse>> {
try {
const response = await this.http.patch<T>(url, body, { observe: 'response' }).toPromise();
const data = {
data: response.body,
status: response.status,
headers: response.headers,
url: response.url || url,
method: '',
}
this.responseSubject.next(ok(data))
return ok(data);
} catch (e) {
this.responseSubject.next(err(e))
return err(e as HttpErrorResponse);
}
}
async delete<T>(url: string, body = {}): Promise<Result<HttpResult<T>, HttpErrorResponse>> {
const options = { const options = {
body: body, // Pass payload as the body of the request body: body, // Pass payload as the body of the request
observe: 'response' as 'body' observe: 'response' as 'body'
}; };
try { return await this.handleRequest<T>(async () => await this.http.delete<T>(url, options).toPromise(), tracing, url, 'DELETE');
const response: any = await this.http.delete<T>(url, options).toPromise();
const data = {
data: response?.body,
status: response?.status,
headers: response?.headers,
url: response?.url || url,
method: '',
}
this.responseSubject.next(ok(data))
return ok(data as any);
} catch (e) {
this.responseSubject.next(err(e))
return err(e as HttpErrorResponse);
}
} }
listen() { listen() {
+7
View File
@@ -15,3 +15,10 @@ export interface HttpResult<T> {
} }
export type IHttPReturn<T> = Promise<Result<HttpResult<T>, HttpErrorResponse>> export type IHttPReturn<T> = Promise<Result<HttpResult<T>, HttpErrorResponse>>
export interface ApiResponse<T> {
success: boolean,
message: string,
data: T
}
@@ -13,8 +13,6 @@ export class MetricsInterceptor implements HttpInterceptor {
if (event instanceof HttpResponse) { if (event instanceof HttpResponse) {
// Capture the status code and check protocol // Capture the status code and check protocol
if (req.method !== 'GET' && !req.urlWithParams.includes('metrics')) { if (req.method !== 'GET' && !req.urlWithParams.includes('metrics')) {
console.log('response', event.body)
const path = req.urlWithParams; const path = req.urlWithParams;
const url = new URL(path); const url = new URL(path);
if (window.location.protocol !== 'https:') { if (window.location.protocol !== 'https:') {
@@ -4,9 +4,6 @@ import { ZodError, ZodObject, ZodSchema } from 'zod';
import { Logger } from 'src/app/services/logger/main/service'; import { Logger } from 'src/app/services/logger/main/service';
import { IDexieRepository, ILocalModel, RepositoryResult } from '../adapter' import { IDexieRepository, ILocalModel, RepositoryResult } from '../adapter'
import { IDBError, IDBErrorParams, IDexieError } from '../types'; import { IDBError, IDBErrorParams, IDexieError } from '../types';
// Define a type for the Result of repository operations
class DBError<T> extends Error implements IDBError<T> { class DBError<T> extends Error implements IDBError<T> {
zodError?: ZodError<T>; zodError?: ZodError<T>;
parameters: T; parameters: T;
@@ -160,7 +160,7 @@ const OwnerSchema = z.object({
wxUserId: z.number(), wxUserId: z.number(),
wxFullName: z.string(), wxFullName: z.string(),
wxeMail: z.string(), wxeMail: z.string(),
userPhoto: z.string().nullable(), userPhoto: z.string().nullable().optional(),
}); });
@@ -0,0 +1,14 @@
import { Injectable } from '@angular/core';
import { IActionLocalRepository } from 'src/app/core/chat/repository/action/member-local-repository';
import { ActionTable, ActionTableSchema } from 'src/app/infra/database/dexie/instance/action/schema/action';
import { actionDatabase } from 'src/app/infra/database/dexie/instance/action/service';
import { DexieRepository } from 'src/app/infra/repository/dexie/dexie-repository.service';
@Injectable({
providedIn: 'root'
})
export class ActionLocalRepositoryService extends DexieRepository<ActionTable, ActionTable> implements IActionLocalRepository {
constructor() {
super(actionDatabase.action, ActionTableSchema, actionDatabase)
}
}
@@ -0,0 +1,47 @@
import { Injectable } from '@angular/core';
import { ActionsCreateInput } from 'src/app/core/actions/use-case/actions-create-use-case.service';
import { ActionGetAllOutPut } from 'src/app/core/actions/use-case/actions-get-all-use-case.service';
import { PublicationGetDocumentByProcessIdOutPut } from 'src/app/core/actions/use-case/publication-get-documents-by-document-id.service';
import { PublicationListByProcessIdOutPut } from 'src/app/core/actions/use-case/publication-list-by-process-id.service';
import { HttpService } from 'src/app/infra/http/http.service';
import { ApiResponse } from 'src/app/infra/http/type';
import { environment } from 'src/environments/environment';
@Injectable({
providedIn: 'root'
})
export class ActionRemoteRepositoryService {
private baseUrl = `${environment.apiURLStage.slice(0, -1)}/PresidentialActions`; // Your base URL
constructor(
private http: HttpService
) { }
async actionGetAll() {
return await this.http.get<ApiResponse<ActionGetAllOutPut>>(`${this.baseUrl}`);
}
async create(input: ActionsCreateInput) {
return await this.http.post<ApiResponse<any>>(`${this.baseUrl}`, input);
}
async postGetListByProcessId(processId: string) {
return await this.http.get<ApiResponse<PublicationListByProcessIdOutPut>>(`${this.baseUrl}/${processId}/Posts`);
}
async postGetDocumentListByProcessId(documentId: number) {
var result = await this.http.get<ApiResponse<PublicationGetDocumentByProcessIdOutPut>>(`${this.baseUrl}/Posts/${documentId}/file`);
return result.map((e) => {
// Add a new attribute to each item
e.data.data = e.data.data.map((item) => ({
...item,
documentId,
}));
return e;
});
}
}
@@ -0,0 +1,14 @@
import { Injectable } from '@angular/core';
import { PublicationFileTable, PublicationFileTableSchema } from 'src/app/infra/database/dexie/instance/action/schema/publicationFile';
import { actionDatabase } from 'src/app/infra/database/dexie/instance/action/service';
import { DexieRepository } from 'src/app/infra/repository/dexie/dexie-repository.service';
@Injectable({
providedIn: 'root'
})
export class PublicationFileLocalRepositoryService extends DexieRepository<PublicationFileTable, PublicationFileTable> {
constructor() {
super(actionDatabase.publicationFile, PublicationFileTableSchema, actionDatabase)
}
}
@@ -0,0 +1,27 @@
import { Injectable } from '@angular/core';
import { PublicationFileGetByDocumentIdInput, PublicationFileGetByDocumentIdOutPut } from 'src/app/core/actions/use-case/publication-file-get-by-document-id.service';
import { PublicationListByProcessIdOutPut } from 'src/app/core/actions/use-case/publication-list-by-process-id.service';
import { ApiResponse } from 'src/app/infra/http/type';
import { HttpService } from 'src/app/services/http.service';
import { environment } from 'src/environments/environment';
@Injectable({
providedIn: 'root'
})
export class PublicationFileRemoteRepositoryService {
private baseUrl = `${environment.apiURLStage.slice(0, -1)}/PresidentialActions`; // Your base URL
constructor(
private http: HttpService
) { }
async listByProcessId(processId: string) {
console.log(this.baseUrl);
return await this.http.get<ApiResponse<PublicationListByProcessIdOutPut>>(`${this.baseUrl}/${processId}/Posts`);
}
async FileListByDocumentId(input: PublicationFileGetByDocumentIdInput) {
return await this.http.get<ApiResponse<PublicationFileGetByDocumentIdOutPut>>(`${this.baseUrl}/Posts/${input.documentId}/file`);
}
}
@@ -0,0 +1,9 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class PublicationFileRepositoryService {
constructor() { }
}
@@ -0,0 +1,15 @@
import { Injectable } from '@angular/core';
import { PublicationTable, PublicationTableSchema } from 'src/app/infra/database/dexie/instance/action/schema/publication';
import { PublicationFileTable } from 'src/app/infra/database/dexie/instance/action/schema/publicationFile';
import { actionDatabase } from 'src/app/infra/database/dexie/instance/action/service';
import { DexieRepository } from 'src/app/infra/repository/dexie/dexie-repository.service';
@Injectable({
providedIn: 'root'
})
export class PublicationLocalRepositoryService extends DexieRepository<PublicationTable, PublicationTable> {
constructor() {
super(actionDatabase.publication, PublicationTableSchema, actionDatabase)
}
}
@@ -0,0 +1,21 @@
import { Injectable } from '@angular/core';
import { PublicationListByProcessIdOutPut } from 'src/app/core/actions/use-case/publication-list-by-process-id.service';
import { HttpService } from 'src/app/infra/http/http.service';
import { ApiResponse } from 'src/app/infra/http/type';
import { environment } from 'src/environments/environment';
@Injectable({
providedIn: 'root'
})
export class PublicationRemoteRepositoryService {
private baseUrl = `${environment.apiURLStage.slice(0, -1)}/PresidentialActions`; // Your base URL
constructor(
private http: HttpService
) { }
async listByProcessId(processId: number) {
return await this.http.get<ApiResponse<PublicationListByProcessIdOutPut>>(`${this.baseUrl}/${processId}/Posts`);
}
}
@@ -1,4 +1,3 @@
import { z } from "zod";
import { SharedCalendarListItemOutputDTO } from "../../dto/sharedCalendarOutputDTO"; import { SharedCalendarListItemOutputDTO } from "../../dto/sharedCalendarOutputDTO";
type Changes = { type Changes = {
@@ -28,14 +28,14 @@ const OwnerSchema = z.object({
wxUserId: z.number(), wxUserId: z.number(),
wxFullName: z.string(), wxFullName: z.string(),
wxeMail: z.string(), wxeMail: z.string(),
userPhoto: z.string().nullable(), userPhoto: z.string().nullable().optional(),
}); });
const OrganizerSchema = z.object({ const OrganizerSchema = z.object({
wxUserId: z.number(), wxUserId: z.number(),
wxFullName: z.string(), wxFullName: z.string(),
wxeMail: z.string(), wxeMail: z.string(),
userPhoto: z.string().nullable(), userPhoto: z.string().nullable().optional(),
}); });
const EventRecurrenceSchema = z.object({ const EventRecurrenceSchema = z.object({
@@ -5,7 +5,7 @@ const OwnerSchema = z.object({
wxUserId: z.number(), wxUserId: z.number(),
wxFullName: z.string(), wxFullName: z.string(),
wxeMail: z.string(), wxeMail: z.string(),
userPhoto: z.string().nullable(), userPhoto: z.string().nullable().optional(),
}); });
@@ -5,7 +5,7 @@ const OwnerSchema = z.object({
wxUserId: z.number(), wxUserId: z.number(),
wxFullName: z.string(), wxFullName: z.string(),
wxeMail: z.string(), wxeMail: z.string(),
userPhoto: z.string().nullable(), userPhoto: z.string().nullable().optional(),
}); });
@@ -20,10 +20,9 @@ export class MemberListRemoteRepository implements IMemberRemoteRepository {
@ValidateSchema(AddMemberToRoomInputDTOSchema) @ValidateSchema(AddMemberToRoomInputDTOSchema)
async addMemberToRoom(data: AddMemberToRoomInputDTO): DataSourceReturn<AddMemberToRoomInputDTO> { async addMemberToRoom(data: AddMemberToRoomInputDTO): DataSourceReturn<AddMemberToRoomInputDTO> {
return await this.httpService.post<any>(`${this.baseUrl}/Room/${data.id}/Member`, { members:data.members }); return await this.httpService.post<any>(`${this.baseUrl}/Room/${data.id}/Member`, { members:data.members, userId: data.userId });
} }
@ValidateSchema(UserRemoveListInputDTOSchema) @ValidateSchema(UserRemoveListInputDTOSchema)
async removeMemberFromRoom(data: UserRemoveListInputDTO): Promise<Result<any ,any>> { async removeMemberFromRoom(data: UserRemoveListInputDTO): Promise<Result<any ,any>> {
return await this.httpService.delete<any>(`${this.baseUrl}/Room/${data.id}/Member`, {} , {members:data.members}); return await this.httpService.delete<any>(`${this.baseUrl}/Room/${data.id}/Member`, {} , {members:data.members});
@@ -80,6 +80,7 @@ export class RoomRemoteDataSourceService implements IRoomRemoteRepository {
const result = await this.socket.sendData({ const result = await this.socket.sendData({
method: 'AddRoomMember', method: 'AddRoomMember',
data: { data: {
userId: SessionStore.user.UserId,
requestId: uuidv4(), requestId: uuidv4(),
roomId: data.id, roomId: data.id,
members: data.members members: data.members
@@ -126,7 +126,7 @@ export class ChatServiceService {
}) })
this.MessageSocketRepositoryService.listenToUpdateMessages().pipe( this.MessageSocketRepositoryService.listenToUpdateMessages().pipe(
filter((message) => message.deviceId != getInstanceId()) filter((message) => message?.deviceId != getInstanceId())
).subscribe(async (message) => { ).subscribe(async (message) => {
if(message?.id) { if(message?.id) {
this.SocketMessageUpdateUseCaseService.execute(message) this.SocketMessageUpdateUseCaseService.execute(message)
@@ -135,7 +135,7 @@ export class ChatServiceService {
this.MessageSocketRepositoryService.listenToMessages().pipe( this.MessageSocketRepositoryService.listenToMessages().pipe(
map(message => message.data), map(message => message.data),
filter((message) => message.deviceId != getInstanceId()) filter((message) => message?.deviceId != getInstanceId())
).subscribe(async (message) => { ).subscribe(async (message) => {
if(message?.id) { if(message?.id) {
this.SocketMessageCreateUseCaseService.execute(message) this.SocketMessageCreateUseCaseService.execute(message)
@@ -20,7 +20,7 @@ export class RoomLastMessageService {
listenToIncomingMessage() { listenToIncomingMessage() {
return this.MessageSocketRepositoryService.listenToMessages().pipe( return this.MessageSocketRepositoryService.listenToMessages().pipe(
map(message => message.data), map(message => message.data),
filter((message) => message.deviceId != getInstanceId()), filter((message) => message?.deviceId != getInstanceId()),
map(message => Object.assign(new MessageEntity(), message)) map(message => Object.assign(new MessageEntity(), message))
).subscribe(async (message) => { ).subscribe(async (message) => {
this.roomLocalRepository.update(message.roomId, { this.roomLocalRepository.update(message.roomId, {
@@ -1,4 +1,3 @@
import { z } from "zod";
import { NotificationTable } from '../../infra/db/notification.db' import { NotificationTable } from '../../infra/db/notification.db'
type Changes = { type Changes = {
@@ -48,22 +48,22 @@
*ngFor="let evento of publicationsEventFolderList"> *ngFor="let evento of publicationsEventFolderList">
<ion-item lines="none" <ion-item lines="none"
class="item cursor-pointer width-100 d-flex ion-no-border ion-no-margin ion-no-padding" class="item cursor-pointer width-100 d-flex ion-no-border ion-no-margin ion-no-padding"
[class.item-active]="evento.ProcessId == idSelected" [class.item-active]="evento.processId == idSelected"
(click)="goToPublicationsList(evento.ProcessId)"> (click)="goToPublicationsList(evento.processId)">
<div class="item-icon2"> <div class="item-icon2">
<ion-icon class="font-40-em" *ngIf="ThemeService.currentTheme == 'default' " slot="end" src='assets/images/icons-nav-actions.svg'></ion-icon> <ion-icon class="font-40-em" *ngIf="ThemeService.currentTheme == 'default' " slot="end" src='assets/images/icons-nav-actions.svg'></ion-icon>
<ion-icon class="font-40-em" *ngIf="ThemeService.currentTheme == 'gov' && evento.ProcessId != idSelected " slot="end" src='assets/images/theme/gov/icons-nav-actions.svg'></ion-icon> <ion-icon class="font-40-em" *ngIf="ThemeService.currentTheme == 'gov' && evento.processId != idSelected " slot="end" src='assets/images/theme/gov/icons-nav-actions.svg'></ion-icon>
<ion-icon class="font-40-em" *ngIf="ThemeService.currentTheme == 'gov' && evento.ProcessId == idSelected " slot="end" src='assets/images/theme/gov/icons-nav-actions-hover.svg'></ion-icon> <ion-icon class="font-40-em" *ngIf="ThemeService.currentTheme == 'gov' && evento.processId == idSelected " slot="end" src='assets/images/theme/gov/icons-nav-actions-hover.svg'></ion-icon>
<ion-icon class="font-40-em" *ngIf="ThemeService.currentTheme == 'doneIt' && evento.ProcessId != idSelected " slot="end" src='assets/images/theme/{{ThemeService.currentTheme}}/icons-nav-actions.svg'></ion-icon> <ion-icon class="font-40-em" *ngIf="ThemeService.currentTheme == 'doneIt' && evento.processId != idSelected " slot="end" src='assets/images/theme/{{ThemeService.currentTheme}}/icons-nav-actions.svg'></ion-icon>
<ion-icon class="font-40-em" *ngIf="ThemeService.currentTheme == 'doneIt' && evento.ProcessId == idSelected " slot="end" src='assets/images/theme/{{ThemeService.currentTheme}}/icons-nav-actions-hover.svg'></ion-icon> <ion-icon class="font-40-em" *ngIf="ThemeService.currentTheme == 'doneIt' && evento.processId == idSelected " slot="end" src='assets/images/theme/{{ThemeService.currentTheme}}/icons-nav-actions-hover.svg'></ion-icon>
</div> </div>
<div class="item-content flex-grow-1"> <div class="item-content flex-grow-1">
<p class="item-content-date font-13-em" [class.item-content-date-active]="evento.ProcessId == idSelected">{{getDate(evento.DateBegin)}}</p> <p class="item-content-date font-13-em" [class.item-content-date-active]="evento.processId == idSelected">{{getDate(evento.dateBegin)}}</p>
<p class="item-content-title font-15-em" [class.item-content-title-active]="evento.ProcessId == idSelected">{{evento.Description}}</p> <p class="item-content-title font-15-em" [class.item-content-title-active]="evento.processId == idSelected">{{evento.detail}}</p>
</div> </div>
</ion-item> </ion-item>
<ion-item-options class="members-options" side="end"> <ion-item-options class="members-options" side="end">
<ion-item-option *ngIf="p.userPermission([p.permissionList.Actions.edit])" class="edit-option" (click)="editAction(evento.ProcessId)"> <ion-item-option *ngIf="p.userPermission([p.permissionList.Actions.edit])" class="edit-option" (click)="editAction(evento.processId)">
<button class="btn-no-color"> <button class="btn-no-color">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="edit" slot="end" src="assets/images/icons-edit.svg" ></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="edit" slot="end" src="assets/images/icons-edit.svg" ></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="edit" slot="end" src="assets/images/theme/gov/icons-edit.svg" ></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="edit" slot="end" src="assets/images/theme/gov/icons-edit.svg" ></ion-icon>
@@ -71,7 +71,7 @@
</button> </button>
</ion-item-option> </ion-item-option>
<ion-item-option *ngIf="p.userPermission([p.permissionList.Actions.delete])" class="delete-option" (click)="deleteAction(evento.ProcessId)"> <ion-item-option *ngIf="p.userPermission([p.permissionList.Actions.delete])" class="delete-option" (click)="deleteAction(evento.processId)">
<button class="btn-no-color"> <button class="btn-no-color">
<ion-icon class="delete" name="trash-sharp"></ion-icon> <ion-icon class="delete" name="trash-sharp"></ion-icon>
</button> </button>
+18 -102
View File
@@ -1,11 +1,9 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router'; import { Router, NavigationEnd } from '@angular/router';
import { AlertController, ModalController, NavParams } from '@ionic/angular'; import { ModalController } from '@ionic/angular';
import { PublicationFolder } from 'src/app/models/publicationfolder';
import { PublicationsService } from 'src/app/services/publications.service'; import { PublicationsService } from 'src/app/services/publications.service';
import { NewActionPage } from './new-action/new-action.page'; import { NewActionPage } from './new-action/new-action.page';
import { ViewPublicationsPage } from './view-publications/view-publications.page'; import { ViewPublicationsPage } from './view-publications/view-publications.page';
import { AnimationController } from '@ionic/angular'; import { AnimationController } from '@ionic/angular';
import { Publication } from 'src/app/models/publication'; import { Publication } from 'src/app/models/publication';
import { ActionsOptionsPage } from 'src/app/shared/popover/actions-options/actions-options.page'; import { ActionsOptionsPage } from 'src/app/shared/popover/actions-options/actions-options.page';
@@ -15,15 +13,10 @@ import { ThemeService } from 'src/app/services/theme.service'
import { PermissionService } from 'src/app/services/permission.service'; import { PermissionService } from 'src/app/services/permission.service';
import { Storage } from '@ionic/storage'; import { Storage } from '@ionic/storage';
import { NewPublicationPage } from './new-publication/new-publication.page'; import { NewPublicationPage } from './new-publication/new-publication.page';
import { ChunkService } from 'src/app/services/stream/chunk.service'
import { StreamService } from 'src/app/services/stream/stream.service'
import { HttpClient, HttpHeaders, HttpEventType } from '@angular/common/http';
import { PublicationFolderService } from 'src/app/store/publication-folder.service'; import { PublicationFolderService } from 'src/app/store/publication-folder.service';
import { ActionsGetAllUseCaseService } from 'src/app/core/actions/use-case/actions-get-all-use-case.service';
// import { ActionModel } from 'src/app/models/beast-orm'; import { ActionRemoteRepositoryService } from 'src/app/module/actions/data/repository/action-remote-repository.service';
import { ActionEntity, IAction } from 'src/app/core/actions/entity/action';
@Component({ @Component({
selector: 'app-publications', selector: 'app-publications',
templateUrl: './publications.page.html', templateUrl: './publications.page.html',
@@ -31,12 +24,12 @@ import { PublicationFolderService } from 'src/app/store/publication-folder.servi
}) })
export class PublicationsPage implements OnInit { export class PublicationsPage implements OnInit {
showLoader: boolean = false showLoader: boolean = false
publicationFolder: PublicationFolder; publicationFolder: IAction;
publication: Publication; publication: Publication;
publicationsEventFolderList: PublicationFolder[] = []; publicationsEventFolderList: IAction[] = [];
actionsListStorage: PublicationFolder[] = new Array(); actionsListStorage: IAction[] = new Array();
publicationsTravelFolderList: PublicationFolder[] = []; publicationsTravelFolderList: IAction[] = [];
theDate: any; theDate: any;
theEndDate: any; theEndDate: any;
@@ -75,12 +68,9 @@ export class PublicationsPage implements OnInit {
public ThemeService: ThemeService, public ThemeService: ThemeService,
public p: PermissionService, public p: PermissionService,
private storage: Storage, private storage: Storage,
private ChunkService: ChunkService,
private StreamService:StreamService,
private http: HttpClient,
public publicationFolderService: PublicationFolderService, public publicationFolderService: PublicationFolderService,
private ActionsGetAllUseCaseService: ActionsGetAllUseCaseService,
private actionRemoteRepository: ActionRemoteRepositoryService
) { ) {
this.months = ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"]; this.months = ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"];
this.days = ["Domingo", "Segunda-feira", "Terça-feira", "Quarta-feira", "Quinta-feira", "Sexta-feira", "Sábado"]; this.days = ["Domingo", "Segunda-feira", "Terça-feira", "Quarta-feira", "Quinta-feira", "Sexta-feira", "Sábado"];
@@ -93,15 +83,11 @@ export class PublicationsPage implements OnInit {
window['updateAction'] = () => { window['updateAction'] = () => {
this.getActions() this.getActions()
} }
} }
checkQueryParameter() { checkQueryParameter() {
// var urlSearchParams = new URLSearchParams(window.location.search);
// var folderId = urlSearchParams.get('folderId');
if (this.publicationFolderService.gotoAction) { if (this.publicationFolderService.gotoAction) {
const folderId = this.publicationFolderService.gotoAction const folderId = this.publicationFolderService.gotoAction
this.goToPublicationsList(folderId) this.goToPublicationsList(folderId)
@@ -118,9 +104,8 @@ export class PublicationsPage implements OnInit {
this.router.events.forEach((event) => { this.router.events.forEach((event) => {
if (event instanceof NavigationEnd && event.url == pathname) { if (event instanceof NavigationEnd && event.url == pathname) {
console.log('=================', this.publicationFolderService.gotoAction)
this.getActions(); this.getActions();
// this.checkQueryParameter() this.ActionsGetAllUseCaseService.execute();
} }
this.intent = window['sharedContent'] this.intent = window['sharedContent']
}); });
@@ -187,16 +172,13 @@ export class PublicationsPage implements OnInit {
getActions = () => { getActions = () => {
this.showLoader = true this.showLoader = true
this.publications.GetPublicationFolderList().subscribe(async res => { this.actionRemoteRepository.actionGetAll().then(async res => {
this.showLoader = false; this.showLoader = false;
const folders: PublicationFolder[] = this.getPublicationFolderMap(res) if(res.isOk()) {
const folders: IAction[] = res.value.data.data;
this.publicationsEventFolderList = folders.filter((e)=>e.ActionType == 'Evento')
await this.storage.set('actionsEvents', this.publicationsEventFolderList); await this.storage.set('actionsEvents', this.publicationsEventFolderList);
this.publicationsEventFolderList = folders;
this.showLoader = false; }
}, (error) => { }, (error) => {
this.showLoader = false; this.showLoader = false;
this.getFromDB() this.getFromDB()
@@ -204,89 +186,23 @@ export class PublicationsPage implements OnInit {
} }
getPublicationFolderMap(events: any):PublicationFolder[] {
return events.map((data) : PublicationFolder => {
return {
ProcessId: data.ProcessId,
Description: data.Description,
Detail: data.Detail,
DateBegin: data.DateBegin,
DateEnd: data.DateEnd,
ActionType: data.ActionType,
}
});
}
async getFromDB() { async getFromDB() {
//const folders: PublicationFolder[] = await ActionModel.all()
//this.showLoader = false;
// this.publicationsEventFolderList = folders
this.storage.get('actionsEvents').then((events = []) => { this.storage.get('actionsEvents').then((events = []) => {
if(Array.isArray(events)) { if(Array.isArray(events)) {
const folders: PublicationFolder[] = this.getPublicationFolderMap(events)
this.showLoader = false; this.showLoader = false;
this.publicationsEventFolderList = folders this.publicationsEventFolderList = events
} }
}); });
this.storage.get('actionsViagens').then((viagens = []) => { this.storage.get('actionsViagens').then((viagens = []) => {
if(Array.isArray(viagens)) { if(Array.isArray(viagens)) {
const folders: PublicationFolder[] = this.getPublicationFolderMap(viagens) this.publicationsTravelFolderList = viagens
this.publicationsTravelFolderList = folders
this.showLoader = false; this.showLoader = false;
} }
}); });
}
async onFileSelect(event: any) {
const file:File = event.target.files[0];
const chunkSize = 1024 * 1024; // Adjust the chunk size as needed
const chunks = [];
let offset = 0;
let i = 0;
let j = 0;
function count () {
j++
return j
}
while (offset < file.size) {
const chunk = file.slice(offset, offset + chunkSize);
const reader = new FileReader();
reader.onload = async () => {
const headers = new HttpHeaders()
.append('X-File-Name', "fileName")
.append('X-File-Extension', "mp4")
.append('X-File-Content-Length', i.toString())
.append('X-File-Index', count().toString());
const a = new Uint8Array(reader.result as ArrayBuffer)
await this.http.post('http://localhost:3001/upload', a.buffer, { headers, responseType: 'blob' }).toPromise();
};
reader.readAsArrayBuffer(chunk);
offset += chunkSize;
i++;
}
} }
@@ -51,43 +51,6 @@
></app-swiper> ></app-swiper>
</div> </div>
<!-- <div *ngIf="platform.is('ios')" style="width: 322px; height: 357px;">
<app-swiper
[publicationList]=publication
></app-swiper>
</div> -->
<!-- <swiper-container #swipers [slidechange]="onSlideChange()">
<swiper-slide *ngFor="let files of publication.Files let k = index">
<div >
<img *ngIf="checkFileType.checkFileType(files.FileExtension ) == 'image'" class="post-img"
[lazyLoad]="'data:image/jpg;base64,' + files.FileBase64">
<video #videoElement [appVisibility]="onVisibilityChange" *ngIf="checkFileType.checkFileType(files.FileExtension ) == 'video'" class="post-video" controls="controls" preload="none"
playsinline webkit-playsinline="webkit-playsinline" (play)="stopvideoService.registerVideoWithEvent($event)" (click)="preventVideoPlay($event)">
<source [src]="files.FileBase64" type="video/mp4" >
</video>
</div>
</swiper-slide>
</swiper-container> -->
<!-- <div *ngIf="publication.FileExtension == 'mp4'"
(click)="goToPublicationDetail(publication.DocumentId, publication.ProcessId)" class="post-video">
</div> -->
<!-- <div *ngIf="publication.Files.length > 2" class="dots-container">
<span *ngFor="let files of publication.Files; let k = index"
[class.dotsSwiper]="true"
[class.active-dot]="swiperIndex === k"
(click)="goToSlide(k)">
</span>
</div> -->
<div (click)="goToPublicationDetail(publication.DocumentId, publication.ProcessId)" class="post-content" > <div (click)="goToPublicationDetail(publication.DocumentId, publication.ProcessId)" class="post-content" >
<div class="post-title-time"> <div class="post-title-time">
@@ -11,14 +11,10 @@ import { BackgroundService } from 'src/app/services/background.service';
import { ThemeService } from 'src/app/services/theme.service' import { ThemeService } from 'src/app/services/theme.service'
import { ToastService } from 'src/app/services/toast.service'; import { ToastService } from 'src/app/services/toast.service';
import { PermissionService } from 'src/app/services/permission.service'; import { PermissionService } from 'src/app/services/permission.service';
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
import { Storage } from '@ionic/storage'; import { Storage } from '@ionic/storage';
import { PublicationFolderService } from 'src/app/store/publication-folder.service'; import { PublicationFolderService } from 'src/app/store/publication-folder.service';
// import { CapacitorVideoPlayer } from 'capacitor-video-player';
import { checkFileTypeService } from 'src/app/services/checkFileType.service'; import { checkFileTypeService } from 'src/app/services/checkFileType.service';
import { PublicationVideoManagerService } from "src/app/services/publication/publication-video-manager.service"
import { StopvideoService } from "src/app/services/stopvideo.service" import { StopvideoService } from "src/app/services/stopvideo.service"
import { Result } from 'neverthrow';
import { App } from '@capacitor/app'; import { App } from '@capacitor/app';
import { ActiveTabService } from 'src/app/services/active-tab.service'; import { ActiveTabService } from 'src/app/services/active-tab.service';
import { PublicationHolderService } from 'src/app/services/publication/publication-holder.service' import { PublicationHolderService } from 'src/app/services/publication/publication-holder.service'
@@ -29,7 +25,7 @@ import { PublicationHolderService } from 'src/app/services/publication/publicati
styleUrls: ['./view-publications.page.scss'], styleUrls: ['./view-publications.page.scss'],
}) })
export class ViewPublicationsPage implements OnInit { export class ViewPublicationsPage implements OnInit {
showLoader = true; showLoader = false;
loading: any; loading: any;
@@ -80,26 +76,13 @@ export class ViewPublicationsPage implements OnInit {
public activeTabService: ActiveTabService, public activeTabService: ActiveTabService,
public PublicationHolderService: PublicationHolderService) { public PublicationHolderService: PublicationHolderService) {
/* this.publicationVideoManagerService.setContainer(this.VideoManager.nativeElement) */
setTimeout(() => {
console.log(this.VideoManager.nativeElement)
}, 2000)
this.createPublicationList() this.createPublicationList()
this.getFromDB(); this.getFromDB();
this.activatedRoute.paramMap.subscribe(params => { this.activatedRoute.paramMap.subscribe(params => {
if (params["params"]) { if (params["params"]) {
this.folderId = params["params"].folderId; this.folderId = params["params"].folderId;
//
} }
window['app-view-publications-page-doRefresh'] = this.doRefresh window['app-view-publications-page-doRefresh'] = this.doRefresh
}); });
} }
@@ -111,29 +94,12 @@ export class ViewPublicationsPage implements OnInit {
} }
this.createPublicationList() this.createPublicationList()
this.getFromDB(); this.getFromDB();
//this.testForkJoin()
this.getPublicationDetail(); this.getPublicationDetail();
this.getPublicationsIds();
/* setTimeout(() => {
this.getPublications();
}, 1000); */
this.backgroundservice.registerBackService('Online', () => { this.backgroundservice.registerBackService('Online', () => {
this.getPublicationDetail(); this.getPublicationDetail();
//this.testForkJoin()
}) })
// console.log(this.publicationFolderService.publicationList[this.folderId])
setTimeout(()=> {
// this.doRefresh({})
}, 1500)
} }
@@ -153,7 +119,6 @@ export class ViewPublicationsPage implements OnInit {
video.pause(); video.pause();
}) })
this.videoElements.forEach(videoElement => { this.videoElements.forEach(videoElement => {
// You can access the native HTML video element using videoElement.nativeElement // You can access the native HTML video element using videoElement.nativeElement
const video: HTMLVideoElement = videoElement.nativeElement; const video: HTMLVideoElement = videoElement.nativeElement;
@@ -174,12 +139,10 @@ export class ViewPublicationsPage implements OnInit {
} }
this.createPublicationList() this.createPublicationList()
this.getFromDB(); this.getFromDB();
} }
createPublicationList(folderId = this.folderId) { createPublicationList(folderId = this.folderId) {
console.log('create')
if (!this.publicationFolderService.publicationList[folderId]) { if (!this.publicationFolderService.publicationList[folderId]) {
this.publicationFolderService.publicationList[folderId] = [] this.publicationFolderService.publicationList[folderId] = []
} }
@@ -192,7 +155,6 @@ export class ViewPublicationsPage implements OnInit {
//setTimeout(() => { //setTimeout(() => {
//this.testForkJoin() //this.testForkJoin()
this.getPublicationDetail(); this.getPublicationDetail();
this.getPublicationsIds();
try { try {
event?.target?.complete(); event?.target?.complete();
} catch (error) { } } catch (error) { }
@@ -215,10 +177,12 @@ export class ViewPublicationsPage implements OnInit {
} }
getPublicationDetail() { getPublicationDetail() {
this.showLoader = true;
const folderId = this.folderId const folderId = this.folderId
this.publications.GetPresidentialAction(folderId).subscribe(res => { this.publications.GetPresidentialAction(folderId).subscribe(res => {
this.publicationFolderService.FolderDetails[folderId] = res this.publicationFolderService.FolderDetails[folderId] = res
this.storage.set(folderId + "name", res) this.storage.set(folderId + "name", res)
this.showLoader = false;
}, (error) => { }, (error) => {
this.showLoader = false; this.showLoader = false;
// this.httpErroHandle.httpStatusHandle(error) // this.httpErroHandle.httpStatusHandle(error)
@@ -230,26 +194,6 @@ export class ViewPublicationsPage implements OnInit {
this.publicationFolderService.getFromDB(folderId) this.publicationFolderService.getFromDB(folderId)
} }
async getPublicationsIds() {
this.showLoader = true;
const folderId = this.folderId
await this.publicationFolderService.getPublicationsIds(folderId)
this.showLoader = false;
}
publicationIsPresent(publicationId, folderId) {
return this.publicationFolderService.publicationList[folderId].find(e => e.DocumentId == publicationId)
}
publicationFind(publicationId, folderId) {
return this.publicationFolderService.publicationList[folderId].find(e => e.DocumentId == publicationId)
}
publicationFindIndex(publicationId, folderId) {
return this.publicationFolderService.publicationList[folderId].findIndex(e => e.DocumentId == publicationId)
}
async AddPublication(publicationType: any, folderId: any) { async AddPublication(publicationType: any, folderId: any) {
@@ -307,10 +251,6 @@ export class ViewPublicationsPage implements OnInit {
// backdropDismiss: false // backdropDismiss: false
}); });
modal.onDidDismiss().then(() => {
this.getPublicationsIds();
});
await modal.present(); await modal.present();
} }
@@ -1,12 +1,12 @@
import { Component, EventEmitter, OnInit, Output } from '@angular/core'; import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms'; import { FormControl, FormGroup, Validators } from '@angular/forms';
import * as moment from 'moment';
import { PublicationFolder } from 'src/app/models/publicationfolder'; import { PublicationFolder } from 'src/app/models/publicationfolder';
import { PublicationsService } from 'src/app/services/publications.service';
import { ToastService } from 'src/app/services/toast.service'; import { ToastService } from 'src/app/services/toast.service';
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service'; import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
import { NgxMatDateFormats } from '@angular-material-components/datetime-picker'; import { NgxMatDateFormats } from '@angular-material-components/datetime-picker';
import { NGX_MAT_DATE_FORMATS } from '@angular-material-components/datetime-picker'; import { NGX_MAT_DATE_FORMATS } from '@angular-material-components/datetime-picker';
import { ActionRemoteRepositoryService } from 'src/app/module/actions/data/repository/action-remote-repository.service';
import { SessionStore } from 'src/app/store/session.service';
const CUSTOM_DATE_FORMATS: NgxMatDateFormats = { const CUSTOM_DATE_FORMATS: NgxMatDateFormats = {
parse: { parse: {
@@ -53,13 +53,12 @@ export class NewActionPage implements OnInit {
@Output() getActions= new EventEmitter<any>(); @Output() getActions= new EventEmitter<any>();
constructor( constructor(
private publication: PublicationsService,
private toastService: ToastService, private toastService: ToastService,
private httpErrorHandle: HttpErrorHandle, private httpErrorHandle: HttpErrorHandle,
private actionRemoteRepository: ActionRemoteRepositoryService
) { ) {
this.folder = new PublicationFolder(); this.folder = new PublicationFolder();
this.setStartDate() this.setStartDate()
this.setEndDate() this.setEndDate()
} }
@@ -88,10 +87,6 @@ export class NewActionPage implements OnInit {
} }
} }
/* get dateValid() {
return new Date(this.folder.DateBegin).getTime() < new Date(this.folder.DateBegin).getTime() ? 'ok': null
} */
runValidation() { runValidation() {
this.validateFrom = true; this.validateFrom = true;
console.log(this.folder.DateBegin) console.log(this.folder.DateBegin)
@@ -125,30 +120,28 @@ export class NewActionPage implements OnInit {
if(this.Form.invalid) return false if(this.Form.invalid) return false
this.folder = {
ProcessId: null,
Description: this.folder.Description,
Detail: this.folder.Detail,
DateBegin: this.folder.DateBegin,
DateEnd: this.folder.DateEnd,
ActionType: this.segment,
}
const loader = this.toastService.loading() const loader = this.toastService.loading()
try { var result = await this.actionRemoteRepository.create({
await this.publication.CreatePublicationFolder(this.folder).toPromise() userId: SessionStore.user.UserId,
description: this.folder.Description,
detail: this.folder.Detail,
location: "string",
dateBegin: this.folder.DateBegin,
dateEnd: this.folder.DateEnd,
actionType: this.segment,
});
if(result.isOk()) {
this.close(); this.close();
this.httpErrorHandle.httpsSucessMessagge('Acção criada') this.httpErrorHandle.httpsSucessMessagge('Acção criada')
this.getActions.emit() this.getActions.emit()
} catch (error) { } else {
this.httpErrorHandle.httpStatusHandle(error) this.httpErrorHandle.httpStatusHandle(result.error)
} finally {
loader.remove()
} }
loader.remove()
} }
close() { close() {
@@ -142,11 +142,9 @@ export class PublicationFromMvService {
window['publicationEdit']() window['publicationEdit']()
} }
this.publicationFolderService.getPublicationsIds(this.folderId) // this.publicationFolderService.getPublicationsIds(this.folderId)
window['upload-header-set-remove'](this.id); window['upload-header-set-remove'](this.id);
// this.goBack();
} catch (error) { } catch (error) {
this.httpErroHandle.httpStatusHandle(error) this.httpErroHandle.httpStatusHandle(error)
@@ -7,13 +7,15 @@ import { IonicModule } from '@ionic/angular';
import { PublicationDetailPageRoutingModule } from './publication-detail-routing.module'; import { PublicationDetailPageRoutingModule } from './publication-detail-routing.module';
import { PublicationDetailPage } from './publication-detail.page'; import { PublicationDetailPage } from './publication-detail.page';
import { SwiperPageModule } from 'src/app/shared/swiper/swiper.module';
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule, CommonModule,
FormsModule, FormsModule,
IonicModule, IonicModule,
PublicationDetailPageRoutingModule PublicationDetailPageRoutingModule,
SwiperPageModule
], ],
exports: [PublicationDetailPage], exports: [PublicationDetailPage],
declarations: [PublicationDetailPage], declarations: [PublicationDetailPage],
@@ -0,0 +1,92 @@
<ion-header class="ion-no-border">
<div *ngIf="publication.Title != ''" class="title-content d-flex pl-20 pt-25">
<div class="back-icon cursor-pointer" (click)="goBack()">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" src='assets/images/icons-arrow-arrow-left.svg'></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="end" src='assets/images/theme/gov/icons-calendar-arrow-left.svg'></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " slot="end" src='assets/images/theme/{{ThemeService.currentTheme}}/icons-calendar-arrow-left.svg'></ion-icon>
</div>
<div class="div-title">
<ion-label class="title"> {{publication.Title}}</ion-label>
<p class="post-data">{{publication.DatePublication | date: 'dd-MM-yyyy | h:mm'}}</p>
</div>
</div>
<!-- OriginalFileName: {{ publication.OriginalFileName }} -->
<div *ngIf="publication.Title == ''" class="title-contentd-flex pl-20 pt-25">
<div class="back-icon cursor-pointer">
<ion-icon (click)="goBack()" slot="end" src='assets/images/assets/images/theme/gov/icons-calendar-arrow-left.svg'></ion-icon>
</div>
<div class="div-title">
<ion-label class="title"><ion-skeleton-text animated style="width: 60%;"></ion-skeleton-text></ion-label>
<p class="post-data"><ion-skeleton-text animated style="width: 20%;"></ion-skeleton-text></p>
</div>
</div>
<ion-progress-bar type="indeterminate" *ngIf="showLoader"></ion-progress-bar>
</ion-header>
<ion-content>
<div class="content-container" #ScrollContainer>
<div *ngIf="publication.Title != ''">
<ion-refresher name="refresher" slot="fixed" (ionRefresh)="doRefresh($event)">
<ion-progress-bar type="indeterminate" *ngIf="showLoader"></ion-progress-bar>
<ion-refresher-content>
</ion-refresher-content>
</ion-refresher>
<div class="post-item px-20">
<swiper-container navigation="true" [pagination]="{clickable: true, dynamicBullets: true }">
<swiper-slide *ngFor="let files of publication.Files let k = index">
<!-- <div (click)="openPreview(publication)"> -->
<div >
<img *ngIf="checkFileType.checkFileType(files.FileExtension ) == 'image' && files.FileBase64!=''" alt="sem image" tappable
src="{{'data:image/jpg;base64,' + files.FileBase64}}"
style="max-height:{{containerMaxHeight}}px"
>
<video *ngIf="checkFileType.checkFileType(files.FileExtension ) == 'video' && files.FileBase64!=''" controls="controls" preload="metadata"
webkit-playsinline="webkit-playsinline" style="max-height:{{containerMaxHeight}}px">
<source [src]="files.FileBase64" type="video/mp4">
</video>
<div *ngIf="files.FileBase64==''" style="height:{{containerMaxHeight}}px">
sem contiudo
</div>
</div>
</swiper-slide>
</swiper-container>
<!-- <div *ngIf="publication.FileBase64.length < 30" class="post-img">
<img src="/assets/icon/icon-no-image.svg" alt="image">
</div> -->
<div class="post-description">
<pre class="text">{{publication.Message}}</pre>
</div>
</div>
</div>
<div *ngIf="publication.Title == ''">
<div class="post-item px-20">
<div class="post-img">
<img src="/assets/icon/icon-no-image.svg" alt="image">
</div>
<div class="post-description">
<p><ion-skeleton-text animated></ion-skeleton-text></p>
<p><ion-skeleton-text animated></ion-skeleton-text></p>
</div>
</div>
</div>
</div>
</ion-content>
<ion-footer>
<ion-toolbar class="footer-toolbar width-md-100 px-md-20">
<ion-buttons *ngIf="p.userPermission([p.permissionList.Actions.deletePost])" slot="start">
<button class="btn-delete" fill="clear" color="#ffe0e0" (click)="deletePost()">
<ion-label>Eliminar</ion-label>
</button>
</ion-buttons>
<ion-buttons *ngIf="p.userPermission([p.permissionList.Actions.editPost])" slot="end">
<button class="btn-ok" fill="clear" color="#fff" (click)="editPost('3')">
<ion-label>Editar</ion-label>
</button>
</ion-buttons>
</ion-toolbar>
</ion-footer>
@@ -1,17 +1,16 @@
<ion-header class="ion-no-border"> <ion-header class="ion-no-border">
<div *ngIf="publication.Title != ''" class="title-content d-flex pl-20 pt-25"> <div *ngIf="publication.title != ''" class="title-content d-flex pl-20 pt-25">
<div class="back-icon cursor-pointer" (click)="goBack()"> <div class="back-icon cursor-pointer" (click)="goBack()">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" src='assets/images/icons-arrow-arrow-left.svg'></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" src='assets/images/icons-arrow-arrow-left.svg'></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="end" src='assets/images/theme/gov/icons-calendar-arrow-left.svg'></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="end" src='assets/images/theme/gov/icons-calendar-arrow-left.svg'></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " slot="end" src='assets/images/theme/{{ThemeService.currentTheme}}/icons-calendar-arrow-left.svg'></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " slot="end" src='assets/images/theme/{{ThemeService.currentTheme}}/icons-calendar-arrow-left.svg'></ion-icon>
</div> </div>
<div class="div-title"> <div class="div-title">
<ion-label class="title"> {{publication.Title}}</ion-label> <ion-label class="title"> {{publication.title}}</ion-label>
<p class="post-data">{{publication.DatePublication | date: 'dd-MM-yyyy | h:mm'}}</p> <p class="post-data">{{publication.datePublication | date: 'dd-MM-yyyy | h:mm'}}</p>
</div> </div>
</div> </div>
<!-- OriginalFileName: {{ publication.OriginalFileName }} --> <div *ngIf="publication.title == ''" class="title-contentd-flex pl-20 pt-25">
<div *ngIf="publication.Title == ''" class="title-contentd-flex pl-20 pt-25">
<div class="back-icon cursor-pointer"> <div class="back-icon cursor-pointer">
<ion-icon (click)="goBack()" slot="end" src='assets/images/assets/images/theme/gov/icons-calendar-arrow-left.svg'></ion-icon> <ion-icon (click)="goBack()" slot="end" src='assets/images/assets/images/theme/gov/icons-calendar-arrow-left.svg'></ion-icon>
</div> </div>
@@ -25,54 +24,25 @@
<ion-content> <ion-content>
<div class="content-container" #ScrollContainer> <div class="content-container" #ScrollContainer>
<div *ngIf="publication.Title != ''"> <div *ngIf="publication.title != ''">
<ion-refresher name="refresher" slot="fixed" (ionRefresh)="doRefresh($event)">
<ion-progress-bar type="indeterminate" *ngIf="showLoader"></ion-progress-bar>
<ion-refresher-content>
</ion-refresher-content>
</ion-refresher>
<div class="post-item px-20"> <div class="post-item px-20">
<swiper-container navigation="true" [pagination]="{clickable: true, dynamicBullets: true }">
<swiper-slide *ngFor="let files of publication.Files let k = index">
<!-- <div (click)="openPreview(publication)"> -->
<div >
<img *ngIf="checkFileType.checkFileType(files.FileExtension ) == 'image' && files.FileBase64!=''" alt="sem image" tappable
src="{{'data:image/jpg;base64,' + files.FileBase64}}"
style="max-height:{{containerMaxHeight}}px"
>
<video *ngIf="checkFileType.checkFileType(files.FileExtension ) == 'video' && files.FileBase64!=''" controls="controls" preload="metadata" <div style="width: 100%; height: 395px;overflow:hidden">
webkit-playsinline="webkit-playsinline" style="max-height:{{containerMaxHeight}}px"> <app-swiper
<source [src]="files.FileBase64" type="video/mp4"> [publicationList]=publication
</video> [navigation]="true"
[pagination]="false"
<div *ngIf="files.FileBase64==''" style="height:{{containerMaxHeight}}px"> [documentId]=publication.documentId
sem contiudo [datePublication]=publication.datePublication
[processId]=publication.processId
></app-swiper>
</div> </div>
</div>
</swiper-slide>
</swiper-container>
<!-- <div *ngIf="publication.FileBase64.length < 30" class="post-img">
<img src="/assets/icon/icon-no-image.svg" alt="image">
</div> -->
<div class="post-description"> <div class="post-description">
<pre class="text">{{publication.Message}}</pre> <pre class="text">{{publication.message}}</pre>
</div> </div>
</div> </div>
</div> </div>
<div *ngIf="publication.Title == ''">
<div class="post-item px-20">
<div class="post-img">
<img src="/assets/icon/icon-no-image.svg" alt="image">
</div>
<div class="post-description">
<p><ion-skeleton-text animated></ion-skeleton-text></p>
<p><ion-skeleton-text animated></ion-skeleton-text></p>
</div>
</div>
</div>
</div> </div>
</ion-content> </ion-content>
<ion-footer> <ion-footer>
@@ -1,6 +1,5 @@
import { Component, OnInit, Input, Output, EventEmitter, ViewChild, ElementRef } from '@angular/core'; import { Component, OnInit, Input, Output, EventEmitter, ViewChild, ElementRef } from '@angular/core';
import { ModalController } from '@ionic/angular'; import { ModalController } from '@ionic/angular';
import { Publication } from 'src/app/models/publication';
import { NewPublicationPage } from 'src/app/shared/publication/new-publication/new-publication.page'; import { NewPublicationPage } from 'src/app/shared/publication/new-publication/new-publication.page';
import { PublicationsService } from 'src/app/services/publications.service'; import { PublicationsService } from 'src/app/services/publications.service';
import { ToastService } from 'src/app/services/toast.service'; import { ToastService } from 'src/app/services/toast.service';
@@ -12,6 +11,8 @@ import { PublicationFolderService } from 'src/app/store/publication-folder.servi
import { PublicationPipe } from 'src/app/pipes/publication.pipe'; import { PublicationPipe } from 'src/app/pipes/publication.pipe';
import { checkFileTypeService } from 'src/app/services/checkFileType.service'; import { checkFileTypeService } from 'src/app/services/checkFileType.service';
import { PublicationHolderService } from 'src/app/services/publication/publication-holder.service' import { PublicationHolderService } from 'src/app/services/publication/publication-holder.service'
import { IPublication } from 'src/app/core/actions/entity/publicationEntity';
import { PublicationLocalRepositoryService } from 'src/app/module/actions/data/repository/publication-local-repository.service';
@Component({ @Component({
selector: 'app-publication-detail-shared', selector: 'app-publication-detail-shared',
@@ -21,7 +22,7 @@ import { PublicationHolderService } from 'src/app/services/publication/publicati
export class PublicationDetailPage implements OnInit { export class PublicationDetailPage implements OnInit {
showLoader: boolean; showLoader: boolean;
/* folderId: string; */ /* folderId: string; */
publication: Publication; publication: IPublication;
@Input() publicationId: string; @Input() publicationId: string;
@Input() folderId: string; @Input() folderId: string;
@Output() addNewPublication = new EventEmitter<any>(); @Output() addNewPublication = new EventEmitter<any>();
@@ -41,23 +42,9 @@ export class PublicationDetailPage implements OnInit {
private httpErrorHandle: HttpErrorHandle, private httpErrorHandle: HttpErrorHandle,
public publicationFolderService: PublicationFolderService, public publicationFolderService: PublicationFolderService,
public checkFileType: checkFileTypeService, public checkFileType: checkFileTypeService,
public PublicationHolderService: PublicationHolderService public PublicationHolderService: PublicationHolderService,
) { private publicationLocal: PublicationLocalRepositoryService,
) {}
/* this.folderId = this.navParams.get('folderIdId'); */
this.publication = {
DateIndex: null,
DocumentId: null,
ProcessId:'',
Title:'',
Message: '',
/* image: null, */
DatePublication: null,
Files: [],
OriginalFileName: '',
FileExtension: '',
};
}
@ViewChild('ScrollContainer', { static: true }) ScrollContainer: ElementRef; @ViewChild('ScrollContainer', { static: true }) ScrollContainer: ElementRef;
@@ -114,41 +101,47 @@ export class PublicationDetailPage implements OnInit {
}, 2000); }, 2000);
} }
getPublicationDetail() { async getPublicationDetail() {
const folderId = this.folderId const folderId = this.folderId
const result = await this.publicationLocal.findOne({ documentId: parseInt(this.publicationId) })
if(result.isOk() && result.value) {
this.publication = result.value;
}
const localPublication = this.publicationFolderService.getLocalPublication(folderId, this.publicationId); const localPublication = this.publicationFolderService.getLocalPublication(folderId, this.publicationId);
if(localPublication?.ProcessId) {
console.log('console.log local storage')
this.publication = localPublication // if(localPublication?.ProcessId) {
console.log('Local publication',this.publication)
} else { // this.publication = localPublication
// console.log('Local publication',this.publication)
console.log('API res') // } else {
this.showLoader = true; // this.publications.GetPublications(this.publicationId);
this.publications.GetPublicationWithArrayOfFilesById(this.publicationId).subscribe(res => {
this.publication = this.publicationPipe.itemList(res) // this.showLoader = true;
// this.publications.GetPublicationWithArrayOfFilesById(this.publicationId).subscribe(res => {
console.log('API pub', this.publication) // this.publication = this.publicationPipe.itemList(res)
this.showLoader = false;
}, (error) => { // console.log('API pub', this.publication)
this.showLoader = false; // this.showLoader = false;
// }, (error) => {
// this.showLoader = false;
console.log(this.publication) // console.log(this.publication)
if(error.status == 404) { // if(error.status == 404) {
this.publicationFolderService.deletePost(this.folderId, this.publicationId) // this.publicationFolderService.deletePost(this.folderId, this.publicationId)
} // }
this.goBack(); // this.goBack();
this.httpErrorHandle.httpStatusHandle(error) // this.httpErrorHandle.httpStatusHandle(error)
}); // });
} // }
} }
@@ -20,7 +20,7 @@ export class ShowMorePage implements OnInit {
} }
run() { run() {
let split = this.text.split(/\r?\n|\r|\n/g) let split = (this.text || "").split(/\r?\n|\r|\n/g)
let text = split[0] let text = split[0]
this.shortText = text.slice(0, 100) this.shortText = text.slice(0, 100)
@@ -5,9 +5,7 @@
<div class="title"> <div class="title">
<ion-label>{{publicationFolderService.FolderDetails[folderId].Description}}</ion-label> <ion-label>{{publicationFolderService.FolderDetails[folderId].Description}}</ion-label>
</div> </div>
<div class="actions-icon align-baseline"> <div class="actions-icon align-baseline">
<!-- <ion-icon (click)="AddPublication('1',item.ProcessId)" slot="end" src='assets/images/icons-add-photo.svg'></ion-icon> -->
<button *ngIf="p.userPermission([p.permissionList.Actions.editPost])" class="btn-no-color" (click)="openEditPublication(publicationFolderService.FolderDetails[folderId].ProcessId)"> <button *ngIf="p.userPermission([p.permissionList.Actions.editPost])" class="btn-no-color" (click)="openEditPublication(publicationFolderService.FolderDetails[folderId].ProcessId)">
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="edit" slot="end" src="assets/images/icons-edit.svg" ></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="edit" slot="end" src="assets/images/icons-edit.svg" ></ion-icon>
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="edit" slot="end" src="assets/images/theme/gov/icons-edit.svg" ></ion-icon> <ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="edit" slot="end" src="assets/images/theme/gov/icons-edit.svg" ></ion-icon>
@@ -38,8 +36,7 @@
<div class="main-container px-20" *ngIf="publicationFolderService.FolderDetails[folderId]" > <div class="main-container px-20" *ngIf="publicationFolderService.FolderDetails[folderId]" >
<p class="item-content-detail">{{publicationFolderService.FolderDetails[folderId].Detail}}</p> <p class="item-content-detail">{{publicationFolderService.FolderDetails[folderId].Detail}}</p>
<ion-card *ngFor="let publication of publicationFolderService.publications[folderId] let i = index">
<ion-card *ngFor="let publication of publicationFolderService.publicationList[folderId] let i = index">
<ion-card-content> <ion-card-content>
<div style="width: 100%; height: 395px;overflow:hidden"> <div style="width: 100%; height: 395px;overflow:hidden">
@@ -47,59 +44,19 @@
[publicationList]=publication [publicationList]=publication
[navigation]="true" [navigation]="true"
[pagination]="false" [pagination]="false"
[documentId]=publication.documentId
[datePublication]=publication.datePublication
[processId]=folderId
></app-swiper> ></app-swiper>
</div> </div>
<!--
<swiper-container [config]="swiperThumbsConfig" [modules]="swiperModules" [speed]=400 navigation="true" [pagination]="{clickable: true, dynamicBullets: true }">
<swiper-slide *ngFor="let files of publication.Files let k = index" class="centered-slide">
<div class="cool">
<div >
<img *ngIf="checkFileType.checkFileType(files.FileExtension ) == 'image'" class="post-img cursor-pointer"
[lazyLoad]="'data:image/jpg;base64,' + files.FileBase64">
<video [appVisibility]="onVisibilityChange" #myVideo #videoElement *ngIf="checkFileType.checkFileType(files.FileExtension ) == 'video'" class="post-video" controls="controls" preload="metadata" <div (click)="viewPublicationDetail(publication.documentId, publication.processId)" class="cursor-pointer">
webkit-playsinline="webkit-playsinline" class="videoPlayer" (click)="preventVideoPlay($event)">
<source [src]="files.FileBase64" type="video/mp4" >
</video>
</div>
</div>
</swiper-slide> -->
<!-- <div *ngIf="publication?.Files?.length == 0">
12
</div>
-->
<!--
<div class="swiper-button-next"
style="
position: absolute;
background: red;
top: 50%;
">
<div>arrow-left</div>
</div>
<div class="slides-per-view"
style="
position: absolute;
background: red;
top: 50%;
right: 0px;
">
<div>arrow-rights</div>
</div>s -->
<!-- </swiper-container> -->
<div (click)="viewPublicationDetail(publication.DocumentId, publication.ProcessId)" class="cursor-pointer">
<div class="post-content" > <div class="post-content" >
<div class="post-title-time"> <div class="post-title-time">
<div class="post-title"> <div class="post-title">
<ion-label>{{publication.Title}}</ion-label> <ion-label>{{publication.title}}</ion-label>
</div> </div>
<div class="post-data">{{publication.DatePublication | date: 'dd-MM-yyyy HH:mm'}}</div> <div class="post-data">{{publication.datePublication | date: 'dd-MM-yyyy HH:mm'}}</div>
</div> </div>
<div class="post-description"> <div class="post-description">
<app-show-more <app-show-more
@@ -1,9 +1,7 @@
import { Component, OnInit, Input, Output, EventEmitter, ViewChild, ViewChildren, QueryList, ElementRef } from '@angular/core'; import { Component, OnInit, Input, Output, EventEmitter, ViewChild, ViewChildren, QueryList, ElementRef } from '@angular/core';
import { IonicSlides, ModalController } from '@ionic/angular'; import { IonicSlides, ModalController } from '@ionic/angular';
import { Publication } from 'src/app/models/publication';
import { PublicationFolder } from 'src/app/models/publicationfolder'; import { PublicationFolder } from 'src/app/models/publicationfolder';
import { PublicationsService } from 'src/app/services/publications.service'; import { PublicationsService } from 'src/app/services/publications.service';
import { NewPublicationPage } from 'src/app/pages/publications/new-publication/new-publication.page'; import { NewPublicationPage } from 'src/app/pages/publications/new-publication/new-publication.page';
import { PublicationPipe } from 'src/app/pipes/publication.pipe'; import { PublicationPipe } from 'src/app/pipes/publication.pipe';
import { ThemeService } from 'src/app/services/theme.service' import { ThemeService } from 'src/app/services/theme.service'
@@ -18,7 +16,7 @@ import { checkFileTypeService } from 'src/app/services/checkFileType.service';
import { PublicationVideoManagerService } from "src/app/services/publication/publication-video-manager.service"; import { PublicationVideoManagerService } from "src/app/services/publication/publication-video-manager.service";
import { StopvideoService } from "src/app/services/stopvideo.service"; import { StopvideoService } from "src/app/services/stopvideo.service";
import { PublicationHolderService } from 'src/app/services/publication/publication-holder.service' import { PublicationHolderService } from 'src/app/services/publication/publication-holder.service'
import { PublicationListByProcessIdService } from 'src/app/core/actions/use-case/publication-list-by-process-id.service'
@Component({ @Component({
selector: 'app-view-publications', selector: 'app-view-publications',
templateUrl: './view-publications.page.html', templateUrl: './view-publications.page.html',
@@ -75,20 +73,10 @@ export class ViewPublicationsPage implements OnInit {
public checkFileType: checkFileTypeService, public checkFileType: checkFileTypeService,
private publicationVideoManagerService: PublicationVideoManagerService, private publicationVideoManagerService: PublicationVideoManagerService,
public StopvideoService: StopvideoService, public StopvideoService: StopvideoService,
public PublicationHolderService: PublicationHolderService public PublicationHolderService: PublicationHolderService,
private publicationListByProcessIdService: PublicationListByProcessIdService
) { ) {
setTimeout(() => {
// document.querySelector("swiper-container").shadowRoot.querySelector(".swiper-button-next").innerHTML = "ok"
// alert("ok")
// console.log("this.VideoManager", this.VideoManager, document.querySelector('.VideoManager'))
/* this.publicationVideoManagerService.setContainer(this.VideoManager.nativeElement) */
}, 15000)
// this.publicationVideoManagerService.setContainer(this.VideoManager.nativeElement)
this.createPublicationList() this.createPublicationList()
} }
@@ -103,7 +91,6 @@ export class ViewPublicationsPage implements OnInit {
} }
this.createPublicationList() this.createPublicationList()
window['app-view-publications-page-doRefresh'] = this.doRefresh window['app-view-publications-page-doRefresh'] = this.doRefresh
window['_deletePublication'] = (a, b) => { window['_deletePublication'] = (a, b) => {
this._deletePublication(a, b) this._deletePublication(a, b)
@@ -123,19 +110,16 @@ export class ViewPublicationsPage implements OnInit {
this.publicationFolderService.FolderDetails[this.folderId] = new PublicationFolder(); this.publicationFolderService.FolderDetails[this.folderId] = new PublicationFolder();
} }
this.publicationFolderService.loadPublications(this.folderId);
this.createPublicationList() this.createPublicationList()
this.getFromDB(); this.getFromDB();
this.getPublicationDetail(); this.getPublicationDetail();
this.getPublicationsIds(); this.getPublicationsIds();
this.stopVideo(); this.stopVideo();
setTimeout(() => { setTimeout(() => {
this.doRefresh({}) this.doRefresh({})
}, 1500) }, 1500);
} }
@@ -177,9 +161,6 @@ export class ViewPublicationsPage implements OnInit {
this.showLoader = true; this.showLoader = true;
const folderId = this.folderId const folderId = this.folderId
await this.publicationFolderService.getPublicationsIds(folderId)
this.showLoader = false; this.showLoader = false;
} }
+18 -20
View File
@@ -1,36 +1,34 @@
<!-- <ion-header>
<ion-toolbar>
<ion-title>swiper</ion-title>
</ion-toolbar>
</ion-header> -->
<div> <div>
<swiper-container id="C{{componentId}}" #swipers (click)="click()" [navigation]="navigation" autoHeight="true"> <swiper-container id="C{{componentId}}" #swipers (click)="click()" [navigation]="navigation" autoHeight="true">
<swiper-slide *ngFor="let files of publicationList.Files let k = index" style="width: 100% !important;">
<swiper-slide *ngFor="let files of publicationList let k = index" style="width: 100% !important;">
<div > <div >
<img *ngIf="checkFileType.checkFileType(files.FileExtension ) == 'image'" class="post-img" <img *ngIf="checkFileType.checkFileType(files.extension ) == 'image'" class="post-img"
[src]="'data:image/jpg;base64,' + files.FileBase64" loading="lazy"> [src]="'data:image/jpg;base64,' + files.file" loading="lazy">
<video #videoElements [appVisibility]="onVisibilityChange" *ngIf="checkFileType.checkFileType(files.FileExtension ) == 'video'" class="post-video" controls="controls" preload="none"
<video #videoElements [appVisibility]="onVisibilityChange" *ngIf="checkFileType.checkFileType(files.extension ) == 'video'" class="post-video" controls="controls" preload="none"
playsinline webkit-playsinline="webkit-playsinline" (play)="stopvideoService.registerVideoWithEvent($event)"q> playsinline webkit-playsinline="webkit-playsinline" (play)="stopvideoService.registerVideoWithEvent($event)"q>
<source [src]="files.FileBase64" type="video/mp4"> <source
*ngIf="files.extension === 'MP4'"
[src]="'data:video/mp4;base64,' + files.file"
type="video/mp4"
>
<source
*ngIf="files.extension === 'MOV'"
[src]="'data:video/quicktime;base64,' + files.file"
type="video/quicktime"
>
</video> </video>
<!-- <button class="play-button" *ngIf="!videoPlaying && checkFileType.checkFileType(files.FileExtension ) == 'video'">
</button> -->
</div> </div>
</swiper-slide> </swiper-slide>
</swiper-container> </swiper-container>
</div> </div>
<ion-footer> <ion-footer>
<div *ngIf="pagination && publicationList?.Files?.length > 1" class="dots-container"> <div *ngIf="pagination && publicationList?.length > 1" class="dots-container">
<span *ngFor="let files of publicationList.Files; let k = index" <span *ngFor="let files of publicationList; let k = index"
[class.dotsSwiper]="true" [class.dotsSwiper]="true"
[class.active-dot]="swiperIndex === k" [class.active-dot]="swiperIndex === k"
(click)="goToSlide(k)" (click)="goToSlide(k)"
+29 -3
View File
@@ -1,4 +1,8 @@
import { Component, ElementRef, Input, OnInit, ViewChild, OnChanges, ViewChildren, QueryList } from '@angular/core'; import { Component, ElementRef, Input, OnInit, ViewChild, OnChanges, ViewChildren, QueryList } from '@angular/core';
import { IPublicationDocument } from 'src/app/core/actions/entity/publicationDocument';
import { PublicationFileGetByDocumentIdService } from 'src/app/core/actions/use-case/publication-file-get-by-document-id.service';
import { PublicationFileLocalRepositoryService } from 'src/app/module/actions/data/repository/publication-file-local-repository.service';
import { PublicationFileRemoteRepositoryService } from 'src/app/module/actions/data/repository/publication-file-remote-repository.service';
import { checkFileTypeService } from 'src/app/services/checkFileType.service'; import { checkFileTypeService } from 'src/app/services/checkFileType.service';
import { StopvideoService } from 'src/app/services/stopvideo.service'; import { StopvideoService } from 'src/app/services/stopvideo.service';
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
@@ -9,9 +13,12 @@ import { v4 as uuidv4 } from 'uuid'
}) })
export class SwiperPage implements OnInit { export class SwiperPage implements OnInit {
@Input() publicationList: any; @Input() publicationList: IPublicationDocument[];
@Input() navigation: boolean; @Input() navigation: boolean;
@Input() pagination: boolean; @Input() pagination: boolean;
@Input() processId: number;
@Input() documentId: number;
@Input() datePublication: string;
swiperIndex: number = 0; swiperIndex: number = 0;
@ViewChildren('videoElement') videoElements: QueryList<ElementRef>; @ViewChildren('videoElement') videoElements: QueryList<ElementRef>;
@@ -25,6 +32,9 @@ export class SwiperPage implements OnInit {
constructor( constructor(
public checkFileType: checkFileTypeService, public checkFileType: checkFileTypeService,
public stopvideoService: StopvideoService, public stopvideoService: StopvideoService,
private local: PublicationFileLocalRepositoryService,
private remote: PublicationFileRemoteRepositoryService,
private publicationFileGetByDocumentIdService: PublicationFileGetByDocumentIdService
) {} ) {}
ngOnInit() { ngOnInit() {
@@ -40,6 +50,22 @@ export class SwiperPage implements OnInit {
} catch(e) {} } catch(e) {}
}, 100) }, 100)
this.local.find({documentId: this.documentId}).then(async e => {
if(e.isOk() && e.value.length == 0) {
var result = await this.publicationFileGetByDocumentIdService.execute({
documentId: this.documentId,
processId: this.processId,
datePublication: this.datePublication
});
if(result.isOk()) {
this.publicationList = result.value.added;
}
} else if(e.isOk()) {
this.publicationList = e.value;
}
})
} }
ngOnChanges() { ngOnChanges() {
@@ -112,8 +138,8 @@ export class SwiperPage implements OnInit {
try { try {
const file = this.publicationList.Files[this.swiperIndex] const file = this.publicationList[this.swiperIndex]
if(this.checkFileType.checkFileType(file.FileExtension ) == 'video') { if(this.checkFileType.checkFileType(file.extension ) == 'video') {
const video = document.querySelector(`#C${this.componentId} .swiper-slide-active video`) as HTMLVideoElement const video = document.querySelector(`#C${this.componentId} .swiper-slide-active video`) as HTMLVideoElement
if(video) { if(video) {
+51 -64
View File
@@ -4,43 +4,80 @@ import { Storage } from '@ionic/storage';
import { Publication } from '../models/publication'; import { Publication } from '../models/publication';
import { PublicationsService } from '../services/publications.service'; import { PublicationsService } from '../services/publications.service';
import { PublicationPipe } from 'src/app/pipes/publication.pipe'; import { PublicationPipe } from 'src/app/pipes/publication.pipe';
import { IPublication } from '../core/actions/entity/publicationEntity';
import { PublicationListByProcessIdService } from '../core/actions/use-case/publication-list-by-process-id.service';
import { PublicationLocalRepositoryService } from '../module/actions/data/repository/publication-local-repository.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class PublicationFolderService { export class PublicationFolderService {
publications: { [key: string]: (IPublication)[] } = {};
publicationList: { [key: string]: Publication[] } = {}; publicationList: { [key: string]: Publication[] } = {};
FolderDetails: { [key: string]: PublicationFolder } = {}; FolderDetails: { [key: string]: PublicationFolder } = {};
restoreFolder: {} = {} restoreFolder: {} = {}
keyName: string keyName: string
showLoader = false
showLoader = true
publicationPipe = new PublicationPipe() publicationPipe = new PublicationPipe()
getpublication = []; getpublication = [];
gotoAction: string | false gotoAction: string | false
constructor( constructor(
private storage: Storage, private storage: Storage,
private publications: PublicationsService, private publicationService: PublicationsService,
private publicationListByProcessIdService: PublicationListByProcessIdService,
private publicationLocalRepo: PublicationLocalRepositoryService,
) { } ) { }
clear() { clear() {
this.publicationList = {}; this.publicationList = {};
this.FolderDetails = {}; this.FolderDetails = {};
this.restoreFolder = {} this.restoreFolder = {}
this.showLoader = false
this.showLoader = true
this.publicationPipe = new PublicationPipe() this.publicationPipe = new PublicationPipe()
this.getpublication = []; this.getpublication = [];
} }
async loadPublications(processId: number) {
this.showLoader = true;
if (!this.publications[processId]) {
this.publications[processId] = []
const result = await this.publicationLocalRepo.find({processId});
if(result.isOk()) {
this.publications[processId] = result.value;
}
}
const result = await this.publicationListByProcessIdService.execute(processId);
if(result.isOk()) {
for(const item of result.value.added) {
this.publications[processId].push(item);
}
// handle removed
for (const item of result.value.remove) {
this.publications[processId] = this.publications[processId].filter(f => f.documentId !== item.documentId);
}
// handle updated
for (const item of result.value.updated) {
const index = this.publications[processId].findIndex(f => f.documentId === item.documentId);
if (index !== -1) {
this.publications[processId][index] = item; // replace with updated version
} else {
this.publications[processId].push(item); // if not found, just add it
}
}
}
this.showLoader = false;
}
createPublicationList(folderId) { createPublicationList(folderId) {
if (!this.publicationList[folderId]) { if (!this.publicationList[folderId]) {
@@ -53,7 +90,6 @@ export class PublicationFolderService {
getFromDB(folderId: any) { getFromDB(folderId: any) {
if (!this.restoreFolder[folderId]) { if (!this.restoreFolder[folderId]) {
this.storage.get(folderId).then((viewPublications) => { this.storage.get(folderId).then((viewPublications) => {
@@ -109,66 +145,19 @@ export class PublicationFolderService {
} }
} }
getPublicationDetail(folderId) { getPublicationDetail(folderId) {
this.publications.GetPresidentialAction(folderId).subscribe(res => { this.publicationService.GetPresidentialAction(folderId).subscribe(res => {
this.FolderDetails[folderId] = res this.FolderDetails[folderId] = res
this.storage.set(folderId + "name", res) this.storage.set(folderId + "name", res)
}, (error) => { }, (error) => {
this.showLoader = false;
// this.httpErroHandle.httpStatusHandle(error) // this.httpErroHandle.httpStatusHandle(error)
}); });
} }
async getPublicationsIds(folderId) {
this.showLoader = true;
try {
const publicationIds: number[] = await this.publications.GetPublicationsList(folderId).toPromise();
this.createPublicationList(folderId)
for (let localPublication of this.publicationList[folderId]) {
const apiPublication = publicationIds.includes(localPublication.DocumentId)
if (!apiPublication) {
this.deletePost(folderId, localPublication.DocumentId)
}
}
let loadLater = []
for (let publicationId of publicationIds) {
if (!this.publicationIsPresent(publicationId, folderId)) {
await this.loadPublication(publicationId, folderId)
} else {
loadLater.push(publicationId)
}
}
for (let publicationId of loadLater) {
await this.loadPublication(publicationId, folderId)
}
this.showLoader = false;
this.storage.set(folderId, this.publicationList[folderId]);
this.getpublication = this.publicationList[folderId];
} catch (error) {
this.showLoader = false;
}
}
async loadPublication(publicationId, folderId) { async loadPublication(publicationId, folderId) {
let Publication = await this.publications.GetPublicationWithArrayOfFilesById(publicationId).toPromise(); let Publication = await this.publicationService.GetPublicationWithArrayOfFilesById(publicationId).toPromise();
let publicationDetails: Publication = this.publicationPipe.itemList(Publication) let publicationDetails: Publication = this.publicationPipe.itemList(Publication)
const findIndex = this.publicationFindIndex(publicationId, folderId) const findIndex = this.publicationFindIndex(publicationId, folderId)
@@ -195,7 +184,7 @@ export class PublicationFolderService {
async CreatePublication(folderId, publication: Publication) { async CreatePublication(folderId, publication: Publication) {
const response = await this.publications.CreatePublication(folderId, publication).toPromise() const response = await this.publicationService.CreatePublication(folderId, publication).toPromise()
let publicationDetails: Publication = this.publicationPipe.itemList(response) let publicationDetails: Publication = this.publicationPipe.itemList(response)
this.publicationList[folderId].push(publicationDetails) this.publicationList[folderId].push(publicationDetails)
this.revertPublicationOrder(folderId) this.revertPublicationOrder(folderId)
@@ -237,8 +226,6 @@ export class PublicationFolderService {
if (this.publicationList[folderId]) { if (this.publicationList[folderId]) {
return this.publicationList[folderId].find(e => e.DocumentId == DocumentId) return this.publicationList[folderId].find(e => e.DocumentId == DocumentId)
} else {
} }
} }
-5
View File
@@ -737,11 +737,6 @@ export class AgendaPage implements OnInit {
let eventsList = response.value; let eventsList = response.value;
tracing.log('range', {
date: { startTime, endTime },
value: response.value
})
this.CalendarStore.pushEvent(eventsList, label, selectedCalendar.wxUserId); this.CalendarStore.pushEvent(eventsList, label, selectedCalendar.wxUserId);
this.listToPresent = this.CalendarStore.getEventsByCalendarIds(selectedCalendarIds) this.listToPresent = this.CalendarStore.getEventsByCalendarIds(selectedCalendarIds)
this.showTimelinePR = true; this.showTimelinePR = true;
@@ -55,7 +55,8 @@ export class GroupContactsPage implements OnInit {
this.showLoader = true; this.showLoader = true;
const addMembers = await this.chatServiceService.addMemberToRoom({ const addMembers = await this.chatServiceService.addMemberToRoom({
id: this.roomId, id: this.roomId,
members: this.selectedUsers members: this.selectedUsers,
userId: SessionStore.user.UserId
}) })
@@ -35,7 +35,6 @@ import { LastMessage } from '../../utils/lastMessage';
import { UserTypingLocalRepository } from 'src/app/module/chat/data/repository/typing/user-typing-local-data-source.service'; import { UserTypingLocalRepository } from 'src/app/module/chat/data/repository/typing/user-typing-local-data-source.service';
import { UserTypingRemoteRepositoryService } from 'src/app/module/chat/data/repository/typing/user-typing-live-data-source.service'; import { UserTypingRemoteRepositoryService } from 'src/app/module/chat/data/repository/typing/user-typing-live-data-source.service';
import { RoomType } from "src/app/core/chat/entity/group"; import { RoomType } from "src/app/core/chat/entity/group";
import { Logger } from 'src/app/services/logger/main/service';
import { tap } from 'rxjs/operators'; import { tap } from 'rxjs/operators';
import { AlertController } from '@ionic/angular'; import { AlertController } from '@ionic/angular';
import { ViewOncesImagePage, ViewOncesImagePageInput } from '../../modal/view-onces/view-onces.page'; import { ViewOncesImagePage, ViewOncesImagePageInput } from '../../modal/view-onces/view-onces.page';
@@ -894,6 +893,10 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
async sendMessage() { async sendMessage() {
if(this.textField.replace(/\s+/g, "") == "") {
return true;
}
const message = this.createMessage(); const message = this.createMessage();
message.message = this.textField message.message = this.textField
@@ -1168,7 +1171,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
askIfOneShot(): Promise<boolean> { askIfOneShot(): Promise<boolean> {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
const alert = await this.alertController.create({ const alert = await this.alertController.create({
header: 'Confirm', header: 'Confirmar',
message: 'Visualização unica?', message: 'Visualização unica?',
buttons: [ buttons: [
{ {
@@ -147,10 +147,10 @@ export class GroupContactsPage implements OnInit {
this.showLoader = true; this.showLoader = true;
const addMembers = await this.chatServiceService.addMemberToRoom({ const addMembers = await this.chatServiceService.addMemberToRoom({
id: this.roomId, id: this.roomId,
members: this.selectedUsers members: this.selectedUsers,
userId: SessionStore.user.UserId
}) })
if(addMembers.isOk()) { if(addMembers.isOk()) {
// this.addContacts(this.roomId); // this.addContacts(this.roomId);
//this.openGroupMessage.emit(this.roomId); //this.openGroupMessage.emit(this.roomId);
@@ -360,6 +360,9 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
async sendMessage() { async sendMessage() {
if(this.textField.replace(/\s+/g, "") == "") {
return true;
}
this.RoomStore.sendMessage(this.textField) this.RoomStore.sendMessage(this.textField)
this.textField = '' this.textField = ''
@@ -85,9 +85,6 @@ export class HeaderPage implements OnInit {
this.profilePictureSubject = this.UserRepositoryService.getProfilePictureLive() as any this.profilePictureSubject = this.UserRepositoryService.getProfilePictureLive() as any
this.notificationCount$ = this.notificationRepositoryService.getNotificationLiveCount() this.notificationCount$ = this.notificationRepositoryService.getNotificationLiveCount()
this.UserRepositoryService.getProfilePictureLive().subscribe((e) => {
console.log(`nice job ${e}`);
});
this.loggeduser = SessionStore.user; this.loggeduser = SessionStore.user;
router.events.subscribe((val) => { router.events.subscribe((val) => {
this.hideSearch(); this.hideSearch();
-1
View File
@@ -2,5 +2,4 @@ import { Environment } from './../app/models/envarioment'
import { environment as oaprDev } from './suport/oapr' import { environment as oaprDev } from './suport/oapr'
import { DevDev } from './suport/dev' import { DevDev } from './suport/dev'
export const environment: Environment = DevDev export const environment: Environment = DevDev
+21
View File
@@ -1723,3 +1723,24 @@ h5, .buttons{
background-color: red; background-color: red;
} }
} }
/* Change arrow color */
::ng-deep .swiper-button-next,
::ng-deep .swiper-button-prev {
color: #2563eb; /* Tailwind blue-600 */
}
/* Change arrow icon size */
::ng-deep .swiper-button-next:after,
::ng-deep .swiper-button-prev:after {
font-size: 28px; /* bigger */
font-weight: bold;
}
/* Example: use emoji instead of default icon */
::ng-deep .swiper-button-next:after {
content: '👉';
}
::ng-deep .swiper-button-prev:after {
content: '👈';
}
+8
View File
@@ -1141,6 +1141,10 @@ swiper-container::part(button-next) {
background-size: 100%; background-size: 100%;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center; background-position: center;
border-radius: 100px;
height: 27px;
border: 1px solid gray;
box-shadow: 0px 0px 10px #6b6b6b5e;
} }
@@ -1155,4 +1159,8 @@ swiper-container::part(button-prev) {
-moz-transform: rotate(180deg); -moz-transform: rotate(180deg);
-ms-transform: rotate(180deg); -ms-transform: rotate(180deg);
-o-transform: rotate(180deg); -o-transform: rotate(180deg);
border-radius: 100px;
height: 27px;
border: 1px solid gray;
box-shadow: 0px 0px 10px #6b6b6b5e;
} }
File diff suppressed because one or more lines are too long