Merge branch 'master' into eliminate-server-user-table

This commit is contained in:
Moriz Wahl 2022-04-25 11:21:00 +02:00 committed by GitHub
commit fb3137892f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 387 additions and 156 deletions

View File

@ -14,7 +14,7 @@
"analyse-bundle": "yarn build && webpack-bundle-analyzer dist/webpack.stats.json",
"lint": "eslint --max-warnings=0 --ext .js,.vue,.json .",
"stylelint": "stylelint --max-warnings=0 '**/*.{scss,vue}'",
"test": "TZ=UTC jest --coverage",
"test": "cross-env TZ=UTC jest --coverage",
"locales": "scripts/sort.sh"
},
"dependencies": {
@ -57,6 +57,7 @@
"@vue/cli-service": "~4.5.0",
"babel-eslint": "^10.1.0",
"babel-plugin-transform-require-context": "^0.1.1",
"cross-env": "^7.0.3",
"eslint": "7.25.0",
"eslint-config-prettier": "^8.3.0",
"eslint-config-standard": "^16.0.3",

View File

@ -4688,6 +4688,13 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7:
safe-buffer "^5.0.1"
sha.js "^2.4.8"
cross-env@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf"
integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==
dependencies:
cross-spawn "^7.0.1"
cross-spawn@^5.0.1:
version "5.1.0"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
@ -4708,7 +4715,7 @@ cross-spawn@^6.0.0:
shebang-command "^1.2.0"
which "^1.2.9"
cross-spawn@^7.0.0, cross-spawn@^7.0.2:
cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==

View File

@ -10,11 +10,11 @@
"scripts": {
"build": "tsc --build",
"clean": "tsc --build --clean",
"start": "TZ=UTC TS_NODE_BASEURL=./build node -r tsconfig-paths/register build/src/index.js",
"dev": "TZ=UTC nodemon -w src --ext ts --exec ts-node -r tsconfig-paths/register src/index.ts",
"start": "cross-env TZ=UTC TS_NODE_BASEURL=./build node -r tsconfig-paths/register build/src/index.js",
"dev": "cross-env TZ=UTC nodemon -w src --ext ts --exec ts-node -r tsconfig-paths/register src/index.ts",
"lint": "eslint --max-warnings=0 --ext .js,.ts .",
"test": "TZ=UTC NODE_ENV=development jest --runInBand --coverage --forceExit --detectOpenHandles",
"seed": "TZ=UTC ts-node -r tsconfig-paths/register src/seeds/index.ts"
"test": "cross-env TZ=UTC NODE_ENV=development jest --runInBand --coverage --forceExit --detectOpenHandles",
"seed": "cross-env TZ=UTC ts-node -r tsconfig-paths/register src/seeds/index.ts"
},
"dependencies": {
"@types/jest": "^27.0.2",
@ -25,6 +25,7 @@
"axios": "^0.21.1",
"class-validator": "^0.13.1",
"cors": "^2.8.5",
"cross-env": "^7.0.3",
"decimal.js-light": "^2.5.1",
"dotenv": "^10.0.0",
"express": "^4.17.1",

View File

@ -1900,7 +1900,14 @@ create-require@^1.1.0:
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
cross-spawn@^7.0.2, cross-spawn@^7.0.3:
cross-env@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf"
integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==
dependencies:
cross-spawn "^7.0.1"
cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==

View File

@ -10,15 +10,15 @@
"scripts": {
"build": "mkdir -p build/src/config/ && cp src/config/*.txt build/src/config/ && tsc --build",
"clean": "tsc --build --clean",
"up": "TZ=UTC node build/src/index.js up",
"down": "TZ=UTC node build/src/index.js down",
"reset": "TZ=UTC node build/src/index.js reset",
"dev_up": "TZ=UTC ts-node src/index.ts up",
"dev_down": "TZ=UTC ts-node src/index.ts down",
"dev_reset": "TZ=UTC ts-node src/index.ts reset",
"up": "cross-env TZ=UTC node build/src/index.js up",
"down": "cross-env TZ=UTC node build/src/index.js down",
"reset": "cross-env TZ=UTC node build/src/index.js reset",
"dev_up": "cross-env TZ=UTC ts-node src/index.ts up",
"dev_down": "cross-env TZ=UTC ts-node src/index.ts down",
"dev_reset": "cross-env TZ=UTC ts-node src/index.ts reset",
"lint": "eslint --max-warnings=0 --ext .js,.ts .",
"seed:config": "ts-node ./node_modules/typeorm-seeding/dist/cli.js config",
"seed": "TZ=UTC ts-node src/index.ts seed"
"seed": "cross-env TZ=UTC ts-node src/index.ts seed"
},
"devDependencies": {
"@types/faker": "^5.5.9",
@ -37,6 +37,7 @@
"typescript": "^4.3.5"
},
"dependencies": {
"cross-env": "^7.0.3",
"crypto": "^1.0.1",
"decimal.js-light": "^2.5.1",
"dotenv": "^10.0.0",

View File

@ -481,7 +481,14 @@ create-require@^1.1.0:
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
cross-spawn@^7.0.2:
cross-env@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf"
integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==
dependencies:
cross-spawn "^7.0.1"
cross-spawn@^7.0.1, cross-spawn@^7.0.2:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==

View File

@ -0,0 +1,135 @@
<mxfile host="65bd71144e">
<diagram id="IM2_X0c97E_FZMH_xTRz" name="Page-1">
<mxGraphModel dx="888" dy="633" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="28" value="Other Community" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#008a00;fontColor=#ffffff;strokeColor=#005700;" vertex="1" parent="1">
<mxGeometry x="360" y="410" width="120" height="90" as="geometry"/>
</mxCell>
<mxCell id="3" value="Appolo Server" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#008a00;fontColor=#ffffff;strokeColor=#005700;" parent="1" vertex="1">
<mxGeometry x="220" y="80" width="280" height="300" as="geometry"/>
</mxCell>
<mxCell id="6" style="edgeStyle=none;html=1;" parent="1" target="5" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="500" y="325" as="sourcePoint"/>
</mxGeometry>
</mxCell>
<mxCell id="25" style="edgeStyle=none;html=1;startArrow=none;startFill=0;" edge="1" parent="1" source="2" target="16">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="27" style="edgeStyle=none;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;startArrow=none;startFill=0;" edge="1" parent="1" source="2" target="26">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="2" value="Node" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#60a917;fontColor=#ffffff;strokeColor=#2D7600;" parent="1" vertex="1">
<mxGeometry x="370" y="300" width="100" height="50" as="geometry"/>
</mxCell>
<mxCell id="5" value="DB" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" parent="1" vertex="1">
<mxGeometry x="600" y="285" width="60" height="80" as="geometry"/>
</mxCell>
<mxCell id="10" value="Node" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#60a917;fontColor=#ffffff;strokeColor=#2D7600;labelPosition=center;verticalLabelPosition=middle;align=center;verticalAlign=middle;" parent="1" vertex="1">
<mxGeometry x="260" y="575" width="240" height="230" as="geometry"/>
</mxCell>
<mxCell id="14" style="edgeStyle=none;html=1;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=0.25;entryY=0;entryDx=0;entryDy=0;startArrow=none;startFill=0;" parent="1" source="11" target="12" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="11" value="DHT (lookup/annoucne)" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#76608a;fontColor=#ffffff;strokeColor=#432D57;" parent="1" vertex="1">
<mxGeometry x="280" y="600" width="200" height="60" as="geometry"/>
</mxCell>
<mxCell id="15" style="edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;startArrow=none;startFill=0;" edge="1" parent="1" source="12" target="13">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="12" value="Direct Connection&lt;br&gt;(exchange endpoints)" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#76608a;fontColor=#ffffff;strokeColor=#432D57;" parent="1" vertex="1">
<mxGeometry x="280" y="730" width="200" height="60" as="geometry"/>
</mxCell>
<mxCell id="13" value="DB" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" parent="1" vertex="1">
<mxGeometry x="600" y="720" width="60" height="80" as="geometry"/>
</mxCell>
<mxCell id="24" value="" style="edgeStyle=none;html=1;startArrow=none;startFill=0;" edge="1" parent="1" source="16" target="23">
<mxGeometry relative="1" as="geometry">
<Array as="points"/>
</mxGeometry>
</mxCell>
<mxCell id="16" value="Verify via GraphQL" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#60a917;fontColor=#ffffff;strokeColor=#2D7600;" vertex="1" parent="1">
<mxGeometry x="240" y="300" width="100" height="50" as="geometry"/>
</mxCell>
<mxCell id="21" value="Other Community" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#008a00;fontColor=#ffffff;strokeColor=#005700;" vertex="1" parent="1">
<mxGeometry x="30" y="71" width="120" height="90" as="geometry"/>
</mxCell>
<mxCell id="22" value="Other Community" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#008a00;fontColor=#ffffff;strokeColor=#005700;" vertex="1" parent="1">
<mxGeometry x="30" y="176" width="120" height="90" as="geometry"/>
</mxCell>
<mxCell id="23" value="Other Community" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#008a00;fontColor=#ffffff;strokeColor=#005700;" vertex="1" parent="1">
<mxGeometry x="30" y="281" width="120" height="90" as="geometry"/>
</mxCell>
<mxCell id="26" value="Node" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#60a917;fontColor=#ffffff;strokeColor=#2D7600;" vertex="1" parent="1">
<mxGeometry x="370" y="430" width="100" height="50" as="geometry"/>
</mxCell>
<mxCell id="29" value="Appolo Server" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#008a00;fontColor=#ffffff;strokeColor=#005700;verticalAlign=top;" vertex="1" parent="1">
<mxGeometry x="110" y="880" width="540" height="500" as="geometry"/>
</mxCell>
<mxCell id="35" value="" style="edgeStyle=none;html=1;startArrow=classic;startFill=1;" edge="1" parent="1" source="30" target="34">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="690" y="940"/>
</Array>
</mxGeometry>
</mxCell>
<mxCell id="30" value="Frontend GraphQL Endpoint (unversionated)" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="150" y="910" width="450" height="60" as="geometry"/>
</mxCell>
<mxCell id="31" value="Versionated Endpoints" style="rounded=0;whiteSpace=wrap;html=1;verticalAlign=top;" vertex="1" parent="1">
<mxGeometry x="150" y="1010" width="450" height="310" as="geometry"/>
</mxCell>
<mxCell id="34" value="Frontend" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="690" y="910" width="120" height="60" as="geometry"/>
</mxCell>
<mxCell id="36" value="Other Community" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#008a00;fontColor=#ffffff;strokeColor=#005700;verticalAlign=top;" vertex="1" parent="1">
<mxGeometry x="700" y="1012" width="140" height="250" as="geometry"/>
</mxCell>
<mxCell id="38" value="&lt;span style=&quot;color: rgba(0 , 0 , 0 , 0) ; font-family: monospace ; font-size: 0px&quot;&gt;%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%22Frontend%20GraphQL%20Endpoint%20(unversionated)%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22150%22%20y%3D%221010%22%20width%3D%22450%22%20height%3D%22310%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E&lt;/span&gt;&lt;span style=&quot;color: rgba(0 , 0 , 0 , 0) ; font-family: monospace ; font-size: 0px&quot;&gt;%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%22Frontend%20GraphQL%20Endpoint%20(unversionated)%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22150%22%20y%3D%221010%22%20width%3D%22450%22%20height%3D%22310%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E&lt;/span&gt;" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="710" y="1042" width="120" height="30" as="geometry"/>
</mxCell>
<mxCell id="39" value="&lt;span style=&quot;color: rgba(0 , 0 , 0 , 0) ; font-family: monospace ; font-size: 0px&quot;&gt;%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%22Frontend%20GraphQL%20Endpoint%20(unversionated)%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22150%22%20y%3D%221010%22%20width%3D%22450%22%20height%3D%22310%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E&lt;/span&gt;&lt;span style=&quot;color: rgba(0 , 0 , 0 , 0) ; font-family: monospace ; font-size: 0px&quot;&gt;%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%22Frontend%20GraphQL%20Endpoint%20(unversionated)%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22150%22%20y%3D%221010%22%20width%3D%22450%22%20height%3D%22310%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E&lt;/span&gt;" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="710" y="1082" width="120" height="170" as="geometry"/>
</mxCell>
<mxCell id="48" style="edgeStyle=none;html=1;startArrow=classic;startFill=1;" edge="1" parent="1" source="31" target="39">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="50" value="1.0" style="whiteSpace=wrap;html=1;aspect=fixed;fillColor=#e51400;fontColor=#ffffff;strokeColor=#B20000;" vertex="1" parent="1">
<mxGeometry x="481" y="1050" width="40" height="40" as="geometry"/>
</mxCell>
<mxCell id="51" value="1.1" style="whiteSpace=wrap;html=1;aspect=fixed;fillColor=#e51400;fontColor=#ffffff;strokeColor=#B20000;" vertex="1" parent="1">
<mxGeometry x="481" y="1100" width="40" height="40" as="geometry"/>
</mxCell>
<mxCell id="52" value="2.1" style="whiteSpace=wrap;html=1;aspect=fixed;fillColor=#f0a30a;fontColor=#000000;strokeColor=#BD7000;" vertex="1" parent="1">
<mxGeometry x="480" y="1200" width="40" height="40" as="geometry"/>
</mxCell>
<mxCell id="53" value="2.0" style="whiteSpace=wrap;html=1;aspect=fixed;fillColor=#fa6800;fontColor=#000000;strokeColor=#C73500;" vertex="1" parent="1">
<mxGeometry x="481" y="1150" width="40" height="40" as="geometry"/>
</mxCell>
<mxCell id="54" value="3.0" style="whiteSpace=wrap;html=1;aspect=fixed;fillColor=#e3c800;fontColor=#000000;strokeColor=#B09500;" vertex="1" parent="1">
<mxGeometry x="481" y="1252" width="40" height="40" as="geometry"/>
</mxCell>
<mxCell id="59" value="&lt;span style=&quot;color: rgba(0 , 0 , 0 , 0) ; font-family: monospace ; font-size: 0px&quot;&gt;%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%222.1%22%20style%3D%22whiteSpace%3Dwrap%3Bhtml%3D1%3Baspect%3Dfixed%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22480%22%20y%3D%221200%22%20width%3D%2240%22%20height%3D%2240%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E&lt;/span&gt;&lt;span style=&quot;color: rgba(0 , 0 , 0 , 0) ; font-family: monospace ; font-size: 0px&quot;&gt;%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%222.1%22%20style%3D%22whiteSpace%3Dwrap%3Bhtml%3D1%3Baspect%3Dfixed%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22480%22%20y%3D%221200%22%20width%3D%2240%22%20height%3D%2240%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E&lt;/span&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e3c800;fontColor=#000000;strokeColor=#B09500;" vertex="1" parent="1">
<mxGeometry x="170" y="1150" width="300" height="142" as="geometry"/>
</mxCell>
<mxCell id="58" value="&lt;font color=&quot;rgba(0, 0, 0, 0)&quot; face=&quot;monospace&quot;&gt;&lt;span style=&quot;font-size: 0px&quot;&gt;Imp&lt;/span&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f0a30a;fontColor=#000000;strokeColor=#BD7000;" vertex="1" parent="1">
<mxGeometry x="220" y="1100" width="250" height="140" as="geometry"/>
</mxCell>
<mxCell id="57" value="&lt;span style=&quot;color: rgba(0 , 0 , 0 , 0) ; font-family: monospace ; font-size: 0px&quot;&gt;%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%222.1%22%20style%3D%22whiteSpace%3Dwrap%3Bhtml%3D1%3Baspect%3Dfixed%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22480%22%20y%3D%221200%22%20width%3D%2240%22%20height%3D%2240%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E&lt;/span&gt;&lt;span style=&quot;color: rgba(0 , 0 , 0 , 0) ; font-family: monospace ; font-size: 0px&quot;&gt;%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%222.1%22%20style%3D%22whiteSpace%3Dwrap%3Bhtml%3D1%3Baspect%3Dfixed%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22480%22%20y%3D%221200%22%20width%3D%2240%22%20height%3D%2240%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E&lt;/span&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e51400;fontColor=#ffffff;strokeColor=#B20000;" vertex="1" parent="1">
<mxGeometry x="280" y="1050" width="190" height="90" as="geometry"/>
</mxCell>
<mxCell id="60" value="Implementation 1.x" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#FFFFFF;" vertex="1" parent="1">
<mxGeometry x="317.5" y="1080" width="115" height="30" as="geometry"/>
</mxCell>
<mxCell id="61" value="Implementation&amp;nbsp;2.x&lt;br&gt;(uses parts of the 1.x implementation)" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#000000;" vertex="1" parent="1">
<mxGeometry x="287.5" y="1170" width="115" height="30" as="geometry"/>
</mxCell>
<mxCell id="62" value="Implementation 3.x" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#000000;" vertex="1" parent="1">
<mxGeometry x="280" y="1252" width="115" height="30" as="geometry"/>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

View File

@ -10,7 +10,7 @@
"analyse-bundle": "yarn build && webpack-bundle-analyzer dist/webpack.stats.json",
"lint": "eslint --max-warnings=0 --ext .js,.vue,.json .",
"stylelint": "stylelint --max-warnings=0 '**/*.{scss,vue}'",
"test": "TZ=UTC jest --coverage",
"test": "cross-env TZ=UTC jest --coverage",
"locales": "scripts/sort.sh"
},
"dependencies": {
@ -72,6 +72,7 @@
"babel-eslint": "^10.1.0",
"babel-plugin-component": "^1.1.0",
"babel-plugin-transform-require-context": "^0.1.1",
"cross-env": "^7.0.3",
"dotenv-webpack": "^7.0.3",
"postcss": "^8.4.8",
"postcss-html": "^1.3.0",

View File

@ -3,9 +3,12 @@
<b-input-group size="lg" class="mb-3" prepend="Link">
<b-form-input :value="link" type="text" readonly></b-form-input>
<b-input-group-append>
<b-button size="sm" text="Button" variant="success" @click="CopyLink">
<b-button size="sm" text="Button" variant="primary" @click="CopyLink">
{{ $t('gdd_per_link.copy') }}
</b-button>
<b-button variant="primary" class="text-light" @click="$emit('show-qr-code-button')">
<b-img src="img/svg/qr-code.svg" width="19" class="svg"></b-img>
</b-button>
</b-input-group-append>
</b-input-group>
</div>
@ -30,3 +33,8 @@ export default {
},
}
</script>
<style>
.svg {
filter: brightness(0) invert(1);
}
</style>

View File

@ -3,13 +3,12 @@
<b-col>
<b-card class="p-0 gradido-custom-background">
<div class="h3 mb-4">{{ $t('gdd_per_link.created') }}</div>
<clipboard-copy :link="link" />
<clipboard-copy :link="link" @show-qr-code-button="showQrCodeButton" />
<div class="text-center">
<figure-qr-code :text="link" />
<figure-qr-code v-if="showQrcode" :link="link" />
<b-button variant="success" @click="$emit('on-reset')" class="mt-4">
<b-button variant="secondary" @click="$emit('on-reset')" class="mt-4">
{{ $t('form.close') }}
</b-button>
</div>
@ -33,5 +32,15 @@ export default {
required: true,
},
},
data() {
return {
showQrcode: false,
}
},
methods: {
showQrCodeButton() {
this.showQrcode = !this.showQrcode
},
},
}
</script>

View File

@ -22,7 +22,9 @@
<div v-else>{{ errorResult }}</div>
</div>
<p class="text-center mt-3">
<b-button variant="success" @click="$emit('on-reset')">{{ $t('form.close') }}</b-button>
<b-button variant="secondary" @click="$emit('on-reset')">
{{ $t('form.close') }}
</b-button>
</p>
</b-card>
</b-col>

View File

@ -9,7 +9,7 @@
{{ $t('form.send_transaction_success') }}
</div>
<p class="text-center mt-3">
<b-button variant="success" @click="$emit('on-reset')">{{ $t('form.close') }}</b-button>
<b-button variant="primary" @click="$emit('on-reset')">{{ $t('form.close') }}</b-button>
</p>
</b-card>
</b-col>

View File

@ -4,7 +4,7 @@ import FigureQrCode from './FigureQrCode'
const localVue = global.localVue
const propsData = {
text: '',
link: '',
}
describe('FigureQrCode', () => {

View File

@ -14,14 +14,14 @@ export default {
QRCanvas,
},
props: {
text: { type: String, required: true },
link: { type: String, required: true },
},
data() {
return {
options: {
cellSize: 8,
correctLevel: 'H',
data: this.text,
data: this.link,
},
}
},

View File

@ -44,115 +44,140 @@ describe('TransactionLink', () => {
expect(wrapper.find('div.transaction-link').exists()).toBeTruthy()
})
describe('Copy link to Clipboard', () => {
const navigatorClipboard = navigator.clipboard
beforeAll(() => {
delete navigator.clipboard
navigator.clipboard = { writeText: navigatorClipboardMock }
})
afterAll(() => {
navigator.clipboard = navigatorClipboard
describe('Link validUntil Date is not valid', () => {
it('has no copy link button', () => {
expect(wrapper.find('.test-copy-link').exists()).toBe(false)
})
describe('copy with success', () => {
beforeEach(async () => {
navigatorClipboardMock.mockResolvedValue()
await wrapper.find('.test-copy-link').trigger('click')
})
it('should call clipboard.writeText', () => {
expect(navigator.clipboard.writeText).toHaveBeenCalledWith(
'http://localhost/redeem/c00000000c000000c0000',
)
})
it('toasts success message', () => {
expect(toastSuccessSpy).toBeCalledWith('gdd_per_link.link-copied')
})
it('has no Qr-Code Button ', () => {
expect(wrapper.find('.test-qr-code').exists()).toBe(false)
})
it('has delete link button ', () => {
expect(wrapper.find('.test-delete-link').exists()).toBe(true)
})
})
describe('qr code modal', () => {
let spy
beforeEach(() => {
describe('Link validUntil Date is valid ', () => {
beforeEach(async () => {
const now = new Date()
jest.clearAllMocks()
await wrapper.setProps({
validUntil: `${new Date(now.getFullYear(), now.getMonth(), now.getDate() + 2)}`,
})
})
describe('with success', () => {
describe('Copy link to Clipboard', () => {
const navigatorClipboard = navigator.clipboard
beforeAll(() => {
delete navigator.clipboard
navigator.clipboard = { writeText: navigatorClipboardMock }
})
afterAll(() => {
navigator.clipboard = navigatorClipboard
})
describe('copy with success', () => {
beforeEach(async () => {
navigatorClipboardMock.mockResolvedValue()
await wrapper.find('.test-copy-link .dropdown-item').trigger('click')
})
it('should call clipboard.writeText', () => {
expect(navigator.clipboard.writeText).toHaveBeenCalledWith(
'http://localhost/redeem/c00000000c000000c0000',
)
})
it('toasts success message', () => {
expect(toastSuccessSpy).toBeCalledWith('gdd_per_link.link-copied')
})
})
})
describe('qr code modal', () => {
let spy
beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'show')
// spy.mockImplementation(() => Promise.resolve('some value'))
// mockAPIcall.mockResolvedValue()
await wrapper.find('.test-qr-code').trigger('click')
jest.clearAllMocks()
})
it('qr-code Modal if show', () => {
expect(spy).toBeCalled()
describe('with success', () => {
beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'show')
// spy.mockImplementation(() => Promise.resolve('some value'))
// mockAPIcall.mockResolvedValue()
await wrapper.find('.test-qr-code .dropdown-item').trigger('click')
})
it('opens the qr-code Modal', () => {
expect(spy).toBeCalled()
})
})
})
})
describe('delete link', () => {
let spy
describe('delete link', () => {
let spy
beforeEach(() => {
jest.clearAllMocks()
})
describe('with success', () => {
beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
spy.mockImplementation(() => Promise.resolve('some value'))
mockAPIcall.mockResolvedValue()
await wrapper.find('.test-delete-link').trigger('click')
jest.clearAllMocks()
})
it('test Modal if confirm true', () => {
expect(spy).toBeCalled()
describe('with success', () => {
beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
spy.mockImplementation(() => Promise.resolve('some value'))
mockAPIcall.mockResolvedValue()
await wrapper.find('.test-delete-link .dropdown-item').trigger('click')
})
it('opens the modal ', () => {
expect(spy).toBeCalled()
})
it('calls the API', () => {
expect(mockAPIcall).toBeCalledWith(
expect.objectContaining({
mutation: deleteTransactionLink,
variables: {
id: 12,
},
}),
)
})
it('toasts a success message', () => {
expect(toastSuccessSpy).toBeCalledWith('gdd_per_link.deleted')
})
it('emits reset transaction link list', () => {
expect(wrapper.emitted('reset-transaction-link-list')).toBeTruthy()
})
})
it('calls the API', () => {
expect(mockAPIcall).toBeCalledWith(
expect.objectContaining({
mutation: deleteTransactionLink,
variables: {
id: 12,
},
}),
)
describe('with error', () => {
beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
spy.mockImplementation(() => Promise.resolve('some value'))
mockAPIcall.mockRejectedValue({ message: 'Something went wrong :(' })
await wrapper.find('.test-delete-link .dropdown-item').trigger('click')
})
it('toasts an error message', () => {
expect(toastErrorSpy).toBeCalledWith('Something went wrong :(')
})
})
it('toasts a success message', () => {
expect(toastSuccessSpy).toBeCalledWith('gdd_per_link.deleted')
})
describe('cancel delete', () => {
beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
spy.mockImplementation(() => Promise.resolve(false))
mockAPIcall.mockResolvedValue()
await wrapper.find('.test-delete-link .dropdown-item').trigger('click')
})
it('emits reset transaction link list', () => {
expect(wrapper.emitted('reset-transaction-link-list')).toBeTruthy()
})
})
describe('with error', () => {
beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
spy.mockImplementation(() => Promise.resolve('some value'))
mockAPIcall.mockRejectedValue({ message: 'Something went wrong :(' })
await wrapper.find('.test-delete-link').trigger('click')
})
it('toasts an error message', () => {
expect(toastErrorSpy).toBeCalledWith('Something went wrong :(')
})
})
describe('cancel delete', () => {
beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
spy.mockImplementation(() => Promise.resolve(false))
mockAPIcall.mockResolvedValue()
await wrapper.find('.test-delete-link').trigger('click')
})
it('does not call the API', () => {
expect(mockAPIcall).not.toBeCalled()
it('does not call the API', () => {
expect(mockAPIcall).not.toBeCalled()
})
})
})
})

View File

@ -1,55 +1,54 @@
<template>
<div class="transaction-link gradido-custom-background">
<b-row class="mb-2 pt-2 pb-2">
<b-col lg="2">
<b-row :class="validLink ? '' : 'bg-muted text-light'" class="mb-2 pt-2 pb-2">
<b-col cols="1">
<type-icon color="text-danger" icon="link45deg" class="pt-4 pl-2" />
</b-col>
<b-col lg="9" md="9">
<b-col cols="11">
<b-row>
<b-col lg="11" md="10">
<b-col>
<amount-and-name-row :amount="amount" :text="$t('form.amount')" />
<memo-row :memo="memo" />
<date-row :date="validUntil" :diffNow="true" />
<date-row :date="validUntil" :diffNow="true" :validLink="validLink" />
<decay-row :decay="decay" />
</b-col>
<b-col lg="1" md="2" class="text-center text-lg-left qr-button">
<b-button
@click="$bvModal.show('modalPopover-' + id)"
class="p-2 test-qr-code"
size="sm"
>
<b-img src="img/svg/qr-code.svg" width="60" class="filter"></b-img>
</b-button>
<b-col cols="12" lg="1" md="1" class="text-center text-md-right pr-5 pr-lg-4">
<b-dropdown no-caret right aria-expanded="false" size="sm">
<template #button-content>
<b-icon icon="three-dots-vertical"></b-icon>
</template>
<b-dropdown-item v-if="validLink" class="test-copy-link" @click="copy">
<b-icon icon="clipboard"></b-icon>
{{ $t('gdd_per_link.copy') }}
</b-dropdown-item>
<b-dropdown-item
v-if="validLink"
@click="$bvModal.show('modalPopover-' + id)"
class="pt-3 pb-3 test-qr-code"
>
<b-img src="img/svg/qr-code.svg" width="18" class="filter"></b-img>
{{ $t('qrCode') }}
</b-dropdown-item>
<b-dropdown-item class="test-delete-link" @click="deleteLink()">
<b-icon icon="trash"></b-icon>
{{ $t('delete') }}
</b-dropdown-item>
</b-dropdown>
</b-col>
</b-row>
</b-col>
<b-col lg="1" md="1" class="text-center text-lg-right">
<b-button
class="p-2 test-copy-link"
size="lg"
variant="outline-primary"
@click="copy"
:title="$t('gdd_per_link.copy')"
>
<b-icon icon="clipboard"></b-icon>
</b-button>
<br />
<b-button
class="p-2 mt-3 test-delete-link"
size="sm"
@click="deleteLink()"
:title="$t('delete')"
>
<b-icon icon="trash"></b-icon>
</b-button>
</b-col>
</b-row>
<b-modal :id="'modalPopover-' + id" title="QR-Code" ok-only hide-header-close>
<div class="text-center">
<figure-qr-code :text="link" />
<p>{{ link }}</p>
</div>
<b-modal :id="'modalPopover-' + id" ok-only hide-header-close>
<b-card header-tag="header" footer-tag="footer">
<template #header>
<h6 class="mb-0">{{ $t('qrCode') }}</h6>
</template>
<b-card-text><figure-qr-code class="text-center" :link="link" /></b-card-text>
<template #footer>
<em>{{ link }}</em>
</template>
</b-card>
</b-modal>
</div>
</template>
@ -115,6 +114,9 @@ export default {
decay() {
return `${this.amount - this.holdAvailableAmount}`
},
validLink() {
return new Date(this.validUntil) > new Date()
},
},
}
</script>

View File

@ -3,7 +3,7 @@
<b-row>
<b-col cols="5">
<div class="text-right">
{{ diffNow ? $t('gdd_per_link.valid_until') : $t('form.date') }}
{{ text }}
</div>
</b-col>
<b-col cols="7">
@ -27,6 +27,20 @@ export default {
required: false,
default: false,
},
validLink: {
type: Boolean,
required: false,
default: false,
},
},
computed: {
text() {
if (this.diffNow)
return this.validLink
? this.$t('gdd_per_link.validUntil')
: this.$t('gdd_per_link.expiredOn')
return this.$t('form.date')
},
},
}
</script>

View File

@ -102,6 +102,7 @@
"decay-14-day": "Vergänglichkeit für 14 Tage",
"delete-the-link": "Den Link löschen?",
"deleted": "Der Link wurde gelöscht!",
"expiredOn": "Abgelaufen am",
"has-account": "Du besitzt bereits ein Gradido Konto?",
"header": "Gradidos versenden per Link",
"isFree": "Gradido ist weltweit kostenfrei.",
@ -121,7 +122,7 @@
"redeemed-title": "eingelöst",
"to-login": "Log dich ein",
"to-register": "Registriere ein neues Konto.",
"valid_until": "Gültig bis"
"validUntil": "Gültig bis"
},
"gdt": {
"calculation": "Berechnung der Gradido Transform",
@ -164,6 +165,7 @@
"infoText": "Wenn dir dein Empfehlungsgeber seine Publisher-Id gegeben hat, trage sie hier ein, sonst lass das Feld bitte unverändert!",
"publisherId": "Publisher-Id:"
},
"qrCode": "QR Code",
"send_gdd": "GDD versenden",
"send_per_link": "GDD versenden per Link",
"settings": {

View File

@ -102,6 +102,7 @@
"decay-14-day": "Decay for 14 days",
"delete-the-link": "Delete the link?",
"deleted": "The link was deleted!",
"expiredOn": "Expired on",
"has-account": "You already have a Gradido account?",
"header": "Send Gradidos via link",
"isFree": "Gradido is free of charge worldwide.",
@ -121,7 +122,7 @@
"redeemed-title": "redeemed",
"to-login": "Log in",
"to-register": "Register a new account.",
"valid_until": "Valid until"
"validUntil": "Valid until"
},
"gdt": {
"calculation": "Calculation of Gradido Transform",
@ -164,6 +165,7 @@
"infoText": "If your referrer has given you his publisher id, enter it here, otherwise leave the field unchanged!",
"publisherId": "PublisherID:"
},
"qrCode": "QR Code",
"send_gdd": "GDD send",
"send_per_link": "GDD send via link",
"settings": {

View File

@ -253,7 +253,7 @@ describe('Send', () => {
describe('close button click', () => {
beforeEach(async () => {
await wrapper.findAll('button').at(1).trigger('click')
await wrapper.findAll('button').at(2).trigger('click')
})
it('Shows the TransactionForm', () => {

View File

@ -5276,6 +5276,13 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7:
safe-buffer "^5.0.1"
sha.js "^2.4.8"
cross-env@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf"
integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==
dependencies:
cross-spawn "^7.0.1"
cross-spawn@^5.0.1, cross-spawn@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
@ -5296,7 +5303,7 @@ cross-spawn@^6.0.0:
shebang-command "^1.2.0"
which "^1.2.9"
cross-spawn@^7.0.0, cross-spawn@^7.0.2:
cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==