0524 sync
This commit is contained in:
parent
b4ef37624c
commit
02c2645e01
|
@ -14,7 +14,23 @@ module.exports = {
|
||||||
rule.use.push({
|
rule.use.push({
|
||||||
loader: 'sass-resources-loader',
|
loader: 'sass-resources-loader',
|
||||||
options: {
|
options: {
|
||||||
resources: [path.join(__dirname, 'styles.scss')]
|
resources: [
|
||||||
|
path.join(
|
||||||
|
__dirname,
|
||||||
|
'..',
|
||||||
|
'node_modules',
|
||||||
|
'@angular/material/prebuilt-themes',
|
||||||
|
'indigo-pink.css'
|
||||||
|
),
|
||||||
|
path.join(
|
||||||
|
__dirname,
|
||||||
|
'..',
|
||||||
|
'node_modules',
|
||||||
|
'perfect-scrollbar/css',
|
||||||
|
'perfect-scrollbar.css'
|
||||||
|
),
|
||||||
|
path.join(__dirname, 'styles.scss')
|
||||||
|
]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
6
.storybook/preview-head.html
Normal file
6
.storybook/preview-head.html
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/icon?family=Material+Icons"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<style></style>
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"extends": "../tsconfig.json",
|
"extends": "../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
"types": ["node"]
|
"types": ["node"]
|
||||||
},
|
},
|
||||||
"exclude": [
|
"exclude": [
|
||||||
|
|
43
angular.json
43
angular.json
|
@ -1264,6 +1264,49 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ui-material": {
|
||||||
|
"projectType": "library",
|
||||||
|
"schematics": {
|
||||||
|
"@schematics/angular:component": {
|
||||||
|
"style": "scss"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "projects/ui-material",
|
||||||
|
"sourceRoot": "projects/ui-material/src",
|
||||||
|
"prefix": "lib",
|
||||||
|
"architect": {
|
||||||
|
"build": {
|
||||||
|
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||||
|
"options": {
|
||||||
|
"tsConfig": "projects/ui-material/tsconfig.lib.json",
|
||||||
|
"project": "projects/ui-material/ng-package.json"
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"tsConfig": "projects/ui-material/tsconfig.lib.prod.json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"builder": "@angular-devkit/build-angular:karma",
|
||||||
|
"options": {
|
||||||
|
"main": "projects/ui-material/src/test.ts",
|
||||||
|
"tsConfig": "projects/ui-material/tsconfig.spec.json",
|
||||||
|
"karmaConfig": "projects/ui-material/karma.conf.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"builder": "@angular-devkit/build-angular:tslint",
|
||||||
|
"options": {
|
||||||
|
"tsConfig": [
|
||||||
|
"projects/ui-material/tsconfig.lib.json",
|
||||||
|
"projects/ui-material/tsconfig.spec.json"
|
||||||
|
],
|
||||||
|
"exclude": ["**/node_modules/**"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"ui": {
|
"ui": {
|
||||||
"projectType": "library",
|
"projectType": "library",
|
||||||
"schematics": {
|
"schematics": {
|
||||||
|
|
52
package-lock.json
generated
52
package-lock.json
generated
|
@ -3503,18 +3503,18 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@ucap/ng-store-authentication": {
|
"@ucap/ng-store-authentication": {
|
||||||
"version": "file:pack/ucap-ng-store-authentication-0.0.10.tgz",
|
"version": "file:pack/ucap-ng-store-authentication-0.0.11.tgz",
|
||||||
"integrity": "sha512-71Jzg9oYSQ89nShT3F64Mfy4edAbmc/vH/0pbPtT0S4zVH/ZMiC11xnocDQTzAKKtP1kXdNGJt/wv1ZbjMNUQQ==",
|
"integrity": "sha512-YwLMW+GIR3Rs7LaP+1xOH9KLI5jlpZx8oS7Zl32m6Wbym4ModIcGh21rRrqFhNXky4s9zl+ziaTRpFNCKJRgng==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@ucap/ng-store-chat": {
|
"@ucap/ng-store-chat": {
|
||||||
"version": "file:pack/ucap-ng-store-chat-0.0.8.tgz",
|
"version": "file:pack/ucap-ng-store-chat-0.0.13.tgz",
|
||||||
"integrity": "sha512-f/Smoy/A97JV2Tsd7IIAeQcNRrthxKT+S01PrVyzjNktDvcxOurnIXGacytU9sfkEMP2rOFCuWKv5p21rvVg6g==",
|
"integrity": "sha512-o+BCCSMxneUenRHEW47sSY22+Zt3lyr202Lg4bub9OVRbW5CVohHez8H+JwK+w+Lf8KbqG32V1ZjKLGclTpboA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@ucap/ng-store-group": {
|
"@ucap/ng-store-group": {
|
||||||
"version": "file:pack/ucap-ng-store-group-0.0.9.tgz",
|
"version": "file:pack/ucap-ng-store-group-0.0.14.tgz",
|
||||||
"integrity": "sha512-KJ4E/kZECAkT6zwA1FiDCrhGevCx9so2Knz08kU49broquZQlOtbV70tPj1fA0XBnaY3hL7uUKXqvAfC7OXj0g==",
|
"integrity": "sha512-sUmdHO7TD5B33DMAoEnelvqbLXTsWPnK2HC8XQ0FdlfGyUtf3kGpwS4BxduUi5wiZckR3hfuBdpCShIhf/qmeQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@ucap/ng-store-organization": {
|
"@ucap/ng-store-organization": {
|
||||||
|
@ -3523,33 +3523,39 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@ucap/ng-ui": {
|
"@ucap/ng-ui": {
|
||||||
"version": "file:pack/ucap-ng-ui-0.0.11.tgz",
|
"version": "file:pack/ucap-ng-ui-0.0.19.tgz",
|
||||||
"integrity": "sha512-Vrl6LFQyBwju76RALrF0/dH9p+PJ4nX33dy99QSx6RUJHQ80C0qAmO/DFS1Ln0LZaDc4KoYIHTAOLvX4WLHS5w==",
|
"integrity": "sha512-UuZSzWM4tBR+e5Z/1PFdNenHS00Pn4K7dTafIicG29YjHE5sTXXRqjDCVrKNxJQoMSEPWjUj7qnTgYwP2U83Vg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@ucap/ng-ui-authentication": {
|
"@ucap/ng-ui-authentication": {
|
||||||
"version": "file:pack/ucap-ng-ui-authentication-0.0.20.tgz",
|
"version": "file:pack/ucap-ng-ui-authentication-0.0.24.tgz",
|
||||||
"integrity": "sha512-1FhqwODVL51NC39mwi/2MECMQiyM+qXAlVp2/BrvN+piXXRz/qp62Iwyf/jww+N8aVCe3dqbktJl/tuPacm4/Q==",
|
"integrity": "sha512-6QMJ8dieTnbPANsBzg2Ll3HH5q6Bzl2iSM19yHq8Ct7XOmElrYqrEZmxbDyYO+aCXIAwd2t7vu+rTsHfz3XOQg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@ucap/ng-ui-chat": {
|
"@ucap/ng-ui-chat": {
|
||||||
"version": "file:pack/ucap-ng-ui-chat-0.0.3.tgz",
|
"version": "file:pack/ucap-ng-ui-chat-0.0.9.tgz",
|
||||||
"integrity": "sha512-RRw533PNi0vVCxH1QiogOkJEC/dWGsSFtK3hdJ/ZlcPCT7G81FnnXVY3HPIzu1MhxnSb7KfVJLZhx2RFEfEXWA==",
|
"integrity": "sha512-6qvzcTuylkxVjsqajsLW15laOyOskxVMy238/Ju1yYvwCRyHygwS1i67APoG5tv+SWu+l38f9uWIqzfy7WYHkQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@ucap/ng-ui-group": {
|
"@ucap/ng-ui-group": {
|
||||||
"version": "file:pack/ucap-ng-ui-group-0.0.30.tgz",
|
"version": "file:pack/ucap-ng-ui-group-0.0.33.tgz",
|
||||||
"integrity": "sha512-LJXwWZ4anO/ScpI+c6IUfwjmcW9tocQq86/cHi8m6SaQwaMq3jltlN2x8WLzRefd72KysLyJHZrX5L1zMLcXog==",
|
"integrity": "sha512-c//Jq00drbMGE3Cgwlh19ScXllGERX2eMVWkVjm311Y8HN9oBBT6Aq2uCM23/76P866oNrhecVDfDHgGYzPRjA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@ucap/ng-ui-material": {
|
||||||
|
"version": "file:pack/ucap-ng-ui-material-0.0.4.tgz",
|
||||||
|
"integrity": "sha512-ySPULAbP+nQ65hBG2VWZ2H5Hr7muuTGGNXs6A+S3lsxLaW452wM3GNyUBhvUopr8LaSsoOPpp4nK1JeC0fG6pA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@ucap/ng-ui-organization": {
|
"@ucap/ng-ui-organization": {
|
||||||
"version": "file:pack/ucap-ng-ui-organization-0.0.27.tgz",
|
"version": "file:pack/ucap-ng-ui-organization-0.0.55.tgz",
|
||||||
"integrity": "sha512-BC0Jxoxia/+Kho+1oAXE+7+K9iXLhVYVWPVCmmzSRGYGrIZu1skNzzKCNZh6WxYOr7LAJ6ZOp+FgYDfKS7iHMg==",
|
"integrity": "sha512-vfpKd3fbd+I0Od8aB2nIFfjuI7wj3Ziu/uiTEmZxKwZy7uZrNYm59BPbctKW3AQsQ4UtnLofhlBbAA7e9pT80Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@ucap/ng-ui-skin-default": {
|
"@ucap/ng-ui-skin-default": {
|
||||||
"version": "file:pack/ucap-ng-ui-skin-default-0.0.1.tgz",
|
"version": "file:pack/ucap-ng-ui-skin-default-0.0.1.tgz",
|
||||||
"integrity": "sha512-kfbbfHZ2b1mQL5SflvM9xn86d53NFEx3yTCaQSx16VSEetbQAtb6Qp1/VedDxK6NcWHp+s/Msw5cfuypN1gwug=="
|
"integrity": "sha512-+lHYAzbnyyWh6hf+Ui7vP/ibyGJXuDUO++82jOiOsnPMCl17hkCCag8vQcB/aVgl0iHmebiPshnsL3CptJfeAg==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"@ucap/ng-web-socket": {
|
"@ucap/ng-web-socket": {
|
||||||
"version": "file:pack/ucap-ng-web-socket-0.0.2.tgz",
|
"version": "file:pack/ucap-ng-web-socket-0.0.2.tgz",
|
||||||
|
@ -3592,9 +3598,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@ucap/protocol-file": {
|
"@ucap/protocol-file": {
|
||||||
"version": "0.0.4",
|
"version": "0.0.5",
|
||||||
"resolved": "https://nexus.loafle.net/repository/npm-all/@ucap/protocol-file/-/protocol-file-0.0.4.tgz",
|
"resolved": "https://nexus.loafle.net/repository/npm-all/@ucap/protocol-file/-/protocol-file-0.0.5.tgz",
|
||||||
"integrity": "sha512-oyne/wiKsEsLzJY9VJUO85AwLtgfq0Dt7RyFLThoqquz6O7lCuWszdtvggAJTgn+XM+nF4hczw2Qm2jwjjCZgQ==",
|
"integrity": "sha512-3XRwtlpcrm2oZeckoOzzAUcqADPCGbgdEb4psfNnphTbGX9nYaBUTpWuLYwD3tVe7Wg4fytaHemcAu8yVZUANw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@ucap/protocol-group": {
|
"@ucap/protocol-group": {
|
||||||
|
@ -3604,9 +3610,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@ucap/protocol-info": {
|
"@ucap/protocol-info": {
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"resolved": "https://nexus.loafle.net/repository/npm-all/@ucap/protocol-info/-/protocol-info-0.0.5.tgz",
|
"resolved": "https://nexus.loafle.net/repository/npm-all/@ucap/protocol-info/-/protocol-info-0.0.6.tgz",
|
||||||
"integrity": "sha512-C2+cJrxdUNLVt3E1a54tCpTmEYE16sUGNvdJGUPywbvLAhjWf71ECjGr16bTMcPr/PxmzjZBu9M2Of39sqngOQ==",
|
"integrity": "sha512-qpt0jfmHDyaMGyADzaDMKbbkfD04yEC0u4KDyoMdjnTi0RXA6cilDRGr9TW/bezB9OxS40yNLK6REfh7aSmcUA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@ucap/protocol-inner": {
|
"@ucap/protocol-inner": {
|
||||||
|
|
39
package.json
39
package.json
|
@ -6,7 +6,7 @@
|
||||||
"ng": "ng",
|
"ng": "ng",
|
||||||
"start": "ng serve",
|
"start": "ng serve",
|
||||||
"build": "ng build",
|
"build": "ng build",
|
||||||
"build:all": "npm-run-all -s build:logger build:core build:util:all build:api:all build:protocol:all build:native:all build:store:all build:ui:all build:ui-skin:all",
|
"build:all": "npm-run-all -s build:logger build:core build:util:all build:api:all build:protocol:all build:native:all build:store:all build:ui-material:all build:ui:all build:ui-skin:all",
|
||||||
"build:api:all": "npm-run-all -s build:api-common build:api-external build:api-message build:api-prompt build:api-public build:pi",
|
"build:api:all": "npm-run-all -s build:api-common build:api-external build:api-message build:api-prompt build:api-public build:pi",
|
||||||
"build:api-common": "node ./scripts/build.js api-common",
|
"build:api-common": "node ./scripts/build.js api-common",
|
||||||
"build:api-external": "node ./scripts/build.js api-external",
|
"build:api-external": "node ./scripts/build.js api-external",
|
||||||
|
@ -45,15 +45,17 @@
|
||||||
"build:store-chat": "node ./scripts/build.js store-chat",
|
"build:store-chat": "node ./scripts/build.js store-chat",
|
||||||
"build:store-group": "node ./scripts/build.js store-group",
|
"build:store-group": "node ./scripts/build.js store-group",
|
||||||
"build:store-organization": "node ./scripts/build.js store-organization",
|
"build:store-organization": "node ./scripts/build.js store-organization",
|
||||||
|
"build:ui-material:all": "npm-run-all -s build:ui-material",
|
||||||
|
"build:ui-material": "node ./scripts/build.js ui-material useScssBundle",
|
||||||
"build:ui:all": "npm-run-all -s build:ui build:ui-organization build:ui-authentication build:ui-group build:ui-chat",
|
"build:ui:all": "npm-run-all -s build:ui build:ui-organization build:ui-authentication build:ui-group build:ui-chat",
|
||||||
"build:ui": "node ./scripts/build.js ui",
|
"build:ui": "node ./scripts/build.js ui useScssBundle",
|
||||||
"build:ui-organization": "node ./scripts/build.js ui-organization",
|
"build:ui-organization": "node ./scripts/build.js ui-organization useScssBundle",
|
||||||
"build:ui-authentication": "node ./scripts/build.js ui-authentication",
|
"build:ui-authentication": "node ./scripts/build.js ui-authentication useScssBundle",
|
||||||
"build:ui-group": "node ./scripts/build.js ui-group",
|
"build:ui-group": "node ./scripts/build.js ui-group useScssBundle",
|
||||||
"build:ui-chat": "node ./scripts/build.js ui-chat",
|
"build:ui-chat": "node ./scripts/build.js ui-chat useScssBundle",
|
||||||
"build:ui-skin:all": "npm-run-all -s build:ui-skin-default",
|
"build:ui-skin:all": "npm-run-all -s build:ui-skin-default",
|
||||||
"build:ui-skin-default": "node ./scripts/build.js ui-skin-default useScssBundle",
|
"build:ui-skin-default": "node ./scripts/build.js ui-skin-default useScssBundle",
|
||||||
"publish:all": "npm-run-all -s publish:logger publish:core publish:util:all publish:api:all publish:protocol:all publish:native:all publish:store:all publish:ui:all publish:ui-skin:all",
|
"publish:all": "npm-run-all -s publish:logger publish:core publish:util:all publish:api:all publish:protocol:all publish:native:all publish:store:all publish:ui-material:all publish:ui:all publish:ui-skin:all",
|
||||||
"publish:api:all": "npm-run-all -s publish:api-common publish:api-external publish:api-message publish:api-prompt publish:api-public publish:pi",
|
"publish:api:all": "npm-run-all -s publish:api-common publish:api-external publish:api-message publish:api-prompt publish:api-public publish:pi",
|
||||||
"publish:api-common": "cd ./dist/api-common && npm publish",
|
"publish:api-common": "cd ./dist/api-common && npm publish",
|
||||||
"publish:api-external": "cd ./dist/api-external && npm publish",
|
"publish:api-external": "cd ./dist/api-external && npm publish",
|
||||||
|
@ -92,6 +94,8 @@
|
||||||
"publish:store-chat": "cd ./dist/store-chat && npm publish",
|
"publish:store-chat": "cd ./dist/store-chat && npm publish",
|
||||||
"publish:store-group": "cd ./dist/store-group && npm publish",
|
"publish:store-group": "cd ./dist/store-group && npm publish",
|
||||||
"publish:store-organization": "cd ./dist/store-organization && npm publish",
|
"publish:store-organization": "cd ./dist/store-organization && npm publish",
|
||||||
|
"publish:ui-material:all": "npm-run-all -s publish:ui-material",
|
||||||
|
"publish:ui-material": "cd ./dist/ui-material && npm publish",
|
||||||
"publish:ui:all": "npm-run-all -s publish:ui publish:ui-organization publish:ui-authentication publish:ui-group publish:ui-chat",
|
"publish:ui:all": "npm-run-all -s publish:ui publish:ui-organization publish:ui-authentication publish:ui-group publish:ui-chat",
|
||||||
"publish:ui": "cd ./dist/ui && npm publish",
|
"publish:ui": "cd ./dist/ui && npm publish",
|
||||||
"publish:ui-organization": "cd ./dist/ui-organization && npm publish",
|
"publish:ui-organization": "cd ./dist/ui-organization && npm publish",
|
||||||
|
@ -180,15 +184,16 @@
|
||||||
"@ucap/ng-protocol-status": "file:pack/ucap-ng-protocol-status-0.0.3.tgz",
|
"@ucap/ng-protocol-status": "file:pack/ucap-ng-protocol-status-0.0.3.tgz",
|
||||||
"@ucap/ng-protocol-sync": "file:pack/ucap-ng-protocol-sync-0.0.3.tgz",
|
"@ucap/ng-protocol-sync": "file:pack/ucap-ng-protocol-sync-0.0.3.tgz",
|
||||||
"@ucap/ng-protocol-umg": "file:pack/ucap-ng-protocol-umg-0.0.3.tgz",
|
"@ucap/ng-protocol-umg": "file:pack/ucap-ng-protocol-umg-0.0.3.tgz",
|
||||||
"@ucap/ng-store-authentication": "file:pack/ucap-ng-store-authentication-0.0.10.tgz",
|
"@ucap/ng-store-authentication": "file:pack/ucap-ng-store-authentication-0.0.11.tgz",
|
||||||
"@ucap/ng-store-chat": "file:pack/ucap-ng-store-chat-0.0.8.tgz",
|
"@ucap/ng-store-chat": "file:pack/ucap-ng-store-chat-0.0.13.tgz",
|
||||||
"@ucap/ng-store-group": "file:pack/ucap-ng-store-group-0.0.9.tgz",
|
"@ucap/ng-store-group": "file:pack/ucap-ng-store-group-0.0.14.tgz",
|
||||||
"@ucap/ng-store-organization": "file:pack/ucap-ng-store-organization-0.0.8.tgz",
|
"@ucap/ng-store-organization": "file:pack/ucap-ng-store-organization-0.0.8.tgz",
|
||||||
"@ucap/ng-ui": "file:pack/ucap-ng-ui-0.0.11.tgz",
|
"@ucap/ng-ui": "file:pack/ucap-ng-ui-0.0.19.tgz",
|
||||||
"@ucap/ng-ui-authentication": "file:pack/ucap-ng-ui-authentication-0.0.20.tgz",
|
"@ucap/ng-ui-authentication": "file:pack/ucap-ng-ui-authentication-0.0.24.tgz",
|
||||||
"@ucap/ng-ui-chat": "file:pack/ucap-ng-ui-chat-0.0.3.tgz",
|
"@ucap/ng-ui-chat": "file:pack/ucap-ng-ui-chat-0.0.9.tgz",
|
||||||
"@ucap/ng-ui-group": "file:pack/ucap-ng-ui-group-0.0.30.tgz",
|
"@ucap/ng-ui-group": "file:pack/ucap-ng-ui-group-0.0.33.tgz",
|
||||||
"@ucap/ng-ui-organization": "file:pack/ucap-ng-ui-organization-0.0.27.tgz",
|
"@ucap/ng-ui-material": "file:pack/ucap-ng-ui-material-0.0.4.tgz",
|
||||||
|
"@ucap/ng-ui-organization": "file:pack/ucap-ng-ui-organization-0.0.55.tgz",
|
||||||
"@ucap/ng-ui-skin-default": "file:pack/ucap-ng-ui-skin-default-0.0.1.tgz",
|
"@ucap/ng-ui-skin-default": "file:pack/ucap-ng-ui-skin-default-0.0.1.tgz",
|
||||||
"@ucap/ng-web-socket": "file:pack/ucap-ng-web-socket-0.0.2.tgz",
|
"@ucap/ng-web-socket": "file:pack/ucap-ng-web-socket-0.0.2.tgz",
|
||||||
"@ucap/ng-web-storage": "file:pack/ucap-ng-web-storage-0.0.3.tgz",
|
"@ucap/ng-web-storage": "file:pack/ucap-ng-web-storage-0.0.3.tgz",
|
||||||
|
@ -197,9 +202,9 @@
|
||||||
"@ucap/protocol-authentication": "~0.0.5",
|
"@ucap/protocol-authentication": "~0.0.5",
|
||||||
"@ucap/protocol-buddy": "~0.0.5",
|
"@ucap/protocol-buddy": "~0.0.5",
|
||||||
"@ucap/protocol-event": "~0.0.5",
|
"@ucap/protocol-event": "~0.0.5",
|
||||||
"@ucap/protocol-file": "~0.0.4",
|
"@ucap/protocol-file": "~0.0.5",
|
||||||
"@ucap/protocol-group": "~0.0.5",
|
"@ucap/protocol-group": "~0.0.5",
|
||||||
"@ucap/protocol-info": "~0.0.5",
|
"@ucap/protocol-info": "~0.0.6",
|
||||||
"@ucap/protocol-inner": "~0.0.4",
|
"@ucap/protocol-inner": "~0.0.4",
|
||||||
"@ucap/protocol-option": "~0.0.7",
|
"@ucap/protocol-option": "~0.0.7",
|
||||||
"@ucap/protocol-ping": "~0.0.4",
|
"@ucap/protocol-ping": "~0.0.4",
|
||||||
|
|
|
@ -11,10 +11,12 @@
|
||||||
"@ucap/api-external": "@ucap/api-external",
|
"@ucap/api-external": "@ucap/api-external",
|
||||||
"@ucap/pi": "@ucap/pi",
|
"@ucap/pi": "@ucap/pi",
|
||||||
"@ucap/protocol-authentication": "@ucap/protocol-authentication",
|
"@ucap/protocol-authentication": "@ucap/protocol-authentication",
|
||||||
|
"@ucap/protocol-info": "@ucap/protocol-info",
|
||||||
"@ucap/protocol-option": "@ucap/protocol-option",
|
"@ucap/protocol-option": "@ucap/protocol-option",
|
||||||
"@ucap/protocol-query": "@ucap/protocol-query",
|
"@ucap/protocol-query": "@ucap/protocol-query",
|
||||||
"@ucap/ng-pi": "@ucap/ng-pi",
|
"@ucap/ng-pi": "@ucap/ng-pi",
|
||||||
"@ucap/ng-protocol-authentication": "@ucap/ng-protocol-authentication",
|
"@ucap/ng-protocol-authentication": "@ucap/ng-protocol-authentication",
|
||||||
|
"@ucap/ng-protocol-info": "@ucap/ng-protocol-info",
|
||||||
"@ucap/ng-protocol-option": "@ucap/ng-protocol-option",
|
"@ucap/ng-protocol-option": "@ucap/ng-protocol-option",
|
||||||
"@ucap/ng-protocol-query": "@ucap/ng-protocol-query"
|
"@ucap/ng-protocol-query": "@ucap/ng-protocol-query"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@ucap/ng-store-authentication",
|
"name": "@ucap/ng-store-authentication",
|
||||||
"version": "0.0.10",
|
"version": "0.0.11",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"registry": "https://nexus.loafle.net/repository/npm-ucap/"
|
"registry": "https://nexus.loafle.net/repository/npm-ucap/"
|
||||||
},
|
},
|
||||||
|
@ -17,10 +17,12 @@
|
||||||
"@ucap/protocol-authentication": "~0.0.1",
|
"@ucap/protocol-authentication": "~0.0.1",
|
||||||
"@ucap/protocol-option": "~0.0.1",
|
"@ucap/protocol-option": "~0.0.1",
|
||||||
"@ucap/protocol-query": "~0.0.1",
|
"@ucap/protocol-query": "~0.0.1",
|
||||||
|
"@ucap/protocol-info": "~0.0.1",
|
||||||
"@ucap/ng-pi": "~0.0.1",
|
"@ucap/ng-pi": "~0.0.1",
|
||||||
"@ucap/ng-protocol-authentication": "~0.0.1",
|
"@ucap/ng-protocol-authentication": "~0.0.1",
|
||||||
"@ucap/ng-protocol-option": "~0.0.1",
|
"@ucap/ng-protocol-option": "~0.0.1",
|
||||||
"@ucap/ng-protocol-query": "~0.0.1",
|
"@ucap/ng-protocol-query": "~0.0.1",
|
||||||
|
"@ucap/ng-protocol-info": "~0.0.1",
|
||||||
"rxjs": "~6.5.4",
|
"rxjs": "~6.5.4",
|
||||||
"tslib": "^1.10.0"
|
"tslib": "^1.10.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
LoginResponse,
|
LoginResponse,
|
||||||
LogoutResponse
|
LogoutResponse
|
||||||
} from '@ucap/protocol-authentication';
|
} from '@ucap/protocol-authentication';
|
||||||
|
import { UserResponse, UserRequest } from '@ucap/protocol-info';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* request of web login
|
* request of web login
|
||||||
|
@ -106,3 +107,29 @@ export const sessionDestroyed = createAction(
|
||||||
'[ucap::authentication::login] session Destroyed',
|
'[ucap::authentication::login] session Destroyed',
|
||||||
props<{ error: any }>()
|
props<{ error: any }>()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* info user request
|
||||||
|
*/
|
||||||
|
export const infoUser = createAction(
|
||||||
|
'[ucap::authentication::login] Info User',
|
||||||
|
props<{ req: UserRequest }>()
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Success of info user request
|
||||||
|
*/
|
||||||
|
export const infoUserSuccess = createAction(
|
||||||
|
'[ucap::authentication::login] Info User Success',
|
||||||
|
props<{
|
||||||
|
res: UserResponse;
|
||||||
|
}>()
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Failure of info user request
|
||||||
|
*/
|
||||||
|
export const infoUserFailure = createAction(
|
||||||
|
'[ucap::authentication::login] Info User Failure',
|
||||||
|
props<{ error: any }>()
|
||||||
|
);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
import { catchError, map, switchMap } from 'rxjs/operators';
|
import { catchError, map, switchMap, exhaustMap } from 'rxjs/operators';
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@ -7,26 +7,52 @@ import { Actions, ofType, createEffect } from '@ngrx/effects';
|
||||||
|
|
||||||
import { PiService } from '@ucap/ng-pi';
|
import { PiService } from '@ucap/ng-pi';
|
||||||
import { AuthenticationProtocolService } from '@ucap/ng-protocol-authentication';
|
import { AuthenticationProtocolService } from '@ucap/ng-protocol-authentication';
|
||||||
|
import { InfoProtocolService } from '@ucap/ng-protocol-info';
|
||||||
|
|
||||||
import { logout, logoutSuccess } from './actions';
|
import {
|
||||||
|
logout,
|
||||||
|
logoutSuccess,
|
||||||
|
infoUser,
|
||||||
|
infoUserSuccess,
|
||||||
|
infoUserFailure
|
||||||
|
} from './actions';
|
||||||
|
import { UserResponse } from '@ucap/protocol-info';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class Effects {
|
export class Effects {
|
||||||
logout$ = createEffect(() => {
|
logout$ = createEffect(() => {
|
||||||
return this.actions$.pipe(
|
return this.actions$.pipe(
|
||||||
ofType(logout),
|
ofType(logout),
|
||||||
switchMap(action => {
|
switchMap((action) => {
|
||||||
return this.authenticationProtocolService.logout({}).pipe(
|
return this.authenticationProtocolService.logout({}).pipe(
|
||||||
map(res => logoutSuccess({ res })),
|
map((res) => logoutSuccess({ res })),
|
||||||
catchError(error => of(error))
|
catchError((error) => of(error))
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
infoUser$ = createEffect(() =>
|
||||||
|
this.actions$.pipe(
|
||||||
|
ofType(infoUser),
|
||||||
|
map((action) => action.req),
|
||||||
|
exhaustMap((req) =>
|
||||||
|
this.infoProtocolService.user(req).pipe(
|
||||||
|
map((res: UserResponse) => {
|
||||||
|
return infoUserSuccess({
|
||||||
|
res
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
catchError((error) => of(infoUserFailure({ error })))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private actions$: Actions,
|
private actions$: Actions,
|
||||||
private piService: PiService,
|
private piService: PiService,
|
||||||
private authenticationProtocolService: AuthenticationProtocolService
|
private authenticationProtocolService: AuthenticationProtocolService,
|
||||||
|
private infoProtocolService: InfoProtocolService
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { createReducer, on } from '@ngrx/store';
|
import { createReducer, on } from '@ngrx/store';
|
||||||
|
|
||||||
import { initialState } from './state';
|
import { initialState } from './state';
|
||||||
import { loginSuccess, logoutSuccess } from './actions';
|
import { loginSuccess, logoutSuccess, infoUserSuccess } from './actions';
|
||||||
|
import { UserInfoUpdateType } from '@ucap/protocol-info';
|
||||||
|
|
||||||
export const reducer = createReducer(
|
export const reducer = createReducer(
|
||||||
initialState,
|
initialState,
|
||||||
|
@ -16,5 +17,41 @@ export const reducer = createReducer(
|
||||||
return {
|
return {
|
||||||
...initialState
|
...initialState
|
||||||
};
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
on(infoUserSuccess, (state, action) => {
|
||||||
|
let loginRes = {
|
||||||
|
...state.loginRes
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (action.res.type) {
|
||||||
|
case UserInfoUpdateType.Image:
|
||||||
|
loginRes = {
|
||||||
|
...loginRes
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case UserInfoUpdateType.Intro:
|
||||||
|
loginRes = {
|
||||||
|
...loginRes,
|
||||||
|
userInfo: {
|
||||||
|
...loginRes.userInfo,
|
||||||
|
intro: action.res.info
|
||||||
|
}
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case UserInfoUpdateType.TelephoneVisible:
|
||||||
|
loginRes = {
|
||||||
|
...loginRes
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
loginRes: {
|
||||||
|
...loginRes
|
||||||
|
}
|
||||||
|
};
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@ucap/ng-store-chat",
|
"name": "@ucap/ng-store-chat",
|
||||||
"version": "0.0.8",
|
"version": "0.0.13",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"registry": "https://nexus.loafle.net/repository/npm-ucap/"
|
"registry": "https://nexus.loafle.net/repository/npm-ucap/"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import { ModuleConfig as CoreModuleConfig } from '@ucap/core';
|
import { ModuleConfig as CoreModuleConfig } from '@ucap/core';
|
||||||
|
|
||||||
// tslint:disable-next-line: no-empty-interface
|
// tslint:disable-next-line: no-empty-interface
|
||||||
export interface ModuleConfig extends CoreModuleConfig {}
|
export interface ModuleConfig extends CoreModuleConfig {
|
||||||
|
eventRequestInitCount?: number;
|
||||||
|
eventRequestDefaultCount?: number;
|
||||||
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@ import {
|
||||||
ReadNotification,
|
ReadNotification,
|
||||||
CancelNotification,
|
CancelNotification,
|
||||||
DelNotification,
|
DelNotification,
|
||||||
EventJson
|
EventJson,
|
||||||
|
ReadResponse
|
||||||
} from '@ucap/protocol-event';
|
} from '@ucap/protocol-event';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -40,7 +41,7 @@ export const eventsSuccess = createAction(
|
||||||
props<{
|
props<{
|
||||||
eventInfoList: Info<EventJson>[];
|
eventInfoList: Info<EventJson>[];
|
||||||
res: EventInfoResponse;
|
res: EventInfoResponse;
|
||||||
remainInfo: boolean;
|
remainEvent: boolean;
|
||||||
}>()
|
}>()
|
||||||
);
|
);
|
||||||
/**
|
/**
|
||||||
|
@ -48,7 +49,7 @@ export const eventsSuccess = createAction(
|
||||||
*/
|
*/
|
||||||
export const eventsFailure = createAction(
|
export const eventsFailure = createAction(
|
||||||
'[ucap::chat::chatting] events Failure',
|
'[ucap::chat::chatting] events Failure',
|
||||||
props<{ error: any }>()
|
props<{ roomId: string; error: any }>()
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,7 +75,7 @@ export const fileInfosSuccess = createAction(
|
||||||
*/
|
*/
|
||||||
export const fileInfosFailure = createAction(
|
export const fileInfosFailure = createAction(
|
||||||
'[ucap::chat::chatting] fileInfos Failure',
|
'[ucap::chat::chatting] fileInfos Failure',
|
||||||
props<{ error: any }>()
|
props<{ roomId: string; error: any }>()
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,3 +85,23 @@ export const addEvent = createAction(
|
||||||
'[ucap::chat::chatting] addEvent',
|
'[ucap::chat::chatting] addEvent',
|
||||||
props<{ req: FileInfoRequest }>()
|
props<{ req: FileInfoRequest }>()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const read = createAction(
|
||||||
|
'[ucap::chat::chatting] read',
|
||||||
|
props<ReadRequest>()
|
||||||
|
);
|
||||||
|
|
||||||
|
export const readSuccess = createAction(
|
||||||
|
'[ucap::chat::chatting] read Success',
|
||||||
|
props<ReadResponse>()
|
||||||
|
);
|
||||||
|
|
||||||
|
// export const readNotification = createAction(
|
||||||
|
// '[ucap::chat::chatting] Read Notification',
|
||||||
|
// props<ReadNotification>()
|
||||||
|
// );
|
||||||
|
|
||||||
|
export const readFailure = createAction(
|
||||||
|
'[ucap::chat::chatting] read Failure',
|
||||||
|
props<{ error: any }>()
|
||||||
|
);
|
||||||
|
|
|
@ -5,33 +5,165 @@ import {
|
||||||
map,
|
map,
|
||||||
catchError,
|
catchError,
|
||||||
exhaustMap,
|
exhaustMap,
|
||||||
withLatestFrom
|
debounceTime
|
||||||
} from 'rxjs/operators';
|
} from 'rxjs/operators';
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable, Inject } from '@angular/core';
|
||||||
|
|
||||||
import { Store, select } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { Actions, createEffect, ofType } from '@ngrx/effects';
|
import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||||
|
|
||||||
import {
|
import { EventProtocolService } from '@ucap/ng-protocol-event';
|
||||||
RoomInfo,
|
|
||||||
UpdateResponse,
|
|
||||||
OpenResponse,
|
|
||||||
ExitResponse,
|
|
||||||
Open3Response,
|
|
||||||
RoomType,
|
|
||||||
InviteResponse,
|
|
||||||
UpdateTimerSetResponse,
|
|
||||||
ExitForcingResponse
|
|
||||||
} from '@ucap/protocol-room';
|
|
||||||
|
|
||||||
import { RoomProtocolService } from '@ucap/ng-protocol-room';
|
import { RoomProtocolService } from '@ucap/ng-protocol-room';
|
||||||
|
import { FileProtocolService } from '@ucap/ng-protocol-file';
|
||||||
|
|
||||||
|
import * as roomActions from '../room/actions';
|
||||||
|
import {
|
||||||
|
events,
|
||||||
|
eventsFailure,
|
||||||
|
eventsSuccess,
|
||||||
|
read,
|
||||||
|
readFailure,
|
||||||
|
readSuccess,
|
||||||
|
fileInfos,
|
||||||
|
fileInfosFailure,
|
||||||
|
fileInfosSuccess
|
||||||
|
} from './actions';
|
||||||
|
|
||||||
|
import { InfoRequest, ReadResponse, FileType } from '@ucap/protocol-event';
|
||||||
|
|
||||||
|
import { ModuleConfig } from '../../config/module-config';
|
||||||
|
import { _MODULE_CONFIG } from '../../config/token';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class Effects {
|
export class Effects {
|
||||||
|
selectedRoom$ = createEffect(
|
||||||
|
() => {
|
||||||
|
return this.actions$.pipe(
|
||||||
|
ofType(roomActions.selectedRoom),
|
||||||
|
debounceTime(300),
|
||||||
|
tap((action) => {
|
||||||
|
const requestCount = this.moduleConfig?.eventRequestInitCount || 50;
|
||||||
|
const req: InfoRequest = {
|
||||||
|
roomId: action.roomId,
|
||||||
|
baseSeq: 0,
|
||||||
|
requestCount
|
||||||
|
};
|
||||||
|
|
||||||
|
this.store.dispatch(events({ req }));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
{ dispatch: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
events$ = createEffect(
|
||||||
|
() => {
|
||||||
|
return this.actions$.pipe(
|
||||||
|
ofType(events),
|
||||||
|
map((action) => action.req),
|
||||||
|
switchMap((req) => {
|
||||||
|
return this.eventProtocolService.info(req).pipe(
|
||||||
|
map((res) => {
|
||||||
|
if (!!res && !!res.res) {
|
||||||
|
const infoList = res.infoList;
|
||||||
|
|
||||||
|
this.store.dispatch(
|
||||||
|
eventsSuccess({
|
||||||
|
eventInfoList: infoList,
|
||||||
|
res: res.res,
|
||||||
|
remainEvent:
|
||||||
|
infoList.length === req.requestCount ? true : false
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
if (req.baseSeq === 0) {
|
||||||
|
// 최초 이벤트 목록 조회.
|
||||||
|
|
||||||
|
// SSVC_TYPE_EVENT_READ_REQ 수행.
|
||||||
|
const maxSeq = Math.max.apply(
|
||||||
|
Math,
|
||||||
|
infoList.map((v) => v.seq)
|
||||||
|
);
|
||||||
|
this.store.dispatch(
|
||||||
|
read({
|
||||||
|
roomId: req.roomId,
|
||||||
|
lastReadSeq: Number(maxSeq)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// File 정보 수집.
|
||||||
|
this.store.dispatch(
|
||||||
|
fileInfos({
|
||||||
|
req: {
|
||||||
|
roomId: res.res.roomId,
|
||||||
|
// { 파일타입 } cf) I : 이미지 V: 동영상 F: 파일 "" 빈값이면 모든 타입을 내려줌
|
||||||
|
type: FileType.All
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
catchError((error) =>
|
||||||
|
of(eventsFailure({ roomId: req.roomId, error }))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
{ dispatch: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
read$ = createEffect(
|
||||||
|
() => {
|
||||||
|
return this.actions$.pipe(
|
||||||
|
ofType(read),
|
||||||
|
exhaustMap((req) =>
|
||||||
|
this.eventProtocolService.read(req).pipe(
|
||||||
|
map((res: ReadResponse) => {
|
||||||
|
this.store.dispatch(readSuccess(res));
|
||||||
|
}),
|
||||||
|
catchError((error) => of(readFailure({ error })))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
{ dispatch: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
fileInfos$ = createEffect(
|
||||||
|
() => {
|
||||||
|
return this.actions$.pipe(
|
||||||
|
ofType(fileInfos),
|
||||||
|
switchMap((action) => {
|
||||||
|
return this.fileProtocolService.info(action.req).pipe(
|
||||||
|
map((res) => {
|
||||||
|
this.store.dispatch(
|
||||||
|
fileInfosSuccess({
|
||||||
|
fileInfoList: res.fileInfos,
|
||||||
|
fileInfoCheckList: res.fileInfoChecks,
|
||||||
|
res: res.res
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
catchError((error) =>
|
||||||
|
of(fileInfosFailure({ roomId: action.req.roomId, error }))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
{ dispatch: false }
|
||||||
|
);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private actions$: Actions,
|
private actions$: Actions,
|
||||||
private store: Store<any>,
|
private store: Store<any>,
|
||||||
private roomProtocolService: RoomProtocolService
|
@Inject(_MODULE_CONFIG) private moduleConfig: ModuleConfig,
|
||||||
|
private roomProtocolService: RoomProtocolService,
|
||||||
|
private eventProtocolService: EventProtocolService,
|
||||||
|
private fileProtocolService: FileProtocolService
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,167 @@
|
||||||
import { createReducer, on } from '@ngrx/store';
|
import { createReducer, on } from '@ngrx/store';
|
||||||
|
|
||||||
import { initialState, adapterChatting } from './state';
|
import {
|
||||||
|
initialState,
|
||||||
|
adapterChatting,
|
||||||
|
adapterEventList,
|
||||||
|
Chatting,
|
||||||
|
adapterFileInfoList,
|
||||||
|
adapterFileInfoCheckList
|
||||||
|
} from './state';
|
||||||
|
|
||||||
export const reducer = createReducer(initialState);
|
import * as roomActions from '../room/actions';
|
||||||
|
import {
|
||||||
|
eventsSuccess,
|
||||||
|
eventsFailure,
|
||||||
|
readSuccess,
|
||||||
|
fileInfosSuccess,
|
||||||
|
fileInfosFailure
|
||||||
|
} from './actions';
|
||||||
|
|
||||||
|
export const reducer = createReducer(
|
||||||
|
initialState,
|
||||||
|
|
||||||
|
on(roomActions.selectedRoom, (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
activeRoomId: action.roomId
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
on(roomActions.clearSelectedRoom, (state, action) => {
|
||||||
|
if (action.roomId === state.activeRoomId) {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
activeRoomId: null
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
on(eventsSuccess, (state, action) => {
|
||||||
|
const roomId = action.res.roomId;
|
||||||
|
|
||||||
|
const chatting = state.chattings.entities[roomId] || {};
|
||||||
|
let trgtChatting: Chatting = {
|
||||||
|
roomId,
|
||||||
|
|
||||||
|
eventListProcessing: false,
|
||||||
|
eventList: adapterEventList.getInitialState(),
|
||||||
|
eventStatus: null,
|
||||||
|
remainEvent: false,
|
||||||
|
|
||||||
|
fileInfoListProcessing: false,
|
||||||
|
fileInfoList: adapterFileInfoList.getInitialState(),
|
||||||
|
fileInfoCheckList: adapterFileInfoCheckList.getInitialState(),
|
||||||
|
fileInfoSyncDate: '',
|
||||||
|
...chatting
|
||||||
|
};
|
||||||
|
|
||||||
|
trgtChatting = {
|
||||||
|
...trgtChatting,
|
||||||
|
eventList: adapterEventList.upsertMany(action.eventInfoList, {
|
||||||
|
...trgtChatting.eventList
|
||||||
|
}),
|
||||||
|
eventStatus: action.res,
|
||||||
|
remainEvent: action.remainEvent,
|
||||||
|
eventListProcessing: false
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
chattings: adapterChatting.upsertOne(trgtChatting, {
|
||||||
|
...state.chattings
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
on(eventsFailure, (state, action) => {
|
||||||
|
const roomId = action.roomId;
|
||||||
|
|
||||||
|
const chatting = state.chattings.entities[roomId];
|
||||||
|
let trgtChatting: Chatting;
|
||||||
|
if (!!chatting) {
|
||||||
|
trgtChatting = {
|
||||||
|
...chatting,
|
||||||
|
eventListProcessing: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
chattings: adapterChatting.upsertOne(trgtChatting, {
|
||||||
|
...state.chattings
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
on(fileInfosSuccess, (state, action) => {
|
||||||
|
const roomId = action.res?.roomId;
|
||||||
|
|
||||||
|
if (!roomId) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
const chatting = state.chattings.entities[roomId] || {};
|
||||||
|
let trgtChatting: Chatting = {
|
||||||
|
roomId,
|
||||||
|
|
||||||
|
eventListProcessing: false,
|
||||||
|
eventList: adapterEventList.getInitialState(),
|
||||||
|
eventStatus: null,
|
||||||
|
remainEvent: false,
|
||||||
|
|
||||||
|
fileInfoListProcessing: false,
|
||||||
|
fileInfoList: adapterFileInfoList.getInitialState(),
|
||||||
|
fileInfoCheckList: adapterFileInfoCheckList.getInitialState(),
|
||||||
|
fileInfoSyncDate: '',
|
||||||
|
...chatting
|
||||||
|
};
|
||||||
|
|
||||||
|
const fileInfoList = action.fileInfoList;
|
||||||
|
const fileInfoCheckList = action.fileInfoCheckList;
|
||||||
|
|
||||||
|
trgtChatting = {
|
||||||
|
...trgtChatting,
|
||||||
|
fileInfoList: !!fileInfoList
|
||||||
|
? adapterFileInfoList.upsertMany(fileInfoList, {
|
||||||
|
...trgtChatting.fileInfoList
|
||||||
|
})
|
||||||
|
: trgtChatting.fileInfoList,
|
||||||
|
fileInfoCheckList: !!fileInfoCheckList
|
||||||
|
? adapterFileInfoCheckList.upsertMany(fileInfoCheckList, {
|
||||||
|
...trgtChatting.fileInfoCheckList
|
||||||
|
})
|
||||||
|
: trgtChatting.fileInfoCheckList,
|
||||||
|
fileInfoListProcessing: false
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
chattings: adapterChatting.upsertOne(trgtChatting, {
|
||||||
|
...state.chattings
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
on(fileInfosFailure, (state, action) => {
|
||||||
|
const roomId = action.roomId;
|
||||||
|
|
||||||
|
const chatting = state.chattings.entities[roomId];
|
||||||
|
let trgtChatting: Chatting;
|
||||||
|
if (!!chatting) {
|
||||||
|
trgtChatting = {
|
||||||
|
...chatting,
|
||||||
|
fileInfoListProcessing: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
chattings: adapterChatting.upsertOne(trgtChatting, {
|
||||||
|
...state.chattings
|
||||||
|
})
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
|
@ -10,19 +10,19 @@ export interface FileInfoListState extends EntityState<FileInfo> {}
|
||||||
export interface FileInfoCheckListState extends EntityState<FileDownloadInfo> {}
|
export interface FileInfoCheckListState extends EntityState<FileDownloadInfo> {}
|
||||||
|
|
||||||
export const adapterEventList = createEntityAdapter<Info<EventJson>>({
|
export const adapterEventList = createEntityAdapter<Info<EventJson>>({
|
||||||
selectId: info => info.seq,
|
selectId: (info) => info.seq,
|
||||||
sortComparer: (a, b) => {
|
sortComparer: (a, b) => {
|
||||||
return a.seq - b.seq;
|
return a.seq - b.seq;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
export const adapterFileInfoList = createEntityAdapter<FileInfo>({
|
export const adapterFileInfoList = createEntityAdapter<FileInfo>({
|
||||||
selectId: info => info.seq,
|
selectId: (info) => info.seq,
|
||||||
sortComparer: (a, b) => {
|
sortComparer: (a, b) => {
|
||||||
return b.seq - a.seq;
|
return b.seq - a.seq;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
export const adapterFileInfoCheckList = createEntityAdapter<FileDownloadInfo>({
|
export const adapterFileInfoCheckList = createEntityAdapter<FileDownloadInfo>({
|
||||||
selectId: info => info.seq,
|
selectId: (info) => info.seq,
|
||||||
sortComparer: (a, b) => {
|
sortComparer: (a, b) => {
|
||||||
return b.seq - a.seq;
|
return b.seq - a.seq;
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ export interface Chatting {
|
||||||
eventListProcessing?: boolean;
|
eventListProcessing?: boolean;
|
||||||
eventList?: EventListState;
|
eventList?: EventListState;
|
||||||
eventStatus?: InfoResponse | null;
|
eventStatus?: InfoResponse | null;
|
||||||
remainEvent?: false;
|
remainEvent?: boolean;
|
||||||
|
|
||||||
fileInfoListProcessing?: boolean;
|
fileInfoListProcessing?: boolean;
|
||||||
fileInfoList?: FileInfoListState;
|
fileInfoList?: FileInfoListState;
|
||||||
|
@ -76,9 +76,11 @@ export interface Chatting {
|
||||||
export interface ChattingState extends EntityState<Chatting> {}
|
export interface ChattingState extends EntityState<Chatting> {}
|
||||||
|
|
||||||
export const adapterChatting = createEntityAdapter<Chatting>({
|
export const adapterChatting = createEntityAdapter<Chatting>({
|
||||||
selectId: chatting => chatting.roomId
|
selectId: (chatting) => chatting.roomId
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const chattingInitialState: ChattingState = adapterChatting.getInitialState({});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
selectAll: selectAllForChatting,
|
selectAll: selectAllForChatting,
|
||||||
selectEntities: selectEntitiesForChatting,
|
selectEntities: selectEntitiesForChatting,
|
||||||
|
@ -86,26 +88,14 @@ const {
|
||||||
selectTotal: selectTotalForChatting
|
selectTotal: selectTotalForChatting
|
||||||
} = adapterChatting.getSelectors();
|
} = adapterChatting.getSelectors();
|
||||||
|
|
||||||
const chattingInitialState: ChattingState = adapterChatting.getInitialState({
|
|
||||||
roomId: undefined,
|
|
||||||
|
|
||||||
eventListProcessing: false,
|
|
||||||
eventList: eventListInitialState,
|
|
||||||
eventStatus: undefined,
|
|
||||||
remainEvent: false,
|
|
||||||
|
|
||||||
fileInfoListProcessing: false,
|
|
||||||
fileInfoList: fileInfoListInitialState,
|
|
||||||
fileInfoCheckList: fileInfoCheckListInitialState,
|
|
||||||
fileInfoSyncDate: undefined
|
|
||||||
});
|
|
||||||
|
|
||||||
export interface State {
|
export interface State {
|
||||||
chattings: ChattingState;
|
chattings: ChattingState;
|
||||||
|
activeRoomId: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initialState: State = {
|
export const initialState: State = {
|
||||||
chattings: chattingInitialState
|
chattings: chattingInitialState,
|
||||||
|
activeRoomId: null
|
||||||
};
|
};
|
||||||
|
|
||||||
export function selectors<S>(selector: Selector<any, State>) {
|
export function selectors<S>(selector: Selector<any, State>) {
|
||||||
|
@ -115,46 +105,55 @@ export function selectors<S>(selector: Selector<any, State>) {
|
||||||
);
|
);
|
||||||
|
|
||||||
const selectChatting = createSelector(
|
const selectChatting = createSelector(
|
||||||
selector,
|
selectChattings,
|
||||||
selectEntitiesForChatting,
|
(state: ChattingState, roomId: string) => {
|
||||||
(state: State, entities: Dictionary<Chatting>, roomId: string) =>
|
return state.entities && state.entities[roomId];
|
||||||
entities && entities[roomId]
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const selectChattingEventListProcessing = createSelector(
|
const selectChattingEventListProcessing = createSelector(
|
||||||
selectChatting,
|
selectChatting,
|
||||||
state => state.eventListProcessing
|
(state) => state.eventListProcessing
|
||||||
);
|
);
|
||||||
const selectChattingEventList = createSelector(
|
const selectChattingEventList = createSelector(
|
||||||
selectChatting,
|
selectChattings,
|
||||||
state => state.eventList
|
(state: ChattingState, roomId: string) => {
|
||||||
|
const chatting = state.entities && state.entities[roomId];
|
||||||
|
if (!!chatting) {
|
||||||
|
return chatting?.eventList;
|
||||||
|
} else {
|
||||||
|
return adapterEventList.getInitialState();
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
const selectChattingEventStatus = createSelector(
|
const selectChattingEventStatus = createSelector(
|
||||||
selectChatting,
|
selectChatting,
|
||||||
state => state.eventStatus
|
(state) => state.eventStatus
|
||||||
);
|
);
|
||||||
const selectChattingRemainEvent = createSelector(
|
const selectChattingRemainEvent = createSelector(
|
||||||
selectChatting,
|
selectChatting,
|
||||||
state => state.remainEvent
|
(state) => state.remainEvent
|
||||||
);
|
);
|
||||||
const selectChattingFileInfoListProcessing = createSelector(
|
const selectChattingFileInfoListProcessing = createSelector(
|
||||||
selectChatting,
|
selectChatting,
|
||||||
state => state.fileInfoListProcessing
|
(state) => state.fileInfoListProcessing
|
||||||
);
|
);
|
||||||
const selectChattingFileInfoList = createSelector(
|
const selectChattingFileInfoList = createSelector(
|
||||||
selectChatting,
|
selectChatting,
|
||||||
state => state.fileInfoList
|
(state) => state.fileInfoList
|
||||||
);
|
);
|
||||||
const selectChattingFileInfoCheckList = createSelector(
|
const selectChattingFileInfoCheckList = createSelector(
|
||||||
selectChatting,
|
selectChatting,
|
||||||
state => state.fileInfoCheckList
|
(state) => state.fileInfoCheckList
|
||||||
);
|
);
|
||||||
const selectChattingFileInfoSyncDate = createSelector(
|
const selectChattingFileInfoSyncDate = createSelector(
|
||||||
selectChatting,
|
selectChatting,
|
||||||
state => state.fileInfoSyncDate
|
(state) => state.fileInfoSyncDate
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
activeRoomId: createSelector(selector, (state) => state.activeRoomId),
|
||||||
|
|
||||||
chattings: createSelector(selectChattings, selectAllForChatting),
|
chattings: createSelector(selectChattings, selectAllForChatting),
|
||||||
chatting: selectChatting,
|
chatting: selectChatting,
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,21 @@ import {
|
||||||
UserInfoShort
|
UserInfoShort
|
||||||
} from '@ucap/protocol-room';
|
} from '@ucap/protocol-room';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retrieve selected Room.
|
||||||
|
*/
|
||||||
|
export const selectedRoom = createAction(
|
||||||
|
'[ucap::chat::selectedRoom] selected room',
|
||||||
|
props<{ roomId: string; localeCode: LocaleCode }>()
|
||||||
|
);
|
||||||
|
/**
|
||||||
|
* clear selected Room.
|
||||||
|
*/
|
||||||
|
export const clearSelectedRoom = createAction(
|
||||||
|
'[ucap::chat::clearSelectedRoom] clear Selected Room',
|
||||||
|
props<{ roomId: string }>()
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* retrieve list of room information and list of user information per room
|
* retrieve list of room information and list of user information per room
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -4,7 +4,9 @@ import {
|
||||||
map,
|
map,
|
||||||
switchMap,
|
switchMap,
|
||||||
exhaustMap,
|
exhaustMap,
|
||||||
withLatestFrom
|
withLatestFrom,
|
||||||
|
tap,
|
||||||
|
debounceTime
|
||||||
} from 'rxjs/operators';
|
} from 'rxjs/operators';
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
@ -21,7 +23,8 @@ import {
|
||||||
UpdateResponse,
|
UpdateResponse,
|
||||||
InviteResponse,
|
InviteResponse,
|
||||||
ExitForcingResponse,
|
ExitForcingResponse,
|
||||||
UpdateTimerSetResponse
|
UpdateTimerSetResponse,
|
||||||
|
InfoRequest
|
||||||
} from '@ucap/protocol-room';
|
} from '@ucap/protocol-room';
|
||||||
|
|
||||||
import { RoomProtocolService } from '@ucap/ng-protocol-room';
|
import { RoomProtocolService } from '@ucap/ng-protocol-room';
|
||||||
|
@ -73,7 +76,8 @@ import {
|
||||||
rooms2Failure,
|
rooms2Failure,
|
||||||
delMulti,
|
delMulti,
|
||||||
delMultiSuccess,
|
delMultiSuccess,
|
||||||
delMultiFailure
|
delMultiFailure,
|
||||||
|
selectedRoom
|
||||||
} from './actions';
|
} from './actions';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -85,6 +89,29 @@ export class Effects {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
selectedRoom$ = createEffect(
|
||||||
|
() => {
|
||||||
|
return this.actions$.pipe(
|
||||||
|
ofType(selectedRoom),
|
||||||
|
debounceTime(300),
|
||||||
|
tap((action) => {
|
||||||
|
const req: InfoRequest = {
|
||||||
|
...action,
|
||||||
|
isDetail: false
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(req);
|
||||||
|
|
||||||
|
// retrieve room info
|
||||||
|
this.store.dispatch(room({ req }));
|
||||||
|
|
||||||
|
// retrieve event info >> chatting.effect.selectedRoom$
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
{ dispatch: false }
|
||||||
|
);
|
||||||
|
|
||||||
rooms$ = createEffect(() => {
|
rooms$ = createEffect(() => {
|
||||||
return this.actions$.pipe(
|
return this.actions$.pipe(
|
||||||
ofType(rooms),
|
ofType(rooms),
|
||||||
|
|
|
@ -26,6 +26,7 @@ import {
|
||||||
delMultiSuccess,
|
delMultiSuccess,
|
||||||
updateSuccess
|
updateSuccess
|
||||||
} from './actions';
|
} from './actions';
|
||||||
|
import { userInfo } from 'os';
|
||||||
|
|
||||||
export const reducer = createReducer(
|
export const reducer = createReducer(
|
||||||
initialState,
|
initialState,
|
||||||
|
@ -214,7 +215,9 @@ export const reducer = createReducer(
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
rooms: adapterRoom.removeOne(roomId, { ...state.rooms }),
|
rooms: adapterRoom.removeOne(roomId, { ...state.rooms }),
|
||||||
roomUsers: adapterRoomUser.removeOne(roomId, { ...state.roomUsers }),
|
roomUsers: adapterRoomUser.removeOne(roomId, {
|
||||||
|
...state.roomUsers
|
||||||
|
}),
|
||||||
roomUsersShort: adapterRoomUserShort.removeOne(roomId, {
|
roomUsersShort: adapterRoomUserShort.removeOne(roomId, {
|
||||||
...state.roomUsersShort
|
...state.roomUsersShort
|
||||||
})
|
})
|
||||||
|
@ -231,10 +234,72 @@ export const reducer = createReducer(
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
rooms: adapterRoom.removeMany(roomIds, { ...state.rooms }),
|
rooms: adapterRoom.removeMany(roomIds, { ...state.rooms }),
|
||||||
roomUsers: adapterRoomUser.removeMany(roomIds, { ...state.roomUsers }),
|
roomUsers: adapterRoomUser.removeMany(roomIds, {
|
||||||
|
...state.roomUsers
|
||||||
|
}),
|
||||||
roomUsersShort: adapterRoomUserShort.removeMany(roomIds, {
|
roomUsersShort: adapterRoomUserShort.removeMany(roomIds, {
|
||||||
...state.roomUsersShort
|
...state.roomUsersShort
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [Chatting Action watching.]
|
||||||
|
*/
|
||||||
|
on(chattingActions.readSuccess, (state, action) => {
|
||||||
|
const roomId = action.roomId;
|
||||||
|
const trgtUserSeq = action.SENDER_SEQ;
|
||||||
|
|
||||||
|
if (!roomId || !trgtUserSeq) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
let roomUser: RoomUserMap = state.roomUsers.entities[roomId];
|
||||||
|
if (!!roomUser) {
|
||||||
|
roomUser = {
|
||||||
|
...roomUser,
|
||||||
|
userInfos: state.roomUsers.entities[roomId].userInfos.map(
|
||||||
|
(roomUserInfo) => {
|
||||||
|
if (roomUserInfo.seq === Number(trgtUserSeq)) {
|
||||||
|
return {
|
||||||
|
...roomUserInfo,
|
||||||
|
lastReadEventSeq: action.lastReadSeq
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return roomUserInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
let roomUserShort: RoomUserShortMap = state.roomUsersShort.entities[roomId];
|
||||||
|
if (!!roomUserShort) {
|
||||||
|
roomUserShort = {
|
||||||
|
...roomUserShort,
|
||||||
|
userInfos: state.roomUsersShort.entities[roomId].userInfos.map(
|
||||||
|
(roomUserInfo) => {
|
||||||
|
if (roomUserInfo.seq === Number(trgtUserSeq)) {
|
||||||
|
return { ...roomUserInfo, lastReadEventSeq: action.lastReadSeq };
|
||||||
|
} else {
|
||||||
|
return roomUserInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
roomUsers: !!roomUser
|
||||||
|
? adapterRoomUser.upsertOne(roomUser, {
|
||||||
|
...state.roomUsers
|
||||||
|
})
|
||||||
|
: state.roomUsers,
|
||||||
|
roomUsersShort: !!roomUserShort
|
||||||
|
? adapterRoomUserShort.upsertOne(roomUserShort, {
|
||||||
|
...state.roomUsersShort
|
||||||
|
})
|
||||||
|
: state.roomUsersShort
|
||||||
|
};
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -101,9 +101,9 @@ export function selectors<S>(selector: Selector<any, State>) {
|
||||||
rooms: createSelector(selectRooms, selectAllForRoom),
|
rooms: createSelector(selectRooms, selectAllForRoom),
|
||||||
room: createSelector(
|
room: createSelector(
|
||||||
selectRooms,
|
selectRooms,
|
||||||
selectEntitiesForRoom,
|
(roomState: RoomState, roomId: string) => {
|
||||||
(roomState: RoomState, entities: Dictionary<RoomInfo>, roomId: string) =>
|
return roomState.entities && roomState.entities[roomId];
|
||||||
entities && entities[roomId]
|
}
|
||||||
),
|
),
|
||||||
roomsSyncDate: createSelector(
|
roomsSyncDate: createSelector(
|
||||||
selectRooms,
|
selectRooms,
|
||||||
|
@ -112,12 +112,9 @@ export function selectors<S>(selector: Selector<any, State>) {
|
||||||
roomUsers: createSelector(selectRoomUsers, selectAllForRoomUser),
|
roomUsers: createSelector(selectRoomUsers, selectAllForRoomUser),
|
||||||
roomUser: createSelector(
|
roomUser: createSelector(
|
||||||
selectRoomUsers,
|
selectRoomUsers,
|
||||||
selectEntitiesForRoomUser,
|
(roomUserState: RoomUserState, roomId: string) => {
|
||||||
(
|
return roomUserState.entities && roomUserState.entities[roomId];
|
||||||
roomUserState: RoomUserState,
|
}
|
||||||
entities: Dictionary<RoomUserDetailData>,
|
|
||||||
roomId: string
|
|
||||||
) => entities && entities[roomId]
|
|
||||||
),
|
),
|
||||||
roomUsersShort: createSelector(
|
roomUsersShort: createSelector(
|
||||||
selectRoomUsersShort,
|
selectRoomUsersShort,
|
||||||
|
@ -125,12 +122,11 @@ export function selectors<S>(selector: Selector<any, State>) {
|
||||||
),
|
),
|
||||||
roomUserShort: createSelector(
|
roomUserShort: createSelector(
|
||||||
selectRoomUsersShort,
|
selectRoomUsersShort,
|
||||||
selectEntitiesForRoomUserShort,
|
(roomUserShortState: RoomUserShortState, roomId: string) => {
|
||||||
(
|
return (
|
||||||
roomUserShortState: RoomUserShortState,
|
roomUserShortState.entities && roomUserShortState.entities[roomId]
|
||||||
entities: Dictionary<RoomUserData>,
|
);
|
||||||
roomId: string
|
}
|
||||||
) => entities && entities[roomId]
|
|
||||||
),
|
),
|
||||||
unreadTotal: createSelector(
|
unreadTotal: createSelector(
|
||||||
selectRooms,
|
selectRooms,
|
||||||
|
|
|
@ -14,9 +14,11 @@
|
||||||
"@ucap/protocol-group": "@ucap/protocol-group",
|
"@ucap/protocol-group": "@ucap/protocol-group",
|
||||||
"@ucap/protocol-buddy": "@ucap/protocol-buddy",
|
"@ucap/protocol-buddy": "@ucap/protocol-buddy",
|
||||||
"@ucap/protocol-query": "@ucap/protocol-query",
|
"@ucap/protocol-query": "@ucap/protocol-query",
|
||||||
|
"@ucap/protocol-info": "@ucap/protocol-info",
|
||||||
"@ucap/ng-protocol-buddy": "@ucap/ng-protocol-buddy",
|
"@ucap/ng-protocol-buddy": "@ucap/ng-protocol-buddy",
|
||||||
"@ucap/ng-protocol-group": "@ucap/ng-protocol-group",
|
"@ucap/ng-protocol-group": "@ucap/ng-protocol-group",
|
||||||
"@ucap/ng-protocol-sync": "@ucap/ng-protocol-sync",
|
"@ucap/ng-protocol-sync": "@ucap/ng-protocol-sync",
|
||||||
|
"@ucap/ng-protocol-info": "@ucap/ng-protocol-info",
|
||||||
"@ucap/ng-store-organization": "@ucap/ng-store-organization",
|
"@ucap/ng-store-organization": "@ucap/ng-store-organization",
|
||||||
"@ucap/ng-store-authentication": "@ucap/ng-store-authentication"
|
"@ucap/ng-store-authentication": "@ucap/ng-store-authentication"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@ucap/ng-store-group",
|
"name": "@ucap/ng-store-group",
|
||||||
"version": "0.0.9",
|
"version": "0.0.14",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"registry": "https://nexus.loafle.net/repository/npm-ucap/"
|
"registry": "https://nexus.loafle.net/repository/npm-ucap/"
|
||||||
},
|
},
|
||||||
|
@ -12,11 +12,13 @@
|
||||||
"@ucap/protocol-group": "~0.0.1",
|
"@ucap/protocol-group": "~0.0.1",
|
||||||
"@ucap/protocol-query": "~0.0.1",
|
"@ucap/protocol-query": "~0.0.1",
|
||||||
"@ucap/protocol-sync": "~0.0.1",
|
"@ucap/protocol-sync": "~0.0.1",
|
||||||
|
"@ucap/protocol-info": "~0.0.1",
|
||||||
"@ucap/ng-protocol-buddy": "~0.0.1",
|
"@ucap/ng-protocol-buddy": "~0.0.1",
|
||||||
"@ucap/ng-protocol-group": "~0.0.1",
|
"@ucap/ng-protocol-group": "~0.0.1",
|
||||||
"@ucap/ng-protocol-sync": "~0.0.1",
|
"@ucap/ng-protocol-sync": "~0.0.1",
|
||||||
"@ucap/ng-store-organization": "~0.0.1",
|
"@ucap/ng-store-organization": "~0.0.1",
|
||||||
"@ucap/ng-store-authentication": "~0.0.1",
|
"@ucap/ng-store-authentication": "~0.0.1",
|
||||||
|
"@ucap/ng-protocol-info": "~0.0.1",
|
||||||
"tslib": "^1.10.0"
|
"tslib": "^1.10.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,10 @@ import {
|
||||||
UpdateRequest as BuddyUpdateRequest,
|
UpdateRequest as BuddyUpdateRequest,
|
||||||
UpdateResponse as BuddyUpdateResponse
|
UpdateResponse as BuddyUpdateResponse
|
||||||
} from '@ucap/protocol-buddy';
|
} from '@ucap/protocol-buddy';
|
||||||
|
import {
|
||||||
|
UserNicknameRequest as NicknameRequest,
|
||||||
|
UserNicknameResponse as NicknameResponse
|
||||||
|
} from '@ucap/protocol-info';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* retrieve list of buddy
|
* retrieve list of buddy
|
||||||
|
@ -116,3 +120,25 @@ export const updateFailure = createAction(
|
||||||
'[ucap::group::buddy] update Failure',
|
'[ucap::group::buddy] update Failure',
|
||||||
props<{ error: any }>()
|
props<{ error: any }>()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 동료 닉네임 변경
|
||||||
|
*/
|
||||||
|
export const nickname = createAction(
|
||||||
|
'[ucap::group::buddy] user nickname',
|
||||||
|
props<{ req: NicknameRequest }>()
|
||||||
|
);
|
||||||
|
/**
|
||||||
|
* Success of update request
|
||||||
|
*/
|
||||||
|
export const nicknameSuccess = createAction(
|
||||||
|
'[ucap::group::buddy] user nickname Success',
|
||||||
|
props<{ res: NicknameResponse }>()
|
||||||
|
);
|
||||||
|
/**
|
||||||
|
* Failure of update request
|
||||||
|
*/
|
||||||
|
export const nicknameFailure = createAction(
|
||||||
|
'[ucap::group::buddy] user nickname Failure',
|
||||||
|
props<{ error: any }>()
|
||||||
|
);
|
||||||
|
|
|
@ -19,6 +19,11 @@ import {
|
||||||
UpdateResponse as BuddyUpdateResponse
|
UpdateResponse as BuddyUpdateResponse
|
||||||
} from '@ucap/protocol-buddy';
|
} from '@ucap/protocol-buddy';
|
||||||
|
|
||||||
|
import {
|
||||||
|
UserNicknameRequest as NicknameRequest,
|
||||||
|
UserNicknameResponse as NicknameResponse
|
||||||
|
} from '@ucap/protocol-info';
|
||||||
|
|
||||||
import { SyncProtocolService } from '@ucap/ng-protocol-sync';
|
import { SyncProtocolService } from '@ucap/ng-protocol-sync';
|
||||||
|
|
||||||
import { BuddyProtocolService } from '@ucap/ng-protocol-buddy';
|
import { BuddyProtocolService } from '@ucap/ng-protocol-buddy';
|
||||||
|
@ -43,6 +48,9 @@ import {
|
||||||
update,
|
update,
|
||||||
updateSuccess,
|
updateSuccess,
|
||||||
updateFailure,
|
updateFailure,
|
||||||
|
nickname,
|
||||||
|
nicknameSuccess,
|
||||||
|
nicknameFailure,
|
||||||
delAndClear
|
delAndClear
|
||||||
} from './actions';
|
} from './actions';
|
||||||
|
|
||||||
|
@ -50,6 +58,7 @@ import { BuddySelector, GroupSelector } from '../state';
|
||||||
|
|
||||||
import { ModuleConfig } from '../../config/module-config';
|
import { ModuleConfig } from '../../config/module-config';
|
||||||
import { _MODULE_CONFIG } from '../../config/token';
|
import { _MODULE_CONFIG } from '../../config/token';
|
||||||
|
import { InfoProtocolService } from '@ucap/ng-protocol-info';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class Effects {
|
export class Effects {
|
||||||
|
@ -126,7 +135,7 @@ export class Effects {
|
||||||
),
|
),
|
||||||
tap(([req, groupList, myDeptUserList]) => {
|
tap(([req, groupList, myDeptUserList]) => {
|
||||||
for (const group of groupList) {
|
for (const group of groupList) {
|
||||||
if (group.userSeqs.indexOf(String(req.seq)) > -1) {
|
if (group.userSeqs.indexOf(req.seq as any) > -1) {
|
||||||
// 소속부서(내부서) 고정그룹 사용시 소속부서원을 삭제하지 않는다.
|
// 소속부서(내부서) 고정그룹 사용시 소속부서원을 삭제하지 않는다.
|
||||||
if (
|
if (
|
||||||
!!this.moduleConfig.useMyDeptGroup &&
|
!!this.moduleConfig.useMyDeptGroup &&
|
||||||
|
@ -145,7 +154,7 @@ export class Effects {
|
||||||
groupSeq: group.seq,
|
groupSeq: group.seq,
|
||||||
groupName: group.name,
|
groupName: group.name,
|
||||||
userSeqs: group.userSeqs.filter(
|
userSeqs: group.userSeqs.filter(
|
||||||
(userSeq) => userSeq !== String(req.seq)
|
(userSeq) => userSeq !== (req.seq as any)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -158,8 +167,9 @@ export class Effects {
|
||||||
if (
|
if (
|
||||||
!!this.moduleConfig.useMyDeptGroup &&
|
!!this.moduleConfig.useMyDeptGroup &&
|
||||||
this.moduleConfig.useMyDeptGroup &&
|
this.moduleConfig.useMyDeptGroup &&
|
||||||
|
!!myDeptUserList &&
|
||||||
myDeptUserList.filter(
|
myDeptUserList.filter(
|
||||||
(deptUser) => deptUser.seq === String(req.seq)
|
(deptUser) => deptUser.seq === (req.seq as any)
|
||||||
).length > 0
|
).length > 0
|
||||||
) {
|
) {
|
||||||
// skip;;
|
// skip;;
|
||||||
|
@ -198,6 +208,21 @@ export class Effects {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
nickname$ = createEffect(() =>
|
||||||
|
this.actions$.pipe(
|
||||||
|
ofType(nickname),
|
||||||
|
map((action) => action.req),
|
||||||
|
exhaustMap((req) =>
|
||||||
|
this.infoProtocolService.userNickname(req).pipe(
|
||||||
|
map((res: NicknameResponse) => {
|
||||||
|
return nicknameSuccess({ res });
|
||||||
|
}),
|
||||||
|
catchError((error) => of(nicknameFailure({ error })))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
groupCreateSuccess$ = createEffect(
|
groupCreateSuccess$ = createEffect(
|
||||||
() => {
|
() => {
|
||||||
return this.actions$.pipe(
|
return this.actions$.pipe(
|
||||||
|
@ -215,7 +240,7 @@ export class Effects {
|
||||||
}
|
}
|
||||||
|
|
||||||
const index = buddyList.findIndex(
|
const index = buddyList.findIndex(
|
||||||
(b) => String(b.seq) === userSeq
|
(b) => b.seq === Number(userSeq)
|
||||||
);
|
);
|
||||||
if (-1 < index) {
|
if (-1 < index) {
|
||||||
addBuddyList.push(userSeq);
|
addBuddyList.push(userSeq);
|
||||||
|
@ -251,7 +276,7 @@ export class Effects {
|
||||||
}
|
}
|
||||||
|
|
||||||
const index = buddyList.findIndex(
|
const index = buddyList.findIndex(
|
||||||
(b) => String(b.seq) === userSeq
|
(b) => b.seq === Number(userSeq)
|
||||||
);
|
);
|
||||||
if (-1 < index) {
|
if (-1 < index) {
|
||||||
addBuddyList.push(userSeq);
|
addBuddyList.push(userSeq);
|
||||||
|
@ -284,6 +309,7 @@ export class Effects {
|
||||||
private store: Store<any>,
|
private store: Store<any>,
|
||||||
@Inject(_MODULE_CONFIG) private moduleConfig: ModuleConfig,
|
@Inject(_MODULE_CONFIG) private moduleConfig: ModuleConfig,
|
||||||
private syncProtocolService: SyncProtocolService,
|
private syncProtocolService: SyncProtocolService,
|
||||||
private buddyProtocolService: BuddyProtocolService
|
private buddyProtocolService: BuddyProtocolService,
|
||||||
|
private infoProtocolService: InfoProtocolService
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,12 @@ import { createReducer, on } from '@ngrx/store';
|
||||||
import { UserInfo } from '@ucap/protocol-sync';
|
import { UserInfo } from '@ucap/protocol-sync';
|
||||||
|
|
||||||
import { initialState, adapterBuddy } from './state';
|
import { initialState, adapterBuddy } from './state';
|
||||||
import { buddy2Success, delSuccess, updateSuccess } from './actions';
|
import {
|
||||||
|
buddy2Success,
|
||||||
|
delSuccess,
|
||||||
|
updateSuccess,
|
||||||
|
nicknameSuccess
|
||||||
|
} from './actions';
|
||||||
|
|
||||||
export const reducer = createReducer(
|
export const reducer = createReducer(
|
||||||
initialState,
|
initialState,
|
||||||
|
@ -34,6 +39,19 @@ export const reducer = createReducer(
|
||||||
isFavorit: res.isFavorit
|
isFavorit: res.isFavorit
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
buddies: adapterBuddy.upsertOne(userInfo, { ...state.buddies })
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
on(nicknameSuccess, (state, action) => {
|
||||||
|
const res = action.res;
|
||||||
|
const userInfo: UserInfo = {
|
||||||
|
...state.buddies.entities[res.userSeq],
|
||||||
|
nickName: res.nickname
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
buddies: adapterBuddy.upsertOne(userInfo, { ...state.buddies })
|
buddies: adapterBuddy.upsertOne(userInfo, { ...state.buddies })
|
||||||
|
|
|
@ -128,8 +128,7 @@ export class Effects {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
updateMember$ = createEffect(
|
updateMember$ = createEffect(() => {
|
||||||
() => {
|
|
||||||
return this.actions$.pipe(
|
return this.actions$.pipe(
|
||||||
ofType(updateMember),
|
ofType(updateMember),
|
||||||
withLatestFrom(
|
withLatestFrom(
|
||||||
|
@ -138,17 +137,19 @@ export class Effects {
|
||||||
),
|
),
|
||||||
switchMap(([action, groupList, myDeptUserList]) => {
|
switchMap(([action, groupList, myDeptUserList]) => {
|
||||||
const targetGroup = action.targetGroup;
|
const targetGroup = action.targetGroup;
|
||||||
const targetUserSeqs = action.targetUserSeqs;
|
const targetUserSeqs = action.targetUserSeqs as any;
|
||||||
|
|
||||||
// Del Buddy
|
// Del Buddy
|
||||||
let userSeqsForDelete: string[] = targetGroup.userSeqs.filter(
|
let userSeqsForDelete: string[] = targetGroup.userSeqs.filter(
|
||||||
(v) => targetUserSeqs.indexOf(v) < 0
|
(v) => targetUserSeqs.indexOf(v + '') < 0
|
||||||
);
|
);
|
||||||
|
|
||||||
// 소속부서(내부서) 고정그룹 사용시 소속부서원을 삭제하지 않는다.
|
// 소속부서(내부서) 고정그룹 사용시 소속부서원을 삭제하지 않는다.
|
||||||
if (
|
if (
|
||||||
!!this.moduleConfig.useMyDeptGroup &&
|
!!this.moduleConfig.useMyDeptGroup &&
|
||||||
this.moduleConfig.useMyDeptGroup
|
this.moduleConfig.useMyDeptGroup &&
|
||||||
|
!!myDeptUserList &&
|
||||||
|
myDeptUserList.length > 0
|
||||||
) {
|
) {
|
||||||
userSeqsForDelete = userSeqsForDelete.filter(
|
userSeqsForDelete = userSeqsForDelete.filter(
|
||||||
(delbuddy) =>
|
(delbuddy) =>
|
||||||
|
@ -188,9 +189,7 @@ export class Effects {
|
||||||
];
|
];
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
},
|
});
|
||||||
{ dispatch: false }
|
|
||||||
);
|
|
||||||
|
|
||||||
moveMember$ = createEffect(() =>
|
moveMember$ = createEffect(() =>
|
||||||
this.actions$.pipe(
|
this.actions$.pipe(
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
"dest": "../../dist/ui-authentication",
|
"dest": "../../dist/ui-authentication",
|
||||||
"lib": {
|
"lib": {
|
||||||
"entryFile": "src/public-api.ts",
|
"entryFile": "src/public-api.ts",
|
||||||
|
"styleIncludePaths": ["./src/assets/scss"],
|
||||||
"umdModuleIds": {
|
"umdModuleIds": {
|
||||||
"moment": "moment",
|
"moment": "moment",
|
||||||
"@ucap/pi": "@ucap/pi",
|
"@ucap/pi": "@ucap/pi",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@ucap/ng-ui-authentication",
|
"name": "@ucap/ng-ui-authentication",
|
||||||
"version": "0.0.20",
|
"version": "0.0.24",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"registry": "https://nexus.loafle.net/repository/npm-ucap/"
|
"registry": "https://nexus.loafle.net/repository/npm-ucap/"
|
||||||
},
|
},
|
||||||
|
@ -10,9 +10,10 @@
|
||||||
"@angular/core": "^9.0.2",
|
"@angular/core": "^9.0.2",
|
||||||
"@angular/material": "^9.0.0",
|
"@angular/material": "^9.0.0",
|
||||||
"@ucap/core": "~0.0.1",
|
"@ucap/core": "~0.0.1",
|
||||||
"@ucap/uc-scss": "~0.0.1",
|
"@ucap/ui-scss": "~0.0.1",
|
||||||
"@ucap/ng-i18n": "~0.0.1",
|
"@ucap/ng-i18n": "~0.0.1",
|
||||||
"@ucap/ng-ui": "~0.0.1",
|
"@ucap/ng-ui": "~0.0.1",
|
||||||
|
"@ucap/ng-ui-material": "~0.0.1",
|
||||||
"tslib": "^1.10.0"
|
"tslib": "^1.10.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
11
projects/ui-authentication/scss-bundle.config.json
Normal file
11
projects/ui-authentication/scss-bundle.config.json
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"bundlerOptions": {
|
||||||
|
"entryFile": "./projects/ui-authentication/src/assets/scss/_theme.scss",
|
||||||
|
"rootDir": "./projects/ui-authentication/src/assets/scss/",
|
||||||
|
"outFile": "./dist/ui-authentication/_theme.scss",
|
||||||
|
"dedupeGlobs": [],
|
||||||
|
"includePaths": [],
|
||||||
|
"ignoreImports": ["~@ucap/.*", "~@angular/.*"],
|
||||||
|
"logLevel": "silent"
|
||||||
|
}
|
||||||
|
}
|
2
projects/ui-authentication/src/assets/scss/_theme.scss
Normal file
2
projects/ui-authentication/src/assets/scss/_theme.scss
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
@import '../../lib/components/change-password.component.theme.scss';
|
||||||
|
@import '../../lib/components/login.component.theme.scss';
|
|
@ -30,8 +30,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.separator {
|
.separator {
|
||||||
font-size: 15px;
|
font: {
|
||||||
font-weight: 600;
|
size: 15px;
|
||||||
|
weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
margin: 24px auto;
|
margin: 24px auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
|
@ -2,58 +2,17 @@ import { moduleMetadata } from '@storybook/angular';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
import { linkTo } from '@storybook/addon-links';
|
import { linkTo } from '@storybook/addon-links';
|
||||||
|
|
||||||
import { ChangePasswordComponent } from './change-password.component';
|
|
||||||
import { AuthenticationUiModule } from '../authentication-ui.module';
|
|
||||||
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
|
|
||||||
import { ChangeDetectorRef } from '@angular/core';
|
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { CommonModule } from '@angular/common';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
|
||||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
|
||||||
import { MatInputModule } from '@angular/material/input';
|
|
||||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
||||||
import { MatSelectModule } from '@angular/material/select';
|
|
||||||
import { I18nService, UCAP_I18N_NAMESPACE, I18nModule } from '@ucap/ng-i18n';
|
|
||||||
import { LogService } from '@ucap/logger';
|
|
||||||
import { Company } from '@ucap/api-external';
|
|
||||||
|
|
||||||
export default {
|
import { FormBuilder } from '@angular/forms';
|
||||||
title: 'ChangePasswordComponent',
|
|
||||||
decorators: [
|
|
||||||
moduleMetadata({
|
|
||||||
imports: [
|
|
||||||
BrowserModule,
|
|
||||||
BrowserAnimationsModule,
|
|
||||||
|
|
||||||
CommonModule,
|
import { LogService } from '@ucap/ng-logger';
|
||||||
ReactiveFormsModule,
|
import { I18nService, UCAP_I18N_NAMESPACE } from '@ucap/ng-i18n';
|
||||||
|
|
||||||
MatButtonModule,
|
import { AuthenticationUiModule } from '../authentication-ui.module';
|
||||||
MatCheckboxModule,
|
|
||||||
MatFormFieldModule,
|
|
||||||
MatIconModule,
|
|
||||||
MatInputModule,
|
|
||||||
MatProgressSpinnerModule,
|
|
||||||
MatSelectModule,
|
|
||||||
|
|
||||||
I18nModule
|
import { ChangePasswordComponent } from './change-password.component';
|
||||||
],
|
|
||||||
providers: [
|
|
||||||
AuthenticationUiModule,
|
|
||||||
{ provide: FormBuilder, useValue: new FormBuilder() },
|
|
||||||
{ provide: I18nService, useValue: new I18nService(new LogService({})) },
|
|
||||||
{
|
|
||||||
provide: UCAP_I18N_NAMESPACE,
|
|
||||||
useValue: 'authentication'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
],
|
|
||||||
excludeStories: /.*Data$/
|
|
||||||
};
|
|
||||||
|
|
||||||
export const actionsData = {
|
export const actionsData = {
|
||||||
changePassword: action('changePassword')
|
changePassword: action('changePassword')
|
||||||
|
@ -61,6 +20,25 @@ export const actionsData = {
|
||||||
|
|
||||||
export const inputData = {};
|
export const inputData = {};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'ui-authentication::ChangePasswordComponent',
|
||||||
|
component: ChangePasswordComponent,
|
||||||
|
decorators: [
|
||||||
|
moduleMetadata({
|
||||||
|
imports: [BrowserModule, BrowserAnimationsModule, AuthenticationUiModule],
|
||||||
|
providers: [
|
||||||
|
{ provide: FormBuilder, useClass: FormBuilder },
|
||||||
|
{ provide: LogService, useValue: new LogService({}) },
|
||||||
|
{ provide: I18nService, useClass: I18nService },
|
||||||
|
{
|
||||||
|
provide: UCAP_I18N_NAMESPACE,
|
||||||
|
useValue: 'authentication'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
export const Default = () => ({
|
export const Default = () => ({
|
||||||
component: ChangePasswordComponent,
|
component: ChangePasswordComponent,
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
@import '~@ucap/ng-ui-material/material';
|
||||||
|
|
||||||
|
@mixin ucap-authentication-change-password-theme($theme) {
|
||||||
|
$is-dark-theme: map-get($theme, is-dark);
|
||||||
|
$primary: map-get($theme, primary);
|
||||||
|
$accent: map-get($theme, accent);
|
||||||
|
$warn: map-get($theme, warn);
|
||||||
|
$background: map-get($theme, background);
|
||||||
|
$foreground: map-get($theme, foreground);
|
||||||
|
|
||||||
|
.ucap-authentication-change-password-container {
|
||||||
|
border-color: mat-color($foreground, secondary-text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin ucap-authentication-change-password-typography($config) {
|
||||||
|
.ucap-authentication-change-password-container {
|
||||||
|
font-family: mat-font-family($config);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
@import '~@ucap/ui-scss/ucap';
|
@import '~@ucap/ng-ui-material/material';
|
||||||
|
|
||||||
.ucap-authentication-login-container {
|
.ucap-authentication-login-container {
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -9,7 +9,9 @@
|
||||||
|
|
||||||
background-color: rgba(255, 255, 255, 1);
|
background-color: rgba(255, 255, 255, 1);
|
||||||
border-radius: 0px;
|
border-radius: 0px;
|
||||||
font-size: 14px;
|
font: {
|
||||||
|
size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
|
@ -52,7 +54,9 @@
|
||||||
display: block;
|
display: block;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
font-size: 1.1em;
|
font: {
|
||||||
|
size: 1.1em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,40 +5,42 @@ import { linkTo } from '@storybook/addon-links';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
|
|
||||||
import { LogService } from '@ucap/logger';
|
|
||||||
import { Company } from '@ucap/api-external';
|
import { Company } from '@ucap/api-external';
|
||||||
|
|
||||||
|
import { LogService } from '@ucap/ng-logger';
|
||||||
import { I18nService, UCAP_I18N_NAMESPACE } from '@ucap/ng-i18n';
|
import { I18nService, UCAP_I18N_NAMESPACE } from '@ucap/ng-i18n';
|
||||||
|
|
||||||
import { AuthenticationUiModule } from '../authentication-ui.module';
|
import { AuthenticationUiModule } from '../authentication-ui.module';
|
||||||
|
|
||||||
import { LoginComponent } from './login.component';
|
import { LoginComponent } from './login.component';
|
||||||
|
|
||||||
|
const actionsData = {
|
||||||
|
login: action('login')
|
||||||
|
};
|
||||||
|
|
||||||
|
const inputData = {
|
||||||
|
companyList: [
|
||||||
|
{ companyName: 'LG CNS', companyCode: 'GUC100' },
|
||||||
|
{ companyName: 'LG UCAP', companyCode: 'GUC101' }
|
||||||
|
] as Company[]
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'LoginComponent',
|
title: 'ui-authentication::LoginComponent',
|
||||||
|
component: LoginComponent,
|
||||||
decorators: [
|
decorators: [
|
||||||
moduleMetadata({
|
moduleMetadata({
|
||||||
imports: [BrowserModule, BrowserAnimationsModule, AuthenticationUiModule],
|
imports: [BrowserModule, BrowserAnimationsModule, AuthenticationUiModule],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: I18nService, useValue: new I18nService(new LogService({})) },
|
{ provide: LogService, useValue: new LogService({}) },
|
||||||
|
{ provide: I18nService, useClass: I18nService },
|
||||||
{
|
{
|
||||||
provide: UCAP_I18N_NAMESPACE,
|
provide: UCAP_I18N_NAMESPACE,
|
||||||
useValue: 'authentication'
|
useValue: 'authentication'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
],
|
]
|
||||||
excludeStories: /.*Data$/
|
|
||||||
};
|
|
||||||
|
|
||||||
export const actionsData = {
|
|
||||||
login: action('login')
|
|
||||||
};
|
|
||||||
|
|
||||||
export const inputData = {
|
|
||||||
companyList: [
|
|
||||||
{ companyName: 'LG CNS', companyCode: 'GUC100' },
|
|
||||||
{ companyName: 'LG UCAP', companyCode: 'GUC101' }
|
|
||||||
] as Company[]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Default = () => ({
|
export const Default = () => ({
|
||||||
|
@ -55,7 +57,6 @@ export const InputContents = () => ({
|
||||||
companyList: inputData.companyList,
|
companyList: inputData.companyList,
|
||||||
companyCode: 'GUC100',
|
companyCode: 'GUC100',
|
||||||
loginId: 'test-loginid',
|
loginId: 'test-loginid',
|
||||||
// loginPw: '111111',
|
|
||||||
login: actionsData.login
|
login: actionsData.login
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
@import '~@ucap/ng-ui-material/material';
|
||||||
|
|
||||||
|
@mixin ucap-authentication-login-theme($theme) {
|
||||||
|
$is-dark-theme: map-get($theme, is-dark);
|
||||||
|
$primary: map-get($theme, primary);
|
||||||
|
$accent: map-get($theme, accent);
|
||||||
|
$warn: map-get($theme, warn);
|
||||||
|
$background: map-get($theme, background);
|
||||||
|
$foreground: map-get($theme, foreground);
|
||||||
|
|
||||||
|
.ucap-authentication-login-container {
|
||||||
|
border-color: mat-color($foreground, secondary-text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin ucap-authentication-login-typography($config) {
|
||||||
|
.ucap-authentication-login-container {
|
||||||
|
font-family: mat-font-family($config);
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,11 +3,13 @@
|
||||||
"dest": "../../dist/ui-chat",
|
"dest": "../../dist/ui-chat",
|
||||||
"lib": {
|
"lib": {
|
||||||
"entryFile": "src/public-api.ts",
|
"entryFile": "src/public-api.ts",
|
||||||
|
"styleIncludePaths": ["./src/assets/scss"],
|
||||||
"umdModuleIds": {
|
"umdModuleIds": {
|
||||||
"ngx-perfect-scrollbar": "ngx-perfect-scrollbar",
|
"ngx-perfect-scrollbar": "ngx-perfect-scrollbar",
|
||||||
"@ucap/core": "@ucap/core",
|
"@ucap/core": "@ucap/core",
|
||||||
"@ucap/protocol-room": "@ucap/protocol-room",
|
"@ucap/protocol-room": "@ucap/protocol-room",
|
||||||
"@ucap/ng-logger": "@ucap/ng-logger",
|
"@ucap/ng-logger": "@ucap/ng-logger",
|
||||||
|
"@ucap/ng-i18n": "@ucap/ng-i18n",
|
||||||
"@ucap/ng-ui": "@ucap/ng-ui"
|
"@ucap/ng-ui": "@ucap/ng-ui"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@ucap/ng-ui-chat",
|
"name": "@ucap/ng-ui-chat",
|
||||||
"version": "0.0.3",
|
"version": "0.0.9",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"registry": "https://nexus.loafle.net/repository/npm-ucap/"
|
"registry": "https://nexus.loafle.net/repository/npm-ucap/"
|
||||||
},
|
},
|
||||||
|
@ -11,8 +11,10 @@
|
||||||
"@angular/material": "^9.0.0",
|
"@angular/material": "^9.0.0",
|
||||||
"@ucap/core": "~0.0.1",
|
"@ucap/core": "~0.0.1",
|
||||||
"@ucap/protocol-room": "~0.0.1",
|
"@ucap/protocol-room": "~0.0.1",
|
||||||
"@ucap/uc-scss": "~0.0.1",
|
"@ucap/ui-scss": "~0.0.1",
|
||||||
"@ucap/ng-ui": "~0.0.1",
|
"@ucap/ng-ui": "~0.0.1",
|
||||||
|
"@ucap/ng-ui-material": "~0.0.1",
|
||||||
|
"@ucap/ng-ui-organization": "~0.0.1",
|
||||||
"tslib": "^1.10.0"
|
"tslib": "^1.10.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
11
projects/ui-chat/scss-bundle.config.json
Normal file
11
projects/ui-chat/scss-bundle.config.json
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"bundlerOptions": {
|
||||||
|
"entryFile": "./projects/ui-chat/src/assets/scss/_theme.scss",
|
||||||
|
"rootDir": "./projects/ui-chat/src/assets/scss/",
|
||||||
|
"outFile": "./dist/ui-chat/_theme.scss",
|
||||||
|
"dedupeGlobs": [],
|
||||||
|
"includePaths": [],
|
||||||
|
"ignoreImports": ["~@ucap/.*", "~@angular/.*"],
|
||||||
|
"logLevel": "silent"
|
||||||
|
}
|
||||||
|
}
|
2
projects/ui-chat/src/assets/scss/_theme.scss
Normal file
2
projects/ui-chat/src/assets/scss/_theme.scss
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
@import '../../lib/components/room-expansion.component.theme.scss';
|
||||||
|
@import '../../lib/components/room-list-item-01.component.theme.scss';
|
|
@ -28,8 +28,48 @@ import {
|
||||||
RoomExpansionNodeDirective
|
RoomExpansionNodeDirective
|
||||||
} from './components/room-expansion.component';
|
} from './components/room-expansion.component';
|
||||||
import { RoomListItem01Component } from './components/room-list-item-01.component';
|
import { RoomListItem01Component } from './components/room-list-item-01.component';
|
||||||
|
import { InformationComponent } from './components/message-box/information.component';
|
||||||
|
import { TextComponent } from './components/message-box/text.component';
|
||||||
|
import { FileComponent } from './components/message-box/file.component';
|
||||||
|
import { AttachFileComponent } from './components/message-box/attach-file.component';
|
||||||
|
import { ImageComponent } from './components/message-box/image.component';
|
||||||
|
import { VideoComponent } from './components/message-box/video.component';
|
||||||
|
import { StickerComponent } from './components/message-box/sticker.component';
|
||||||
|
import { MassComponent } from './components/message-box/mass.component';
|
||||||
|
import { ScheduleComponent } from './components/message-box/schedule.component';
|
||||||
|
import { VideoConferenceComponent } from './components/message-box/video-conference.component';
|
||||||
|
import { TranslationComponent } from './components/message-box/translation.component';
|
||||||
|
import { MassTranslationComponent } from './components/message-box/mass-translation.component';
|
||||||
|
import { RecallComponent } from './components/message-box/recall.component';
|
||||||
|
import { ReadHereComponent } from './components/message-box/read-here.component';
|
||||||
|
import { DateSplitterComponent } from './components/message-box/date-splitter.component';
|
||||||
|
import { SmsComponent } from './components/message-box/sms.component';
|
||||||
|
import { ReplyComponent } from './components/message-box/reply.component';
|
||||||
|
|
||||||
const COMPONENTS = [RoomExpansionComponent, RoomListItem01Component];
|
const COMPONENTS = [
|
||||||
|
RoomExpansionComponent,
|
||||||
|
RoomListItem01Component,
|
||||||
|
|
||||||
|
InformationComponent,
|
||||||
|
TextComponent,
|
||||||
|
FileComponent,
|
||||||
|
AttachFileComponent,
|
||||||
|
ImageComponent,
|
||||||
|
VideoComponent,
|
||||||
|
StickerComponent,
|
||||||
|
MassComponent,
|
||||||
|
ScheduleComponent,
|
||||||
|
VideoConferenceComponent,
|
||||||
|
TranslationComponent,
|
||||||
|
MassTranslationComponent,
|
||||||
|
RecallComponent,
|
||||||
|
|
||||||
|
ReadHereComponent,
|
||||||
|
DateSplitterComponent,
|
||||||
|
|
||||||
|
SmsComponent,
|
||||||
|
ReplyComponent
|
||||||
|
];
|
||||||
const DIALOGS = [];
|
const DIALOGS = [];
|
||||||
const PIPES = [];
|
const PIPES = [];
|
||||||
const DIRECTIVES = [RoomExpansionHeaderDirective, RoomExpansionNodeDirective];
|
const DIRECTIVES = [RoomExpansionHeaderDirective, RoomExpansionNodeDirective];
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
<div class="ucap-chat-message-box-attach-file" (click)="onClickOpenViewer()">
|
||||||
|
<!--파일명에 따라 doc exe hwp ppt xls zip 으로 추가되고 나머지 파일 명은 file로 기간이 만료된 파일은 그뒤에 disable도 추가-->
|
||||||
|
<!-- <div class="file-img" [ngClass]="fileInfo.FileExt"></div> -->
|
||||||
|
<div [ngClass]="['mime-icon', 'light', 'ico-' + fileInfo.fileExt]">
|
||||||
|
<div class="ico"></div>
|
||||||
|
</div>
|
||||||
|
<ul class="file-info">
|
||||||
|
<li class="file-name">
|
||||||
|
{{ fileInfo.fileName }}
|
||||||
|
</li>
|
||||||
|
<li class="date">
|
||||||
|
{{ fileInfo.attachmentRegDate | ucapDate }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="btn-box over">
|
||||||
|
<ul *ngIf="!expired">
|
||||||
|
<li>
|
||||||
|
<button mat-button (click)="onClickSave()">
|
||||||
|
저장
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button mat-button (click)="onClickSave()">
|
||||||
|
폴더열기
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button mat-button (click)="onClickSave()">
|
||||||
|
???
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="progress over">
|
||||||
|
프로그레스 영역
|
||||||
|
</div>
|
|
@ -0,0 +1,126 @@
|
||||||
|
// $tablet-s-width: 768px;
|
||||||
|
|
||||||
|
// .bubble-main {
|
||||||
|
// display: flex;
|
||||||
|
// flex-direction: row;
|
||||||
|
// padding: 14px;
|
||||||
|
// min-width: 300px;
|
||||||
|
// .file-img {
|
||||||
|
// display: inline-flex;
|
||||||
|
// width: 50px;
|
||||||
|
// height: 50px;
|
||||||
|
// float: left;
|
||||||
|
// margin-right: 14px;
|
||||||
|
// background-repeat: no-repeat;
|
||||||
|
// &.doc {
|
||||||
|
// background-image: url(/assets/images/file/icon_talk_doc.png);
|
||||||
|
// &.disable {
|
||||||
|
// background-image: url(/assets/images/file/icon_talk_doc_d.png);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// &.exe {
|
||||||
|
// background-image: url(/assets/images/file/icon_talk_exe.png);
|
||||||
|
// &.disable {
|
||||||
|
// background-image: url(/assets/images/file/icon_talk_exe_d.png);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// &.file {
|
||||||
|
// background-image: url(/assets/images/file/icon_talk_file.png);
|
||||||
|
// &.disable {
|
||||||
|
// background-image: url(/assets/images/file/icon_talk_file_d.png);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// &.hwp {
|
||||||
|
// background-image: url(/assets/images/file/icon_talk_hwp.png);
|
||||||
|
// &.disable {
|
||||||
|
// background-image: url(/assets/images/file/icon_talk_hwp_d.png);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// &.ppt,
|
||||||
|
// &.pptx {
|
||||||
|
// background-image: url(/assets/images/file/icon_talk_ppt.png);
|
||||||
|
// &.disable {
|
||||||
|
// background-image: url(/assets/images/file/icon_talk_ppt_d.png);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// &.xls,
|
||||||
|
// &.xlsm,
|
||||||
|
// &.xlsx {
|
||||||
|
// background-image: url(/assets/images/file/icon_talk_xls.png);
|
||||||
|
// &.disable {
|
||||||
|
// background-image: url(/assets/images/file/icon_talk_xls_d.png);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// &.zip {
|
||||||
|
// background-image: url(/assets/images/file/icon_talk_zip.png);
|
||||||
|
// &.disable {
|
||||||
|
// background-image: url(/assets/images/file/icon_talk_doc_d.png);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// .file-info {
|
||||||
|
// display: inline-flex;
|
||||||
|
// flex-direction: column;
|
||||||
|
// text-align: left;
|
||||||
|
// float: left;
|
||||||
|
// line-height: 1.6em;
|
||||||
|
// .file-name {
|
||||||
|
// font-size: 1em;
|
||||||
|
// font-weight: bold;
|
||||||
|
// display: inline-flex;
|
||||||
|
// }
|
||||||
|
// .file-size {
|
||||||
|
// display: inline-flex;
|
||||||
|
// font-size: 11px;
|
||||||
|
// color: #666666;
|
||||||
|
// }
|
||||||
|
// .file-ext {
|
||||||
|
// font-size: 12px;
|
||||||
|
// color: #848d95;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// .btn-box {
|
||||||
|
// width: 100%;
|
||||||
|
// height: 40px;
|
||||||
|
// border-top: 1px solid #dddddd;
|
||||||
|
// display: flex;
|
||||||
|
// width: 100%;
|
||||||
|
// text-align: center;
|
||||||
|
// font-size: 1em;
|
||||||
|
// ul {
|
||||||
|
// width: 100%;
|
||||||
|
// li {
|
||||||
|
// width: 50%;
|
||||||
|
// height: 100%;
|
||||||
|
// display: inline-block;
|
||||||
|
// text-align: center;
|
||||||
|
// align-items: center;
|
||||||
|
// border-right: 1px solid #dddddd;
|
||||||
|
// @media screen and (max-width: #{$tablet-s-width}) {
|
||||||
|
// width: 30%;
|
||||||
|
// }
|
||||||
|
// &:last-child {
|
||||||
|
// border-right: none;
|
||||||
|
// @media screen and (max-width: #{$tablet-s-width}) {
|
||||||
|
// width: 70%;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// .mat-button {
|
||||||
|
// width: 100%;
|
||||||
|
// display: block;
|
||||||
|
// height: 100%;
|
||||||
|
// font-size: 1em;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// &.expired {
|
||||||
|
// li {
|
||||||
|
// width: 100%;
|
||||||
|
// white-space: nowrap;
|
||||||
|
// color: #999999;
|
||||||
|
// align-items: center;
|
||||||
|
// line-height: 40px;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
|
@ -0,0 +1,28 @@
|
||||||
|
/* tslint:disable:no-unused-variable */
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { DebugElement } from '@angular/core';
|
||||||
|
|
||||||
|
import { AttachFileComponent } from './attach-file.component';
|
||||||
|
|
||||||
|
describe('AttachFileComponent', () => {
|
||||||
|
let component: AttachFileComponent;
|
||||||
|
let fixture: ComponentFixture<AttachFileComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ AttachFileComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(AttachFileComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { FileEventJson } from '@ucap/protocol-event';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ucap-chat-message-box-attach-file',
|
||||||
|
templateUrl: './attach-file.component.html',
|
||||||
|
styleUrls: ['./attach-file.component.scss']
|
||||||
|
})
|
||||||
|
export class AttachFileComponent implements OnInit {
|
||||||
|
@Input()
|
||||||
|
fileInfo: FileEventJson;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
expired = false;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
save = new EventEmitter<string>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
openViewer = new EventEmitter();
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
ngOnInit() {}
|
||||||
|
|
||||||
|
onClickSave() {
|
||||||
|
this.save.emit('save');
|
||||||
|
}
|
||||||
|
onClickSaveAs() {
|
||||||
|
this.save.emit('saveAs');
|
||||||
|
}
|
||||||
|
onClickOpenViewer() {
|
||||||
|
this.openViewer.emit();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
<div class="ucap-chat-message-box-date-splitter">
|
||||||
|
<span class="date bg-warn-chat">{{
|
||||||
|
this.message.sendDate | ucapDate: 'L dddd'
|
||||||
|
}}</span>
|
||||||
|
</div>
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { DateSplitterComponent } from './date-splitter.component';
|
||||||
|
|
||||||
|
describe('Chat::MessageBox::DateSplitterComponent', () => {
|
||||||
|
let component: DateSplitterComponent;
|
||||||
|
let fixture: ComponentFixture<DateSplitterComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [DateSplitterComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(DateSplitterComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
|
import { Info, EventJson } from '@ucap/protocol-event';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ucap-chat-message-box-date-splitter',
|
||||||
|
templateUrl: './date-splitter.component.html',
|
||||||
|
styleUrls: ['./date-splitter.component.scss']
|
||||||
|
})
|
||||||
|
export class DateSplitterComponent implements OnInit {
|
||||||
|
@Input()
|
||||||
|
message: Info<EventJson>;
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
ngOnInit() {}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
<ng-container
|
||||||
|
*ngIf="fileInfo && fileInfo.fileType"
|
||||||
|
[ngSwitch]="fileInfo.fileType"
|
||||||
|
class="ucap-chat-message-box-file"
|
||||||
|
>
|
||||||
|
<ucap-chat-message-box-attach-file
|
||||||
|
*ngSwitchCase="FileType.File"
|
||||||
|
[expired]="getExpiredFile()"
|
||||||
|
(openViewer)="onClickFileViewer(fileInfo)"
|
||||||
|
(save)="onSave($event)"
|
||||||
|
>
|
||||||
|
</ucap-chat-message-box-attach-file>
|
||||||
|
|
||||||
|
<ucap-chat-message-box-attach-file
|
||||||
|
*ngSwitchCase="FileType.Sound"
|
||||||
|
[expired]="getExpiredFile()"
|
||||||
|
(openViewer)="onClickFileViewer(fileInfo)"
|
||||||
|
(save)="onSave($event)"
|
||||||
|
>
|
||||||
|
</ucap-chat-message-box-attach-file>
|
||||||
|
|
||||||
|
<ucap-chat-message-box-image
|
||||||
|
*ngSwitchCase="FileType.Image"
|
||||||
|
[expired]="getExpiredFile()"
|
||||||
|
(openViewer)="onClickFileViewer(fileInfo)"
|
||||||
|
(save)="onSave($event)"
|
||||||
|
></ucap-chat-message-box-image>
|
||||||
|
|
||||||
|
<ucap-chat-message-box-video
|
||||||
|
*ngSwitchCase="FileType.Video"
|
||||||
|
[expired]="getExpiredFile()"
|
||||||
|
(openViewer)="onClickFileViewer(fileInfo)"
|
||||||
|
(save)="onSave($event)"
|
||||||
|
></ucap-chat-message-box-video>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<ucap-chat-message-box-text
|
||||||
|
*ngSwitchDefault
|
||||||
|
[message]="message"
|
||||||
|
></ucap-chat-message-box-text> -->
|
||||||
|
</ng-container>
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FileComponent } from './file.component';
|
||||||
|
|
||||||
|
describe('Chat::MessageBox::FileComponent', () => {
|
||||||
|
let component: FileComponent;
|
||||||
|
let fixture: ComponentFixture<FileComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [FileComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FileComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,71 @@
|
||||||
|
import { Component, OnInit, Output, Input, EventEmitter } from '@angular/core';
|
||||||
|
import { FileType, Info, FileEventJson } from '@ucap/protocol-event';
|
||||||
|
import { RoomInfo } from '@ucap/protocol-room';
|
||||||
|
import { FileDownloadItem, StatusCode } from '@ucap/api';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ucap-chat-message-box-file',
|
||||||
|
templateUrl: './file.component.html',
|
||||||
|
styleUrls: ['./file.component.scss']
|
||||||
|
})
|
||||||
|
export class FileComponent implements OnInit {
|
||||||
|
@Input()
|
||||||
|
message: Info<FileEventJson>;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
roomInfo: RoomInfo;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
save = new EventEmitter<{
|
||||||
|
fileInfo: FileEventJson;
|
||||||
|
fileDownloadItem: FileDownloadItem;
|
||||||
|
type: string;
|
||||||
|
}>();
|
||||||
|
@Output()
|
||||||
|
fileViewer = new EventEmitter<FileEventJson>();
|
||||||
|
|
||||||
|
fileInfo?: FileEventJson;
|
||||||
|
fileDownloadItem: FileDownloadItem;
|
||||||
|
errorMessage?: string;
|
||||||
|
FileType = FileType;
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (StatusCode.Success === this.message.sentMessageJson.statusCode) {
|
||||||
|
this.fileInfo = this.message.sentMessageJson;
|
||||||
|
} else {
|
||||||
|
this.errorMessage =
|
||||||
|
this.message.sentMessageJson.errorMessage || '[Error] System Error!!';
|
||||||
|
}
|
||||||
|
|
||||||
|
this.fileDownloadItem = new FileDownloadItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
getExpiredFile() {
|
||||||
|
if (
|
||||||
|
!!this.roomInfo &&
|
||||||
|
this.roomInfo.expiredFileStdSeq <= this.message.seq
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickFileViewer(fileInfo: FileEventJson) {
|
||||||
|
if (!this.getExpiredFile()) {
|
||||||
|
this.fileViewer.emit(fileInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onSave(value: string) {
|
||||||
|
if (!this.getExpiredFile()) {
|
||||||
|
this.save.emit({
|
||||||
|
fileInfo: this.fileInfo,
|
||||||
|
fileDownloadItem: this.fileDownloadItem,
|
||||||
|
type: value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<div
|
||||||
|
class="ucap-chat-message-box-image"
|
||||||
|
(mouseenter)="mouseEnter($event)"
|
||||||
|
(mouseleave)="mouseLeave($event)"
|
||||||
|
>
|
||||||
|
<div *ngIf="showExpired" class="expired-text">
|
||||||
|
<span>만기된 파일입니다.</span>
|
||||||
|
</div>
|
||||||
|
<img [src]="fileInfo.thumbUrl" />
|
||||||
|
</div>
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ImageComponent } from './image.component';
|
||||||
|
|
||||||
|
describe('Chat::MessageBox::ImageComponent', () => {
|
||||||
|
let component: ImageComponent;
|
||||||
|
let fixture: ComponentFixture<ImageComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ImageComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ImageComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
|
import { FileEventJson } from '@ucap/protocol-event';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ucap-chat-message-box-image',
|
||||||
|
templateUrl: './image.component.html',
|
||||||
|
styleUrls: ['./image.component.scss']
|
||||||
|
})
|
||||||
|
export class ImageComponent implements OnInit {
|
||||||
|
@Input()
|
||||||
|
fileInfo: FileEventJson;
|
||||||
|
@Input()
|
||||||
|
expired = false;
|
||||||
|
|
||||||
|
showExpired = false;
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
ngOnInit() {}
|
||||||
|
|
||||||
|
mouseEnter(event: MouseEvent): void {
|
||||||
|
if (this.expired) {
|
||||||
|
this.showExpired = true;
|
||||||
|
}
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
mouseLeave(event: MouseEvent): void {
|
||||||
|
if (this.expired) {
|
||||||
|
this.showExpired = false;
|
||||||
|
}
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
39
projects/ui-chat/src/lib/components/message-box/index.ts
Normal file
39
projects/ui-chat/src/lib/components/message-box/index.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import { InformationComponent } from './information.component';
|
||||||
|
import { TextComponent } from './text.component';
|
||||||
|
import { FileComponent } from './file.component';
|
||||||
|
import { AttachFileComponent } from './attach-file.component';
|
||||||
|
import { ImageComponent } from './image.component';
|
||||||
|
import { VideoComponent } from './video.component';
|
||||||
|
import { StickerComponent } from './sticker.component';
|
||||||
|
import { MassComponent } from './mass.component';
|
||||||
|
import { ScheduleComponent } from './schedule.component';
|
||||||
|
import { VideoConferenceComponent } from './video-conference.component';
|
||||||
|
import { TranslationComponent } from './translation.component';
|
||||||
|
import { MassTranslationComponent } from './mass-translation.component';
|
||||||
|
import { RecallComponent } from './recall.component';
|
||||||
|
import { SmsComponent } from './sms.component';
|
||||||
|
import { ReplyComponent } from './reply.component';
|
||||||
|
import { ReadHereComponent } from './read-here.component';
|
||||||
|
import { DateSplitterComponent } from './date-splitter.component';
|
||||||
|
|
||||||
|
export const COMPONENTS = [
|
||||||
|
InformationComponent,
|
||||||
|
TextComponent,
|
||||||
|
FileComponent,
|
||||||
|
AttachFileComponent,
|
||||||
|
ImageComponent,
|
||||||
|
VideoComponent,
|
||||||
|
StickerComponent,
|
||||||
|
MassComponent,
|
||||||
|
ScheduleComponent,
|
||||||
|
VideoConferenceComponent,
|
||||||
|
TranslationComponent,
|
||||||
|
MassTranslationComponent,
|
||||||
|
RecallComponent,
|
||||||
|
|
||||||
|
ReadHereComponent,
|
||||||
|
DateSplitterComponent,
|
||||||
|
|
||||||
|
SmsComponent,
|
||||||
|
ReplyComponent
|
||||||
|
];
|
|
@ -0,0 +1,88 @@
|
||||||
|
<div class="ucap-chat-message-box-information">
|
||||||
|
<ng-container [ngSwitch]="message.type">
|
||||||
|
<ng-container *ngSwitchCase="EventType.Join">
|
||||||
|
{{ getI18nForSir(getOwnerForJoinEventJson()) }}이
|
||||||
|
{{ getI18nForSir(getInviterForJoinEventJson()) }}을 초대했습니다.
|
||||||
|
<!-- {{
|
||||||
|
'chat.event.inviteToRoomWith'
|
||||||
|
| translate
|
||||||
|
: {
|
||||||
|
owner: getI18nForSir(message.sentMessageJson.owner),
|
||||||
|
inviter: getI18nForSir(message.sentMessageJson.inviter)
|
||||||
|
}
|
||||||
|
}} -->
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="EventType.Exit">
|
||||||
|
{{ message.sentMessage }}님이 퇴장하셨습니다.
|
||||||
|
<!-- {{
|
||||||
|
'chat.event.exitFromRoomWith'
|
||||||
|
| translate: { exitor: message.sentMessage }
|
||||||
|
}} -->
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="EventType.ForcedExit">
|
||||||
|
{{ message.exitForcingRequestUserName }}님이 {{ message.sentMessage }}님을
|
||||||
|
퇴장 시키셨습니다.
|
||||||
|
<!-- {{
|
||||||
|
'chat.event.ejectedFromRoomWith'
|
||||||
|
| translate
|
||||||
|
: {
|
||||||
|
requester: message.exitForcingRequestUserName,
|
||||||
|
ejected: message.sentMessage
|
||||||
|
}
|
||||||
|
}} -->
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="EventType.RenameRoom">
|
||||||
|
{{ getRequesterForRenameRoom() }}님이 대화방명을 '{{
|
||||||
|
getRoomNameForRenameRoom()
|
||||||
|
}}'으로 변경하셨습니다.
|
||||||
|
<!-- {{
|
||||||
|
'chat.event.renamedRoomWith'
|
||||||
|
| translate
|
||||||
|
: {
|
||||||
|
requester: message.sentMessageJson.requester,
|
||||||
|
roomName: message.sentMessageJson.roomName
|
||||||
|
}
|
||||||
|
}} -->
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="EventType.NotificationForTimerRoom">
|
||||||
|
{{ message.sentMessage }}
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="EventType.GuideForRoomTimerChanged">
|
||||||
|
{{ senderName }}님이 타이머를 설정하였습니다. ({{
|
||||||
|
getCalcTimerForGuideForRoomTimerChanged()
|
||||||
|
}})
|
||||||
|
<!-- {{
|
||||||
|
'chat.event.setTimerWith'
|
||||||
|
| translate
|
||||||
|
: {
|
||||||
|
requester: senderName,
|
||||||
|
timer: getCalcTimer(message.sentMessageJson.time * 1000)
|
||||||
|
}
|
||||||
|
}} -->
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="EventType.NotificationForiOSCapture">
|
||||||
|
{{ message.sentMessage }}님이 대화내용을 캡쳐하였습니다.
|
||||||
|
<!-- {{
|
||||||
|
'chat.event.iosCapture'
|
||||||
|
| translate
|
||||||
|
: {
|
||||||
|
requester: message.sentMessage
|
||||||
|
}
|
||||||
|
}} -->
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- <div class="ucap-chat-info-event">
|
||||||
|
<div class="info bg-primary-chat">
|
||||||
|
<strong class="text-warn-chat"
|
||||||
|
>김나영, 김준혁,강은정,나정미,박미영,박정은, 박훈, 문영준, 이지은, 이진현,
|
||||||
|
이현준, 임영찬, 임찬우, 정민우,정현욱, 최남진, 최영은, 최진우, 한고은,
|
||||||
|
한정후, 한지민</strong
|
||||||
|
>님이 초대되었습니다.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chat-event others bg-accent-chat">
|
||||||
|
자동 삭제 타이머가 10분으로 변경되었습니다.
|
||||||
|
</div>
|
||||||
|
</div> -->
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { InformationComponent } from './information.component';
|
||||||
|
|
||||||
|
describe('Chat::MessageBox::InformationComponent', () => {
|
||||||
|
let component: InformationComponent;
|
||||||
|
let fixture: ComponentFixture<InformationComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [InformationComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(InformationComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,134 @@
|
||||||
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
|
import {
|
||||||
|
EventType,
|
||||||
|
Info,
|
||||||
|
EventJson,
|
||||||
|
RenameRoomEventJson,
|
||||||
|
GuideForRoomTimerChangedEventJson,
|
||||||
|
JoinEventJson
|
||||||
|
} from '@ucap/protocol-event';
|
||||||
|
import { TranslateService } from '@ucap/ng-ui-organization';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ucap-chat-message-box-information',
|
||||||
|
templateUrl: './information.component.html',
|
||||||
|
styleUrls: ['./information.component.scss']
|
||||||
|
})
|
||||||
|
export class InformationComponent implements OnInit {
|
||||||
|
@Input()
|
||||||
|
message: Info<EventJson>;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
senderName?: string;
|
||||||
|
|
||||||
|
EventType = EventType;
|
||||||
|
|
||||||
|
constructor(private translateService: TranslateService) {}
|
||||||
|
|
||||||
|
ngOnInit() {}
|
||||||
|
|
||||||
|
getI18nForSir(names: string | string[]) {
|
||||||
|
if (Array.isArray(names)) {
|
||||||
|
const inviter: string[] = [];
|
||||||
|
|
||||||
|
// names.forEach((userName, idx) => {
|
||||||
|
// inviter.push(
|
||||||
|
// this.translateService.instant('common.messages.sirWith', {
|
||||||
|
// sir: userName
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
// });
|
||||||
|
names.forEach((userName, idx) => {
|
||||||
|
inviter.push(userName);
|
||||||
|
});
|
||||||
|
|
||||||
|
return inviter.join(',');
|
||||||
|
} else {
|
||||||
|
// return this.translateService.instant('common.messages.sirWith', {
|
||||||
|
// sir: names
|
||||||
|
// });
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getOwnerForJoinEventJson() {
|
||||||
|
return (this.message.sentMessageJson as JoinEventJson).owner;
|
||||||
|
}
|
||||||
|
getInviterForJoinEventJson() {
|
||||||
|
return (this.message.sentMessageJson as JoinEventJson).inviter;
|
||||||
|
}
|
||||||
|
getCalcTimerForGuideForRoomTimerChanged() {
|
||||||
|
const millisec =
|
||||||
|
Number(
|
||||||
|
(this.message.sentMessageJson as GuideForRoomTimerChangedEventJson).time
|
||||||
|
) * 1000;
|
||||||
|
// const langs = this.translateService.instant([
|
||||||
|
// 'common.units.hourFrom',
|
||||||
|
// 'common.units.minute',
|
||||||
|
// 'common.units.second'
|
||||||
|
// ]);
|
||||||
|
|
||||||
|
// switch (millisec) {
|
||||||
|
// case 5000:
|
||||||
|
// return `5 ${langs['common.units.second']}`;
|
||||||
|
// case 10000:
|
||||||
|
// return `10 ${langs['common.units.second']}`;
|
||||||
|
// case 30000:
|
||||||
|
// return `30 ${langs['common.units.second']}`;
|
||||||
|
// case 60000:
|
||||||
|
// return `1 ${langs['common.units.minute']}`;
|
||||||
|
// case 300000:
|
||||||
|
// return `5 ${langs['common.units.minute']}`;
|
||||||
|
// case 600000:
|
||||||
|
// return `10 ${langs['common.units.minute']}`;
|
||||||
|
// case 1800000:
|
||||||
|
// return `30 ${langs['common.units.minute']}`;
|
||||||
|
// case 3600000:
|
||||||
|
// return `1 ${langs['common.units.hourFrom']}`;
|
||||||
|
// case 21600000:
|
||||||
|
// return `6 ${langs['common.units.hourFrom']}`;
|
||||||
|
// case 43200000:
|
||||||
|
// return `12 ${langs['common.units.hourFrom']}`;
|
||||||
|
// case 86400000:
|
||||||
|
// return `24 ${langs['common.units.hourFrom']}`;
|
||||||
|
// default:
|
||||||
|
// return `0 ${langs['common.units.second']}`;
|
||||||
|
// }
|
||||||
|
|
||||||
|
const langs = ['초', '분', '시간'];
|
||||||
|
|
||||||
|
switch (millisec) {
|
||||||
|
case 5000:
|
||||||
|
return `5 ${langs[0]}`;
|
||||||
|
case 10000:
|
||||||
|
return `10 ${langs[0]}`;
|
||||||
|
case 30000:
|
||||||
|
return `30 ${langs[0]}`;
|
||||||
|
case 60000:
|
||||||
|
return `1 ${langs[1]}`;
|
||||||
|
case 300000:
|
||||||
|
return `5 ${langs[1]}`;
|
||||||
|
case 600000:
|
||||||
|
return `10 ${langs[1]}`;
|
||||||
|
case 1800000:
|
||||||
|
return `30 ${langs[1]}`;
|
||||||
|
case 3600000:
|
||||||
|
return `1 ${langs[2]}`;
|
||||||
|
case 21600000:
|
||||||
|
return `6 ${langs[2]}`;
|
||||||
|
case 43200000:
|
||||||
|
return `12 ${langs[2]}`;
|
||||||
|
case 86400000:
|
||||||
|
return `24 ${langs[2]}`;
|
||||||
|
default:
|
||||||
|
return `0 ${langs[0]}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getRequesterForRenameRoom() {
|
||||||
|
return (this.message.sentMessageJson as RenameRoomEventJson).requester;
|
||||||
|
}
|
||||||
|
getRoomNameForRenameRoom() {
|
||||||
|
return (this.message.sentMessageJson as RenameRoomEventJson).roomName;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
<div class="ucap-chat-message-box-mass-translation">
|
||||||
|
<div
|
||||||
|
*ngIf="!translationSimpleview || (!!translationSimpleview && !!isMe)"
|
||||||
|
class="contents original"
|
||||||
|
[innerHTML]="
|
||||||
|
message.sentMessageJson.original
|
||||||
|
| ucapSafeHtml
|
||||||
|
| ucapLinefeedToHtml
|
||||||
|
| ucapLinky
|
||||||
|
"
|
||||||
|
(contextmenu)="onContextMenuMessage($event, 'original')"
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
*ngIf="!translationSimpleview || (!!translationSimpleview && !isMe)"
|
||||||
|
class="contents translation"
|
||||||
|
(contextmenu)="onContextMenuMessage($event, 'translation')"
|
||||||
|
>
|
||||||
|
<span class="language">{{ message.sentMessageJson.destLocale }}</span>
|
||||||
|
<span
|
||||||
|
[innerHTML]="
|
||||||
|
message.sentMessageJson.translation
|
||||||
|
| ucapSafeHtml
|
||||||
|
| ucapLinefeedToHtml
|
||||||
|
| ucapLinky
|
||||||
|
"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="btn-box">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<button mat-button (click)="onClickMassDetail('O')">
|
||||||
|
전체보기
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button mat-button (click)="onClickMassDetail('T')">
|
||||||
|
<span class="language">{{ message.sentMessageJson.destLocale }}</span>
|
||||||
|
번역보기
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { MassTranslationComponent } from './mass-translation.component';
|
||||||
|
|
||||||
|
describe('Chat::MessageBox::MassTranslationComponent', () => {
|
||||||
|
let component: MassTranslationComponent;
|
||||||
|
let fixture: ComponentFixture<MassTranslationComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [MassTranslationComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(MassTranslationComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,73 @@
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
Input,
|
||||||
|
Output,
|
||||||
|
EventEmitter,
|
||||||
|
AfterViewInit,
|
||||||
|
ElementRef,
|
||||||
|
Inject
|
||||||
|
} from '@angular/core';
|
||||||
|
import { Info, MassTranslationEventJson } from '@ucap/protocol-event';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ucap-chat-message-box-mass-translation',
|
||||||
|
templateUrl: './mass-translation.component.html',
|
||||||
|
styleUrls: ['./mass-translation.component.scss']
|
||||||
|
})
|
||||||
|
export class MassTranslationComponent implements OnInit, AfterViewInit {
|
||||||
|
@Input()
|
||||||
|
message: Info<MassTranslationEventJson>;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
translationSimpleview: boolean;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
isMe: boolean;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
massTranslationDetail = new EventEmitter<{
|
||||||
|
message: Info<MassTranslationEventJson>;
|
||||||
|
contentsType: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
contextMenu = new EventEmitter<{
|
||||||
|
event: MouseEvent;
|
||||||
|
type: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
openLink = new EventEmitter<string>();
|
||||||
|
|
||||||
|
constructor(private elementRef: ElementRef) {}
|
||||||
|
|
||||||
|
ngOnInit() {}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
if (
|
||||||
|
!!this.elementRef.nativeElement &&
|
||||||
|
!!this.elementRef.nativeElement.querySelector('a')
|
||||||
|
) {
|
||||||
|
const elements = this.elementRef.nativeElement.querySelectorAll('a');
|
||||||
|
elements.forEach((element) => {
|
||||||
|
element.addEventListener('click', this.onClickEvent.bind(this));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickEvent(event: MouseEvent) {
|
||||||
|
this.openLink.emit((event.target as HTMLAnchorElement).text);
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickMassDetail(contentsType: string) {
|
||||||
|
this.massTranslationDetail.emit({
|
||||||
|
message: this.message,
|
||||||
|
contentsType
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onContextMenuMessage(event: MouseEvent, type: string) {
|
||||||
|
this.contextMenu.emit({ event, type });
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
<div class="ucap-chat-message-box-mass">
|
||||||
|
<span
|
||||||
|
class="content"
|
||||||
|
[innerHTML]="content | ucapSafeHtml | ucapLinefeedToHtml | ucapLinky"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="detailButteonShow" class="btn-box">
|
||||||
|
<button mat-button (click)="onClickDetailView()">
|
||||||
|
전체보기
|
||||||
|
</button>
|
||||||
|
</div>
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { MassComponent } from './mass.component';
|
||||||
|
|
||||||
|
describe('Chat::MessageBox::MassComponent', () => {
|
||||||
|
let component: MassComponent;
|
||||||
|
let fixture: ComponentFixture<MassComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [MassComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(MassComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,74 @@
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
Input,
|
||||||
|
Output,
|
||||||
|
EventEmitter,
|
||||||
|
ElementRef,
|
||||||
|
AfterViewInit,
|
||||||
|
Inject
|
||||||
|
} from '@angular/core';
|
||||||
|
import { Info, MassTextEventJson } from '@ucap/protocol-event';
|
||||||
|
import { StatusCode } from '@ucap/api';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ucap-chat-message-box-mass',
|
||||||
|
templateUrl: './mass.component.html',
|
||||||
|
styleUrls: ['./mass.component.scss']
|
||||||
|
})
|
||||||
|
export class MassComponent implements OnInit, AfterViewInit {
|
||||||
|
@Input()
|
||||||
|
message: Info<MassTextEventJson>;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
massDetail = new EventEmitter<number>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
openLink = new EventEmitter<string>();
|
||||||
|
|
||||||
|
content: string;
|
||||||
|
eventMassSeq: number;
|
||||||
|
detailButteonShow = true;
|
||||||
|
|
||||||
|
constructor(private elementRef: ElementRef) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
try {
|
||||||
|
if (StatusCode.Success === this.message.sentMessageJson.statusCode) {
|
||||||
|
this.content = this.message.sentMessageJson.content;
|
||||||
|
} else {
|
||||||
|
this.content =
|
||||||
|
this.message.sentMessageJson.errorMessage || '[Error] System Error!!';
|
||||||
|
this.detailButteonShow = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!!this.message.sentMessageJson.massSeq) {
|
||||||
|
this.eventMassSeq = this.message.sentMessageJson.massSeq;
|
||||||
|
} else {
|
||||||
|
this.detailButteonShow = false;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.detailButteonShow = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
if (
|
||||||
|
!!this.elementRef.nativeElement &&
|
||||||
|
!!this.elementRef.nativeElement.querySelector('a')
|
||||||
|
) {
|
||||||
|
const elements = this.elementRef.nativeElement.querySelectorAll('a');
|
||||||
|
elements.forEach((element) => {
|
||||||
|
element.addEventListener('click', this.onClickEvent.bind(this));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickEvent(event: MouseEvent) {
|
||||||
|
this.openLink.emit((event.target as HTMLAnchorElement).text);
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickDetailView() {
|
||||||
|
this.massDetail.emit(this.eventMassSeq);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
<div class="ucap-chat-message-box-read-here">
|
||||||
|
<span>여기까지 읽었습니다</span>
|
||||||
|
</div>
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ReadHereComponent } from './read-here.component';
|
||||||
|
|
||||||
|
describe('Chat::MessageBox::ReadHereComponent', () => {
|
||||||
|
let component: ReadHereComponent;
|
||||||
|
let fixture: ComponentFixture<ReadHereComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ReadHereComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ReadHereComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ucap-chat-message-box-read-here',
|
||||||
|
templateUrl: './read-here.component.html',
|
||||||
|
styleUrls: ['./read-here.component.scss']
|
||||||
|
})
|
||||||
|
export class ReadHereComponent implements OnInit {
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
ngOnInit() {}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
<div class="ucap-chat-message-box-recall">
|
||||||
|
<span class="icon-recall"><i class="material-icons">redo</i></span>
|
||||||
|
<span class="recall-msg">회수된 메시지</span>
|
||||||
|
</div>
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { RecallComponent } from './recall.component';
|
||||||
|
|
||||||
|
describe('Chat::MessageBox::RecallComponent', () => {
|
||||||
|
let component: RecallComponent;
|
||||||
|
let fixture: ComponentFixture<RecallComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [RecallComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(RecallComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ucap-chat-message-box-recall',
|
||||||
|
templateUrl: './recall.component.html',
|
||||||
|
styleUrls: ['./recall.component.scss']
|
||||||
|
})
|
||||||
|
export class RecallComponent implements OnInit {
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
ngOnInit() {}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
<div class="ucap-chat-message-box-reply">
|
||||||
|
<div class="event-header" style="color: black;">
|
||||||
|
<ul>
|
||||||
|
<li class="sub-title">나에게 답장</li>
|
||||||
|
<li class="parent-contents">
|
||||||
|
올려 놓았습니다. 확인해 보시기 바랍니다.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="contents">
|
||||||
|
<span class="language">→</span>
|
||||||
|
네 감사합니다. 수고가 많으시네요. 오늘 중으로 확인해 보겠습니다.
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { TextComponent } from './text.component';
|
||||||
|
|
||||||
|
describe('Chat::MessageBox::TextComponent', () => {
|
||||||
|
let component: TextComponent;
|
||||||
|
let fixture: ComponentFixture<TextComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [TextComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(TextComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,21 @@
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
Input,
|
||||||
|
ElementRef,
|
||||||
|
AfterViewInit,
|
||||||
|
Inject
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ucap-chat-message-box-reply',
|
||||||
|
templateUrl: './reply.component.html',
|
||||||
|
styleUrls: ['./reply.component.scss']
|
||||||
|
})
|
||||||
|
export class ReplyComponent implements OnInit, AfterViewInit {
|
||||||
|
constructor(private elementRef: ElementRef) {}
|
||||||
|
|
||||||
|
ngOnInit() {}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
<div class="ucap-chat-message-box-schedule">
|
||||||
|
<div class="event-header" style="color: black;">
|
||||||
|
<ng-container
|
||||||
|
*ngIf="!!message.sentMessageJson && !!message.sentMessageJson.contents"
|
||||||
|
>
|
||||||
|
<ng-container [ngSwitch]="message.sentMessageJson.contents">
|
||||||
|
<ng-container *ngSwitchCase="PlanContentType.New">
|
||||||
|
{{ 'chat.event.scheduleTypeNew' | ucapI18n }}
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="PlanContentType.Update">
|
||||||
|
{{ 'chat.event.scheduleTypeUpdate' | ucapI18n }}
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngSwitchCase="PlanContentType.Delete">
|
||||||
|
{{ 'chat.event.scheduleTypeDelete' | ucapI18n }}
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngSwitchDefault>
|
||||||
|
<!-- {{ 'chat.event.scheduleTypeDefault' | translate }} -->
|
||||||
|
{{ getAlertLeftTime() }}
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
<ul class="event-info">
|
||||||
|
<li class="place">
|
||||||
|
마곡 E14동 906호
|
||||||
|
</li>
|
||||||
|
<li class="date">
|
||||||
|
2020.05.23 9:30 ~ 2020.05.23 11:30
|
||||||
|
</li>
|
||||||
|
<li class="event-content">
|
||||||
|
{{ message.sentMessageJson.title }}
|
||||||
|
{{ message.sentMessageJson.contents }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="btn-box">
|
||||||
|
<button mat-button>상세보기</button>
|
||||||
|
</div>
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ScheduleComponent } from './schedule.component';
|
||||||
|
|
||||||
|
describe('Chat::MessageBox::ScheduleComponent', () => {
|
||||||
|
let component: ScheduleComponent;
|
||||||
|
let fixture: ComponentFixture<ScheduleComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ScheduleComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ScheduleComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,64 @@
|
||||||
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
|
import { Info, PlanEventJson, PlanContentType } from '@ucap/protocol-event';
|
||||||
|
import { TranslateService } from '@ucap/ng-ui-organization';
|
||||||
|
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ucap-chat-message-box-schedule',
|
||||||
|
templateUrl: './schedule.component.html',
|
||||||
|
styleUrls: ['./schedule.component.scss']
|
||||||
|
})
|
||||||
|
export class ScheduleComponent implements OnInit {
|
||||||
|
@Input()
|
||||||
|
message: Info<PlanEventJson>;
|
||||||
|
|
||||||
|
PlanContentType = PlanContentType;
|
||||||
|
date: any;
|
||||||
|
endDate: any;
|
||||||
|
|
||||||
|
constructor(private translateService: TranslateService) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (!!this.message && !!this.message.sentMessageJson) {
|
||||||
|
if (!!this.message.sentMessageJson.date) {
|
||||||
|
let strDate = this.message.sentMessageJson.date
|
||||||
|
.replace(/ /g, '')
|
||||||
|
.replace(/\n/g, '')
|
||||||
|
.replace(/(\([월,화,수,목,금,토,일]\))/g, '');
|
||||||
|
if (strDate.indexOf('오전') > -1) {
|
||||||
|
strDate = strDate.replace('오전', ' ');
|
||||||
|
} else if (strDate.indexOf('오후') > -1) {
|
||||||
|
strDate = strDate.replace('오후', ' ');
|
||||||
|
const arr = strDate.split(' ');
|
||||||
|
const h = Number(arr[1].split(':')[0]) + 12;
|
||||||
|
strDate = arr[0] + ' ' + h + ':' + arr[1].split(':')[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.date = moment(strDate).toDate();
|
||||||
|
if (this.date === 'Invalid Date') {
|
||||||
|
this.date = this.message.sentMessageJson.date.replace(/\n/g, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickSave(): void {}
|
||||||
|
|
||||||
|
getAlertLeftTime(): string {
|
||||||
|
let content = this.message.sentMessageJson.contents;
|
||||||
|
if (content.indexOf('PLAN_CONTENTS_MINUTE') > -1) {
|
||||||
|
content = content.replace('PLAN_CONTENTS_MINUTE', '분');
|
||||||
|
} else if (content.indexOf('PLAN_CONTENTS_HOUR') > -1) {
|
||||||
|
content = content.replace('PLAN_CONTENTS_HOUR', '시간');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (content.indexOf('PLAN_CONTENTS_AFTER') > -1) {
|
||||||
|
content = content.replace('PLAN_CONTENTS_AFTER', ' 전 알림');
|
||||||
|
}
|
||||||
|
|
||||||
|
content = '[이벤트] ' + content;
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
<div class="ucap-chat-message-box-sms">
|
||||||
|
<div class="event-header" style="color: black;">
|
||||||
|
SMS
|
||||||
|
</div>
|
||||||
|
<div class="contents">
|
||||||
|
SMS 내용 공간입니다. 내용을 보여주세요 SMS 내용 공간입니다. 내용을
|
||||||
|
보여주세요 SMS 내용 공간입니다. 내용을 보여주세요
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { TextComponent } from './text.component';
|
||||||
|
|
||||||
|
describe('Chat::MessageBox::TextComponent', () => {
|
||||||
|
let component: TextComponent;
|
||||||
|
let fixture: ComponentFixture<TextComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [TextComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(TextComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,21 @@
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
Input,
|
||||||
|
ElementRef,
|
||||||
|
AfterViewInit,
|
||||||
|
Inject
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ucap-chat-message-box-sms',
|
||||||
|
templateUrl: './sms.component.html',
|
||||||
|
styleUrls: ['./sms.component.scss']
|
||||||
|
})
|
||||||
|
export class SmsComponent implements OnInit, AfterViewInit {
|
||||||
|
constructor(private elementRef: ElementRef) {}
|
||||||
|
|
||||||
|
ngOnInit() {}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
<div class="ucap-chat-message-box-sticker">
|
||||||
|
<ul>
|
||||||
|
<li *ngIf="stickerUrl">
|
||||||
|
<img [src]="stickerUrl" />
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
*ngIf="contents"
|
||||||
|
[innerHTML]="contents | ucapSafeHtml | ucapLinefeedToHtml | ucapLinky"
|
||||||
|
></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { StickerComponent } from './sticker.component';
|
||||||
|
|
||||||
|
describe('Chat::MessageBox::StickerComponent', () => {
|
||||||
|
let component: StickerComponent;
|
||||||
|
let fixture: ComponentFixture<StickerComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [StickerComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(StickerComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,54 @@
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
Input,
|
||||||
|
ElementRef,
|
||||||
|
AfterViewInit,
|
||||||
|
EventEmitter,
|
||||||
|
Output
|
||||||
|
} from '@angular/core';
|
||||||
|
import { Info, StickerEventJson } from '@ucap/protocol-event';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ucap-chat-message-box-sticker',
|
||||||
|
templateUrl: './sticker.component.html',
|
||||||
|
styleUrls: ['./sticker.component.scss']
|
||||||
|
})
|
||||||
|
export class StickerComponent implements OnInit, AfterViewInit {
|
||||||
|
@Input()
|
||||||
|
message: Info<StickerEventJson>;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
stickerUrl?: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
stickerDefaultImagePath: string;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
openLink = new EventEmitter<string>();
|
||||||
|
|
||||||
|
contents: string;
|
||||||
|
constructor(private elementRef: ElementRef) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (!!this.message.sentMessageJson?.chat) {
|
||||||
|
this.contents = this.message.sentMessageJson.chat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
if (
|
||||||
|
!!this.elementRef.nativeElement &&
|
||||||
|
!!this.elementRef.nativeElement.querySelector('a')
|
||||||
|
) {
|
||||||
|
const elements = this.elementRef.nativeElement.querySelectorAll('a');
|
||||||
|
elements.forEach((element) => {
|
||||||
|
element.addEventListener('click', this.onClickEvent.bind(this));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickEvent(event: MouseEvent) {
|
||||||
|
this.openLink.emit((event.target as HTMLAnchorElement).text);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
<div class="ucap-chat-message-box-text">
|
||||||
|
<span [innerHTML]="message.sentMessage | ucapSafeHtml | ucapLinky"></span>
|
||||||
|
</div>
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { TextComponent } from './text.component';
|
||||||
|
|
||||||
|
describe('Chat::MessageBox::TextComponent', () => {
|
||||||
|
let component: TextComponent;
|
||||||
|
let fixture: ComponentFixture<TextComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [TextComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(TextComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,43 @@
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
Input,
|
||||||
|
ElementRef,
|
||||||
|
AfterViewInit,
|
||||||
|
Output,
|
||||||
|
EventEmitter
|
||||||
|
} from '@angular/core';
|
||||||
|
import { Info, EventJson } from '@ucap/protocol-event';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ucap-chat-message-box-text',
|
||||||
|
templateUrl: './text.component.html',
|
||||||
|
styleUrls: ['./text.component.scss']
|
||||||
|
})
|
||||||
|
export class TextComponent implements OnInit, AfterViewInit {
|
||||||
|
@Input()
|
||||||
|
message: Info<EventJson>;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
openLink = new EventEmitter<string>();
|
||||||
|
|
||||||
|
constructor(private elementRef: ElementRef) {}
|
||||||
|
|
||||||
|
ngOnInit() {}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
if (
|
||||||
|
!!this.elementRef.nativeElement &&
|
||||||
|
!!this.elementRef.nativeElement.querySelector('a')
|
||||||
|
) {
|
||||||
|
const elements = this.elementRef.nativeElement.querySelectorAll('a');
|
||||||
|
elements.forEach((element) => {
|
||||||
|
element.addEventListener('click', this.onClickEvent.bind(this));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickEvent(event: MouseEvent) {
|
||||||
|
this.openLink.emit((event.target as HTMLAnchorElement).text);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
<div class="ucap-chat-message-box-translation">
|
||||||
|
<div class="sticker" *ngIf="!!stickerUrl && stickerUrl.trim().length > 0">
|
||||||
|
<img [src]="stickerUrl" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
*ngIf="!translationSimpleview || (!!translationSimpleview && !!isMe)"
|
||||||
|
class="original"
|
||||||
|
[innerHTML]="message.sentMessageJson.original | ucapLinky"
|
||||||
|
(contextmenu)="onContextMenuMessage($event, 'original')"
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
*ngIf="!translationSimpleview || (!!translationSimpleview && !isMe)"
|
||||||
|
class="translation"
|
||||||
|
(contextmenu)="onContextMenuMessage($event, 'translation')"
|
||||||
|
>
|
||||||
|
<span class="language">{{ message.sentMessageJson.locale }}</span>
|
||||||
|
<span [innerHTML]="message.sentMessageJson.translation | ucapLinky"> </span>
|
||||||
|
</div>
|
||||||
|
</div>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user